From 83d5d3faf4e15087495d7892b0642c0b5aa3cc73 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 29 Jan 2023 12:28:22 +0600 Subject: [PATCH] improve flow as state functionality --- .../common/compose/MutableStateAsState.kt | 6 +++ .../coroutines/compose/FlowAsListState.kt | 24 ++++++++++-- .../coroutines/compose/FlowAsState.kt | 38 +++++++++++++++---- .../coroutines/compose/FlowToMutableState.kt | 10 ++--- 4 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/MutableStateAsState.kt diff --git a/common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/MutableStateAsState.kt b/common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/MutableStateAsState.kt new file mode 100644 index 00000000000..b551a9e6b74 --- /dev/null +++ b/common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/MutableStateAsState.kt @@ -0,0 +1,6 @@ +package dev.inmo.micro_utils.common.compose + +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.derivedStateOf + +fun MutableState.asState() = derivedStateOf { this.value } diff --git a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsListState.kt b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsListState.kt index 3ce3e860eac..bed242faa49 100644 --- a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsListState.kt +++ b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsListState.kt @@ -3,24 +3,40 @@ package dev.inmo.micro_utils.coroutines.compose import androidx.compose.runtime.* import androidx.compose.runtime.snapshots.SnapshotStateList import dev.inmo.micro_utils.common.applyDiff +import dev.inmo.micro_utils.coroutines.ExceptionHandler +import dev.inmo.micro_utils.coroutines.defaultSafelyWithoutExceptionHandlerWithNull import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.withContext +import kotlin.coroutines.CoroutineContext @Suppress("NOTHING_TO_INLINE") inline fun Flow>.asMutableComposeListState( - scope: CoroutineScope + scope: CoroutineScope, + useContextOnChange: CoroutineContext? = Dispatchers.Main, + noinline onException: ExceptionHandler?> = defaultSafelyWithoutExceptionHandlerWithNull, ): SnapshotStateList { val state = mutableStateListOf() - subscribeSafelyWithoutExceptions(scope) { + val changeBlock: suspend (List) -> Unit = useContextOnChange ?.let { + { + withContext(useContextOnChange) { + state.applyDiff(it) + } + } + } ?: { state.applyDiff(it) } + subscribeSafelyWithoutExceptions(scope, onException, changeBlock) return state } @Suppress("NOTHING_TO_INLINE") inline fun Flow>.asComposeList( - scope: CoroutineScope -): List = asMutableComposeListState(scope) + scope: CoroutineScope, + useContextOnChange: CoroutineContext? = Dispatchers.Main, + noinline onException: ExceptionHandler?> = defaultSafelyWithoutExceptionHandlerWithNull, +): List = asMutableComposeListState(scope, useContextOnChange, onException) diff --git a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsState.kt b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsState.kt index b6d6fb12833..9bbee0e172c 100644 --- a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsState.kt +++ b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowAsState.kt @@ -1,36 +1,58 @@ package dev.inmo.micro_utils.coroutines.compose import androidx.compose.runtime.* +import dev.inmo.micro_utils.coroutines.ExceptionHandler +import dev.inmo.micro_utils.coroutines.defaultSafelyWithoutExceptionHandlerWithNull import dev.inmo.micro_utils.coroutines.doInUI import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.withContext +import kotlin.coroutines.CoroutineContext fun Flow.asMutableComposeState( initial: T, - scope: CoroutineScope + scope: CoroutineScope, + useContextOnChange: CoroutineContext? = Dispatchers.Main, + onException: ExceptionHandler = defaultSafelyWithoutExceptionHandlerWithNull, ): MutableState { val state = mutableStateOf(initial) - subscribeSafelyWithoutExceptions(scope) { doInUI { state.value = it } } + val changeBlock: suspend (T) -> Unit = useContextOnChange ?.let { + { + withContext(useContextOnChange) { + state.value = it + } + } + } ?: { + state.value = it + } + subscribeSafelyWithoutExceptions(scope, onException, block = changeBlock) return state } @Suppress("NOTHING_TO_INLINE") inline fun StateFlow.asMutableComposeState( - scope: CoroutineScope -): MutableState = asMutableComposeState(value, scope) + scope: CoroutineScope, + useContextOnChange: CoroutineContext? = Dispatchers.Main, + noinline onException: ExceptionHandler = defaultSafelyWithoutExceptionHandlerWithNull, +): MutableState = asMutableComposeState(value, scope, useContextOnChange, onException) fun Flow.asComposeState( initial: T, - scope: CoroutineScope + scope: CoroutineScope, + useContextOnChange: CoroutineContext? = Dispatchers.Main, + onException: ExceptionHandler = defaultSafelyWithoutExceptionHandlerWithNull, ): State { - val state = asMutableComposeState(initial, scope) + val state = asMutableComposeState(initial, scope, useContextOnChange, onException) return derivedStateOf { state.value } } @Suppress("NOTHING_TO_INLINE") inline fun StateFlow.asComposeState( - scope: CoroutineScope -): State = asComposeState(value, scope) + scope: CoroutineScope, + useContextOnChange: CoroutineContext? = Dispatchers.Main, + noinline onException: ExceptionHandler = defaultSafelyWithoutExceptionHandlerWithNull, +): State = asComposeState(value, scope, useContextOnChange, onException) diff --git a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToMutableState.kt b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToMutableState.kt index 7c6d856b22d..92fba8f2176 100644 --- a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToMutableState.kt +++ b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToMutableState.kt @@ -7,17 +7,15 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow +@Deprecated("Duplicated functionality", ReplaceWith("asMutableComposeState(initial, scope)", "dev.inmo.micro_utils.coroutines.compose.asMutableComposeState")) fun Flow.toMutableState( initial: T, scope: CoroutineScope -): MutableState { - val state = mutableStateOf(initial) - subscribeSafelyWithoutExceptions(scope) { state.value = it } - return state -} +): MutableState = asMutableComposeState(initial, scope) +@Deprecated("Duplicated functionality", ReplaceWith("asMutableComposeState(scope)", "dev.inmo.micro_utils.coroutines.compose.asMutableComposeState")) @Suppress("NOTHING_TO_INLINE") inline fun StateFlow.toMutableState( scope: CoroutineScope -): MutableState = toMutableState(value, scope) +): MutableState = asMutableComposeState(scope)