diff --git a/mvikotlin-extensions-coroutines/api/android/mvikotlin-extensions-coroutines.api b/mvikotlin-extensions-coroutines/api/android/mvikotlin-extensions-coroutines.api index b31873ab..0ccd97e1 100644 --- a/mvikotlin-extensions-coroutines/api/android/mvikotlin-extensions-coroutines.api +++ b/mvikotlin-extensions-coroutines/api/android/mvikotlin-extensions-coroutines.api @@ -66,8 +66,11 @@ public final class com/arkivanov/mvikotlin/extensions/coroutines/StoreExtKt { public static final fun getLabels (Lcom/arkivanov/mvikotlin/core/store/Store;)Lkotlinx/coroutines/flow/Flow; public static final fun getStateFlow (Lcom/arkivanov/mvikotlin/core/store/Store;)Lkotlinx/coroutines/flow/StateFlow; public static final fun getStates (Lcom/arkivanov/mvikotlin/core/store/Store;)Lkotlinx/coroutines/flow/Flow; + public static final fun labelsChannel (Lcom/arkivanov/mvikotlin/core/store/Store;Lcom/arkivanov/essenty/lifecycle/Lifecycle;I)Lkotlinx/coroutines/channels/ReceiveChannel; public static final fun labelsChannel (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;I)Lkotlinx/coroutines/channels/ReceiveChannel; + public static synthetic fun labelsChannel$default (Lcom/arkivanov/mvikotlin/core/store/Store;Lcom/arkivanov/essenty/lifecycle/Lifecycle;IILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel; public static synthetic fun labelsChannel$default (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;IILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel; + public static final fun stateFlow (Lcom/arkivanov/mvikotlin/core/store/Store;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lkotlinx/coroutines/flow/StateFlow; public static final fun stateFlow (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/SharingStarted;)Lkotlinx/coroutines/flow/StateFlow; public static synthetic fun stateFlow$default (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/SharingStarted;ILjava/lang/Object;)Lkotlinx/coroutines/flow/StateFlow; } diff --git a/mvikotlin-extensions-coroutines/api/jvm/mvikotlin-extensions-coroutines.api b/mvikotlin-extensions-coroutines/api/jvm/mvikotlin-extensions-coroutines.api index b31873ab..0ccd97e1 100644 --- a/mvikotlin-extensions-coroutines/api/jvm/mvikotlin-extensions-coroutines.api +++ b/mvikotlin-extensions-coroutines/api/jvm/mvikotlin-extensions-coroutines.api @@ -66,8 +66,11 @@ public final class com/arkivanov/mvikotlin/extensions/coroutines/StoreExtKt { public static final fun getLabels (Lcom/arkivanov/mvikotlin/core/store/Store;)Lkotlinx/coroutines/flow/Flow; public static final fun getStateFlow (Lcom/arkivanov/mvikotlin/core/store/Store;)Lkotlinx/coroutines/flow/StateFlow; public static final fun getStates (Lcom/arkivanov/mvikotlin/core/store/Store;)Lkotlinx/coroutines/flow/Flow; + public static final fun labelsChannel (Lcom/arkivanov/mvikotlin/core/store/Store;Lcom/arkivanov/essenty/lifecycle/Lifecycle;I)Lkotlinx/coroutines/channels/ReceiveChannel; public static final fun labelsChannel (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;I)Lkotlinx/coroutines/channels/ReceiveChannel; + public static synthetic fun labelsChannel$default (Lcom/arkivanov/mvikotlin/core/store/Store;Lcom/arkivanov/essenty/lifecycle/Lifecycle;IILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel; public static synthetic fun labelsChannel$default (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;IILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel; + public static final fun stateFlow (Lcom/arkivanov/mvikotlin/core/store/Store;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lkotlinx/coroutines/flow/StateFlow; public static final fun stateFlow (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/SharingStarted;)Lkotlinx/coroutines/flow/StateFlow; public static synthetic fun stateFlow$default (Lcom/arkivanov/mvikotlin/core/store/Store;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/SharingStarted;ILjava/lang/Object;)Lkotlinx/coroutines/flow/StateFlow; } diff --git a/mvikotlin-extensions-coroutines/src/commonMain/kotlin/com/arkivanov/mvikotlin/extensions/coroutines/StoreExt.kt b/mvikotlin-extensions-coroutines/src/commonMain/kotlin/com/arkivanov/mvikotlin/extensions/coroutines/StoreExt.kt index 417e600c..69c1b240 100644 --- a/mvikotlin-extensions-coroutines/src/commonMain/kotlin/com/arkivanov/mvikotlin/extensions/coroutines/StoreExt.kt +++ b/mvikotlin-extensions-coroutines/src/commonMain/kotlin/com/arkivanov/mvikotlin/extensions/coroutines/StoreExt.kt @@ -1,8 +1,9 @@ package com.arkivanov.mvikotlin.extensions.coroutines +import com.arkivanov.essenty.lifecycle.Lifecycle +import com.arkivanov.essenty.lifecycle.doOnDestroy import com.arkivanov.mvikotlin.core.rx.observer import com.arkivanov.mvikotlin.core.store.Store -import com.arkivanov.mvikotlin.core.utils.ExperimentalMviKotlinApi import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi @@ -19,7 +20,7 @@ import kotlinx.coroutines.launch import kotlin.coroutines.CoroutineContext /** - * Returns a [Flow] that emits [Store] states. + * Creates and returns a [Flow] that emits [Store] states. * * Please note that the actual collection of the [Flow] may not be synchronous depending on [CoroutineContext] being used. */ @@ -27,7 +28,7 @@ val Store<*, State, *>.states: Flow get() = toFlow(Store<*, State, *>::states) /** - * Returns a [StateFlow] that emits [Store] states. The returned [StateFlow] is hot, + * Creates and returns a [StateFlow] that emits [Store] states. The returned [StateFlow] is hot, * started in the given coroutine [scope], sharing the most recently emitted state from * a single subscription to the [Store] with multiple downstream subscribers. * @@ -42,7 +43,25 @@ fun Store<*, State, *>.stateFlow( ): StateFlow = states.stateIn(scope, started, state) /** - * Returns a [StateFlow] that emits [Store] states. + * Creates and returns a [StateFlow] that emits [Store] states. The returned [StateFlow] is hot, + * sharing the most recently emitted state from a single subscription to the [Store] + * with multiple downstream subscribers. + * + * Please note that the actual collection of the [StateFlow] may not be synchronous + * depending on [CoroutineContext] being used. + * + * @param lifecycle a [Lifecycle] used for cancelling the underlying [MutableStateFlow]. + */ +fun Store<*, State, *>.stateFlow(lifecycle: Lifecycle): StateFlow { + val stateFlow = MutableStateFlow(state) + val disposable = states(observer(onNext = { stateFlow.value = it })) + lifecycle.doOnDestroy { disposable.dispose() } + + return stateFlow +} + +/** + * Creates and returns a [StateFlow] that emits [Store] states. * * This API is experimental because [StateFlow] interface is not stable for inheritance in 3rd party libraries. * Please mind binary compatibility when using this API. @@ -53,6 +72,7 @@ fun Store<*, State, *>.stateFlow( val Store<*, State, *>.stateFlow: StateFlow get() = StoreStateFlow(store = this) +@Suppress("UnnecessaryOptInAnnotation") @OptIn(ExperimentalForInheritanceCoroutinesApi::class) private class StoreStateFlow( private val store: Store<*, State, *>, @@ -74,7 +94,7 @@ private class StoreStateFlow( } /** - * Returns a [Flow] that emits [Store] labels. + * Creates and returns a [Flow] that emits [Store] labels. * * Please note that the actual collection of the [Flow] may not be synchronous depending on [CoroutineContext] being used. */ @@ -90,12 +110,12 @@ val