Skip to content

Commit

Permalink
added activating
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Nov 18, 2023
1 parent f26048e commit f0dc635
Show file tree
Hide file tree
Showing 25 changed files with 508 additions and 142 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package dev.datlag.burningseries.ui.screen.initial.series.activate.component

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import com.multiplatform.webview.web.rememberWebViewNavigator
import com.multiplatform.webview.web.rememberWebViewState
import dev.datlag.burningseries.common.withIOContext
import dev.datlag.burningseries.common.withMainContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive

@Composable
actual fun WebView(url: String, scrapingJs: String, modifier: Modifier, onScraped: (String) -> Unit) {
val state = rememberWebViewState(url)
val navigator = rememberWebViewNavigator()

com.multiplatform.webview.web.WebView(
state = state,
modifier = modifier,
navigator = navigator
)

LaunchedEffect(navigator) {
withIOContext {
do {
delay(3000)
withMainContext {
navigator.evaluateJavaScript(scrapingJs) {
onScraped(it)
}
}
} while (isActive)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import dev.datlag.burningseries.network.Firestore
import dev.datlag.burningseries.network.JsonBase
import dev.datlag.burningseries.network.state.EpisodeStateMachine
import dev.datlag.burningseries.network.state.HomeStateMachine
import dev.datlag.burningseries.network.state.SaveStateMachine
import dev.datlag.burningseries.network.state.SearchStateMachine
import dev.datlag.burningseries.other.StateSaver
import io.ktor.client.*
Expand Down Expand Up @@ -62,5 +63,8 @@ object NetworkModule {
bindEagerSingleton {
EpisodeStateMachine(instance(), instance(), instanceOrNull(), instanceOrNull(), instanceOrNull())
}
bindEagerSingleton {
SaveStateMachine(instance(), instance(), instanceOrNull(), instanceOrNull(), instanceOrNull())
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ interface ActivateComponent : Component {
val scrapingJs: String

fun back()
fun onScraped(data: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,11 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBackIosNew
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Modifier
import com.multiplatform.webview.web.rememberWebViewNavigator
import com.multiplatform.webview.web.rememberWebViewState
import dev.icerock.moko.resources.compose.stringResource
import dev.datlag.burningseries.SharedRes
import dev.datlag.burningseries.common.withIOContext
import dev.datlag.burningseries.common.withMainContext
import dev.datlag.burningseries.model.BSUtil
import dev.datlag.burningseries.ui.custom.PlatformWebView
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import dev.datlag.burningseries.ui.screen.initial.series.activate.component.WebView

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand All @@ -46,10 +38,13 @@ fun ActivateScreen(component: ActivateComponent) {
}
) {
Box(modifier = Modifier.padding(it)) {
val state = rememberWebViewState(url = BSUtil.getBurningSeriesLink(component.episode.href))
val navigator = rememberWebViewNavigator()

PlatformWebView(state, navigator, Modifier.fillMaxSize())
WebView(
url = BSUtil.getBurningSeriesLink(component.episode.href),
scrapingJs = component.scrapingJs,
modifier = Modifier.fillMaxSize()
) { data ->
component.onScraped(data)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ import com.arkivanov.essenty.backhandler.BackCallback
import dev.datlag.burningseries.model.Series
import org.kodein.di.DI
import dev.datlag.burningseries.SharedRes
import dev.datlag.burningseries.common.ioScope
import dev.datlag.burningseries.common.launchIO
import dev.datlag.burningseries.model.HosterScraping
import dev.datlag.burningseries.model.common.scopeCatching
import dev.datlag.burningseries.model.state.EpisodeAction
import dev.datlag.burningseries.model.state.EpisodeState
import dev.datlag.burningseries.model.state.SaveAction
import dev.datlag.burningseries.model.state.SaveState
import dev.datlag.burningseries.network.state.EpisodeStateMachine
import dev.datlag.burningseries.network.state.SaveStateMachine
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn
import kotlinx.serialization.json.Json
import org.kodein.di.instance

class ActivateScreenComponent(
componentContext: ComponentContext,
Expand All @@ -15,13 +29,28 @@ class ActivateScreenComponent(
) : ActivateComponent, ComponentContext by componentContext {

override val scrapingJs: String = SharedRes.assets.scrape_hoster.readText()
private val saveStateMachine by di.instance<SaveStateMachine>()
private val saveState = saveStateMachine.state.stateIn(ioScope(), SharingStarted.Lazily, SaveState.Waiting)
private val json by di.instance<Json>()
private val savedData: MutableSet<String> = mutableSetOf()

private val backCallback = BackCallback {
onGoBack()
}

init {
backHandler.register(backCallback)

ioScope().launchIO {
saveState.collect { state ->
when (val current = state) {
is SaveState.Saving -> {
println("Saving data: ${current.data}")
}
else -> { }
}
}
}
}

@Composable
Expand All @@ -32,4 +61,23 @@ class ActivateScreenComponent(
override fun back() {
onGoBack()
}

override fun onScraped(data: String) {
val trimmed = data.trim()
if (trimmed.isNotBlank() && !trimmed.equals("null", true) && !trimmed.equals("undefined", true)) {
val converted = scopeCatching {
json.decodeFromString<HosterScraping>(trimmed)
}.getOrNull()

if (converted != null) {
if (!savedData.contains(converted.href)) {
ioScope().launchIO {
saveStateMachine.dispatch(SaveAction.Save(converted))
}
}

savedData.add(converted.href)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.datlag.burningseries.ui.screen.initial.series.activate.component

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier

@Composable
expect fun WebView(url: String, scrapingJs: String, modifier: Modifier = Modifier, onScraped: (String) -> Unit)
48 changes: 23 additions & 25 deletions app/shared/src/commonMain/resources/MR/assets/scrape_hoster.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
(function() {
const hosterTabs = document.getElementsByClassName("hoster-tabs");
let activeHoster = null;
if ((hosterTabs !== null && hosterTabs !== undefined) && hosterTabs.length > 0) {
const activeTabs = hosterTabs[0].getElementsByClassName("active");
if ((activeTabs !== null && activeTabs !== undefined) && activeTabs.length > 0) {
const hosters = activeTabs[0].getElementsByTagName("a");
if ((hosters !== null && hosters !== undefined) && hosters.length > 0) {
activeHoster = hosters[0].getAttribute("href");
}
const hosterTabs = document.getElementsByClassName("hoster-tabs");
let activeHoster = null;
if ((hosterTabs !== null && hosterTabs !== undefined) && hosterTabs.length > 0) {
const activeTabs = hosterTabs[0].getElementsByClassName("active");
if ((activeTabs !== null && activeTabs !== undefined) && activeTabs.length > 0) {
const hosters = activeTabs[0].getElementsByTagName("a");
if ((hosters !== null && hosters !== undefined) && hosters.length > 0) {
activeHoster = hosters[0].getAttribute("href");
}
}
}

const hosterPlayers = document.getElementsByClassName("hoster-player");
if ((hosterPlayers !== null && hosterPlayers !== undefined) && hosterPlayers.length > 0) {
const player = hosterPlayers[0];
const links = player.getElementsByTagName("a");
if ((links !== null && links !== undefined) && links.length > 0) {
const link = links[0].getAttribute("href");
return {href: activeHoster, url: link, embed: false};
const hosterPlayers = document.getElementsByClassName("hoster-player");
if ((hosterPlayers !== null && hosterPlayers !== undefined) && hosterPlayers.length > 0) {
const player = hosterPlayers[0];
const links = player.getElementsByTagName("a");
if ((links !== null && links !== undefined) && links.length > 0) {
const link = links[0].getAttribute("href");
return JSON.stringify({href: activeHoster, url: link, embed: false});
} else {
const frames = player.getElementsByTagName("iframe");
if ((frames !== null && frames !== undefined) && frames.length > 0) {
const link = frames[0].getAttribute("src");
return JSON.stringify({href: activeHoster, url: link, embed: true});
} else {
const frames = player.getElementsByTagName("iframe");
if ((frames !== null && frames !== undefined) && frames.length > 0) {
const link = frames[0].getAttribute("src");
return {href: activeHoster, url: link, embed: true};
} else {
return null;
}
return null;
}
}
})();
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dev.datlag.burningseries.ui.screen.initial.series.activate.component

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.SwingPanel
import com.multiplatform.webview.web.WebContent
import dev.datlag.burningseries.SharedRes
import dev.datlag.burningseries.common.withIOContext
import dev.datlag.burningseries.common.withMainContext
import dev.datlag.burningseries.other.CEFState
import dev.datlag.burningseries.other.LocalCEFInitialization
import dev.datlag.burningseries.ui.custom.state.BrowserState
import dev.datlag.kcef.KCEF
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive

@Composable
actual fun WebView(url: String, scrapingJs: String, modifier: Modifier, onScraped: (String) -> Unit) {
val cefInitState by LocalCEFInitialization.current

if (cefInitState is CEFState.INITIALIZED) {
val client = remember { KCEF.newClientBlocking() }
val browser = remember { client.createBrowser(url) }
SwingPanel(
background = MaterialTheme.colorScheme.background,
factory = {
browser.uiComponent
},
modifier = modifier
)

LaunchedEffect(browser) {
withIOContext {
do {
delay(3000)
withMainContext {
browser.evaluateJavaScript(scrapingJs) {
if (it != null) {
onScraped(it)
}
}
}
} while (isActive)
}
}
} else {
BrowserState(SharedRes.strings.browser_initializing)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.datlag.burningseries.model

import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
@OptIn(ExperimentalSerializationApi::class)
data class FirestoreDocument(
@EncodeDefault(EncodeDefault.Mode.NEVER) @SerialName("name") val name: String? = null,
@SerialName("fields") val fields: Map<String, FirestoreQuery.Value>
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
@OptIn(ExperimentalSerializationApi::class)
data class FirestoreQuery(
@SerialName("structuredQuery") val structuredQuery: StructuredQuery
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,5 @@ import kotlinx.serialization.Serializable

@Serializable
data class FirestoreQueryResponse(
@SerialName("document") val document: Document
) {

@Serializable
data class Document(
@SerialName("fields") val fields: Map<String, FirestoreQuery.Value>
)
}
@SerialName("document") val document: FirestoreDocument
)
Loading

0 comments on commit f0dc635

Please sign in to comment.