Add Koin as the DI mechanism for shared code

Hilt is Android/Dagger-only and can't run on Kotlin/Native, so it
can't be used for anything moving into :shared. Koin is the standard
KMP alternative — this wires it up for real: a Koin module
(sharedModule) providing GreetingViewModel via the koin viewmodel DSL,
CmpSmokeTest now resolves it through koinViewModel() instead of
constructing it directly, and AppApplication.onCreate() calls
initSharedKoin() at startup so this isn't just compile-checked dead
code — Koin actually starts alongside Hilt (the two coexist fine,
verified by compiling the full app afterward).

This is the pattern for every ViewModel/ScreenModel that moves to
:shared going forward. HomeViewModel/DetailViewModel themselves stay
Hilt-based in app for now — porting them means porting their
repositories to KMP first, which is separate, larger work.

Verified compiling for android, iosArm64, iosSimulatorArm64, and both
app product flavors still build with Koin initialized at startup.
This commit is contained in:
KhooLy 2026-07-13 03:09:18 +03:00
parent 89ee3eb95f
commit 31cfd2b931
6 changed files with 40 additions and 1 deletions

View file

@ -21,6 +21,7 @@ import com.lagradost.cloudstream3.AcraApplication
import com.lagradost.cloudstream3.app
import com.fluxa.app.common.AppStrings
import com.fluxa.app.common.initialize
import com.fluxa.app.shared.di.initSharedKoin
import com.fluxa.app.ui.catalog.EpisodeReleaseWorker
import com.fluxa.app.plugins.PluginAutoUpdateWorker
import com.fluxa.app.ui.catalog.TrailerResolver
@ -51,6 +52,7 @@ class AppApplication : Application(), SingletonImageLoader.Factory, Configuratio
// CloudStream library's app singleton is auto-initialized by the library
AppStrings.initialize(this)
initSharedKoin()
TrailerResolver.init(cacheDir)
PluginAutoUpdateWorker.enqueue(this)
EpisodeReleaseWorker.enqueue(this)

View file

@ -39,6 +39,7 @@ kotlinMetadataJvm = "2.4.0"
kotlinxSerialization = "1.11.0"
kotlinxDatetime = "0.8.0"
composeMultiplatform = "1.11.1"
koin = "4.2.2"
[libraries]
# Build-logic plugin artifacts (compileOnly in build-logic)
@ -54,6 +55,7 @@ androidx-activity-compose = { group = "androidx.activity", n
androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" }
androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" }
androidx-lifecycle-viewmodel-compose= { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }
androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "lifecycle" }
androidx-work-runtime = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workManager" }
androidx-hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltAndroidx" }
androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltAndroidx" }
@ -124,6 +126,11 @@ kotlin-metadata-jvm = { group = "org.jetbrains.kotlin", name = "kotlin-metadat
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinxDatetime" }
# Koin (multiplatform DI, replaces Hilt in :shared)
koin-core = { group = "io.insert-koin", name = "koin-core", version.ref = "koin" }
koin-compose = { group = "io.insert-koin", name = "koin-compose", version.ref = "koin" }
koin-compose-viewmodel = { group = "io.insert-koin", name = "koin-compose-viewmodel", version.ref = "koin" }
# Jackson
jackson-databind = { group = "com.fasterxml.jackson.core", name = "jackson-databind", version.ref = "jackson" }
jackson-module-kotlin = { group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version.ref = "jackson" }

View file

@ -12,6 +12,10 @@ kotlin {
implementation(project(":core"))
implementation(libs.coil3)
implementation(libs.coil3.compose)
implementation(libs.koin.core)
implementation(libs.koin.compose)
implementation(libs.koin.compose.viewmodel)
implementation(libs.androidx.lifecycle.viewmodel)
}
}
}

View file

@ -3,10 +3,13 @@ package com.fluxa.app.shared
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.fluxa.app.shared.di.GreetingViewModel
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun CmpSmokeTest() {
val viewModel = koinViewModel<GreetingViewModel>()
Column {
Text("Fluxa on ${platformName()}")
Text(viewModel.greeting)
}
}

View file

@ -0,0 +1,9 @@
package com.fluxa.app.shared.di
import org.koin.core.context.startKoin
fun initSharedKoin() {
startKoin {
modules(sharedModule)
}
}

View file

@ -0,0 +1,14 @@
package com.fluxa.app.shared.di
import androidx.lifecycle.ViewModel
import com.fluxa.app.shared.platformName
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module
class GreetingViewModel : ViewModel() {
val greeting: String = "Fluxa on ${platformName()}"
}
val sharedModule = module {
viewModel { GreetingViewModel() }
}