diff --git a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowState.kt b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowState.kt new file mode 100644 index 00000000000..e5649e153c7 --- /dev/null +++ b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowState.kt @@ -0,0 +1,43 @@ +package dev.inmo.micro_utils.coroutines.compose + +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.State +import androidx.compose.runtime.derivedStateOf +import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow +import dev.inmo.micro_utils.coroutines.doInUI +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers + +class FlowState( + private val state: MutableState, + internalScope: CoroutineScope = CoroutineScope(Dispatchers.Main) +) : MutableState, + SpecialMutableStateFlow.Default(state.value, internalScope) { + override var value: T + get() = super.value + set(value) { + tryEmit(value) + } + + override fun component1(): T = state.component1() + + override fun component2(): (T) -> Unit = state.component2() + + private val stateState = derivedStateOf { + if (value != state.value) { + value = state.value + } + } + + override suspend fun onChange(value: T) { + super.onChange(value) + + if (state.value != value) { + doInUI { + state.value = value + } + } + } +} + +fun MutableState.asFlowState(scope: CoroutineScope = CoroutineScope(Dispatchers.Main)) = FlowState(this, scope) diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/SpecialStateFlow.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/SpecialStateFlow.kt index 7c43e0e9f99..8509aa6c8fd 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/SpecialStateFlow.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/SpecialStateFlow.kt @@ -10,27 +10,31 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow interface SpecialMutableStateFlow : StateFlow, FlowCollector, MutableSharedFlow { - class Default( + open class Default( initialValue: T, internalScope: CoroutineScope = CoroutineScope(Dispatchers.Default) ) : SpecialMutableStateFlow { - private val internalSharedFlow: MutableSharedFlow = MutableSharedFlow( + protected val internalSharedFlow: MutableSharedFlow = MutableSharedFlow( replay = 0, extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST ) - private val publicSharedFlow: MutableSharedFlow = MutableSharedFlow( + protected val publicSharedFlow: MutableSharedFlow = MutableSharedFlow( replay = 1, extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST ) - override var value: T = initialValue - private set - private val job = internalSharedFlow.subscribe(internalScope) { - if (value != it) { - value = it - publicSharedFlow.emit(it) + protected var _value: T = initialValue + override val value: T + get() = _value + protected open suspend fun onChange(value: T) { + _value = value + publicSharedFlow.emit(value) + } + protected val job = internalSharedFlow.subscribeSafelyWithoutExceptions(internalScope) { + if (_value != it) { + onChange(it) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9702c5454ba..7b5779f4107 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kt-coroutines = "1.7.3" kslog = "1.3.1" jb-compose = "1.5.11" -jb-exposed = "0.44.1" +jb-exposed = "0.45.0" jb-dokka = "1.9.10" korlibs = "4.0.10" @@ -21,7 +21,7 @@ koin = "3.5.0" okio = "3.6.0" -ksp = "1.9.20-1.0.14" +ksp = "1.9.21-1.0.15" kotlin-poet = "1.15.1" versions = "0.50.0"