diff options
Diffstat (limited to 'flow-mvi/src/main/java/foundation')
5 files changed, 0 insertions, 285 deletions
diff --git a/flow-mvi/src/main/java/foundation/e/flowmvi/MVIView.kt b/flow-mvi/src/main/java/foundation/e/flowmvi/MVIView.kt deleted file mode 100644 index aa6f624..0000000 --- a/flow-mvi/src/main/java/foundation/e/flowmvi/MVIView.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2021 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package foundation.e.flowmvi - -import kotlinx.coroutines.flow.Flow - -interface MVIView<State, out Action> { - - fun render(state: State) - - fun actions(): Flow<Action> -} diff --git a/flow-mvi/src/main/java/foundation/e/flowmvi/Store.kt b/flow-mvi/src/main/java/foundation/e/flowmvi/Store.kt deleted file mode 100644 index 3040f3f..0000000 --- a/flow-mvi/src/main/java/foundation/e/flowmvi/Store.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2021 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package foundation.e.flowmvi - -import kotlinx.coroutines.flow.StateFlow - -interface Store<State : Any, in Action : Any> { - val state: StateFlow<State> -} diff --git a/flow-mvi/src/main/java/foundation/e/flowmvi/Types.kt b/flow-mvi/src/main/java/foundation/e/flowmvi/Types.kt deleted file mode 100644 index 1f22a35..0000000 --- a/flow-mvi/src/main/java/foundation/e/flowmvi/Types.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2021 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package foundation.e.flowmvi - -import kotlinx.coroutines.flow.Flow - -/** - * Actor is a function that receives the current state and the action which just happened - * and acts on it. - * - * It returns a [Flow] of Effects which then can be used in a reducer to reduce to a new state. - */ -typealias Actor<State, Action, Effect> = (state: State, action: Action) -> Flow<Effect> - -/** - * Reducer is a function that applies the effect to current state and return a new state. - * - * This function should be free from any side-effect and make sure it is idempotent. - */ -typealias Reducer<State, Effect> = (state: State, effect: Effect) -> State - -typealias SingleEventProducer<State, Action, Effect, SingleEvent> = (state: State, action: Action, effect: Effect) -> SingleEvent? - -/** - * Logger is function used for logging - */ -typealias Logger = (String) -> Unit diff --git a/flow-mvi/src/main/java/foundation/e/flowmvi/feature/BaseFeature.kt b/flow-mvi/src/main/java/foundation/e/flowmvi/feature/BaseFeature.kt deleted file mode 100644 index 1429d1a..0000000 --- a/flow-mvi/src/main/java/foundation/e/flowmvi/feature/BaseFeature.kt +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2021 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package foundation.e.flowmvi.feature - -import foundation.e.flowmvi.Actor -import foundation.e.flowmvi.Logger -import foundation.e.flowmvi.MVIView -import foundation.e.flowmvi.Reducer -import foundation.e.flowmvi.SingleEventProducer -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.emitAll -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.receiveAsFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock - -open class BaseFeature<State : Any, in Action : Any, in Effect : Any, SingleEvent : Any>( - initialState: State, - private val actor: Actor<State, Action, Effect>, - private val reducer: Reducer<State, Effect>, - private val coroutineScope: CoroutineScope, - private val defaultLogger: Logger = {}, - private val singleEventProducer: SingleEventProducer<State, Action, Effect, SingleEvent>? = null -) : - Feature<State, Action, SingleEvent> { - - private val mutex = Mutex() - - private val _state = MutableStateFlow(initialState) - override val state: StateFlow<State> = _state.asStateFlow() - - private val singleEventChannel = Channel<SingleEvent>() - override val singleEvents: Flow<SingleEvent> = singleEventChannel.receiveAsFlow() - - override fun takeView( - viewCoroutineScope: CoroutineScope, - view: MVIView<State, Action>, - initialActions: List<Action>, - logger: Logger? - ) { - viewCoroutineScope.launch { - sendStateUpdatesIntoView(this, view, logger ?: defaultLogger) - handleViewActions(this, view, initialActions, logger ?: defaultLogger) - } - } - - private fun sendStateUpdatesIntoView( - callerCoroutineScope: CoroutineScope, - view: MVIView<State, Action>, - @Suppress("UNUSED_PARAMETER") logger: Logger - ) { - state - .onEach { - view.render(it) - } - .launchIn(callerCoroutineScope) - } - - private fun handleViewActions( - coroutineScope: CoroutineScope, - view: MVIView<State, Action>, - initialActions: List<Action>, - logger: Logger - ) { - coroutineScope.launch { - view - .actions() - .onStart { - emitAll(initialActions.asFlow()) - } - .collectIntoHandler(this, logger) - } - } - - override fun addExternalActions(actions: Flow<Action>, logger: Logger?) { - coroutineScope.launch { - actions.collectIntoHandler(this, logger ?: defaultLogger) - } - } - - private suspend fun Flow<Action>.collectIntoHandler( - callerCoroutineScope: CoroutineScope, - @Suppress("UNUSED_PARAMETER") logger: Logger - ) { - onEach { action -> - callerCoroutineScope.launch { - actor.invoke(_state.value, action) - .onEach { effect -> - mutex.withLock { - val newState = reducer.invoke(_state.value, effect) - _state.value = newState - singleEventProducer?.also { - it.invoke(newState, action, effect)?.let { singleEvent -> - singleEventChannel.send( - singleEvent - ) - } - } - } - } - .launchIn(coroutineScope) - } - } - .launchIn(callerCoroutineScope) - } -} diff --git a/flow-mvi/src/main/java/foundation/e/flowmvi/feature/Feature.kt b/flow-mvi/src/main/java/foundation/e/flowmvi/feature/Feature.kt deleted file mode 100644 index bd9ca16..0000000 --- a/flow-mvi/src/main/java/foundation/e/flowmvi/feature/Feature.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2021 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package foundation.e.flowmvi.feature - -import foundation.e.flowmvi.Logger -import foundation.e.flowmvi.MVIView -import foundation.e.flowmvi.Store -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow - -interface Feature<State : Any, in Action : Any, SingleEvent : Any> : Store<State, Action> { - val singleEvents: Flow<SingleEvent> - - /** - * Call this method when a new [View] is ready to render the state of this MVFlow object. - * - * @param viewCoroutineScope the scope of the view. This will be used to launch a coroutine which will run listening - * to actions until this scope is cancelled. - * @param view the view that will render the state. - * @param initialActions an optional list of Actions that can be passed to introduce an initial action into the - * screen (for example, to trigger a refresh of data). - * @param logger Optional [Logger] to log events inside this MVFlow object associated with this view (but not - * others). If null, a default logger might be used. - */ - fun takeView( - viewCoroutineScope: CoroutineScope, - view: MVIView<State, Action>, - initialActions: List<Action> = emptyList(), - logger: Logger? = null - ) - - /** - * This method adds an external source of actions into the MVFlow object. - * - * This might be useful if you need to update your state based on things happening outside the [View], such as - * timers, external database updates, push notifications, etc. - * - * @param actions the flow of events. You might want to have a look at - * [kotlinx.coroutines.flow.callbackFlow]. - * @param logger Optional [Logger] to log events inside this MVFlow object associated with this external Flow (but - * not others). If null, a default logger might be used. - */ - fun addExternalActions( - actions: Flow<Action>, - logger: Logger? = null - ) -} |