diff --git a/.github/workflows/compilation-check.yml b/.github/workflows/compilation-check.yml index f3d2bd12..b220396d 100644 --- a/.github/workflows/compilation-check.yml +++ b/.github/workflows/compilation-check.yml @@ -19,4 +19,14 @@ jobs: - name: Build K/N cache run: ./gradlew :mvvm:runCommonizer - name: Build and test - run: ./gradlew build publishToMavenLocal + run: ./gradlew build publishToMavenLocal syncMultiPlatformLibraryDebugFrameworkIosX64 -x linkMultiPlatformLibraryDebugFrameworkIosArm64 -x linkMultiPlatformLibraryReleaseFrameworkIosArm64 -x linkMultiPlatformLibraryReleaseFrameworkIosX64 + - name: Install pods + run: cd sample/ios-app && pod install + - name: build ios sample + run: cd sample/ios-app && xcodebuild -scheme TestProj -workspace TestProj.xcworkspace -configuration Debug build CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO + - name: Publish Test Report + uses: mikepenz/action-junit-report@v2 + if: ${{ always() }} + with: + report_paths: '**/build/test-results/**/TEST-*.xml' + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 2cc486a6..d1bc513c 100755 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ This is a Kotlin Multiplatform library that provides architecture components of ### mavenCentral - kotlin 1.4.31 - 0.9.2 + - 0.10.0 ## Installation root build.gradle @@ -66,15 +67,15 @@ allprojects { project build.gradle ```groovy dependencies { - commonMainApi("dev.icerock.moko:mvvm-core:0.9.2") // only ViewModel, EventsDispatcher, Dispatchers.UI - commonMainApi("dev.icerock.moko:mvvm-livedata:0.9.2") // api mvvm-core, LiveData and extensions - androidMainApi("dev.icerock.moko:mvvm-livedata-material:0.9.2") // api mvvm-livedata, Material library android extensions - androidMainApi("dev.icerock.moko:mvvm-livedata-glide:0.9.2") // api mvvm-livedata, Glide library android extensions - androidMainApi("dev.icerock.moko:mvvm-livedata-swiperefresh:0.9.2") // api mvvm-livedata, SwipeRefreshLayout library android extensions - commonMainApi("dev.icerock.moko:mvvm-state:0.9.2") // api mvvm-livedata, ResourceState class and extensions - androidMainApi("dev.icerock.moko:mvvm-databinding:0.9.2") // api mvvm-livedata, DataBinding support for Android - androidMainApi("dev.icerock.moko:mvvm-viewbinding:0.9.2") // api mvvm-livedata, ViewBinding support for Android - commonTestImplementation("dev.icerock.moko:mvvm-test:0.9.2") // test utilities + commonMainApi("dev.icerock.moko:mvvm-core:0.10.0") // only ViewModel, EventsDispatcher, Dispatchers.UI + commonMainApi("dev.icerock.moko:mvvm-livedata:0.10.0") // api mvvm-core, LiveData and extensions + androidMainApi("dev.icerock.moko:mvvm-livedata-material:0.10.0") // api mvvm-livedata, Material library android extensions + androidMainApi("dev.icerock.moko:mvvm-livedata-glide:0.10.0") // api mvvm-livedata, Glide library android extensions + androidMainApi("dev.icerock.moko:mvvm-livedata-swiperefresh:0.10.0") // api mvvm-livedata, SwipeRefreshLayout library android extensions + commonMainApi("dev.icerock.moko:mvvm-state:0.10.0") // api mvvm-livedata, ResourceState class and extensions + androidMainApi("dev.icerock.moko:mvvm-databinding:0.10.0") // api mvvm-livedata, DataBinding support for Android + androidMainApi("dev.icerock.moko:mvvm-viewbinding:0.10.0") // api mvvm-livedata, ViewBinding support for Android + commonTestImplementation("dev.icerock.moko:mvvm-test:0.10.0") // test utilities } ``` @@ -89,7 +90,7 @@ kotlin { else -> throw IllegalArgumentException() } binaries.withType(org.jetbrains.kotlin.gradle.plugin.mpp.Framework::class.java).all { - export("dev.icerock.moko:mvvm-$arch:0.8.1") + export("dev.icerock.moko:mvvm-$arch:0.10.0") } } } @@ -97,7 +98,7 @@ kotlin { On iOS, in addition to the Kotlin library add in Podfile ```ruby -pod 'MultiPlatformLibraryMvvm', :git => 'https://github.com/icerockdev/moko-mvvm.git', :tag => 'release/0.9.1' +pod 'MultiPlatformLibraryMvvm', :git => 'https://github.com/icerockdev/moko-mvvm.git', :tag => 'release/0.10.0' ``` **`MultiPlatformLibraryMvvm` CocoaPod requires that the framework compiled from Kotlin be named `MultiPlatformLibrary` and be connected as a CocoaPod `MultiPlatformLibrary`. diff --git a/build.gradle.kts b/build.gradle.kts index d36cbcd0..277245d5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,7 @@ import java.util.Base64 plugins { plugin(Deps.Plugins.detekt) apply false plugin(Deps.Plugins.dokka) apply false + id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.5.0" } buildscript { @@ -17,6 +18,7 @@ buildscript { allprojects { repositories { + mavenCentral() google() mavenCentral() @@ -121,18 +123,26 @@ allprojects { } } +val sampleProjects: Set = project(":sample").allprojects + +apiValidation { + ignoredPackages.add("dev.icerock.moko.mvvm.internal") + + ignoredProjects.addAll(sampleProjects.map { it.name }) +} + +tasks.register("clean", Delete::class).configure { + group = "build" + delete(rootProject.buildDir) +} + tasks.withType().all { - removeChildTasks(listOf( - ":mvvm", - ":sample", - ":sample:android-app", - ":sample:mpp-library" - ).map { project(it) }) + removeChildTasks(sampleProjects.plus(project(":mvvm"))) doLast { val dir = outputDirectory.get() - val from = File(dir,"-modules.html") - val to = File(dir,"index.html") + val from = File(dir, "-modules.html") + val to = File(dir, "index.html") from.renameTo(to) diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt index a858296c..f2189080 100755 --- a/buildSrc/src/main/kotlin/Deps.kt +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -14,7 +14,7 @@ object Deps { private const val coroutinesVersion = "1.4.2" private const val mokoResourcesVersion = "0.15.1" private const val mokoTestVersion = "0.2.1" - const val mokoMvvmVersion = "0.9.2" + const val mokoMvvmVersion = "0.10.0" object Android { const val compileSdk = 29 diff --git a/mvvm-core/api/mvvm-core.api b/mvvm-core/api/mvvm-core.api new file mode 100644 index 00000000..a0408937 --- /dev/null +++ b/mvvm-core/api/mvvm-core.api @@ -0,0 +1,38 @@ +public final class dev/icerock/moko/mvvm/UIKt { + public static final fun getUI (Lkotlinx/coroutines/Dispatchers;)Lkotlinx/coroutines/CoroutineDispatcher; +} + +public final class dev/icerock/moko/mvvm/ViewModelFactory : androidx/lifecycle/ViewModelProvider$Factory { + public fun (Lkotlin/jvm/functions/Function0;)V + public fun create (Ljava/lang/Class;)Landroidx/lifecycle/ViewModel; +} + +public final class dev/icerock/moko/mvvm/core/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public final class dev/icerock/moko/mvvm/dispatcher/EventsDispatcher { + public fun ()V + public fun (Ljava/util/concurrent/Executor;)V + public fun (Ljava/util/concurrent/Executor;Ljava/lang/Object;)V + public final fun bind (Landroidx/lifecycle/LifecycleOwner;Ljava/lang/Object;)V + public final fun dispatchEvent (Lkotlin/jvm/functions/Function1;)V +} + +public final class dev/icerock/moko/mvvm/dispatcher/EventsDispatcherExtKt { + public static final fun createExecutorOnMainLooper ()Ljava/util/concurrent/Executor; +} + +public abstract interface class dev/icerock/moko/mvvm/dispatcher/EventsDispatcherOwner { + public abstract fun getEventsDispatcher ()Ldev/icerock/moko/mvvm/dispatcher/EventsDispatcher; +} + +public class dev/icerock/moko/mvvm/viewmodel/ViewModel : androidx/lifecycle/ViewModel { + public fun ()V + protected final fun getViewModelScope ()Lkotlinx/coroutines/CoroutineScope; + public fun onCleared ()V +} + diff --git a/mvvm-core/build.gradle.kts b/mvvm-core/build.gradle.kts index 8a4d3bb1..4265bcf1 100644 --- a/mvvm-core/build.gradle.kts +++ b/mvvm-core/build.gradle.kts @@ -12,6 +12,8 @@ plugins { dependencies { commonMainImplementation(Deps.Libs.MultiPlatform.coroutines) + commonMainImplementation(project(":mvvm-internal")) + androidMainApi(Deps.Libs.Android.appCompat) androidMainApi(Deps.Libs.Android.androidViewModel) diff --git a/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/UI.kt b/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/UI.kt deleted file mode 100644 index 444432f2..00000000 --- a/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/UI.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.mvvm - -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers - -actual val Dispatchers.UI: CoroutineDispatcher - get() = Dispatchers.Main diff --git a/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt b/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt index 3d166c39..6a132bb1 100644 --- a/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt +++ b/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt @@ -23,6 +23,14 @@ actual class EventsDispatcher { this.executor = executor } + /** + * Constructor without lifecycle connection. Used for tests + */ + constructor(executor: Executor, listener: ListenerType) { + this.executor = executor + this.eventsListener = listener + } + fun bind(lifecycleOwner: LifecycleOwner, listener: ListenerType) { val observer = object : LifecycleObserver { diff --git a/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt b/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt index d608bbe9..e47c8a1e 100644 --- a/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt +++ b/mvvm-core/src/androidMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt @@ -5,15 +5,13 @@ package dev.icerock.moko.mvvm.viewmodel import androidx.lifecycle.ViewModel -import dev.icerock.moko.mvvm.UI +import dev.icerock.moko.mvvm.internal.createViewModelScope import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel @Suppress("EmptyDefaultConstructor") actual open class ViewModel actual constructor() : ViewModel() { - // for now dispatcher fixed on Main. after implementing multithread coroutines on native - we can change it - protected actual val viewModelScope: CoroutineScope = CoroutineScope(Dispatchers.UI) + protected actual val viewModelScope: CoroutineScope = createViewModelScope() public actual override fun onCleared() { super.onCleared() diff --git a/mvvm-core/src/commonMain/kotlin/dev/icerock/moko/mvvm/UI.kt b/mvvm-core/src/commonMain/kotlin/dev/icerock/moko/mvvm/UI.kt index 5980ebdf..3b3378f5 100644 --- a/mvvm-core/src/commonMain/kotlin/dev/icerock/moko/mvvm/UI.kt +++ b/mvvm-core/src/commonMain/kotlin/dev/icerock/moko/mvvm/UI.kt @@ -4,7 +4,9 @@ package dev.icerock.moko.mvvm +import dev.icerock.moko.mvvm.internal.createUIDispatcher import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -expect val Dispatchers.UI: CoroutineDispatcher +val Dispatchers.UI: CoroutineDispatcher + get() = createUIDispatcher() diff --git a/mvvm-core/src/iosArm64Main b/mvvm-core/src/iosArm64Main new file mode 120000 index 00000000..46be4b86 --- /dev/null +++ b/mvvm-core/src/iosArm64Main @@ -0,0 +1 @@ +iosX64Main \ No newline at end of file diff --git a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/UI.kt b/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/UI.kt deleted file mode 100644 index ac943215..00000000 --- a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/UI.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.mvvm - -import dev.icerock.moko.mvvm.viewmodel.UIDispatcher -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers - -actual val Dispatchers.UI: CoroutineDispatcher - get() = UIDispatcher() diff --git a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt b/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt index 970dcc86..774ae844 100644 --- a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt +++ b/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/dispatcher/EventsDispatcher.kt @@ -5,6 +5,7 @@ package dev.icerock.moko.mvvm.dispatcher import platform.darwin.dispatch_async +import platform.darwin.dispatch_get_current_queue import platform.darwin.dispatch_get_main_queue import platform.darwin.dispatch_queue_t import kotlin.native.ref.WeakReference @@ -44,8 +45,10 @@ actual class EventsDispatcher { return } - dispatch_async(queue) { + if (dispatch_get_current_queue() == queue) { block(listener) + } else { + dispatch_async(queue) { block(listener) } } } } diff --git a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt b/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt index 8d578983..970efc01 100644 --- a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt +++ b/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/viewmodel/ViewModel.kt @@ -4,27 +4,20 @@ package dev.icerock.moko.mvvm.viewmodel -import dev.icerock.moko.mvvm.UI +import dev.icerock.moko.mvvm.internal.createViewModelScope import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel +import platform.darwin.dispatch_async +import platform.darwin.dispatch_get_main_queue import kotlin.native.internal.GC -@ThreadLocal -private var isGCWorking = false - @Suppress("EmptyDefaultConstructor") actual open class ViewModel actual constructor() { - // for now dispatcher fixed on Main. after implementing multithread coroutines on native - we can change it - protected actual val viewModelScope: CoroutineScope = CoroutineScope(Dispatchers.UI) + protected actual val viewModelScope: CoroutineScope = createViewModelScope() actual open fun onCleared() { viewModelScope.cancel() - // run Kotlin/Native GC - if (!isGCWorking) { - isGCWorking = true - GC.collect() - isGCWorking = false - } + + dispatch_async(dispatch_get_main_queue()) { GC.collect() } } } diff --git a/mvvm-databinding/api/mvvm-databinding.api b/mvvm-databinding/api/mvvm-databinding.api new file mode 100644 index 00000000..446e3b5a --- /dev/null +++ b/mvvm-databinding/api/mvvm-databinding.api @@ -0,0 +1,89 @@ +public abstract interface class androidx/databinding/DataBindingComponent { +} + +public class androidx/databinding/library/baseAdapters/BR { + public static field _all I + public fun ()V +} + +public abstract class dev/icerock/moko/mvvm/MvvmActivity : androidx/appcompat/app/AppCompatActivity { + protected field binding Landroidx/databinding/ViewDataBinding; + protected field viewModel Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + public fun ()V + protected final fun getBinding ()Landroidx/databinding/ViewDataBinding; + protected abstract fun getLayoutId ()I + protected final fun getViewModel ()Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + protected abstract fun getViewModelClass ()Ljava/lang/Class; + protected abstract fun getViewModelVariableId ()I + protected fun onCreate (Landroid/os/Bundle;)V + protected final fun setBinding (Landroidx/databinding/ViewDataBinding;)V + protected final fun setViewModel (Ldev/icerock/moko/mvvm/viewmodel/ViewModel;)V + protected abstract fun viewModelFactory ()Landroidx/lifecycle/ViewModelProvider$Factory; +} + +public abstract class dev/icerock/moko/mvvm/MvvmEventsActivity : dev/icerock/moko/mvvm/MvvmActivity { + public fun ()V + protected fun onCreate (Landroid/os/Bundle;)V +} + +public abstract class dev/icerock/moko/mvvm/MvvmEventsFragment : dev/icerock/moko/mvvm/MvvmFragment { + public fun ()V + public fun onCreate (Landroid/os/Bundle;)V +} + +public abstract class dev/icerock/moko/mvvm/MvvmFragment : androidx/fragment/app/Fragment { + protected field viewModel Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + public fun ()V + protected final fun getBinding ()Landroidx/databinding/ViewDataBinding; + protected abstract fun getLayoutId ()I + protected final fun getViewModel ()Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + protected abstract fun getViewModelClass ()Ljava/lang/Class; + protected abstract fun getViewModelVariableId ()I + public fun onCreate (Landroid/os/Bundle;)V + public fun onCreateView (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Landroid/os/Bundle;)Landroid/view/View; + public fun onDestroyView ()V + public fun onViewCreated (Landroid/view/View;Landroid/os/Bundle;)V + protected final fun setViewModel (Ldev/icerock/moko/mvvm/viewmodel/ViewModel;)V + protected abstract fun viewModelFactory ()Landroidx/lifecycle/ViewModelProvider$Factory; + protected fun viewModelStoreOwner ()Landroidx/lifecycle/ViewModelStoreOwner; +} + +public class dev/icerock/moko/mvvm/databinding/BR { + public static field _all I + public fun ()V +} + +public final class dev/icerock/moko/mvvm/databinding/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public class dev/icerock/moko/mvvm/databinding/DataBinderMapperImpl : androidx/databinding/DataBinderMapper { + public fun ()V + public fun collectDependencies ()Ljava/util/List; + public fun convertBrIdToString (I)Ljava/lang/String; + public fun getDataBinder (Landroidx/databinding/DataBindingComponent;Landroid/view/View;I)Landroidx/databinding/ViewDataBinding; + public fun getDataBinder (Landroidx/databinding/DataBindingComponent;[Landroid/view/View;I)Landroidx/databinding/ViewDataBinding; + public fun getLayoutId (Ljava/lang/String;)I +} + +public class dev/icerock/moko/mvvm/databinding/DataBindingTriggerClass { + public fun ()V +} + +public final class dev/icerock/moko/mvvm/databinding/StringDescAdapters { + public static final field INSTANCE Ldev/icerock/moko/mvvm/databinding/StringDescAdapters; + public static final fun setError (Lcom/google/android/material/textfield/TextInputLayout;Ldev/icerock/moko/resources/desc/StringDesc;)V + public static final fun setText (Landroid/widget/Button;Ldev/icerock/moko/resources/desc/StringDesc;)V + public static final fun setText (Landroid/widget/TextView;Ldev/icerock/moko/resources/desc/StringDesc;)V +} + +public final class dev/icerock/moko/mvvm/databinding/ViewBindingAdapters { + public static final field INSTANCE Ldev/icerock/moko/mvvm/databinding/ViewBindingAdapters; + public static final fun setInvisibleOrGone (Landroid/view/View;Z)V + public static final fun setVisibleOrGone (Landroid/view/View;Z)V + public static final fun setVisibleOrInvisible (Landroid/view/View;Z)V +} + diff --git a/mvvm-internal/api/mvvm-internal.api b/mvvm-internal/api/mvvm-internal.api new file mode 100644 index 00000000..e69de29b diff --git a/mvvm-internal/build.gradle.kts b/mvvm-internal/build.gradle.kts new file mode 100644 index 00000000..6ff05b66 --- /dev/null +++ b/mvvm-internal/build.gradle.kts @@ -0,0 +1,17 @@ +/* + * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + plugin(Deps.Plugins.androidLibrary) + plugin(Deps.Plugins.kotlinMultiplatform) + plugin(Deps.Plugins.mobileMultiplatform) + plugin(Deps.Plugins.mavenPublish) +} + +group = "dev.icerock.moko" +version = Deps.mokoMvvmVersion + +dependencies { + commonMainApi(Deps.Libs.MultiPlatform.coroutines) +} diff --git a/mvvm-internal/src/androidMain/AndroidManifest.xml b/mvvm-internal/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..ceb8451f --- /dev/null +++ b/mvvm-internal/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/mvvm-internal/src/androidMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt b/mvvm-internal/src/androidMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt new file mode 100644 index 00000000..726c16bd --- /dev/null +++ b/mvvm-internal/src/androidMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.mvvm.internal + +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers + +actual fun createUIDispatcher(): CoroutineDispatcher = Dispatchers.Main diff --git a/mvvm-internal/src/commonMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt b/mvvm-internal/src/commonMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt new file mode 100644 index 00000000..73509d48 --- /dev/null +++ b/mvvm-internal/src/commonMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.mvvm.internal + +import kotlinx.coroutines.CoroutineDispatcher + +expect fun createUIDispatcher(): CoroutineDispatcher diff --git a/mvvm-internal/src/commonMain/kotlin/dev/icerock/moko/mvvm/internal/createViewModelScope.kt b/mvvm-internal/src/commonMain/kotlin/dev/icerock/moko/mvvm/internal/createViewModelScope.kt new file mode 100644 index 00000000..a2e335c4 --- /dev/null +++ b/mvvm-internal/src/commonMain/kotlin/dev/icerock/moko/mvvm/internal/createViewModelScope.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.mvvm.internal + +import kotlinx.coroutines.CoroutineScope +import kotlin.native.concurrent.ThreadLocal + +/** + * Factory of viewModelScope. Internal API, for ability of mvvm-test to change viewModelScope + * dispatcher. + * + * In default implementation create main-thread dispatcher scope. + */ +@ThreadLocal +var createViewModelScope: () -> CoroutineScope = { + CoroutineScope(createUIDispatcher()) +} diff --git a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/viewmodel/UIDispatcher.kt b/mvvm-internal/src/iosMain/kotlin/dev/icerock/moko/mvvm/internal/UIDispatcher.kt similarity index 91% rename from mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/viewmodel/UIDispatcher.kt rename to mvvm-internal/src/iosMain/kotlin/dev/icerock/moko/mvvm/internal/UIDispatcher.kt index 6dcecb6f..3de81abb 100644 --- a/mvvm-core/src/iosMain/kotlin/dev/icerock/moko/mvvm/viewmodel/UIDispatcher.kt +++ b/mvvm-internal/src/iosMain/kotlin/dev/icerock/moko/mvvm/internal/UIDispatcher.kt @@ -1,8 +1,8 @@ /* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. */ -package dev.icerock.moko.mvvm.viewmodel +package dev.icerock.moko.mvvm.internal import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.CoroutineDispatcher @@ -18,7 +18,7 @@ import platform.darwin.dispatch_get_main_queue import platform.darwin.dispatch_time import kotlin.coroutines.CoroutineContext -@UseExperimental(InternalCoroutinesApi::class) +@OptIn(ExperimentalUnsignedTypes::class, InternalCoroutinesApi::class) internal class UIDispatcher : CoroutineDispatcher(), Delay { private val mQueue = dispatch_get_main_queue() diff --git a/mvvm-internal/src/iosMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt b/mvvm-internal/src/iosMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt new file mode 100644 index 00000000..23808798 --- /dev/null +++ b/mvvm-internal/src/iosMain/kotlin/dev/icerock/moko/mvvm/internal/createUIDispatcher.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.mvvm.internal + +import kotlinx.coroutines.CoroutineDispatcher + +actual fun createUIDispatcher(): CoroutineDispatcher = UIDispatcher() diff --git a/mvvm-livedata-glide/api/mvvm-livedata-glide.api b/mvvm-livedata-glide/api/mvvm-livedata-glide.api new file mode 100644 index 00000000..927befa1 --- /dev/null +++ b/mvvm-livedata-glide/api/mvvm-livedata-glide.api @@ -0,0 +1,14 @@ +public final class dev/icerock/moko/mvvm/livedata/glide/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public final class dev/icerock/moko/mvvm/livedata/glide/GlideImageViewBindingsKt { + public static final fun bindToImageViewSrc (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/ImageView;Landroid/graphics/drawable/Drawable;Landroid/graphics/drawable/Drawable;)V + public static final fun bindToImageViewSrc (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/ImageView;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun bindToImageViewSrc$default (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/ImageView;Landroid/graphics/drawable/Drawable;Landroid/graphics/drawable/Drawable;ILjava/lang/Object;)V + public static synthetic fun bindToImageViewSrc$default (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/ImageView;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V +} + diff --git a/mvvm-livedata-material/api/mvvm-livedata-material.api b/mvvm-livedata-material/api/mvvm-livedata-material.api new file mode 100644 index 00000000..e19d5288 --- /dev/null +++ b/mvvm-livedata-material/api/mvvm-livedata-material.api @@ -0,0 +1,12 @@ +public final class dev/icerock/moko/mvvm/livedata/material/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public final class dev/icerock/moko/mvvm/livedata/material/TextInputLayoutBindingsKt { + public static final fun bindToTextInputLayoutErrorString (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Lcom/google/android/material/textfield/TextInputLayout;)V + public static final fun bindToTextInputLayoutErrorStringDesc (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Lcom/google/android/material/textfield/TextInputLayout;)V +} + diff --git a/mvvm-livedata-swiperefresh/api/mvvm-livedata-swiperefresh.api b/mvvm-livedata-swiperefresh/api/mvvm-livedata-swiperefresh.api new file mode 100644 index 00000000..1661b3f6 --- /dev/null +++ b/mvvm-livedata-swiperefresh/api/mvvm-livedata-swiperefresh.api @@ -0,0 +1,13 @@ +public final class dev/icerock/moko/mvvm/livedata/swiperefresh/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public final class dev/icerock/moko/mvvm/livedata/swiperefresh/SwipeRefreshBindingsKt { + public static final fun bindToSwipeRefreshLayoutRefreshing (Ldev/icerock/moko/mvvm/livedata/MutableLiveData;Landroidx/lifecycle/LifecycleOwner;Landroidx/swiperefreshlayout/widget/SwipeRefreshLayout;)V + public static final fun setRefreshAction (Landroidx/swiperefreshlayout/widget/SwipeRefreshLayout;Lkotlin/jvm/functions/Function1;)V + public static final fun setRefreshAction (Landroidx/swiperefreshlayout/widget/SwipeRefreshLayout;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function1;)V +} + diff --git a/mvvm-livedata/api/mvvm-livedata.api b/mvvm-livedata/api/mvvm-livedata.api new file mode 100644 index 00000000..1b5bb408 --- /dev/null +++ b/mvvm-livedata/api/mvvm-livedata.api @@ -0,0 +1,108 @@ +public final class dev/icerock/moko/mvvm/livedata/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public final class dev/icerock/moko/mvvm/livedata/CheckBoxBindingsKt { + public static final fun bindToCheckBoxChecked (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/CheckBox;)V + public static final fun bindTwoWayToCheckBoxChecked (Ldev/icerock/moko/mvvm/livedata/MutableLiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/CheckBox;)V +} + +public final class dev/icerock/moko/mvvm/livedata/DebounceLiveDataKt { + public static final fun debounce (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlinx/coroutines/CoroutineScope;J)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/EditTextBindingsKt { + public static final fun bindTwoWayToEditTextText (Ldev/icerock/moko/mvvm/livedata/MutableLiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/EditText;)V +} + +public class dev/icerock/moko/mvvm/livedata/LiveData { + public fun (Landroidx/lifecycle/LiveData;)V + public final fun addObserver (Lkotlin/jvm/functions/Function1;)V + protected final fun getArchLiveData ()Landroidx/lifecycle/LiveData; + public fun getValue ()Ljava/lang/Object; + public fun ld ()Landroidx/lifecycle/LiveData; + public final fun removeObserver (Lkotlin/jvm/functions/Function1;)V +} + +public final class dev/icerock/moko/mvvm/livedata/LiveDataAndroidExtKt { + public static final fun mapToStringStringDesc (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroid/content/Context;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun mapToStringStringDescOptional (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroid/content/Context;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/LiveDataCoroutinesKt { + public static final fun asFlow (Ldev/icerock/moko/mvvm/livedata/LiveData;)Lkotlinx/coroutines/flow/Flow; + public static final fun asLiveData (Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/Object;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun asLiveData (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/CoroutineScope;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/LiveDataExtKt { + public static final fun ListLiveDataOrEmpty (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun distinct (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun mapOrNull (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun mapTrueOrNull (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun not (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun orEmpty (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun required (Ldev/icerock/moko/mvvm/livedata/LiveData;Ljava/lang/Object;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun revert (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/LiveDataTransformsKt { + public static final fun flatMap (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun flatMapBuffered (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function2;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun map (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun mapBuffered (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function2;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun mergeWith (Ldev/icerock/moko/mvvm/livedata/LiveData;Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function2;)Ldev/icerock/moko/mvvm/livedata/MediatorLiveData; +} + +public class dev/icerock/moko/mvvm/livedata/MediatorLiveData : dev/icerock/moko/mvvm/livedata/MutableLiveData { + public fun (Ljava/lang/Object;)V + public final fun addSource (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)V +} + +public final class dev/icerock/moko/mvvm/livedata/MediatorLiveDataExtKt { + public static final fun all (Ljava/util/List;Z)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun any (Ljava/util/List;Z)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun compose (Ldev/icerock/moko/mvvm/livedata/MediatorLiveData;Ldev/icerock/moko/mvvm/livedata/LiveData;Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function2;)Ldev/icerock/moko/mvvm/livedata/MediatorLiveData; + public static final fun composition (Ldev/icerock/moko/mvvm/livedata/MediatorLiveData;Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/MediatorLiveData; + public static final fun mediator (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public class dev/icerock/moko/mvvm/livedata/MutableLiveData : dev/icerock/moko/mvvm/livedata/LiveData { + public fun (Landroidx/lifecycle/MutableLiveData;)V + public fun (Ljava/lang/Object;)V + public fun getValue ()Ljava/lang/Object; + public synthetic fun ld ()Landroidx/lifecycle/LiveData; + public fun ld ()Landroidx/lifecycle/MutableLiveData; + public final fun postValue (Ljava/lang/Object;)V + public fun setValue (Ljava/lang/Object;)V +} + +public final class dev/icerock/moko/mvvm/livedata/MutableLiveDataExtKt { + public static final fun readOnly (Ldev/icerock/moko/mvvm/livedata/MutableLiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun setValue (Ldev/icerock/moko/mvvm/livedata/MutableLiveData;Ljava/lang/Object;Z)V +} + +public final class dev/icerock/moko/mvvm/livedata/TextViewBindingsKt { + public static final fun bindToTextViewTextString (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/TextView;)V + public static final fun bindToTextViewTextStringDesc (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/widget/TextView;)V +} + +public final class dev/icerock/moko/mvvm/livedata/ThrowableLiveDataExtKt { + public static final fun throwableMessage (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static synthetic fun throwableMessage$default (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/ViewBindingsKt { + public static final fun bindToViewEnabled (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/view/View;)V + public static final fun bindToViewVisibleOrGone (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/view/View;)V + public static final fun bindToViewVisibleOrInvisible (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Landroid/view/View;)V +} + +public final class dev/icerock/moko/mvvm/utils/LiveDataExtKt { + public static final fun bind (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Lkotlin/jvm/functions/Function1;)V + public static final fun bindNotNull (Ldev/icerock/moko/mvvm/livedata/LiveData;Landroidx/lifecycle/LifecycleOwner;Lkotlin/jvm/functions/Function1;)V +} + diff --git a/mvvm-livedata/src/iosMain/swift/Core/UILabel+LiveData.swift b/mvvm-livedata/src/iosMain/swift/Core/UILabel+LiveData.swift index d729da9a..59bc195e 100644 --- a/mvvm-livedata/src/iosMain/swift/Core/UILabel+LiveData.swift +++ b/mvvm-livedata/src/iosMain/swift/Core/UILabel+LiveData.swift @@ -13,7 +13,7 @@ public extension UILabel { UILabelBindingKt.bindText( self, liveData: liveData, - formatter_____: formatter + formatter_: formatter ) } @@ -24,7 +24,7 @@ public extension UILabel { UILabelBindingKt.bindText( self, liveData: liveData, - formatter____: formatter + formatter: formatter ) } } diff --git a/mvvm-livedata/src/iosMain/swift/Core/UITextView+LiveData.swift b/mvvm-livedata/src/iosMain/swift/Core/UITextView+LiveData.swift index 3410d489..b694abf9 100644 --- a/mvvm-livedata/src/iosMain/swift/Core/UITextView+LiveData.swift +++ b/mvvm-livedata/src/iosMain/swift/Core/UITextView+LiveData.swift @@ -10,7 +10,7 @@ public extension UITextView { UITextViewBindingKt.bindText( self, liveData: liveData, - formatter__: nil + formatter: nil ) } @@ -18,7 +18,7 @@ public extension UITextView { UITextViewBindingKt.bindText( self, liveData: liveData, - formatter___: nil + formatter_: nil ) } } diff --git a/mvvm-state-deprecated/api/mvvm-state-deprecated.api b/mvvm-state-deprecated/api/mvvm-state-deprecated.api new file mode 100644 index 00000000..329de748 --- /dev/null +++ b/mvvm-state-deprecated/api/mvvm-state-deprecated.api @@ -0,0 +1,84 @@ +public abstract class dev/icerock/moko/mvvm/State { + public final fun dataValue ()Ljava/lang/Object; + public final fun errorValue ()Ljava/lang/Object; + public final fun isEmpty ()Z + public final fun isError ()Z + public final fun isLoading ()Z + public final fun isSuccess ()Z +} + +public final class dev/icerock/moko/mvvm/State$Data : dev/icerock/moko/mvvm/State { + public fun (Ljava/lang/Object;)V + public final fun component1 ()Ljava/lang/Object; + public final fun copy (Ljava/lang/Object;)Ldev/icerock/moko/mvvm/State$Data; + public static synthetic fun copy$default (Ldev/icerock/moko/mvvm/State$Data;Ljava/lang/Object;ILjava/lang/Object;)Ldev/icerock/moko/mvvm/State$Data; + public fun equals (Ljava/lang/Object;)Z + public final fun getData ()Ljava/lang/Object; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/icerock/moko/mvvm/State$Empty : dev/icerock/moko/mvvm/State { + public fun ()V +} + +public final class dev/icerock/moko/mvvm/State$Error : dev/icerock/moko/mvvm/State { + public fun (Ljava/lang/Object;)V + public final fun component1 ()Ljava/lang/Object; + public final fun copy (Ljava/lang/Object;)Ldev/icerock/moko/mvvm/State$Error; + public static synthetic fun copy$default (Ldev/icerock/moko/mvvm/State$Error;Ljava/lang/Object;ILjava/lang/Object;)Ldev/icerock/moko/mvvm/State$Error; + public fun equals (Ljava/lang/Object;)Z + public final fun getError ()Ljava/lang/Object; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/icerock/moko/mvvm/State$Loading : dev/icerock/moko/mvvm/State { + public fun ()V +} + +public final class dev/icerock/moko/mvvm/StateExtKt { + public static final fun asState (Ljava/lang/Object;)Ldev/icerock/moko/mvvm/State; + public static final fun asState (Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/State; + public static final fun asState (Ljava/util/List;)Ldev/icerock/moko/mvvm/State; + public static final fun asState (Ljava/util/List;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/State; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataConditionsKt { + public static final fun isEmptyState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isEmptyState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isErrorState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isErrorState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isLoadingState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isLoadingState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isSuccessState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isSuccessState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataExtKt { + public static final fun data (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun dataValue (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ljava/lang/Object; + public static final fun error (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun error (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun errorValue (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ljava/lang/Object; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataMergesKt { + public static final fun concatData (Ldev/icerock/moko/mvvm/livedata/LiveData;Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function2;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataTransformsKt { + public static final fun dataTransform (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun emptyAsData (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun emptyAsError (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun emptyIf (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun errorTransform (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/state/deprecated/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + diff --git a/mvvm-state/api/mvvm-state.api b/mvvm-state/api/mvvm-state.api new file mode 100644 index 00000000..8319bca9 --- /dev/null +++ b/mvvm-state/api/mvvm-state.api @@ -0,0 +1,84 @@ +public abstract class dev/icerock/moko/mvvm/ResourceState { + public final fun dataValue ()Ljava/lang/Object; + public final fun errorValue ()Ljava/lang/Object; + public final fun isEmpty ()Z + public final fun isFailed ()Z + public final fun isLoading ()Z + public final fun isSuccess ()Z +} + +public final class dev/icerock/moko/mvvm/ResourceState$Empty : dev/icerock/moko/mvvm/ResourceState { + public fun ()V +} + +public final class dev/icerock/moko/mvvm/ResourceState$Failed : dev/icerock/moko/mvvm/ResourceState { + public fun (Ljava/lang/Object;)V + public final fun component1 ()Ljava/lang/Object; + public final fun copy (Ljava/lang/Object;)Ldev/icerock/moko/mvvm/ResourceState$Failed; + public static synthetic fun copy$default (Ldev/icerock/moko/mvvm/ResourceState$Failed;Ljava/lang/Object;ILjava/lang/Object;)Ldev/icerock/moko/mvvm/ResourceState$Failed; + public fun equals (Ljava/lang/Object;)Z + public final fun getError ()Ljava/lang/Object; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/icerock/moko/mvvm/ResourceState$Loading : dev/icerock/moko/mvvm/ResourceState { + public fun ()V +} + +public final class dev/icerock/moko/mvvm/ResourceState$Success : dev/icerock/moko/mvvm/ResourceState { + public fun (Ljava/lang/Object;)V + public final fun component1 ()Ljava/lang/Object; + public final fun copy (Ljava/lang/Object;)Ldev/icerock/moko/mvvm/ResourceState$Success; + public static synthetic fun copy$default (Ldev/icerock/moko/mvvm/ResourceState$Success;Ljava/lang/Object;ILjava/lang/Object;)Ldev/icerock/moko/mvvm/ResourceState$Success; + public fun equals (Ljava/lang/Object;)Z + public final fun getData ()Ljava/lang/Object; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/icerock/moko/mvvm/StateExtKt { + public static final fun asState (Ljava/lang/Object;)Ldev/icerock/moko/mvvm/ResourceState; + public static final fun asState (Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/ResourceState; + public static final fun asState (Ljava/util/List;)Ldev/icerock/moko/mvvm/ResourceState; + public static final fun asState (Ljava/util/List;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/ResourceState; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataConditionsKt { + public static final fun isEmptyState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isEmptyState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isErrorState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isErrorState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isLoadingState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isLoadingState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isSuccessState (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun isSuccessState (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataExtKt { + public static final fun data (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun dataValue (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ljava/lang/Object; + public static final fun error (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun error (Ljava/util/List;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun errorValue (Ldev/icerock/moko/mvvm/livedata/LiveData;)Ljava/lang/Object; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataMergesKt { + public static final fun concatData (Ldev/icerock/moko/mvvm/livedata/LiveData;Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function2;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/livedata/StateLiveDataTransformsKt { + public static final fun dataTransform (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun emptyAsData (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun emptyAsError (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function0;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun emptyIf (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; + public static final fun errorTransform (Ldev/icerock/moko/mvvm/livedata/LiveData;Lkotlin/jvm/functions/Function1;)Ldev/icerock/moko/mvvm/livedata/LiveData; +} + +public final class dev/icerock/moko/mvvm/state/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + diff --git a/mvvm-test/api/mvvm-test.api b/mvvm-test/api/mvvm-test.api new file mode 100644 index 00000000..2f93ea6d --- /dev/null +++ b/mvvm-test/api/mvvm-test.api @@ -0,0 +1,26 @@ +public final class dev/icerock/moko/mvvm/test/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public final class dev/icerock/moko/mvvm/test/TestEventsDispatcherKt { + public static final fun createTestEventsDispatcher ()Ldev/icerock/moko/mvvm/dispatcher/EventsDispatcher; + public static final fun createTestEventsDispatcher (Ljava/lang/Object;)Ldev/icerock/moko/mvvm/dispatcher/EventsDispatcher; +} + +public final class dev/icerock/moko/mvvm/test/TestObserver : kotlin/jvm/functions/Function1 { + public fun ()V + public final fun getInvokeCount ()I + public final fun getLastObservedValue ()Ljava/lang/Object; + public synthetic fun invoke (Ljava/lang/Object;)Ljava/lang/Object; + public fun invoke (Ljava/lang/Object;)V +} + +public final class dev/icerock/moko/mvvm/test/TestViewModelScope { + public static final field INSTANCE Ldev/icerock/moko/mvvm/test/TestViewModelScope; + public final fun resetViewModelScope ()V + public final fun setupViewModelScope (Lkotlinx/coroutines/CoroutineScope;)V +} + diff --git a/mvvm-test/build.gradle.kts b/mvvm-test/build.gradle.kts index 500a42c6..7b72a983 100644 --- a/mvvm-test/build.gradle.kts +++ b/mvvm-test/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { commonMainApi(Deps.Libs.MultiPlatform.coroutines) commonMainApi(project(":mvvm-core")) + commonMainImplementation(project(":mvvm-internal")) commonMainApi(Deps.Libs.Tests.kotlinTestJUnit) androidMainApi(Deps.Libs.Tests.coroutinesTest) diff --git a/mvvm-test/src/androidMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt b/mvvm-test/src/androidMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt index abd36de2..aacc80d5 100644 --- a/mvvm-test/src/androidMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt +++ b/mvvm-test/src/androidMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt @@ -7,5 +7,9 @@ package dev.icerock.moko.mvvm.test import dev.icerock.moko.mvvm.dispatcher.EventsDispatcher actual fun createTestEventsDispatcher(): EventsDispatcher { - return EventsDispatcher { it.run() } + return EventsDispatcher(executor = { it.run() }) +} + +actual fun createTestEventsDispatcher(listener: T): EventsDispatcher { + return EventsDispatcher(executor = { it.run() }, listener = listener) } diff --git a/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt b/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt index c1b7536e..facd6c77 100644 --- a/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt +++ b/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt @@ -7,3 +7,5 @@ package dev.icerock.moko.mvvm.test import dev.icerock.moko.mvvm.dispatcher.EventsDispatcher expect fun createTestEventsDispatcher(): EventsDispatcher + +expect fun createTestEventsDispatcher(listener: T): EventsDispatcher diff --git a/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestObserver.kt b/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestObserver.kt new file mode 100644 index 00000000..cb7c3ab6 --- /dev/null +++ b/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestObserver.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.mvvm.test + +class TestObserver : (T) -> Unit { + private var _invokeCount: Int = 0 + val invokeCount: Int get() = _invokeCount + + private var _lastObservedValue: T? = null + val lastObservedValue: T? get() = _lastObservedValue + + override fun invoke(p1: T) { + _lastObservedValue = p1 + _invokeCount++ + } +} diff --git a/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestViewModelScope.kt b/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestViewModelScope.kt new file mode 100644 index 00000000..8abe8bbb --- /dev/null +++ b/mvvm-test/src/commonMain/kotlin/dev/icerock/moko/mvvm/test/TestViewModelScope.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.mvvm.test + +import dev.icerock.moko.mvvm.internal.createViewModelScope +import kotlinx.coroutines.CoroutineScope +import kotlin.native.concurrent.ThreadLocal + +@ThreadLocal +object TestViewModelScope { + private val originalScope = createViewModelScope + + fun setupViewModelScope(coroutineScope: CoroutineScope) { + createViewModelScope = { coroutineScope } + } + + fun resetViewModelScope() { + createViewModelScope = originalScope + } +} diff --git a/mvvm-test/src/iosMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt b/mvvm-test/src/iosMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt index 2fa3826e..a4b233de 100644 --- a/mvvm-test/src/iosMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt +++ b/mvvm-test/src/iosMain/kotlin/dev/icerock/moko/mvvm/test/TestEventsDispatcher.kt @@ -9,3 +9,7 @@ import dev.icerock.moko.mvvm.dispatcher.EventsDispatcher actual fun createTestEventsDispatcher(): EventsDispatcher { return EventsDispatcher() } + +actual fun createTestEventsDispatcher(listener: T): EventsDispatcher { + return EventsDispatcher(listener = listener) +} diff --git a/mvvm-viewbinding/api/mvvm-viewbinding.api b/mvvm-viewbinding/api/mvvm-viewbinding.api new file mode 100644 index 00000000..360fb027 --- /dev/null +++ b/mvvm-viewbinding/api/mvvm-viewbinding.api @@ -0,0 +1,46 @@ +public final class dev/icerock/moko/mvvm/viewbinding/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + +public abstract class dev/icerock/moko/mvvm/viewbinding/MvvmActivity : androidx/appcompat/app/AppCompatActivity { + protected field binding Landroidx/viewbinding/ViewBinding; + protected field viewModel Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + public fun ()V + protected final fun getBinding ()Landroidx/viewbinding/ViewBinding; + protected final fun getViewModel ()Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + protected abstract fun getViewModelClass ()Ljava/lang/Class; + protected fun onCreate (Landroid/os/Bundle;)V + protected final fun setBinding (Landroidx/viewbinding/ViewBinding;)V + protected final fun setViewModel (Ldev/icerock/moko/mvvm/viewmodel/ViewModel;)V + protected abstract fun viewBindingInflate ()Landroidx/viewbinding/ViewBinding; + protected abstract fun viewModelFactory ()Landroidx/lifecycle/ViewModelProvider$Factory; +} + +public abstract class dev/icerock/moko/mvvm/viewbinding/MvvmEventsActivity : dev/icerock/moko/mvvm/viewbinding/MvvmActivity { + public fun ()V + protected fun onCreate (Landroid/os/Bundle;)V +} + +public abstract class dev/icerock/moko/mvvm/viewbinding/MvvmEventsFragment : dev/icerock/moko/mvvm/viewbinding/MvvmFragment { + public fun ()V + public fun onCreate (Landroid/os/Bundle;)V +} + +public abstract class dev/icerock/moko/mvvm/viewbinding/MvvmFragment : androidx/fragment/app/Fragment { + protected field viewModel Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + public fun ()V + protected final fun getBinding ()Landroidx/viewbinding/ViewBinding; + protected final fun getViewModel ()Ldev/icerock/moko/mvvm/viewmodel/ViewModel; + protected abstract fun getViewModelClass ()Ljava/lang/Class; + public fun onCreate (Landroid/os/Bundle;)V + public fun onCreateView (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Landroid/os/Bundle;)Landroid/view/View; + public fun onDestroyView ()V + protected final fun setViewModel (Ldev/icerock/moko/mvvm/viewmodel/ViewModel;)V + protected abstract fun viewBindingInflate (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;)Landroidx/viewbinding/ViewBinding; + protected abstract fun viewModelFactory ()Landroidx/lifecycle/ViewModelProvider$Factory; + protected fun viewModelStoreOwner ()Landroidx/lifecycle/ViewModelStoreOwner; +} + diff --git a/mvvm/api/mvvm.api b/mvvm/api/mvvm.api new file mode 100644 index 00000000..cefac523 --- /dev/null +++ b/mvvm/api/mvvm.api @@ -0,0 +1,7 @@ +public final class dev/icerock/moko/mvvm/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public fun ()V +} + diff --git a/sample/ios-app/Podfile b/sample/ios-app/Podfile index fb9a9c3a..5ea8b250 100644 --- a/sample/ios-app/Podfile +++ b/sample/ios-app/Podfile @@ -10,6 +10,12 @@ platform :ios, '11.0' # need for correct invalidate of cache MultiPlatformLibrary.framework install! 'cocoapods', :disable_input_output_paths => true +pre_install do |installer| + puts "prebuild mpp-library..." + `cd .. && ./gradlew :sample:mpp-library:syncMultiPlatformLibraryDebugFrameworkIosX64` + puts "prebuild completed" +end + target 'TestProj' do # MultiPlatformLibrary pod 'MultiPlatformLibrary', :path => '../mpp-library' diff --git a/sample/ios-app/Podfile.lock b/sample/ios-app/Podfile.lock index 971e0605..ab9dedd7 100644 --- a/sample/ios-app/Podfile.lock +++ b/sample/ios-app/Podfile.lock @@ -3,17 +3,17 @@ PODS: - AlamofireImage (4.1.0): - Alamofire (~> 5.1) - MultiPlatformLibrary (0.1.0) - - MultiPlatformLibraryMvvm (0.8.1): + - MultiPlatformLibraryMvvm (0.9.1): - MultiPlatformLibrary - - MultiPlatformLibraryMvvm/AlamofireImage (= 0.8.1) - - MultiPlatformLibraryMvvm/Core (= 0.8.1) - - MultiPlatformLibraryMvvm/SkyFloatingLabelTextField (= 0.8.1) - - MultiPlatformLibraryMvvm/AlamofireImage (0.8.1): + - MultiPlatformLibraryMvvm/AlamofireImage (= 0.9.1) + - MultiPlatformLibraryMvvm/Core (= 0.9.1) + - MultiPlatformLibraryMvvm/SkyFloatingLabelTextField (= 0.9.1) + - MultiPlatformLibraryMvvm/AlamofireImage (0.9.1): - AlamofireImage (~> 4.1.0) - MultiPlatformLibrary - - MultiPlatformLibraryMvvm/Core (0.8.1): + - MultiPlatformLibraryMvvm/Core (0.9.1): - MultiPlatformLibrary - - MultiPlatformLibraryMvvm/SkyFloatingLabelTextField (0.8.1): + - MultiPlatformLibraryMvvm/SkyFloatingLabelTextField (0.9.1): - MultiPlatformLibrary - SkyFloatingLabelTextField (~> 3.8.0) - SkyFloatingLabelTextField (3.8.0) @@ -38,9 +38,9 @@ SPEC CHECKSUMS: Alamofire: 3b6a534a3df22db367e4dedeeca73d1ddfcf0e2f AlamofireImage: c4a2ba349885fb3064feb74d2e547bd42ce9be10 MultiPlatformLibrary: 176fb8ade516666cd47e93de1b71ba0441a541bb - MultiPlatformLibraryMvvm: 0a77485160fa428e6a9fec3f1fcfce653d017cfe + MultiPlatformLibraryMvvm: b5eb90eeae57e9f8d63dce913e7dfb7f84271aee SkyFloatingLabelTextField: 5a338412114808e961fe2d14ea2c5452c8b6e4aa -PODFILE CHECKSUM: 8f0d11a22b8a433f8c575123e905e01cd4b049b8 +PODFILE CHECKSUM: 75dc53cf3febda3def87d3458f29d3390ea7c08d COCOAPODS: 1.10.0 diff --git a/sample/ios-app/TestProj.xcodeproj/xcshareddata/xcschemes/TestProj.xcscheme b/sample/ios-app/TestProj.xcodeproj/xcshareddata/xcschemes/TestProj.xcscheme new file mode 100644 index 00000000..b7f11f23 --- /dev/null +++ b/sample/ios-app/TestProj.xcodeproj/xcshareddata/xcschemes/TestProj.xcscheme @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sample/ios-app/src/AppDelegate.swift b/sample/ios-app/src/AppDelegate.swift index 3274ae7b..530af297 100755 --- a/sample/ios-app/src/AppDelegate.swift +++ b/sample/ios-app/src/AppDelegate.swift @@ -14,4 +14,9 @@ class AppDelegate: NSObject, UIApplicationDelegate { return true } + + func applicationDidReceiveMemoryWarning(_ application: UIApplication) { + GarbageCollectorKt.collect() + GarbageCollectorKt.cycles() + } } diff --git a/sample/mpp-library/build.gradle.kts b/sample/mpp-library/build.gradle.kts index 8a20b685..dedf8a3b 100644 --- a/sample/mpp-library/build.gradle.kts +++ b/sample/mpp-library/build.gradle.kts @@ -14,6 +14,9 @@ dependencies { androidMainApi(Deps.Libs.MultiPlatform.mokoMvvmLiveDataGlide) androidMainApi(Deps.Libs.MultiPlatform.mokoMvvmLiveDataMaterial) androidMainApi(Deps.Libs.MultiPlatform.mokoMvvmLiveDataSwipeRefresh) + + commonTestImplementation(Deps.Libs.MultiPlatform.mokoTest) + commonTestImplementation(Deps.Libs.MultiPlatform.mokoMvvmTest) } framework { diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample5/ValidationAllViewModel.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample5/ValidationAllViewModel.kt index b6ce3795..1876441b 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample5/ValidationAllViewModel.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample5/ValidationAllViewModel.kt @@ -16,5 +16,6 @@ class ValidationAllViewModel : ViewModel() { private val isEmailValid: LiveData = email.map { it.isNotEmpty() } private val isPasswordValid: LiveData = password.map { it.isNotEmpty() } - val isLoginButtonEnabled: LiveData = listOf(isEmailValid, isPasswordValid).all(true) + val isLoginButtonEnabled: LiveData = + listOf(isEmailValid, isPasswordValid).all(value = true) } diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample6/LoginViewModel.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample6/LoginViewModel.kt index 42f85bed..92dcae5a 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample6/LoginViewModel.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample6/LoginViewModel.kt @@ -8,7 +8,8 @@ import dev.icerock.moko.mvvm.dispatcher.EventsDispatcher import dev.icerock.moko.mvvm.dispatcher.EventsDispatcherOwner import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData -import dev.icerock.moko.mvvm.livedata.not +import dev.icerock.moko.mvvm.livedata.all +import dev.icerock.moko.mvvm.livedata.map import dev.icerock.moko.mvvm.livedata.readOnly import dev.icerock.moko.mvvm.livedata.revert import dev.icerock.moko.mvvm.viewmodel.ViewModel @@ -28,7 +29,11 @@ class LoginViewModel( private val _isLoading: MutableLiveData = MutableLiveData(false) val isLoading: LiveData = _isLoading.readOnly() - val isLoginButtonVisible: LiveData = isLoading.revert() + val isLoginButtonVisible: LiveData = listOf( + isLoading.revert(), + email.map { it.isNotBlank() }, + password.map { it.isNotBlank() } + ).all(true) init { eventsDispatcher.dispatchEvent { showError("inited".desc()) } @@ -51,7 +56,7 @@ class LoginViewModel( userRepository.login(email = emailValue, password = passwordValue) eventsDispatcher.dispatchEvent { routeToMainScreen() } - } catch (error: Throwable) { + } catch (error: Exception) { val message = error.message ?: error.toString() val errorDesc = message.desc() diff --git a/sample/mpp-library/src/commonTest/kotlin/dev/icerock/moko/mvvm/LoginViewModelTests.kt b/sample/mpp-library/src/commonTest/kotlin/dev/icerock/moko/mvvm/LoginViewModelTests.kt new file mode 100644 index 00000000..e145e111 --- /dev/null +++ b/sample/mpp-library/src/commonTest/kotlin/dev/icerock/moko/mvvm/LoginViewModelTests.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.mvvm + +import com.icerockdev.library.sample6.LoginViewModel +import com.icerockdev.library.sample6.UserRepository +import dev.icerock.moko.test.AndroidArchitectureInstantTaskExecutorRule +import dev.icerock.moko.test.TestRule +import dev.icerock.moko.mvvm.test.TestObserver +import dev.icerock.moko.mvvm.test.TestViewModelScope +import dev.icerock.moko.mvvm.test.createTestEventsDispatcher +import dev.icerock.moko.resources.desc.StringDesc +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals + +class LoginViewModelTests { + @get:TestRule + val instantTaskExecutorRule = AndroidArchitectureInstantTaskExecutorRule() + + @BeforeTest + fun setup() { + TestViewModelScope.setupViewModelScope(CoroutineScope(Dispatchers.Unconfined)) + } + + @AfterTest + fun reset() { + TestViewModelScope.resetViewModelScope() + } + + @Test + fun `login successful`() { + val events = mutableListOf() + val listener = object : LoginViewModel.EventsListener { + override fun routeToMainScreen() { + events.add("routeToMainScreen") + } + + override fun showError(error: StringDesc) { + events.add("showError($error)") + } + } + val viewModel = LoginViewModel( + eventsDispatcher = createTestEventsDispatcher(listener), + userRepository = object : UserRepository { + override suspend fun login(email: String, password: String) { + assertEquals(expected = "am@icerock.dev", actual = email) + assertEquals(expected = "666666", actual = password) + events.add("login") + } + } + ) + val loginButtonVisibleObserver = TestObserver() + viewModel.isLoginButtonVisible.addObserver(loginButtonVisibleObserver) + + assertEquals(expected = false, actual = viewModel.isLoginButtonVisible.value) + + viewModel.email.value = "am@icerock.dev" + viewModel.password.value = "666666" + + assertEquals(expected = true, actual = viewModel.isLoginButtonVisible.value) + + assertEquals(expected = 1, actual = events.size) + viewModel.onLoginButtonPressed() + assertEquals( + expected = listOf( + "showError(RawStringDesc(string=inited))", + "login", + "routeToMainScreen" + ), + actual = events + ) + } +} diff --git a/sample/mpp-library/src/iosMain/kotlin/GarbageCollector.kt b/sample/mpp-library/src/iosMain/kotlin/GarbageCollector.kt new file mode 100644 index 00000000..b0793132 --- /dev/null +++ b/sample/mpp-library/src/iosMain/kotlin/GarbageCollector.kt @@ -0,0 +1,11 @@ +import kotlin.native.internal.GC + +fun collect() { + GC.collect() +} + +fun cycles() { + val cycles = GC.detectCycles() + println("cycles count: ${cycles?.size}") + cycles?.forEachIndexed { index, item -> println("cycle $index : $item") } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index ec271751..94b78b72 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,6 +11,7 @@ pluginManagement { } } +include(":mvvm-internal") include(":mvvm-core") include(":mvvm-livedata") include(":mvvm-livedata-material")