diff --git a/.gitignore b/.gitignore index 92004580..e84d01e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ app/release/* !app/release/.gitkeep +sekret.properties app/shared/sekret.properties app/desktop/mongodb-realm app/shared/sekret/src diff --git a/app/shared/build.gradle.kts b/app/shared/build.gradle.kts index b60585a0..95d71da2 100644 --- a/app/shared/build.gradle.kts +++ b/app/shared/build.gradle.kts @@ -20,6 +20,7 @@ version = appVersion sekret { packageName = artifact + propertiesFile = rootDir.canonicalPath } kotlin { diff --git a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.android.kt b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.android.kt new file mode 100644 index 00000000..c8380b1f --- /dev/null +++ b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.android.kt @@ -0,0 +1,18 @@ +package dev.datlag.burningseries.ui.screen.initial.series + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import dev.datlag.burningseries.ui.KeyEventDispatcher +import dev.datlag.burningseries.ui.PIPActions +import dev.datlag.burningseries.ui.PIPEventDispatcher +import dev.datlag.burningseries.ui.PIPModeListener + +@Composable +actual fun EnterSeriesScreen() { + SideEffect { + KeyEventDispatcher = { null } + PIPEventDispatcher = { null } + PIPModeListener = { } + PIPActions = { null } + } +} \ No newline at end of file diff --git a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/ui/screen/video/VideoScreen.android.kt b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/ui/screen/video/VideoScreen.android.kt index 61fb3457..edbf84b1 100644 --- a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/ui/screen/video/VideoScreen.android.kt +++ b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/ui/screen/video/VideoScreen.android.kt @@ -96,7 +96,7 @@ actual fun VideoScreen(component: VideoComponent) { val castState by remember(castContext) { mutableStateOf(castContext?.castState) } val casting by remember(castState) { mutableStateOf(castState == CastState.CONNECTED || castState == CastState.CONNECTING) } var cast by remember(casting) { mutableStateOf(casting) } - val useCastPlayer by remember(headers, cast) { mutableStateOf(headers.isEmpty() && cast) } + val useCastPlayer = remember(headers, cast) { headers.isEmpty() && cast } val sessionListener = remember { object : SessionAvailabilityListener { override fun onCastSessionAvailable() { diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/module/NetworkModule.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/module/NetworkModule.kt index e42286b7..c46f628d 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/module/NetworkModule.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/module/NetworkModule.kt @@ -10,6 +10,7 @@ import dev.datlag.burningseries.getPackageName import dev.datlag.burningseries.network.Firestore import dev.datlag.burningseries.network.JsonBase import dev.datlag.burningseries.network.WrapAPI +import dev.datlag.burningseries.network.realm.RealmLoader import dev.datlag.burningseries.network.state.EpisodeStateMachine import dev.datlag.burningseries.network.state.HomeStateMachine import dev.datlag.burningseries.network.state.SaveStateMachine @@ -104,8 +105,11 @@ object NetworkModule { firestoreKtor.create() } } + bindEagerSingleton { + RealmLoader(instanceOrNull()) + } bindProvider { - EpisodeStateMachine(instance(), instance(), instanceOrNull(), instanceOrNull(), instanceOrNull()) + EpisodeStateMachine(instance(), instance(), instance(), instanceOrNull(), instanceOrNull()) } bindEagerSingleton { SaveStateMachine(instance(), instance(), instanceOrNull(), instanceOrNull(), instanceOrNull()) diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt index c6150a93..fc06d340 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt @@ -93,8 +93,12 @@ fun SeriesScreen(component: SeriesComponent) { } dialogState.child?.instance?.render() + EnterSeriesScreen() } +@Composable +expect fun EnterSeriesScreen() + @Composable private fun CompactScreen(component: SeriesComponent) { val seriesState by component.seriesState.collectAsStateWithLifecycle() diff --git a/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.desktop.kt b/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.desktop.kt new file mode 100644 index 00000000..e07e12bd --- /dev/null +++ b/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.desktop.kt @@ -0,0 +1,6 @@ +package dev.datlag.burningseries.ui.screen.initial.series + +import androidx.compose.runtime.Composable + +@Composable +actual fun EnterSeriesScreen() { } \ No newline at end of file diff --git a/extension/build.gradle.kts b/extension/build.gradle.kts new file mode 100644 index 00000000..68e477cf --- /dev/null +++ b/extension/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + alias(libs.plugins.multiplatform) + alias(libs.plugins.serialization) + alias(libs.plugins.ktorfit) +} + +val artifact = VersionCatalog.artifactName("extension") +group = artifact + +kotlin { + js(IR) { + browser() + binaries.executable() + } + + sourceSets { + jsMain.get().dependencies { + runtimeOnly(npm("webextension-polyfill", "0.10.0")) + } + } +} \ No newline at end of file diff --git a/extension/src/jsMain/resources/manifest.json b/extension/src/jsMain/resources/manifest.json new file mode 100644 index 00000000..19121aeb --- /dev/null +++ b/extension/src/jsMain/resources/manifest.json @@ -0,0 +1,55 @@ +{ + "manifest_version": 3, + + "name": "Burning-Series Activate", + "description": "Burning-Series Activate is an extension to activate episodes for the app in your browser.", + "version": "0.0.0", + + "action": { + "default_icon": "icons/launcher_128.png", + "default_popup": "popup.html" + }, + + "icons": { + "16": "icons/launcher_16.png", + "32": "icons/launcher_32.png", + "48": "icons/launcher_48.png", + "64": "icons/launcher_64.png", + "96": "icons/launcher_96.png", + "128": "icons/launcher_128.png" + }, + + "content_scripts": [ + { + "matches": [ + "*://*.bs.to/serie/*", + "*://*.burningseries.co/serie/*", + "*://*.burningseries.sx/serie/*", + "*://*.burningseries.ac/serie/*", + "*://*.burningseries.vc/serie/*", + "*://*.burningseries.cx/serie/*", + "*://*.burningseries.nz/serie/*", + "*://*.burningseries.se/serie/*", + "*://*.burningseries.tw/serie/*" + ], + "js": [ + "browser-polyfill.min.js", + "content_script.js" + ] + } + ], + + "background": { + "service_worker": "background.js" + }, + + "permissions": [ + "storage", + "background" + ], + + "host_permissions": [ + "https://jsonbase.com/*", + "https://*.googleapis.com/*" + ] +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 90e53555..3cd9a992 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,7 +40,7 @@ parcelable = "1.2.0" protobuf = "0.9.4" protoc = "3.24.4" realm = "1.12.0" -sekret = "0.1.1" +sekret = "0.2.0" serialization-json = "1.6.0" splashscreen = "1.0.1" sqldelight = "2.0.0" diff --git a/model/build.gradle.kts b/model/build.gradle.kts index 3f26f72e..5ae2690a 100644 --- a/model/build.gradle.kts +++ b/model/build.gradle.kts @@ -14,6 +14,11 @@ kotlin { iosX64() iosArm64() iosSimulatorArm64() + js(IR) { + browser() + nodejs() + binaries.executable() + } jvmToolchain(CompileOptions.jvmTargetVersion) @@ -43,6 +48,10 @@ kotlin { jvmMain.get().dependencies { api(libs.lang) } + + jsMain.get().dependencies { + api(libs.coroutines.js) + } } } diff --git a/network/build.gradle.kts b/network/build.gradle.kts index 4b032c0e..aa36f524 100644 --- a/network/build.gradle.kts +++ b/network/build.gradle.kts @@ -17,6 +17,11 @@ kotlin { iosX64() iosArm64() iosSimulatorArm64() + js(IR) { + browser() + nodejs() + binaries.executable() + } jvmToolchain(CompileOptions.jvmTargetVersion) @@ -34,13 +39,23 @@ kotlin { api(libs.ktsoup) api(libs.ktsoup.fs) api(libs.ktsoup.ktor) - api(libs.realm) - api(libs.realm.sync) implementation(libs.jsunpacker) api(libs.firebase.auth) api(libs.firebase.store) } } + + val realmCompatible by creating { + dependsOn(commonMain) + dependencies { + api(libs.realm) + api(libs.realm.sync) + } + } + + jvmMain.get().dependsOn(realmCompatible) + androidMain.get().dependsOn(realmCompatible) + nativeMain.get().dependsOn(realmCompatible) } } @@ -75,4 +90,5 @@ dependencies { add("kspIosX64", libs.ktorfit.ksp) add("kspIosArm64", libs.ktorfit.ksp) add("kspIosSimulatorArm64", libs.ktorfit.ksp) + add("kspJs", libs.ktorfit.ksp) } \ No newline at end of file diff --git a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.kt b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.kt new file mode 100644 index 00000000..8a529b1d --- /dev/null +++ b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.kt @@ -0,0 +1,7 @@ +package dev.datlag.burningseries.network.realm + +expect class RealmLoader { + suspend fun login() + + suspend fun loadEpisodes(hosterHref: List): List +} \ No newline at end of file diff --git a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/EpisodeStateMachine.kt b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/EpisodeStateMachine.kt index 91d62e90..6d0a2b10 100644 --- a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/EpisodeStateMachine.kt +++ b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/EpisodeStateMachine.kt @@ -9,25 +9,22 @@ import dev.datlag.burningseries.model.state.EpisodeState import dev.datlag.burningseries.network.Firestore import dev.datlag.burningseries.network.JsonBase import dev.datlag.burningseries.network.firebase.FireStore +import dev.datlag.burningseries.network.realm.RealmLoader import dev.datlag.burningseries.network.scraper.Video import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.auth.auth import dev.gitlive.firebase.firestore.FirebaseFirestore import io.ktor.client.* -import io.realm.kotlin.mongodb.App -import io.realm.kotlin.mongodb.Credentials -import io.realm.kotlin.mongodb.ext.call import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope -import org.mongodb.kbson.BsonDocument @OptIn(ExperimentalCoroutinesApi::class) class EpisodeStateMachine( private val client: HttpClient, private val jsonBase: JsonBase, - private val app: App?, + private val realmLoader: RealmLoader, private val firestore: FirebaseFirestore?, private val firestoreApi: Firestore? ) : FlowReduxStateMachine(initialState = EpisodeState.Waiting) { @@ -36,11 +33,7 @@ class EpisodeStateMachine( spec { inState { onEnterEffect { - if (NetworkStateSaver.mongoUser == null) { - NetworkStateSaver.mongoUser = suspendCatching { - app?.login(Credentials.anonymous()) - }.getOrNull() - } + realmLoader.login() if (NetworkStateSaver.firebaseUser == null) { NetworkStateSaver.firebaseUser = suspendCatching { Firebase.auth.signInAnonymously().user @@ -76,11 +69,7 @@ class EpisodeStateMachine( val mongoHoster = NetworkStateSaver.mongoHosterMap[episodeHref] ?: emptyList() val mongoDBResults = async { mongoHoster.ifEmpty { - val newList = suspendCatching { - val doc = NetworkStateSaver.mongoUser!!.functions.call("query", hosterHref.toTypedArray()) - doc.getArray("result").values.map { it.asDocument().getString("url").value } - }.getOrNull() ?: emptyList() - + val newList = realmLoader.loadEpisodes(hosterHref) NetworkStateSaver.mongoHosterMap[episodeHref] = newList newList } diff --git a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/NetworkStateSaver.kt b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/NetworkStateSaver.kt index 65c85b7f..6f857fd0 100644 --- a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/NetworkStateSaver.kt +++ b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/NetworkStateSaver.kt @@ -1,11 +1,9 @@ package dev.datlag.burningseries.network.state import dev.gitlive.firebase.auth.FirebaseUser -import io.realm.kotlin.mongodb.User data object NetworkStateSaver { - var mongoUser: User? = null var firebaseUser: FirebaseUser? = null val mongoHosterMap: MutableMap> = mutableMapOf() diff --git a/network/src/jsMain/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.js.kt b/network/src/jsMain/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.js.kt new file mode 100644 index 00000000..91ecca84 --- /dev/null +++ b/network/src/jsMain/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.js.kt @@ -0,0 +1,10 @@ +package dev.datlag.burningseries.network.realm + +actual object RealmLoader { + actual suspend fun login() { } + + actual suspend fun loadEpisodes(hosterHref: List): List { + return emptyList() + } + +} \ No newline at end of file diff --git a/network/src/realmCompatible/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.kt b/network/src/realmCompatible/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.kt new file mode 100644 index 00000000..c4d8e545 --- /dev/null +++ b/network/src/realmCompatible/kotlin/dev/datlag/burningseries/network/realm/RealmLoader.kt @@ -0,0 +1,30 @@ +package dev.datlag.burningseries.network.realm + +import dev.datlag.burningseries.model.common.suspendCatching +import dev.datlag.burningseries.network.state.NetworkStateSaver +import io.realm.kotlin.mongodb.App +import io.realm.kotlin.mongodb.Credentials +import io.realm.kotlin.mongodb.User +import org.mongodb.kbson.BsonDocument +import io.realm.kotlin.mongodb.ext.call + +actual class RealmLoader(private val app: App?) { + actual suspend fun login() { + if (mongoUser == null) { + mongoUser = suspendCatching { + app?.login(Credentials.anonymous()) + }.getOrNull() + } + } + + actual suspend fun loadEpisodes(hosterHref: List): List { + return suspendCatching { + val doc = mongoUser?.functions?.call("query", hosterHref.toTypedArray()) + doc?.getArray("result")?.values?.map { it.asDocument().getString("url").value } + }.getOrNull() ?: emptyList() + } + + companion object { + private var mongoUser: User? = null + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 8b0c207e..d7ee6304 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,6 +10,8 @@ include(":network") include(":color") include(":database") +include(":extension") + pluginManagement { repositories { google()