All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.episode6.redux.impl.kt Maven / Gradle / Ivy

The newest version!
package com.episode6.redux

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch

/**
 * Creates a new [StoreFlow], a redux store backed by a [kotlinx.coroutines.flow.StateFlow]
 */
@Suppress("FunctionName") fun  StoreFlow(
  scope: CoroutineScope,
  initialValue: State,
  reducer: Reducer,
  middlewares: List> = emptyList(),
): StoreFlow = StoreFlowImpl(
  scope = scope,
  initialState = initialValue,
  reducer = reducer,
  middlewares = middlewares,
)

private class StoreFlowImpl(
  scope: CoroutineScope,
  override val initialState: T,
  reducer: Reducer,
  middlewares: List>,
  private val stateFlow: MutableStateFlow = MutableStateFlow(initialState)
) : StoreFlow, Flow by stateFlow {

  private val actionChannel: Channel = Channel(capacity = UNLIMITED)

  init {
    scope.launch {
      val reduce: Dispatch = middlewares.foldRight(
        initial = { action -> stateFlow.value = stateFlow.value.reducer(action) },
        operation = { middleware, next -> with(middleware) { interfere(this@StoreFlowImpl, next) } }
      )
      try {
        for (action in actionChannel) {
          reduce(action)
        }
      } finally {
        actionChannel.close()
      }
    }
  }

  override val state: T get() = stateFlow.value

  override fun dispatch(action: Action) {
    actionChannel.trySend(action)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy