Pragnesh Meniya
09/05/2023, 3:05 AMdata class State (
val showMsg: String? = "",
val showMsgLocalError: StringResource? = null,
val isProgressShow: Boolean? = false,
)
@OptIn(ExperimentalCoroutinesApi::class)
val state: StateFlow<BaseStore.State> = baseStore.stateFlow
I am using above codeKirill Zhukov
09/05/2023, 5:08 AMPragnesh Meniya
09/05/2023, 3:57 PMclass BaseComponent (
componentContext: ComponentContext,
storeFactory: StoreFactory,
private val output: (Output) -> Unit
) : ComponentContext by componentContext {
private val baseStore = instanceKeeper.getStore {
BaseStoreFactory(storeFactory = storeFactory).create()
}
val state: Flow<BaseStore.State> = baseStore.states
fun onEvent(event: BaseStore.Intent) {
baseStore.accept(event)
}
sealed class Output {
}
}
BaseStoreFactory :
class BaseStoreFactory(private val storeFactory: StoreFactory) : KoinComponent {
private val TAG = "BaseStoreFactory"
fun create(): BaseStore =
object : BaseStore, Store<BaseStore.Intent, BaseStore.State, Nothing> by storeFactory.create(
name = "BaseStore",
initialState = BaseStore.State(),
bootstrapper = SimpleBootstrapper(Unit),
executorFactory = ::ExecutorImpl,
reducer = ReducerImpl
) {}
private inner class ExecutorImpl : CoroutineExecutor<BaseStore.Intent, Unit, BaseStore.State, Msg, Nothing>(
Dispatchers.Main) {
override fun executeIntent(intent: BaseStore.Intent, getState: () -> BaseStore.State): Unit =
when (intent) {
is BaseStore.Intent.ON_PROGRESS_SHOW -> {
dispatch(Msg.ProgressShow(true))
}
is BaseStore.Intent.ON_PROGRESS_HIDE -> {
dispatch(Msg.ProgressShow(false))
}
is BaseStore.Intent.SHOW_SNACKBAR -> {
dispatch(Msg.ShowMsg(intent.showMsg))
}
is BaseStore.Intent.SHOW_LOCAL_ERROR -> {
dispatch(Msg.ShowMsgLocalError(intent.showMsgLocalError))
}
}
}
private object ReducerImpl: Reducer<BaseStore.State, Msg> {
override fun BaseStore.State.reduce(msg: Msg): BaseStore.State =
when (msg) {
is Msg.ShowMsg -> copy(showMsg = msg.showMsg)
is Msg.ShowMsgLocalError -> copy(showMsgLocalError = msg.stringResource)
is Msg.ProgressShow -> copy(isProgressShow = msg.progressShow)
}
}
private sealed class Msg {
data class ShowMsg(val showMsg: String) : Msg()
data class ShowMsgLocalError(val stringResource: StringResource) : Msg()
data class ProgressShow(val progressShow: Boolean) : Msg()
}
}
And fire the state from other components like as below :
baseComponent.onEvent(BaseStore.Intent.SHOW_LOCAL_ERROR(MR.strings.interne_not_available))
And consume the state RootContentView like below :
val baseState by component.getBaseComponent().state.collectAsState(initial = BaseStore.State())
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
if (!baseState.showMsg.isNullOrBlank()) {
scope.launch {
snackbarHostState.showSnackbar(baseState.showMsg.toString())
}
}
if (baseState.showMsgLocalError != null) {
val msg = getStrings(baseState.showMsgLocalError!!)
scope.launch {
snackbarHostState.showSnackbar(msg)
}
}
In code snippet Snackbar only show 1 time, when 2 event occur Snackbar not showing?