Created
June 11, 2024 08:07
-
-
Save hoc081098/d2e982052e9be27473fad238f75860b4 to your computer and use it in GitHub Desktop.
buildStore.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FlowRedux is from | |
https://github.com/hoc081098/GithubSearchKMM-Compose-SwiftUI/tree/master/flowredux/src/commonMain/kotlin/com/hoc081098/flowredux | |
package com.hoc081098.flowredux.dsl | |
import com.hoc081098.flowredux.FlowReduxStore | |
import com.hoc081098.flowredux.SideEffect | |
import com.hoc081098.flowredux.createFlowReduxStore | |
import com.hoc081098.flowredux.liftAction | |
import kotlinx.coroutines.CoroutineScope | |
import kotlinx.coroutines.flow.Flow | |
import kotlinx.coroutines.flow.StateFlow | |
import kotlinx.coroutines.flow.filterIsInstance | |
import kotlinx.coroutines.flow.map | |
@DslMarker | |
public annotation class FlowReduxDsl | |
public fun <Action, State, Change> buildStore(block: FlowReduxStoreBuilder<Action, State, Change>.() -> Unit): FlowReduxStore<Action, State> { | |
val builder = FlowReduxStoreBuilder<Action, State, Change>() | |
block(builder) | |
return builder.build() | |
} | |
private object UnInitialized | |
public typealias DslReducer<State, Change> = State.(change: Change) -> State | |
public typealias DslSideEffect<Action, Change> = (actionFlow: Flow<Action>) -> Flow<Change> | |
public typealias DslSideEffectWithReceiver<Action, Change> = Flow<Action>.() -> Flow<Change> | |
@FlowReduxDsl | |
public class FlowReduxStoreBuilder<Action, State, Change> internal constructor() { | |
private var _scope: CoroutineScope? = null | |
private var _initialState: Any? = UnInitialized | |
private var _reducer: DslReducer<State, Change>? = null | |
private val _sideEffects = mutableListOf<DslSideEffect<Action, Change>>() | |
private lateinit var stateFlow: StateFlow<State> | |
@FlowReduxDsl | |
public fun coroutineScope(coroutineScope: CoroutineScope) { | |
_scope = coroutineScope | |
} | |
@FlowReduxDsl | |
public fun initialState(initialState: State) { | |
_initialState = initialState | |
} | |
@FlowReduxDsl | |
public fun reduce(block: DslReducer<State, Change>) { | |
_reducer = block | |
} | |
@FlowReduxDsl | |
public fun actions(block: ActionsBuilder<Action, State, Change>.() -> Unit) { | |
val actionsBuilder = ActionsBuilder<Action, State, Change> { stateFlow } | |
block(actionsBuilder) | |
_sideEffects.addAll(actionsBuilder._sideEffects) | |
} | |
internal fun build(): FlowReduxStore<Action, State> { | |
val reducer = requireNotNull(_reducer) { "Reducer must be set" } | |
require(_initialState !== UnInitialized) { "Initial state must be set" } | |
@Suppress("UNCHECKED_CAST") | |
return requireNotNull(_scope) { "CoroutineScope must be set" } | |
.createFlowReduxStore<DlsAction<Action, Change>, State>( | |
initialState = _initialState as State, | |
sideEffects = _sideEffects.map { dlsSideEffect -> | |
SideEffect { actionFlow, stateFlow, coroutineScope -> | |
actionFlow | |
.filterIsInstance<DlsAction.External<Action>>() | |
.map { it.action } | |
.let(dlsSideEffect) | |
.map { DlsAction.Internal(it) } | |
} | |
}, | |
reducer = { state, action -> | |
when (action) { | |
is DlsAction.External -> state | |
is DlsAction.Internal -> reducer(state, action.change) | |
} | |
}, | |
) | |
.liftAction<DlsAction<Action, Change>, State, Action> { DlsAction.External(it) } | |
.also { stateFlow = it.stateFlow } | |
} | |
} | |
internal sealed interface DlsAction<out Action, out Change> { | |
data class External<Action>(val action: Action) : DlsAction<Action, Nothing> | |
data class Internal<Change>(val change: Change) : DlsAction<Nothing, Change> | |
} | |
@FlowReduxDsl | |
public class ActionsBuilder<Action, State, Change> internal constructor( | |
private val getStateFlow: () -> StateFlow<State>, | |
) { | |
public val stateFlow: StateFlow<State> get() = getStateFlow() | |
@PublishedApi | |
internal val _sideEffects: MutableList<DslSideEffect<Action, Change>> = mutableListOf() | |
@FlowReduxDsl | |
public inline fun <reified T : Action> perform(noinline block: DslSideEffectWithReceiver<Action, Change>) { | |
_sideEffects.add(block) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment