From 4cec957fb656fc77520199e5a038d847591c436c Mon Sep 17 00:00:00 2001 From: pawansoni Date: Wed, 3 Apr 2024 16:36:57 +0530 Subject: [PATCH 1/7] MKMPT-5: Add common ViewModel --- .../mindera/kmpexample/presentation/App.kt | 0 .../kmpexample/presentation/main/MainScene.kt | 0 common/compose-ktx/build.gradle.kts | 8 +++- common/viewmodel/build.gradle.kts | 8 +++- .../kotlin/com/mindera/BundleOfArguments.kt | 2 + .../kotlin/com/mindera/lifecycle/ViewModel.kt | 4 +- .../com/mindera/viewmodel/Extensions.kt | 26 +++++----- .../launches/composables/build.gradle.kts | 5 ++ .../composables/CurrencyExchangeScreen.kt | 3 +- features/launches/di/build.gradle.kts | 4 +- .../iosMain/kotlin/com.mindera.di/DIHelper.kt | 2 + .../launches/presentation/build.gradle.kts | 47 ++++++++++++++++--- .../launches/CurrencyExchangeScene.kt | 0 gradle.properties | 3 ++ libraries/precompose/build.gradle.kts | 23 ++++++++- .../precompose/navigation/BackHandler.kt | 0 .../precompose/navigation/BackStackEntry.kt | 0 .../mindera/precompose/navigation/NavHost.kt | 0 .../precompose/navigation/Navigator.kt | 0 .../precompose/navigation/RouteBuilder.kt | 0 .../navigation/transition/Transitions.kt | 0 21 files changed, 106 insertions(+), 29 deletions(-) rename app/navigation/src/{commonMain => androidMain}/kotlin/com/mindera/kmpexample/presentation/App.kt (100%) rename app/navigation/src/{commonMain => androidMain}/kotlin/com/mindera/kmpexample/presentation/main/MainScene.kt (100%) rename features/launches/presentation/src/{commonMain => androidMain}/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt (100%) rename libraries/precompose/src/{commonMain => androidMain}/kotlin/com/mindera/precompose/navigation/BackHandler.kt (100%) rename libraries/precompose/src/{commonMain => androidMain}/kotlin/com/mindera/precompose/navigation/BackStackEntry.kt (100%) rename libraries/precompose/src/{commonMain => androidMain}/kotlin/com/mindera/precompose/navigation/NavHost.kt (100%) rename libraries/precompose/src/{commonMain => androidMain}/kotlin/com/mindera/precompose/navigation/Navigator.kt (100%) rename libraries/precompose/src/{commonMain => androidMain}/kotlin/com/mindera/precompose/navigation/RouteBuilder.kt (100%) rename libraries/precompose/src/{commonMain => androidMain}/kotlin/com/mindera/precompose/navigation/transition/Transitions.kt (100%) diff --git a/app/navigation/src/commonMain/kotlin/com/mindera/kmpexample/presentation/App.kt b/app/navigation/src/androidMain/kotlin/com/mindera/kmpexample/presentation/App.kt similarity index 100% rename from app/navigation/src/commonMain/kotlin/com/mindera/kmpexample/presentation/App.kt rename to app/navigation/src/androidMain/kotlin/com/mindera/kmpexample/presentation/App.kt diff --git a/app/navigation/src/commonMain/kotlin/com/mindera/kmpexample/presentation/main/MainScene.kt b/app/navigation/src/androidMain/kotlin/com/mindera/kmpexample/presentation/main/MainScene.kt similarity index 100% rename from app/navigation/src/commonMain/kotlin/com/mindera/kmpexample/presentation/main/MainScene.kt rename to app/navigation/src/androidMain/kotlin/com/mindera/kmpexample/presentation/main/MainScene.kt diff --git a/common/compose-ktx/build.gradle.kts b/common/compose-ktx/build.gradle.kts index be5b165..cfaf083 100644 --- a/common/compose-ktx/build.gradle.kts +++ b/common/compose-ktx/build.gradle.kts @@ -8,7 +8,13 @@ group = "com.mindera.compose.extensions" version = "1.0.0" kotlin { - jvm() + androidTarget() + jvm("desktop") + iOS { + iosX64() + iosArm64() + iosSimulatorArm64() + } sourceSets { val commonMain by getting { diff --git a/common/viewmodel/build.gradle.kts b/common/viewmodel/build.gradle.kts index b32020c..d2e87ea 100644 --- a/common/viewmodel/build.gradle.kts +++ b/common/viewmodel/build.gradle.kts @@ -10,12 +10,18 @@ version = "1.0.0" kotlin { androidTarget() jvm("desktop") + iOS { + iosX64() + iosArm64() + iosSimulatorArm64() + } sourceSets { val commonMain by getting { dependencies { - api(libs.precompose.viewmodel) +// api(libs.precompose.viewmodel) implementation(compose.runtime) + implementation("androidx.lifecycle:lifecycle-viewmodel:2.8.0-alpha03") } } } diff --git a/common/viewmodel/src/commonMain/kotlin/com/mindera/BundleOfArguments.kt b/common/viewmodel/src/commonMain/kotlin/com/mindera/BundleOfArguments.kt index 01f62d9..e198d7e 100644 --- a/common/viewmodel/src/commonMain/kotlin/com/mindera/BundleOfArguments.kt +++ b/common/viewmodel/src/commonMain/kotlin/com/mindera/BundleOfArguments.kt @@ -1,5 +1,7 @@ package com.mindera +import kotlin.jvm.JvmSuppressWildcards + typealias BundleOfArguments = Map<@JvmSuppressWildcards Any, @JvmSuppressWildcards Any?> fun BundleOfArguments.getString(key: Any) = this[key]?.toString().orEmpty() fun BundleOfArguments.getInt(key: Any) = getString(key).toInt() diff --git a/common/viewmodel/src/commonMain/kotlin/com/mindera/lifecycle/ViewModel.kt b/common/viewmodel/src/commonMain/kotlin/com/mindera/lifecycle/ViewModel.kt index 28fc434..db8f01d 100644 --- a/common/viewmodel/src/commonMain/kotlin/com/mindera/lifecycle/ViewModel.kt +++ b/common/viewmodel/src/commonMain/kotlin/com/mindera/lifecycle/ViewModel.kt @@ -1,14 +1,14 @@ package com.mindera.lifecycle +import androidx.lifecycle.viewModelScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.async import kotlinx.coroutines.launch -import moe.tlaster.precompose.viewmodel.viewModelScope import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext -open class ViewModel: moe.tlaster.precompose.viewmodel.ViewModel() +open class ViewModel: androidx.lifecycle.ViewModel() fun ViewModel.launch( context: CoroutineContext = EmptyCoroutineContext, diff --git a/common/viewmodel/src/commonMain/kotlin/com/mindera/viewmodel/Extensions.kt b/common/viewmodel/src/commonMain/kotlin/com/mindera/viewmodel/Extensions.kt index d3091a7..9496825 100644 --- a/common/viewmodel/src/commonMain/kotlin/com/mindera/viewmodel/Extensions.kt +++ b/common/viewmodel/src/commonMain/kotlin/com/mindera/viewmodel/Extensions.kt @@ -24,16 +24,16 @@ fun create( vararg args: Pair, ): VM = create(klass, mapOf(pairs = args)) -@Composable -fun viewModel( - klass: KClass, - bundle: BundleOfArguments? = null, - keys: List = emptyList(), -): VM = moe.tlaster.precompose.viewmodel.viewModel(klass, keys) { create(klass, bundle) } - -@Composable -fun viewModel( - klass: KClass, - vararg args: Pair, - keys: List = emptyList(), -): VM = viewModel(klass, mapOf(pairs = args), keys) +//@Composable +//fun viewModel( +// klass: KClass, +// bundle: BundleOfArguments? = null, +// keys: List = emptyList(), +//): VM = moe.tlaster.precompose.viewmodel.viewModel(klass, keys) { create(klass, bundle) } +// +//@Composable +//fun viewModel( +// klass: KClass, +// vararg args: Pair, +// keys: List = emptyList(), +//): VM = viewModel(klass, mapOf(pairs = args), keys) diff --git a/features/launches/composables/build.gradle.kts b/features/launches/composables/build.gradle.kts index 7ccb41e..a10a294 100644 --- a/features/launches/composables/build.gradle.kts +++ b/features/launches/composables/build.gradle.kts @@ -10,6 +10,11 @@ version = "1.0.0" kotlin { androidTarget() jvm("desktop") + iOS { + iosX64() + iosArm64() + iosSimulatorArm64() + } sourceSets { val commonMain by getting { diff --git a/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt b/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt index d76d69e..e9b8990 100644 --- a/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt +++ b/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.mindera.compose.collections.ImmutableList import com.mindera.kmpexample.launches.domain.model.CurrencyExchangeResponseItem -import java.util.Locale @Composable fun CurrencyExchangeScreen( @@ -33,7 +32,7 @@ fun CurrencyExchangeScreen( } Text(launch.id) Text(launch.currency.replaceFirstChar { - if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() + if (it.isLowerCase()) it.titlecase() else it.toString() }) Text(launch.code, color = Color.Blue) Text(launch.currencyRate.toString(), color = Color.Gray) diff --git a/features/launches/di/build.gradle.kts b/features/launches/di/build.gradle.kts index eafdad2..bf45cfa 100644 --- a/features/launches/di/build.gradle.kts +++ b/features/launches/di/build.gradle.kts @@ -27,7 +27,7 @@ kotlin { implementation(libs.koin.core) implementation(libs.ktor.core) implementation(libs.ktor.content.negotiation) - + implementation(projects.features.launches.presentation) } } @@ -35,7 +35,7 @@ kotlin { dependsOn(commonMain) dependencies { implementation(libs.ktor.okhttp) - implementation(projects.features.launches.presentation) + } } diff --git a/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt b/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt index 210e9d9..1576f1a 100644 --- a/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt +++ b/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt @@ -2,9 +2,11 @@ package com.mindera.di import com.mindera.kmpexample.launches.domain.usecase.GetCurrencyExchangeUseCase import com.mindera.kmpexample.launches.usecase.GetCurrencyExchangeUseCaseV1 +import com.mindera.kmpexample.launches.viewmodel.CurrencyExchangeViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject class DIHelper: KoinComponent { val getGetCurrencyExchangeUseCase: GetCurrencyExchangeUseCase by inject() + val getCurrencyExchangeViewModel: CurrencyExchangeViewModel by inject() } diff --git a/features/launches/presentation/build.gradle.kts b/features/launches/presentation/build.gradle.kts index ddbfbff..4611825 100644 --- a/features/launches/presentation/build.gradle.kts +++ b/features/launches/presentation/build.gradle.kts @@ -1,21 +1,26 @@ plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.compose.multiplatform) + alias(libs.plugins.android.library) } group = "com.mindera.kmpexample.features.launches.presentation" version = "1.0.0" kotlin { - jvm() + androidTarget() + jvm("desktop") + iOS { + iosX64() + iosArm64() + iosSimulatorArm64() + } + sourceSets { val commonMain by getting { dependencies { - implementation(compose.foundation) - implementation(compose.runtime) - implementation(compose.ui) - implementation(compose.material3) + implementation(projects.common.domain) implementation(projects.common.coroutinesKtx) implementation(projects.common.composeKtx) @@ -36,9 +41,39 @@ kotlin { implementation(libs.ktor.serialization) implementation(libs.kotlinx.serialization) implementation(libs.ktor.logging) - implementation(libs.ktor.okhttp) implementation(libs.koin.core) + + } + } + + val androidMain by getting { + dependsOn(commonMain) + dependencies { + implementation(compose.foundation) + implementation(compose.runtime) + implementation(compose.ui) + implementation(compose.material3) + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0-alpha03") + implementation("androidx.activity:activity-compose") { + exclude(group = "androidx.lifecycle", module = "lifecycle-viewmodel-ktx") // Here we are exlcuding the ViewModel dependency + } + } + } + + if (iOSEnabled) { + val iosX64Main by getting + val iosArm64Main by getting + val iosSimulatorArm64Main by getting + val iosMain by creating { + dependsOn(commonMain) + iosX64Main.dependsOn(this) + iosArm64Main.dependsOn(this) + iosSimulatorArm64Main.dependsOn(this) + dependencies { + implementation("androidx.lifecycle:lifecycle-viewmodel:2.8.0-alpha03") + } } } } + } diff --git a/features/launches/presentation/src/commonMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt b/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt similarity index 100% rename from features/launches/presentation/src/commonMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt rename to features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt diff --git a/gradle.properties b/gradle.properties index 3f00940..a6f5565 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,3 +33,6 @@ kotlin.native.binary.memoryModel=experimental kotlin.native.binary.objcExportSuspendFunctionLaunchThreadRestriction=none kotlin.native.disableCompilerDaemon=true kotlin.native.ignoreDisabledTargets=true + + +org.jetbrains.compose.experimental.uikit.enabled=true diff --git a/libraries/precompose/build.gradle.kts b/libraries/precompose/build.gradle.kts index 01ce23a..a249eec 100644 --- a/libraries/precompose/build.gradle.kts +++ b/libraries/precompose/build.gradle.kts @@ -5,22 +5,41 @@ plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.compose.multiplatform) + alias(libs.plugins.android.library) } group = "com.mindera.precompose" version = "1.0.0" kotlin { - jvm() +// jvm() + androidTarget() + jvm("desktop") + iOS { + iosX64() + iosArm64() + iosSimulatorArm64() + } sourceSets { val commonMain by getting { dependencies { +// implementation(compose.foundation) +// implementation(compose.material3) +// implementation(libs.kotlinx.datetime) +// implementation(libs.precompose) + +// implementation(libs.precompose.viewmodel) + } + } + + val androidMain by getting { + dependsOn(commonMain) + dependencies { implementation(compose.foundation) implementation(compose.material3) implementation(libs.kotlinx.datetime) implementation(libs.precompose) - implementation(libs.precompose.viewmodel) } } } diff --git a/libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/BackHandler.kt b/libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/BackHandler.kt similarity index 100% rename from libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/BackHandler.kt rename to libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/BackHandler.kt diff --git a/libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/BackStackEntry.kt b/libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/BackStackEntry.kt similarity index 100% rename from libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/BackStackEntry.kt rename to libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/BackStackEntry.kt diff --git a/libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/NavHost.kt b/libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/NavHost.kt similarity index 100% rename from libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/NavHost.kt rename to libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/NavHost.kt diff --git a/libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/Navigator.kt b/libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/Navigator.kt similarity index 100% rename from libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/Navigator.kt rename to libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/Navigator.kt diff --git a/libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/RouteBuilder.kt b/libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/RouteBuilder.kt similarity index 100% rename from libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/RouteBuilder.kt rename to libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/RouteBuilder.kt diff --git a/libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/transition/Transitions.kt b/libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/transition/Transitions.kt similarity index 100% rename from libraries/precompose/src/commonMain/kotlin/com/mindera/precompose/navigation/transition/Transitions.kt rename to libraries/precompose/src/androidMain/kotlin/com/mindera/precompose/navigation/transition/Transitions.kt From 61613abab33e2b46120f7dbd68cecd99f34048a4 Mon Sep 17 00:00:00 2001 From: pawansoni Date: Thu, 4 Apr 2024 13:42:56 +0530 Subject: [PATCH 2/7] MKMPT-5: ViewModel for IOS --- app/shared/build.gradle.kts | 1 + .../iosMain/kotlin/com.mindera.di/DIHelper.kt | 3 +- .../launches/CurrencyExchangeScene.kt | 2 +- .../viewmodel/CurrencyExchangeViewModel.kt | 33 ++++++++++++++++--- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/app/shared/build.gradle.kts b/app/shared/build.gradle.kts index 4542b31..750b0bd 100644 --- a/app/shared/build.gradle.kts +++ b/app/shared/build.gradle.kts @@ -60,6 +60,7 @@ private val modules: List = listOf( projects.common.coroutinesKtx, projects.common.domain, projects.features.launches.di, + projects.features.launches.presentation, ) kotlin { diff --git a/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt b/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt index 1576f1a..15015ff 100644 --- a/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt +++ b/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt @@ -1,12 +1,11 @@ package com.mindera.di import com.mindera.kmpexample.launches.domain.usecase.GetCurrencyExchangeUseCase -import com.mindera.kmpexample.launches.usecase.GetCurrencyExchangeUseCaseV1 import com.mindera.kmpexample.launches.viewmodel.CurrencyExchangeViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject class DIHelper: KoinComponent { val getGetCurrencyExchangeUseCase: GetCurrencyExchangeUseCase by inject() - val getCurrencyExchangeViewModel: CurrencyExchangeViewModel by inject() + val viewModel: CurrencyExchangeViewModel by inject() } diff --git a/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt b/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt index 6e92ef4..79113f2 100644 --- a/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt +++ b/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt @@ -23,7 +23,7 @@ fun CurrencyExchangeScene(onBack: (() -> Unit)) { BackHandler(onBack = onBack) val viewModel = remember { KoinHelper().viewModel } - val state = viewModel.state.collectAsState() + val state = viewModel.mutableStateFlow.collectAsState() Column(modifier = Modifier.fillMaxSize()) { Text( diff --git a/features/launches/presentation/src/commonMain/kotlin/com/mindera/kmpexample/launches/viewmodel/CurrencyExchangeViewModel.kt b/features/launches/presentation/src/commonMain/kotlin/com/mindera/kmpexample/launches/viewmodel/CurrencyExchangeViewModel.kt index 0281e42..93a5c5f 100644 --- a/features/launches/presentation/src/commonMain/kotlin/com/mindera/kmpexample/launches/viewmodel/CurrencyExchangeViewModel.kt +++ b/features/launches/presentation/src/commonMain/kotlin/com/mindera/kmpexample/launches/viewmodel/CurrencyExchangeViewModel.kt @@ -8,26 +8,51 @@ import com.mindera.kmpexample.launches.domain.model.CurrencyExchangeResponseItem import com.mindera.kmpexample.launches.domain.usecase.GetCurrencyExchangeUseCase import com.mindera.lifecycle.ViewModel import com.mindera.lifecycle.launch +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach class CurrencyExchangeViewModel constructor( private val getCurrencyExchange: GetCurrencyExchangeUseCase, ) : ViewModel() { - data class State( + data class CurrencyState( val loading: Boolean = true, val launches: ImmutableList = ImmutableList(), val error: Error? = null, ) - var state = MutableStateFlow(value = State()) + var mutableStateFlow = MutableStateFlow(value = CurrencyState()) private set + val currencyStateFlow: StateFlow + get() = mutableStateFlow + + fun onChange(provideNewState: ((CurrencyState) -> Unit)) { + currencyStateFlow.onEach { + provideNewState.invoke(it) + }.launchIn(CoroutineScope(Dispatchers.Main)) + } + +// This example to access data in IOS +// class AppViewModel: ObservableObject { +// let coreModel : CurrencyExchangeViewModel = DIHelper().viewModel +// +// func fetchData() { +// coreModel.onChange { newState in +// print(newState.launches) +// } +// } +// } + init { launch { getCurrencyExchange().on( left = { println(">>> Rates: $it") - state.value = with(state.value) { + mutableStateFlow.value = with(mutableStateFlow.value) { copy( loading = false, launches = it.immutable(), @@ -37,7 +62,7 @@ class CurrencyExchangeViewModel constructor( }, right = { println(">>> Rates error: $it") - state.value = with(state.value) { + mutableStateFlow.value = with(mutableStateFlow.value) { copy( loading = false, launches = ImmutableList(emptyList()), From 4a8b22c85835e33ce76b35c80131710a9748bdd1 Mon Sep 17 00:00:00 2001 From: pawansoni Date: Fri, 5 Apr 2024 10:31:09 +0530 Subject: [PATCH 3/7] MKMPT-5: lifecycle viewmodel in toml --- common/viewmodel/build.gradle.kts | 3 +-- features/launches/presentation/build.gradle.kts | 4 ++-- gradle/libs.versions.toml | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/viewmodel/build.gradle.kts b/common/viewmodel/build.gradle.kts index d2e87ea..13d45e6 100644 --- a/common/viewmodel/build.gradle.kts +++ b/common/viewmodel/build.gradle.kts @@ -19,9 +19,8 @@ kotlin { sourceSets { val commonMain by getting { dependencies { -// api(libs.precompose.viewmodel) implementation(compose.runtime) - implementation("androidx.lifecycle:lifecycle-viewmodel:2.8.0-alpha03") + implementation(libs.lifecycle.viewmodel) } } } diff --git a/features/launches/presentation/build.gradle.kts b/features/launches/presentation/build.gradle.kts index 4611825..4282494 100644 --- a/features/launches/presentation/build.gradle.kts +++ b/features/launches/presentation/build.gradle.kts @@ -55,7 +55,7 @@ kotlin { implementation(compose.material3) implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0-alpha03") implementation("androidx.activity:activity-compose") { - exclude(group = "androidx.lifecycle", module = "lifecycle-viewmodel-ktx") // Here we are exlcuding the ViewModel dependency + exclude(group = "androidx.lifecycle", module = "lifecycle-viewmodel-ktx") } } } @@ -70,7 +70,7 @@ kotlin { iosArm64Main.dependsOn(this) iosSimulatorArm64Main.dependsOn(this) dependencies { - implementation("androidx.lifecycle:lifecycle-viewmodel:2.8.0-alpha03") + implementation(libs.lifecycle.viewmodel) } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 935776b..25fa284 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,6 +62,7 @@ tealium-remotecommands-dispatcher = "1.2.0" tealium-remotecommands-firebase = "1.2.0" zoomable = "1.4.3" koin = "3.5.3" +lifecycle-viewmodel = "2.8.0-alpha03" [plugins] android-application = { id = "com.android.application", version.ref = "gradle" } @@ -182,6 +183,7 @@ optimizely-log = { group = "com.noveogroup.android", name = "android-logger", ve precompose = { group = "moe.tlaster", name = "precompose", version.ref = "precompose" } precompose-viewmodel = { group = "moe.tlaster", name = "precompose-viewmodel", version.ref = "precompose" } +lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "lifecycle-viewmodel" } sqldelight-android-driver = { group = "com.squareup.sqldelight", name = "android-driver", version.ref = "sqldelight" } sqldelight-coroutines-extensions = { group = "com.squareup.sqldelight", name = "coroutines-extensions", version.ref = "sqldelight" } From 017c410aa9159077ef1dee05700ffafac9ce4b00 Mon Sep 17 00:00:00 2001 From: pawansoni Date: Fri, 5 Apr 2024 10:45:58 +0530 Subject: [PATCH 4/7] MKMPT-5: lifecycle viewmodel ktx in toml --- features/launches/presentation/build.gradle.kts | 5 +---- gradle/libs.versions.toml | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/features/launches/presentation/build.gradle.kts b/features/launches/presentation/build.gradle.kts index 4282494..6fac0e3 100644 --- a/features/launches/presentation/build.gradle.kts +++ b/features/launches/presentation/build.gradle.kts @@ -53,10 +53,7 @@ kotlin { implementation(compose.runtime) implementation(compose.ui) implementation(compose.material3) - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0-alpha03") - implementation("androidx.activity:activity-compose") { - exclude(group = "androidx.lifecycle", module = "lifecycle-viewmodel-ktx") - } + implementation(libs.lifecycle.viewmodel.ktx) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 25fa284..29325e1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -184,6 +184,7 @@ optimizely-log = { group = "com.noveogroup.android", name = "android-logger", ve precompose = { group = "moe.tlaster", name = "precompose", version.ref = "precompose" } precompose-viewmodel = { group = "moe.tlaster", name = "precompose-viewmodel", version.ref = "precompose" } lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "lifecycle-viewmodel" } +lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle-viewmodel" } sqldelight-android-driver = { group = "com.squareup.sqldelight", name = "android-driver", version.ref = "sqldelight" } sqldelight-coroutines-extensions = { group = "com.squareup.sqldelight", name = "coroutines-extensions", version.ref = "sqldelight" } From 4f19b60f804f77a720ba85e5e26b8dd7809694fc Mon Sep 17 00:00:00 2001 From: pawansoni Date: Fri, 5 Apr 2024 10:49:17 +0530 Subject: [PATCH 5/7] MKMPT-5: DIHelper in object and removed GetCurrencyExchangeUseCase --- .../launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt b/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt index 15015ff..f477aca 100644 --- a/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt +++ b/features/launches/di/src/iosMain/kotlin/com.mindera.di/DIHelper.kt @@ -5,7 +5,7 @@ import com.mindera.kmpexample.launches.viewmodel.CurrencyExchangeViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject -class DIHelper: KoinComponent { +object DIHelper: KoinComponent { val getGetCurrencyExchangeUseCase: GetCurrencyExchangeUseCase by inject() val viewModel: CurrencyExchangeViewModel by inject() } From 064dd5161548faab18e629fccde9b777b2cbfc11 Mon Sep 17 00:00:00 2001 From: pawansoni Date: Fri, 5 Apr 2024 10:50:09 +0530 Subject: [PATCH 6/7] MKMPT-5: remove extra line --- gradle.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a6f5565..debbde8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,5 +34,4 @@ kotlin.native.binary.objcExportSuspendFunctionLaunchThreadRestriction=none kotlin.native.disableCompilerDaemon=true kotlin.native.ignoreDisabledTargets=true - org.jetbrains.compose.experimental.uikit.enabled=true From 45b5f07ee185a7a3a7777e3cfd1f036692a57b80 Mon Sep 17 00:00:00 2001 From: pawansoni Date: Mon, 8 Apr 2024 17:27:53 +0530 Subject: [PATCH 7/7] MKMPT-2: API changes with last 10 records --- .../composables/CurrencyExchangeScreen.kt | 28 ++++++++++--------- .../KtorCurrencyExchangeRemoteSource.kt | 5 ++-- .../datasource/remote/converters/Api.kt | 3 ++ .../CurrencyExchangeResponse.kt | 9 ++++++ .../domain/model/CurrencyExchangeResponse.kt | 6 ++++ .../launches/CurrencyExchangeScene.kt | 2 +- 6 files changed, 36 insertions(+), 17 deletions(-) diff --git a/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt b/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt index e9b8990..f2ccc66 100644 --- a/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt +++ b/features/launches/composables/src/commonMain/kotlin/com/mindera/kmpexample/composables/CurrencyExchangeScreen.kt @@ -16,28 +16,30 @@ import com.mindera.kmpexample.launches.domain.model.CurrencyExchangeResponseItem @Composable fun CurrencyExchangeScreen( modifier: Modifier = Modifier, - launches: ImmutableList, + currencies: ImmutableList, ) { val lazyListState = rememberLazyListState() - if (launches.isNotEmpty()) { + if (currencies.isNotEmpty()) { LazyColumn( modifier = modifier.fillMaxWidth(), state = lazyListState, ) { - itemsIndexed(items = launches[0].rates, key = { index, _ -> index }) { index, launch -> - - if (index != 0) { - Divider(thickness = 2.dp) + currencies.forEach { + itemsIndexed(items = it.rates, key = { index, _ -> index }) { index, launch -> + if (index != 0) { + Divider(thickness = 2.dp) + } + Text(it.no) + Text(launch.id) + Text(launch.currency.replaceFirstChar { + if (it.isLowerCase()) it.titlecase() else it.toString() + }) + Text(launch.code, color = Color.Blue) + Text(launch.currencyRate.toString(), color = Color.Gray) } - Text(launch.id) - Text(launch.currency.replaceFirstChar { - if (it.isLowerCase()) it.titlecase() else it.toString() - }) - Text(launch.code, color = Color.Blue) - Text(launch.currencyRate.toString(), color = Color.Gray) } } - } + } } diff --git a/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/KtorCurrencyExchangeRemoteSource.kt b/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/KtorCurrencyExchangeRemoteSource.kt index 102ce36..cef7d13 100644 --- a/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/KtorCurrencyExchangeRemoteSource.kt +++ b/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/KtorCurrencyExchangeRemoteSource.kt @@ -13,10 +13,9 @@ class KtorCurrencyExchangeRemoteSource constructor( private val client: HttpClient, ) : CurrencyExchangeRemoteSource { + override suspend fun getCurrencyExchange(): List = - getCurrencyExchange("A").zip(getCurrencyExchange("B")) { listA, listB -> - DomainCurrencyExchangeResponseItem(listA.rates + listB.rates) - } + getCurrencyExchange("A/last/10/") private suspend fun getCurrencyExchange(table: String): List = client.get("$baseUrl/$table") diff --git a/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/converters/Api.kt b/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/converters/Api.kt index f937354..11aec8b 100644 --- a/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/converters/Api.kt +++ b/features/launches/data/remote/mindera/rest/ktor/src/commonMain/kotlin/com/mindera/datasource/remote/converters/Api.kt @@ -5,6 +5,9 @@ import com.mindera.uuid internal fun CurrencyExchangeResponseItem.toDomain() = com.mindera.kmpexample.launches.domain.model.CurrencyExchangeResponseItem( + table = table, + no = no, + effectiveDate = effectiveDate, rates = rates.map { it.toDomain() }, ) diff --git a/features/launches/data/remote/mindera/rest/schema/src/commonMain/kotlin/com.mindera.rest/CurrencyExchangeResponse.kt b/features/launches/data/remote/mindera/rest/schema/src/commonMain/kotlin/com.mindera.rest/CurrencyExchangeResponse.kt index c46e790..b0356ce 100644 --- a/features/launches/data/remote/mindera/rest/schema/src/commonMain/kotlin/com.mindera.rest/CurrencyExchangeResponse.kt +++ b/features/launches/data/remote/mindera/rest/schema/src/commonMain/kotlin/com.mindera.rest/CurrencyExchangeResponse.kt @@ -19,6 +19,15 @@ data class RatesItem( @Serializable data class CurrencyExchangeResponseItem( + @SerialName("table") + val table: String, + + @SerialName("no") + val no: String, + + @SerialName("effectiveDate") + val effectiveDate: String, + @SerialName("rates") val rates: List, ) diff --git a/features/launches/domain/src/commonMain/kotlin/com/mindera/kmpexample/launches/domain/model/CurrencyExchangeResponse.kt b/features/launches/domain/src/commonMain/kotlin/com/mindera/kmpexample/launches/domain/model/CurrencyExchangeResponse.kt index 3a78536..b62493f 100644 --- a/features/launches/domain/src/commonMain/kotlin/com/mindera/kmpexample/launches/domain/model/CurrencyExchangeResponse.kt +++ b/features/launches/domain/src/commonMain/kotlin/com/mindera/kmpexample/launches/domain/model/CurrencyExchangeResponse.kt @@ -13,5 +13,11 @@ data class RatesItem( data class CurrencyExchangeResponseItem( + val table: String, + + val no: String, + + val effectiveDate: String, + val rates: List, ) diff --git a/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt b/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt index 79113f2..fb4e57e 100644 --- a/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt +++ b/features/launches/presentation/src/androidMain/kotlin/com/mindera/kmpexample/launches/CurrencyExchangeScene.kt @@ -31,7 +31,7 @@ fun CurrencyExchangeScene(onBack: (() -> Unit)) { fontSize = 40.sp, ) CurrencyExchangeScreen( - launches = state.value.launches + currencies = state.value.launches ) } }