diff --git a/convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts b/convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts index bcffa9b6..d8960a87 100644 --- a/convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts +++ b/convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts @@ -19,7 +19,7 @@ afterEvaluate { if (extension.useKoin) { ksp { // enable compile time check - arg("KOIN_CONFIG_CHECK", "false") + arg("KOIN_CONFIG_CHECK", "true") // disable default module generation arg("KOIN_DEFAULT_MODULE", "false") } @@ -32,6 +32,10 @@ afterEvaluate { dependencies { if (extension.useKoin) { add("kspCommonMainMetadata", libs.koin.ksp.compiler) + add("kspAndroid", libs.koin.ksp.compiler) + add("kspIosX64", libs.koin.ksp.compiler) + add("kspIosArm64", libs.koin.ksp.compiler) + add("kspIosSimulatorArm64", libs.koin.ksp.compiler) } // Enable source generation by KSP to commonMain only diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9eb23aa0..b33f3436 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] -agp = "8.9.0" -kotlin = "2.1.10" -ksp = "2.1.10-1.0.31" # Must be compatible with: `kotlin` +agp = "8.11.0" +kotlin = "2.1.20" +ksp = "2.1.20-1.0.32" # Must be compatible with: `kotlin` desugarLibs = "2.1.5" androidxLifecycle = "2.8.6" androidxComposeBom = "2024.10.00" @@ -9,8 +9,8 @@ jetbrainsComposeRuntime = "1.7.0" # Needs to align with version in Compose BOM a androidxActivity = "1.9.2" decompose = "3.1.0" essenty = "2.1.0" -koin = "3.5.6" -koinAnnotations = "1.4.0" # Must be compatible with: `ksp` +koin = "4.1.0" +koinAnnotations = "2.1.0" # Must be compatible with: `ksp` kotlinx-coroutines = "1.8.1" kotlinx-immutableCollections = "0.3.8" kotlinx-dateTime = "0.6.1" @@ -24,7 +24,7 @@ ktor = "3.1.0" # Must be compatible with: `ktorfit` kotlinx-serialization = "1.8.0" # Must be compatible with: `kotlin` timber = "5.0.1" kermit = "2.0.2" -skie = "0.10.1" # Must be compatible with: `kotlin` +skie = "0.10.2" # Must be compatible with: `kotlin` buildkonfig = "0.15.2" nsExceptionKt = "1.0.0-BETA-7" datastore = "1.1.1" diff --git a/shared/app/src/commonMain/kotlin/app/futured/kmptemplate/app/injection/AppInjection.kt b/shared/app/src/commonMain/kotlin/app/futured/kmptemplate/app/injection/AppInjection.kt index 63306aab..6b12403e 100644 --- a/shared/app/src/commonMain/kotlin/app/futured/kmptemplate/app/injection/AppInjection.kt +++ b/shared/app/src/commonMain/kotlin/app/futured/kmptemplate/app/injection/AppInjection.kt @@ -3,7 +3,7 @@ package app.futured.kmptemplate.app.injection import app.futured.kmptemplate.feature.injection.FeatureModule import app.futured.kmptemplate.network.graphql.injection.NetworkGraphqlModule import app.futured.kmptemplate.network.rest.injection.NetworkRestModule -import app.futured.kmptemplate.persistence.injection.persistenceModule +import app.futured.kmptemplate.persistence.injection.PersistenceModule import app.futured.kmptemplate.platform.binding.PlatformBindings import app.futured.kmptemplate.platform.injection.platformModule import org.koin.core.context.startKoin @@ -30,7 +30,7 @@ internal object AppInjection { FeatureModule().module, NetworkGraphqlModule().module, NetworkRestModule().module, - persistenceModule(), + PersistenceModule().module, ) } } diff --git a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/domain/IsUserLoggedInUseCase.kt b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/domain/IsUserLoggedInUseCase.kt new file mode 100644 index 00000000..e9ebb848 --- /dev/null +++ b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/domain/IsUserLoggedInUseCase.kt @@ -0,0 +1,10 @@ +package app.futured.kmptemplate.feature.domain + +import app.futured.arkitekt.crusecases.UseCase +import app.futured.kmptemplate.persistence.persistence.user.UserPersistence +import org.koin.core.annotation.Factory + +@Factory +class IsUserLoggedInUseCase(private val userPersistence: UserPersistence) : UseCase() { + override suspend fun build(args: Unit): Boolean = userPersistence.isUserLoggedIn() +} diff --git a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/domain/SetUserLoggedInUseCase.kt b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/domain/SetUserLoggedInUseCase.kt new file mode 100644 index 00000000..b7c0b698 --- /dev/null +++ b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/domain/SetUserLoggedInUseCase.kt @@ -0,0 +1,13 @@ +package app.futured.kmptemplate.feature.domain + +import app.futured.arkitekt.crusecases.UseCase +import app.futured.kmptemplate.persistence.persistence.user.UserPersistence +import org.koin.core.annotation.Factory + +@Factory +class SetUserLoggedInUseCase(private val userPersistence: UserPersistence) : UseCase() { + + override suspend fun build(args: Args) = userPersistence.setUserLoggedIn(args.isLoggedIn) + + data class Args(val isLoggedIn: Boolean) +} diff --git a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/navigation/root/RootNavHostComponent.kt b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/navigation/root/RootNavHostComponent.kt index 8eb0143d..0e30ee09 100644 --- a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/navigation/root/RootNavHostComponent.kt +++ b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/navigation/root/RootNavHostComponent.kt @@ -1,6 +1,7 @@ package app.futured.kmptemplate.feature.navigation.root import app.futured.arkitekt.decompose.ext.asStateFlow +import app.futured.kmptemplate.feature.domain.IsUserLoggedInUseCase import app.futured.kmptemplate.feature.navigation.deepLink.DeepLinkDestination import app.futured.kmptemplate.feature.navigation.deepLink.DeepLinkResolver import app.futured.kmptemplate.feature.navigation.signedIn.SignedInNavHostComponentFactory @@ -18,8 +19,11 @@ import org.koin.core.annotation.Factory import org.koin.core.annotation.InjectedParam @Factory -internal class RootNavHostComponent(@InjectedParam componentContext: AppComponentContext, private val deepLinkResolver: DeepLinkResolver) : - AppComponent(componentContext, RootNavHostViewState), +internal class RootNavHostComponent( + @InjectedParam componentContext: AppComponentContext, + private val deepLinkResolver: DeepLinkResolver, + private val isUserLoggedInUseCase: IsUserLoggedInUseCase, +) : AppComponent(componentContext, RootNavHostViewState), RootNavHost { private val rootNavigator: RootNavHostNavigation = RootNavHostNavigator() @@ -55,7 +59,7 @@ internal class RootNavHostComponent(@InjectedParam componentContext: AppComponen init { doOnCreate { if (!consumeDeepLink()) { - rootNavigator.slotNavigator.activate(RootConfig.Login) + checkUserLoggedIn() } } } @@ -84,4 +88,16 @@ internal class RootNavHostComponent(@InjectedParam componentContext: AppComponen rootNavigator.slotNavigator.activate(deepLinkConfig) return true } + + private fun checkUserLoggedIn() { + isUserLoggedInUseCase.execute { + onSuccess { isLoggedIn -> + if (isLoggedIn) { + rootNavigator.slotNavigator.activate(RootConfig.SignedIn()) + } else { + rootNavigator.slotNavigator.activate(RootConfig.Login) + } + } + } + } } diff --git a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginComponent.kt b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginComponent.kt index 63aafefd..39014678 100644 --- a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginComponent.kt +++ b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginComponent.kt @@ -1,6 +1,7 @@ package app.futured.kmptemplate.feature.ui.loginScreen import app.futured.factorygenerator.annotation.GenerateFactory +import app.futured.kmptemplate.feature.domain.SetUserLoggedInUseCase import app.futured.kmptemplate.feature.ui.base.AppComponentContext import app.futured.kmptemplate.feature.ui.base.ScreenComponent import kotlinx.coroutines.flow.StateFlow @@ -12,6 +13,7 @@ import org.koin.core.annotation.InjectedParam internal class LoginComponent( @InjectedParam componentContext: AppComponentContext, @InjectedParam override val navigation: LoginScreenNavigation, + private val setUserLoggedInUseCase: SetUserLoggedInUseCase, ) : ScreenComponent( componentContext = componentContext, defaultState = LoginViewState, @@ -23,5 +25,11 @@ internal class LoginComponent( override val actions: LoginScreen.Actions = this override val viewState: StateFlow = componentState - override fun onLoginClick() = navigateToSignedIn() + override fun onLoginClick() { + setUserLoggedInUseCase.execute(SetUserLoggedInUseCase.Args(true)) { + onSuccess { + navigateToSignedIn() + } + } + } } diff --git a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/profileScreen/ProfileComponent.kt b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/profileScreen/ProfileComponent.kt index 68b0066e..33149324 100644 --- a/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/profileScreen/ProfileComponent.kt +++ b/shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/profileScreen/ProfileComponent.kt @@ -1,6 +1,7 @@ package app.futured.kmptemplate.feature.ui.profileScreen import app.futured.factorygenerator.annotation.GenerateFactory +import app.futured.kmptemplate.feature.domain.SetUserLoggedInUseCase import app.futured.kmptemplate.feature.ui.base.AppComponentContext import app.futured.kmptemplate.feature.ui.base.ScreenComponent import kotlinx.coroutines.flow.StateFlow @@ -12,6 +13,7 @@ import org.koin.core.annotation.InjectedParam internal class ProfileComponent( @InjectedParam componentContext: AppComponentContext, @InjectedParam override val navigation: ProfileScreenNavigation, + private val setUserLoggedInUseCase: SetUserLoggedInUseCase, ) : ScreenComponent( componentContext, ProfileViewState, @@ -22,6 +24,12 @@ internal class ProfileComponent( override val actions: ProfileScreen.Actions = this override val viewState: StateFlow = componentState - override fun onLogout() = navigateToLogin() + override fun onLogout() { + setUserLoggedInUseCase.execute(SetUserLoggedInUseCase.Args(false)) { + onSuccess { + navigateToLogin() + } + } + } override fun onThird() = navigateToThird("hello third from profile") } diff --git a/shared/network/rest/src/commonMain/kotlin/app/futured/kmptemplate/network/rest/plugin/UserAgentPlugin.kt b/shared/network/rest/src/commonMain/kotlin/app/futured/kmptemplate/network/rest/plugin/UserAgentPlugin.kt index 9d0c43c8..685db8a8 100644 --- a/shared/network/rest/src/commonMain/kotlin/app/futured/kmptemplate/network/rest/plugin/UserAgentPlugin.kt +++ b/shared/network/rest/src/commonMain/kotlin/app/futured/kmptemplate/network/rest/plugin/UserAgentPlugin.kt @@ -4,10 +4,11 @@ import app.futured.kmptemplate.network.rest.FlavorConstants import app.futured.kmptemplate.platform.binding.Platform import io.ktor.client.HttpClientConfig import io.ktor.client.plugins.UserAgent +import org.koin.core.annotation.Provided import org.koin.core.annotation.Single @Single -internal class UserAgentPlugin(platform: Platform) : HttpClientPlugin { +internal class UserAgentPlugin(@Provided platform: Platform) : HttpClientPlugin { private val userAgentString = with(platform) { listOf( diff --git a/shared/persistence/build.gradle.kts b/shared/persistence/build.gradle.kts index 555211b4..7edbbef5 100644 --- a/shared/persistence/build.gradle.kts +++ b/shared/persistence/build.gradle.kts @@ -7,6 +7,11 @@ plugins { alias(libs.plugins.kotlin.serialization) id(libs.plugins.conventions.lint.get().pluginId) + id(libs.plugins.conventions.annotationProcessing.get().pluginId) +} + +annotations { + useKoin = true } kotlin { @@ -24,8 +29,11 @@ kotlin { sourceSets { commonMain { + kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") + dependencies { implementation(libs.koin.core) + implementation(libs.koin.annotations) implementation(libs.kotlinx.coroutines.core) implementation(libs.logging.kermit) implementation(libs.kotlinx.serialization.json) diff --git a/shared/persistence/src/androidMain/kotlin/app/futured/kmptemplate/persistence/injection/DataStoreModule.kt b/shared/persistence/src/androidMain/kotlin/app/futured/kmptemplate/persistence/injection/DataStoreModule.kt new file mode 100644 index 00000000..16449ec7 --- /dev/null +++ b/shared/persistence/src/androidMain/kotlin/app/futured/kmptemplate/persistence/injection/DataStoreModule.kt @@ -0,0 +1,23 @@ +package app.futured.kmptemplate.persistence.injection + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.PreferenceDataStoreFactory +import androidx.datastore.preferences.core.Preferences +import app.futured.kmptemplate.persistence.tools.SETTINGS_DATASTORE_FILENAME +import okio.Path.Companion.toPath +import org.koin.core.annotation.Module +import org.koin.core.annotation.Single +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject + +@Module +actual class DataStoreModule actual constructor() : KoinComponent { + + private val context: Context by inject() + + @Single + actual fun provideDataStore(): DataStore = PreferenceDataStoreFactory.createWithPath( + produceFile = { context.filesDir.resolve(SETTINGS_DATASTORE_FILENAME).absolutePath.toPath() }, + ) +} diff --git a/shared/persistence/src/androidMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt b/shared/persistence/src/androidMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt deleted file mode 100644 index 886fde07..00000000 --- a/shared/persistence/src/androidMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.futured.kmptemplate.persistence.injection - -import android.content.Context -import app.futured.kmptemplate.persistence.tools.SETTINGS_DATASTORE_FILENAME -import okio.Path.Companion.toPath -import org.koin.dsl.module - -internal actual fun persistencePlatformModule() = module { - single(Qualifiers.DataStorePath) { - get().filesDir.resolve(SETTINGS_DATASTORE_FILENAME).absolutePath.toPath() - } -} diff --git a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistenceModule.kt b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistenceModule.kt index dd34c68c..129454a1 100644 --- a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistenceModule.kt +++ b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistenceModule.kt @@ -1,31 +1,29 @@ package app.futured.kmptemplate.persistence.injection -import androidx.datastore.preferences.core.PreferenceDataStoreFactory -import app.futured.kmptemplate.persistence.persistence.JsonPersistence -import app.futured.kmptemplate.persistence.persistence.PrimitivePersistence +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences import kotlinx.serialization.json.Json -import org.koin.core.module.dsl.singleOf -import org.koin.dsl.module +import org.koin.core.annotation.ComponentScan +import org.koin.core.annotation.Module +import org.koin.core.annotation.Single -fun persistenceModule() = module { - // expect/actual Koin module - includes(persistencePlatformModule()) +@Module(includes = [DataStoreModule::class]) +@ComponentScan("app.futured.kmptemplate.persistence") +class PersistenceModule { - single { - PreferenceDataStoreFactory.createWithPath( - produceFile = { get(Qualifiers.DataStorePath) }, - ) + @Single + @PersistenceJson + internal fun provideJson(): Json = Json { + encodeDefaults = true + isLenient = false + ignoreUnknownKeys = true + prettyPrint = false } +} - singleOf(::PrimitivePersistence) - single { JsonPersistence(get(), get(Qualifiers.PersistenceJson)) } +@Module +expect class DataStoreModule() { - single(Qualifiers.PersistenceJson) { - Json { - encodeDefaults = true - isLenient = false - ignoreUnknownKeys = true - prettyPrint = false - } - } + @Single + fun provideDataStore(): DataStore } diff --git a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt deleted file mode 100644 index 65440820..00000000 --- a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt +++ /dev/null @@ -1,5 +0,0 @@ -package app.futured.kmptemplate.persistence.injection - -import org.koin.core.module.Module - -internal expect fun persistencePlatformModule(): Module diff --git a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/Qualifiers.kt b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/Qualifiers.kt index f3261393..81c5f4d6 100644 --- a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/Qualifiers.kt +++ b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/injection/Qualifiers.kt @@ -1,9 +1,6 @@ package app.futured.kmptemplate.persistence.injection -import org.koin.core.qualifier.named +import org.koin.core.annotation.Named -internal object Qualifiers { - - val PersistenceJson = named("PersistenceJson") - val DataStorePath = named("DataStoreFilePath") -} +@Named +annotation class PersistenceJson diff --git a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/JsonPersistence.kt b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/JsonPersistence.kt index 038b53e1..618cc2dd 100644 --- a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/JsonPersistence.kt +++ b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/JsonPersistence.kt @@ -3,6 +3,7 @@ package app.futured.kmptemplate.persistence.persistence import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit +import app.futured.kmptemplate.persistence.injection.PersistenceJson import co.touchlab.kermit.Logger import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull @@ -10,12 +11,15 @@ import kotlinx.coroutines.flow.map import kotlinx.serialization.SerializationException import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import org.koin.core.annotation.Provided +import org.koin.core.annotation.Single /** * [DataStore]-backed Persistence which allows storage and observing of complex JSON objects. * Uses [kotlinx.serialization] to serialize and deserialize objects into Strings. */ -internal class JsonPersistence(private val dataStore: DataStore, private val json: Json) { +@Single +internal class JsonPersistence(@Provided private val dataStore: DataStore, @PersistenceJson private val json: Json) { private val logger = Logger.withTag("JsonPersistence") diff --git a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/PrimitivePersistence.kt b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/PrimitivePersistence.kt index 13190ab4..0644fe1d 100644 --- a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/PrimitivePersistence.kt +++ b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/PrimitivePersistence.kt @@ -6,11 +6,14 @@ import androidx.datastore.preferences.core.edit import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.mapNotNull +import org.koin.core.annotation.Provided +import org.koin.core.annotation.Single /** * [DataStore]-backed Persistence which allows storage and observing of persisted entities. */ -internal class PrimitivePersistence(private val dataStore: DataStore) { +@Single +internal class PrimitivePersistence(@Provided private val dataStore: DataStore) { suspend fun get(key: Preferences.Key): T? = dataStore.data.firstOrNull()?.run { this[key] diff --git a/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/user/UserPersistence.kt b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/user/UserPersistence.kt new file mode 100644 index 00000000..b6a8fc98 --- /dev/null +++ b/shared/persistence/src/commonMain/kotlin/app/futured/kmptemplate/persistence/persistence/user/UserPersistence.kt @@ -0,0 +1,25 @@ +package app.futured.kmptemplate.persistence.persistence.user + +import androidx.datastore.preferences.core.booleanPreferencesKey +import app.futured.kmptemplate.persistence.persistence.PrimitivePersistence +import org.koin.core.annotation.Single + +interface UserPersistence { + suspend fun isUserLoggedIn(): Boolean + + suspend fun setUserLoggedIn(isLoggedIn: Boolean) +} + +@Single +internal class UserPersistenceImpl(private val primitivePersistence: PrimitivePersistence) : UserPersistence { + + private companion object { + val IS_USER_LOGGED_IN_KEY = booleanPreferencesKey("IS_USER_LOGGED_IN") + } + + override suspend fun isUserLoggedIn(): Boolean = primitivePersistence.get(IS_USER_LOGGED_IN_KEY) ?: false + + override suspend fun setUserLoggedIn(isLoggedIn: Boolean) { + primitivePersistence.save(IS_USER_LOGGED_IN_KEY, isLoggedIn) + } +} diff --git a/shared/persistence/src/iosMain/kotlin/app/futured/kmptemplate/persistence/injection/DataStoreModule.kt b/shared/persistence/src/iosMain/kotlin/app/futured/kmptemplate/persistence/injection/DataStoreModule.kt new file mode 100644 index 00000000..3c9ab0db --- /dev/null +++ b/shared/persistence/src/iosMain/kotlin/app/futured/kmptemplate/persistence/injection/DataStoreModule.kt @@ -0,0 +1,34 @@ +package app.futured.kmptemplate.persistence.injection + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.PreferenceDataStoreFactory +import androidx.datastore.preferences.core.Preferences +import app.futured.kmptemplate.persistence.tools.SETTINGS_DATASTORE_FILENAME +import kotlinx.cinterop.ExperimentalForeignApi +import okio.Path.Companion.toPath +import org.koin.core.annotation.Module +import org.koin.core.annotation.Single +import platform.Foundation.NSDocumentDirectory +import platform.Foundation.NSFileManager +import platform.Foundation.NSURL +import platform.Foundation.NSUserDomainMask + +@Module +actual class DataStoreModule { + + @OptIn(ExperimentalForeignApi::class) + @Single + actual fun provideDataStore(): DataStore = PreferenceDataStoreFactory.createWithPath( + produceFile = { + val documentDirectory: NSURL? = NSFileManager.defaultManager.URLForDirectory( + directory = NSDocumentDirectory, + inDomain = NSUserDomainMask, + appropriateForURL = null, + create = false, + error = null, + ) + + (requireNotNull(documentDirectory).path + "/$SETTINGS_DATASTORE_FILENAME").toPath() + }, + ) +} diff --git a/shared/persistence/src/iosMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt b/shared/persistence/src/iosMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt deleted file mode 100644 index c28b6685..00000000 --- a/shared/persistence/src/iosMain/kotlin/app/futured/kmptemplate/persistence/injection/PersistencePlatformModule.kt +++ /dev/null @@ -1,25 +0,0 @@ -package app.futured.kmptemplate.persistence.injection - -import app.futured.kmptemplate.persistence.tools.SETTINGS_DATASTORE_FILENAME -import kotlinx.cinterop.ExperimentalForeignApi -import okio.Path.Companion.toPath -import org.koin.dsl.module -import platform.Foundation.NSDocumentDirectory -import platform.Foundation.NSFileManager -import platform.Foundation.NSURL -import platform.Foundation.NSUserDomainMask - -@OptIn(ExperimentalForeignApi::class) -internal actual fun persistencePlatformModule() = module { - single(Qualifiers.DataStorePath) { - val documentDirectory: NSURL? = NSFileManager.defaultManager.URLForDirectory( - directory = NSDocumentDirectory, - inDomain = NSUserDomainMask, - appropriateForURL = null, - create = false, - error = null, - ) - - (requireNotNull(documentDirectory).path + "/$SETTINGS_DATASTORE_FILENAME").toPath() - } -}