Skip to content

Commit f7d6484

Browse files
authored
Merge pull request #126 from futuredapp/feature/koin-annotations
Use koin annotations in persistence module
2 parents 799040c + 3223eea commit f7d6484

File tree

20 files changed

+197
-87
lines changed

20 files changed

+197
-87
lines changed

convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ afterEvaluate {
1919
if (extension.useKoin) {
2020
ksp {
2121
// enable compile time check
22-
arg("KOIN_CONFIG_CHECK", "false")
22+
arg("KOIN_CONFIG_CHECK", "true")
2323
// disable default module generation
2424
arg("KOIN_DEFAULT_MODULE", "false")
2525
}
@@ -32,6 +32,10 @@ afterEvaluate {
3232
dependencies {
3333
if (extension.useKoin) {
3434
add("kspCommonMainMetadata", libs.koin.ksp.compiler)
35+
add("kspAndroid", libs.koin.ksp.compiler)
36+
add("kspIosX64", libs.koin.ksp.compiler)
37+
add("kspIosArm64", libs.koin.ksp.compiler)
38+
add("kspIosSimulatorArm64", libs.koin.ksp.compiler)
3539
}
3640

3741
// Enable source generation by KSP to commonMain only

gradle/libs.versions.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
[versions]
2-
agp = "8.9.0"
3-
kotlin = "2.1.10"
4-
ksp = "2.1.10-1.0.31" # Must be compatible with: `kotlin`
2+
agp = "8.11.0"
3+
kotlin = "2.1.20"
4+
ksp = "2.1.20-1.0.32" # Must be compatible with: `kotlin`
55
desugarLibs = "2.1.5"
66
androidxLifecycle = "2.8.6"
77
androidxComposeBom = "2024.10.00"
88
jetbrainsComposeRuntime = "1.7.0" # Needs to align with version in Compose BOM as closely as possible
99
androidxActivity = "1.9.2"
1010
decompose = "3.1.0"
1111
essenty = "2.1.0"
12-
koin = "3.5.6"
13-
koinAnnotations = "1.4.0" # Must be compatible with: `ksp`
12+
koin = "4.1.0"
13+
koinAnnotations = "2.1.0" # Must be compatible with: `ksp`
1414
kotlinx-coroutines = "1.8.1"
1515
kotlinx-immutableCollections = "0.3.8"
1616
kotlinx-dateTime = "0.6.1"
@@ -24,7 +24,7 @@ ktor = "3.1.0" # Must be compatible with: `ktorfit`
2424
kotlinx-serialization = "1.8.0" # Must be compatible with: `kotlin`
2525
timber = "5.0.1"
2626
kermit = "2.0.2"
27-
skie = "0.10.1" # Must be compatible with: `kotlin`
27+
skie = "0.10.2" # Must be compatible with: `kotlin`
2828
buildkonfig = "0.15.2"
2929
nsExceptionKt = "1.0.0-BETA-7"
3030
datastore = "1.1.1"

shared/app/src/commonMain/kotlin/app/futured/kmptemplate/app/injection/AppInjection.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package app.futured.kmptemplate.app.injection
33
import app.futured.kmptemplate.feature.injection.FeatureModule
44
import app.futured.kmptemplate.network.graphql.injection.NetworkGraphqlModule
55
import app.futured.kmptemplate.network.rest.injection.NetworkRestModule
6-
import app.futured.kmptemplate.persistence.injection.persistenceModule
6+
import app.futured.kmptemplate.persistence.injection.PersistenceModule
77
import app.futured.kmptemplate.platform.binding.PlatformBindings
88
import app.futured.kmptemplate.platform.injection.platformModule
99
import org.koin.core.context.startKoin
@@ -30,7 +30,7 @@ internal object AppInjection {
3030
FeatureModule().module,
3131
NetworkGraphqlModule().module,
3232
NetworkRestModule().module,
33-
persistenceModule(),
33+
PersistenceModule().module,
3434
)
3535
}
3636
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package app.futured.kmptemplate.feature.domain
2+
3+
import app.futured.arkitekt.crusecases.UseCase
4+
import app.futured.kmptemplate.persistence.persistence.user.UserPersistence
5+
import org.koin.core.annotation.Factory
6+
7+
@Factory
8+
class IsUserLoggedInUseCase(private val userPersistence: UserPersistence) : UseCase<Unit, Boolean>() {
9+
override suspend fun build(args: Unit): Boolean = userPersistence.isUserLoggedIn()
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package app.futured.kmptemplate.feature.domain
2+
3+
import app.futured.arkitekt.crusecases.UseCase
4+
import app.futured.kmptemplate.persistence.persistence.user.UserPersistence
5+
import org.koin.core.annotation.Factory
6+
7+
@Factory
8+
class SetUserLoggedInUseCase(private val userPersistence: UserPersistence) : UseCase<SetUserLoggedInUseCase.Args, Unit>() {
9+
10+
override suspend fun build(args: Args) = userPersistence.setUserLoggedIn(args.isLoggedIn)
11+
12+
data class Args(val isLoggedIn: Boolean)
13+
}

shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/navigation/root/RootNavHostComponent.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package app.futured.kmptemplate.feature.navigation.root
22

33
import app.futured.arkitekt.decompose.ext.asStateFlow
4+
import app.futured.kmptemplate.feature.domain.IsUserLoggedInUseCase
45
import app.futured.kmptemplate.feature.navigation.deepLink.DeepLinkDestination
56
import app.futured.kmptemplate.feature.navigation.deepLink.DeepLinkResolver
67
import app.futured.kmptemplate.feature.navigation.signedIn.SignedInNavHostComponentFactory
@@ -18,8 +19,11 @@ import org.koin.core.annotation.Factory
1819
import org.koin.core.annotation.InjectedParam
1920

2021
@Factory
21-
internal class RootNavHostComponent(@InjectedParam componentContext: AppComponentContext, private val deepLinkResolver: DeepLinkResolver) :
22-
AppComponent<RootNavHostViewState, Nothing>(componentContext, RootNavHostViewState),
22+
internal class RootNavHostComponent(
23+
@InjectedParam componentContext: AppComponentContext,
24+
private val deepLinkResolver: DeepLinkResolver,
25+
private val isUserLoggedInUseCase: IsUserLoggedInUseCase,
26+
) : AppComponent<RootNavHostViewState, Nothing>(componentContext, RootNavHostViewState),
2327
RootNavHost {
2428

2529
private val rootNavigator: RootNavHostNavigation = RootNavHostNavigator()
@@ -55,7 +59,7 @@ internal class RootNavHostComponent(@InjectedParam componentContext: AppComponen
5559
init {
5660
doOnCreate {
5761
if (!consumeDeepLink()) {
58-
rootNavigator.slotNavigator.activate(RootConfig.Login)
62+
checkUserLoggedIn()
5963
}
6064
}
6165
}
@@ -84,4 +88,16 @@ internal class RootNavHostComponent(@InjectedParam componentContext: AppComponen
8488
rootNavigator.slotNavigator.activate(deepLinkConfig)
8589
return true
8690
}
91+
92+
private fun checkUserLoggedIn() {
93+
isUserLoggedInUseCase.execute {
94+
onSuccess { isLoggedIn ->
95+
if (isLoggedIn) {
96+
rootNavigator.slotNavigator.activate(RootConfig.SignedIn())
97+
} else {
98+
rootNavigator.slotNavigator.activate(RootConfig.Login)
99+
}
100+
}
101+
}
102+
}
87103
}

shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginComponent.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package app.futured.kmptemplate.feature.ui.loginScreen
22

33
import app.futured.factorygenerator.annotation.GenerateFactory
4+
import app.futured.kmptemplate.feature.domain.SetUserLoggedInUseCase
45
import app.futured.kmptemplate.feature.ui.base.AppComponentContext
56
import app.futured.kmptemplate.feature.ui.base.ScreenComponent
67
import kotlinx.coroutines.flow.StateFlow
@@ -12,6 +13,7 @@ import org.koin.core.annotation.InjectedParam
1213
internal class LoginComponent(
1314
@InjectedParam componentContext: AppComponentContext,
1415
@InjectedParam override val navigation: LoginScreenNavigation,
16+
private val setUserLoggedInUseCase: SetUserLoggedInUseCase,
1517
) : ScreenComponent<LoginViewState, Nothing, LoginScreenNavigation>(
1618
componentContext = componentContext,
1719
defaultState = LoginViewState,
@@ -23,5 +25,11 @@ internal class LoginComponent(
2325
override val actions: LoginScreen.Actions = this
2426
override val viewState: StateFlow<LoginViewState> = componentState
2527

26-
override fun onLoginClick() = navigateToSignedIn()
28+
override fun onLoginClick() {
29+
setUserLoggedInUseCase.execute(SetUserLoggedInUseCase.Args(true)) {
30+
onSuccess {
31+
navigateToSignedIn()
32+
}
33+
}
34+
}
2735
}

shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/profileScreen/ProfileComponent.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package app.futured.kmptemplate.feature.ui.profileScreen
22

33
import app.futured.factorygenerator.annotation.GenerateFactory
4+
import app.futured.kmptemplate.feature.domain.SetUserLoggedInUseCase
45
import app.futured.kmptemplate.feature.ui.base.AppComponentContext
56
import app.futured.kmptemplate.feature.ui.base.ScreenComponent
67
import kotlinx.coroutines.flow.StateFlow
@@ -12,6 +13,7 @@ import org.koin.core.annotation.InjectedParam
1213
internal class ProfileComponent(
1314
@InjectedParam componentContext: AppComponentContext,
1415
@InjectedParam override val navigation: ProfileScreenNavigation,
16+
private val setUserLoggedInUseCase: SetUserLoggedInUseCase,
1517
) : ScreenComponent<ProfileViewState, Nothing, ProfileScreenNavigation>(
1618
componentContext,
1719
ProfileViewState,
@@ -22,6 +24,12 @@ internal class ProfileComponent(
2224

2325
override val actions: ProfileScreen.Actions = this
2426
override val viewState: StateFlow<ProfileViewState> = componentState
25-
override fun onLogout() = navigateToLogin()
27+
override fun onLogout() {
28+
setUserLoggedInUseCase.execute(SetUserLoggedInUseCase.Args(false)) {
29+
onSuccess {
30+
navigateToLogin()
31+
}
32+
}
33+
}
2634
override fun onThird() = navigateToThird("hello third from profile")
2735
}

shared/network/rest/src/commonMain/kotlin/app/futured/kmptemplate/network/rest/plugin/UserAgentPlugin.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import app.futured.kmptemplate.network.rest.FlavorConstants
44
import app.futured.kmptemplate.platform.binding.Platform
55
import io.ktor.client.HttpClientConfig
66
import io.ktor.client.plugins.UserAgent
7+
import org.koin.core.annotation.Provided
78
import org.koin.core.annotation.Single
89

910
@Single
10-
internal class UserAgentPlugin(platform: Platform) : HttpClientPlugin {
11+
internal class UserAgentPlugin(@Provided platform: Platform) : HttpClientPlugin {
1112

1213
private val userAgentString = with(platform) {
1314
listOf(

shared/persistence/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ plugins {
77
alias(libs.plugins.kotlin.serialization)
88

99
id(libs.plugins.conventions.lint.get().pluginId)
10+
id(libs.plugins.conventions.annotationProcessing.get().pluginId)
11+
}
12+
13+
annotations {
14+
useKoin = true
1015
}
1116

1217
kotlin {
@@ -24,8 +29,11 @@ kotlin {
2429

2530
sourceSets {
2631
commonMain {
32+
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
33+
2734
dependencies {
2835
implementation(libs.koin.core)
36+
implementation(libs.koin.annotations)
2937
implementation(libs.kotlinx.coroutines.core)
3038
implementation(libs.logging.kermit)
3139
implementation(libs.kotlinx.serialization.json)

0 commit comments

Comments
 (0)