From 8cce81ea619aa1d484a24e5d7427b8a1706fec2e Mon Sep 17 00:00:00 2001 From: ikarenkov Date: Fri, 16 Feb 2024 10:43:05 +0300 Subject: [PATCH] replaced Cancelable with AutoCloseable --- .../ikarenkov/kombucha/compose/ComposeKombucha.kt | 11 +++++------ .../io/github/ikarenkov/kombucha/Cancelable.kt | 7 ------- .../kotlin/io/github/ikarenkov/kombucha/Utils.kt | 12 ------------ .../ikarenkov/kombucha/aggregator/AggregatorStore.kt | 2 +- .../kombucha/aggregator/TwoStoreAggregatorStore.kt | 8 ++++---- .../ikarenkov/kombucha/store/CoroutinesStore.kt | 4 ++-- .../io/github/ikarenkov/kombucha/store/Store.kt | 4 ++-- ...ncellationTest.kt => CoroutinesStoreCloseTest.kt} | 6 +++--- .../kombucha/instancekeeper/InstanceKeeperExt.kt | 2 +- .../io/github/ikarenkov/kombucha/ui/UiStore.kt | 10 +++++----- .../github/ikarenkov/kombucha/ui/UiStoreBuilder.kt | 8 ++++---- .../io/github/ikarenkov/kombucha/ui/UiStoreTest.kt | 12 ++++++------ .../sample/modo_kombucha/ModoKombuchaScreenModel.kt | 2 +- .../kombucha/sample/counter/impl/CounterScreen.kt | 2 +- .../sample/shikimori/impl/ShikimoriAnimesScreen.kt | 2 +- .../shikimori/impl/animes/AnimesAggregatorStore.kt | 8 ++++---- 16 files changed, 40 insertions(+), 60 deletions(-) delete mode 100644 kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Cancelable.kt delete mode 100644 kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Utils.kt rename kombucha/core/src/commonTest/kotlin/io/github/ikarenkov/kombucha/store/{CoroutinesStoreCancellationTest.kt => CoroutinesStoreCloseTest.kt} (89%) diff --git a/kombucha/compose/src/main/kotlin/io/github/ikarenkov/kombucha/compose/ComposeKombucha.kt b/kombucha/compose/src/main/kotlin/io/github/ikarenkov/kombucha/compose/ComposeKombucha.kt index 380b00c..6eaff29 100644 --- a/kombucha/compose/src/main/kotlin/io/github/ikarenkov/kombucha/compose/ComposeKombucha.kt +++ b/kombucha/compose/src/main/kotlin/io/github/ikarenkov/kombucha/compose/ComposeKombucha.kt @@ -4,9 +4,8 @@ import androidx.lifecycle.ViewModelStoreOwner import com.arkivanov.essenty.instancekeeper.InstanceKeeper import com.arkivanov.essenty.instancekeeper.getOrCreate import com.arkivanov.essenty.instancekeeper.instanceKeeper -import kotlinx.coroutines.flow.StateFlow -import io.github.ikarenkov.kombucha.Cancelable import io.github.ikarenkov.kombucha.store.Store +import kotlinx.coroutines.flow.StateFlow /** * This interface provides Ui related part of TEA for compose. @@ -14,7 +13,7 @@ import io.github.ikarenkov.kombucha.store.Store * @param Model - model of screen that can be observed * @param UiEff - single event effects that can be consumed by compose screen (WIP) */ -interface ComposeKombucha : Cancelable { +interface ComposeKombucha : AutoCloseable { fun accept(msg: UiMsg) @@ -32,8 +31,8 @@ open class ComposeKombuchaImpl( composeKombucha: ComposeKombucha ) : ComposeKombucha by composeKombucha, InstanceKeeper.Instance { override fun onDestroy() { - cancel() + close() } } diff --git a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Cancelable.kt b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Cancelable.kt deleted file mode 100644 index 3328cf7..0000000 --- a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Cancelable.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.ikarenkov.kombucha - -fun interface Cancelable { - - fun cancel() - -} diff --git a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Utils.kt b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Utils.kt deleted file mode 100644 index 97a44d1..0000000 --- a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/Utils.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.ikarenkov.kombucha - -internal fun List<(T) -> Unit>.notifyAll(msg: T) = forEach { listener -> listener.invoke(msg) } - -internal fun MutableList<(T) -> Unit>.addListenerAndMakeCancelable(listener: (T) -> Unit): Cancelable { - add(listener) - return object : Cancelable { - override fun cancel() { - remove(listener) - } - } -} diff --git a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/AggregatorStore.kt b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/AggregatorStore.kt index 42f6646..8e0755d 100644 --- a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/AggregatorStore.kt +++ b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/AggregatorStore.kt @@ -19,7 +19,7 @@ abstract class AggregatorStore( coroutineExceptionHandler: CoroutineExceptionHandler = DefaultStoreCoroutineExceptionHandler() ) : this(StoreScope(name, coroutineExceptionHandler)) - override fun cancel() { + override fun close() { coroutineScope.cancel() } diff --git a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/TwoStoreAggregatorStore.kt b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/TwoStoreAggregatorStore.kt index 305bf40..9eb2a53 100644 --- a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/TwoStoreAggregatorStore.kt +++ b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/aggregator/TwoStoreAggregatorStore.kt @@ -41,10 +41,10 @@ class TwoStoreAggregatorStore< } } - override fun cancel() { - super.cancel() - store1.cancel() - store2.cancel() + override fun close() { + super.close() + store1.close() + store2.close() } } diff --git a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStore.kt b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStore.kt index 712a04f..61aa42a 100644 --- a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStore.kt +++ b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStore.kt @@ -60,7 +60,7 @@ open class CoroutinesStore( override fun accept(msg: Msg) { if (!isActive) { - error("Trying to call accept in canceled store with name \"$name\".") + error("Trying to call accept in closed store with name \"$name\".") } coroutinesScope.launch { val storeUpdate = stateUpdateMutex.withLock { @@ -90,7 +90,7 @@ open class CoroutinesStore( } } - override fun cancel() { + override fun close() { coroutinesScope.cancel() } diff --git a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/Store.kt b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/Store.kt index 2aa17c2..29bcd68 100644 --- a/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/Store.kt +++ b/kombucha/core/src/commonMain/kotlin/io/github/ikarenkov/kombucha/store/Store.kt @@ -1,6 +1,5 @@ package io.github.ikarenkov.kombucha.store -import io.github.ikarenkov.kombucha.Cancelable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow @@ -8,7 +7,8 @@ import kotlinx.coroutines.flow.StateFlow * The base component of library that hold state and converst incoming [Msg] to a new [State] and [Eff]. * Take a look and the main implementation: [CoroutinesStore] */ -interface Store : Cancelable { +@OptIn(ExperimentalStdlibApi::class) +interface Store : AutoCloseable { /** * Represent current state of this store. Can be modified only through [accept]. diff --git a/kombucha/core/src/commonTest/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStoreCancellationTest.kt b/kombucha/core/src/commonTest/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStoreCloseTest.kt similarity index 89% rename from kombucha/core/src/commonTest/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStoreCancellationTest.kt rename to kombucha/core/src/commonTest/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStoreCloseTest.kt index 2fb1d59..9977660 100644 --- a/kombucha/core/src/commonTest/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStoreCancellationTest.kt +++ b/kombucha/core/src/commonTest/kotlin/io/github/ikarenkov/kombucha/store/CoroutinesStoreCloseTest.kt @@ -5,14 +5,14 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFails -class CoroutinesStoreCancellationTest { +class CoroutinesStoreCloseTest { @Test @JsName("test1") fun `When accept on canceled store - Then crush`() { val store = NoOpTestStore() store.accept(Any()) - store.cancel() + store.close() assertFails { store.accept(Any()) } @@ -22,7 +22,7 @@ class CoroutinesStoreCancellationTest { @JsName("test2") fun `When canceled - Then isActive false`() { val store = NoOpTestStore() - store.cancel() + store.close() assertEquals(false, store.isActive) } diff --git a/kombucha/instanceKeeper/src/main/kotlin/io/github/ikarenkov/kombucha/instancekeeper/InstanceKeeperExt.kt b/kombucha/instanceKeeper/src/main/kotlin/io/github/ikarenkov/kombucha/instancekeeper/InstanceKeeperExt.kt index 4682331..65c8573 100644 --- a/kombucha/instanceKeeper/src/main/kotlin/io/github/ikarenkov/kombucha/instancekeeper/InstanceKeeperExt.kt +++ b/kombucha/instanceKeeper/src/main/kotlin/io/github/ikarenkov/kombucha/instancekeeper/InstanceKeeperExt.kt @@ -23,7 +23,7 @@ private class StoreInstance>( ) : InstanceKeeper.Instance { override fun onDestroy() { - store.cancel() + store.close() } } diff --git a/kombucha/ui-adapter/src/commonMain/kotlin/io/github/ikarenkov/kombucha/ui/UiStore.kt b/kombucha/ui-adapter/src/commonMain/kotlin/io/github/ikarenkov/kombucha/ui/UiStore.kt index b5f2a6e..341fe4c 100644 --- a/kombucha/ui-adapter/src/commonMain/kotlin/io/github/ikarenkov/kombucha/ui/UiStore.kt +++ b/kombucha/ui-adapter/src/commonMain/kotlin/io/github/ikarenkov/kombucha/ui/UiStore.kt @@ -20,14 +20,14 @@ import kotlinx.coroutines.isActive * Wrapper for store, that allows handle basic UI scenarios: * 1. Convert models to Ui Models * 2. Cache ui effects when there is no subscribers and emit cached effects with a first subscription - * @param cancelOriginalStoreOnCancel shows if we need to call [Store.cancel] on the [store] when this store is canceling. + * @param propagateCloseToOriginal shows if we need to call [Store.close] on the [store] when this store is closed. */ class UiStore( private val store: Store, private val uiMsgToMsgConverter: (UiMsg) -> Msg, private val uiStateConverter: (State) -> UiState, private val uiEffConverter: (Eff) -> UiEff?, - private val cancelOriginalStoreOnCancel: Boolean = true, + private val propagateCloseToOriginal: Boolean = true, coroutineExceptionHandler: CoroutineExceptionHandler = DefaultStoreCoroutineExceptionHandler(), uiDispatcher: CoroutineDispatcher = Dispatchers.Main, cacheUiEffects: Boolean = true, @@ -64,10 +64,10 @@ class UiStore( uiStateConverter: (State) -> UiState, uiEffConverter: (Eff) -> UiEff?, cacheUiEffects: Boolean = true, - cancelOriginalStoreOnCancel: Boolean = true, + propagateCloseToOriginal: Boolean = true, uiDispatcher: CoroutineDispatcher = Dispatchers.Main, ): UiStore = UiStore( store = store, uiMsgToMsgConverter = uiMsgToMsgConverter, uiStateConverter = uiStateConverter, uiEffConverter = uiEffConverter, - cancelOriginalStoreOnCancel = cancelOriginalStoreOnCancel, + propagateCloseToOriginal = propagateCloseToOriginal, cacheUiEffects = cacheUiEffects, uiDispatcher = uiDispatcher ) @@ -34,7 +34,7 @@ class UiStoreBuilder( */ inline fun using( cacheUiEffects: Boolean = true, - cancelOriginalStoreOnCancel: Boolean = true, + propagateCloseToOriginal: Boolean = true, uiDispatcher: CoroutineDispatcher = Dispatchers.Main, noinline uiStateConverter: (State) -> UiState, ): UiStore = UiStore( @@ -43,7 +43,7 @@ class UiStoreBuilder( uiStateConverter = uiStateConverter, uiEffConverter = { it as? UiEff }, uiDispatcher = uiDispatcher, - cancelOriginalStoreOnCancel = cancelOriginalStoreOnCancel, + propagateCloseToOriginal = propagateCloseToOriginal, cacheUiEffects = cacheUiEffects ) diff --git a/kombucha/ui-adapter/src/commonTest/kotlin/io/github/ikarenkov/kombucha/ui/UiStoreTest.kt b/kombucha/ui-adapter/src/commonTest/kotlin/io/github/ikarenkov/kombucha/ui/UiStoreTest.kt index a4051cc..a14ce9f 100644 --- a/kombucha/ui-adapter/src/commonTest/kotlin/io/github/ikarenkov/kombucha/ui/UiStoreTest.kt +++ b/kombucha/ui-adapter/src/commonTest/kotlin/io/github/ikarenkov/kombucha/ui/UiStoreTest.kt @@ -12,30 +12,30 @@ class UiStoreTest { @Test @JsName("test1") - fun `When cancel original is false - original is not canceled`() { + fun `When close original is false - original is not closed`() { val store = DummyStore() val uiStore = store.uiBuilder() .using( - cancelOriginalStoreOnCancel = false, + propagateCloseToOriginal = false, uiDispatcher = StandardTestDispatcher() ) { it } - uiStore.cancel() + uiStore.close() assertTrue(store.isActive) } @Test @JsName("test2") - fun `When cancel original is true - original is canceled`() { + fun `When close original is true - original is closed`() { val store = DummyStore() val uiStore = store.uiBuilder() .using( - cancelOriginalStoreOnCancel = true, + propagateCloseToOriginal = true, uiDispatcher = StandardTestDispatcher() ) { it } - uiStore.cancel() + uiStore.close() assertFalse(store.isActive) } diff --git a/sample/core/modo-kombucha/src/main/kotlin/io/github/ikarenkov/kombucha/sample/modo_kombucha/ModoKombuchaScreenModel.kt b/sample/core/modo-kombucha/src/main/kotlin/io/github/ikarenkov/kombucha/sample/modo_kombucha/ModoKombuchaScreenModel.kt index cc8a5fd..2b00a62 100644 --- a/sample/core/modo-kombucha/src/main/kotlin/io/github/ikarenkov/kombucha/sample/modo_kombucha/ModoKombuchaScreenModel.kt +++ b/sample/core/modo-kombucha/src/main/kotlin/io/github/ikarenkov/kombucha/sample/modo_kombucha/ModoKombuchaScreenModel.kt @@ -8,7 +8,7 @@ class ModoKombuchaScreenModel( ) : ScreenModel { override fun onDispose() { - store.cancel() + store.close() } } \ No newline at end of file diff --git a/sample/features/counter/impl/src/main/kotlin/io/github/ikarenkov/kombucha/sample/counter/impl/CounterScreen.kt b/sample/features/counter/impl/src/main/kotlin/io/github/ikarenkov/kombucha/sample/counter/impl/CounterScreen.kt index 6f1944b..9b4e120 100644 --- a/sample/features/counter/impl/src/main/kotlin/io/github/ikarenkov/kombucha/sample/counter/impl/CounterScreen.kt +++ b/sample/features/counter/impl/src/main/kotlin/io/github/ikarenkov/kombucha/sample/counter/impl/CounterScreen.kt @@ -57,7 +57,7 @@ internal class CounterScreenModel( val state = store.state override fun onDispose() { - store.cancel() + store.close() } } diff --git a/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/ShikimoriAnimesScreen.kt b/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/ShikimoriAnimesScreen.kt index 383594a..4dac240 100644 --- a/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/ShikimoriAnimesScreen.kt +++ b/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/ShikimoriAnimesScreen.kt @@ -69,7 +69,7 @@ internal class AnimesScreenModel( val store = animesStoreAgregatorFactory.createStore() override fun onDispose() { - store.cancel() + store.close() } } diff --git a/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/animes/AnimesAggregatorStore.kt b/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/animes/AnimesAggregatorStore.kt index 032c8e5..9c38dbf 100644 --- a/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/animes/AnimesAggregatorStore.kt +++ b/sample/features/shikimori/src/main/kotlin/io/github/ikarenkov/sample/shikimori/impl/animes/AnimesAggregatorStore.kt @@ -60,10 +60,10 @@ internal class AnimesAggregatorStore( } } - override fun cancel() { - super.cancel() - paginationStore.cancel() - animesStore.cancel() + override fun close() { + super.close() + paginationStore.close() + animesStore.close() } data class State(