Skip to content

Instantly share code, notes, and snippets.

@opengamer29
Created July 18, 2023 11:33
Show Gist options
  • Save opengamer29/97ab2380065248679286eca0339f2c2b to your computer and use it in GitHub Desktop.
Save opengamer29/97ab2380065248679286eca0339f2c2b to your computer and use it in GitHub Desktop.
LinkedStores
fun <
ConsumerEvent : Any,
ConsumerState : Any,
ConsumerEffect : Any,
ProducerEvent : Any,
ProducerState : Any,
ProducerEffect : Any,
> Store<ConsumerEvent, ConsumerState, ConsumerEffect>.linkTo(
producerStore: Store<ProducerEvent, ProducerEffect, ProducerState>,
effectMapper: (ProducerEffect) -> ConsumerEvent?,
stateMapper: (ProducerState) -> ConsumerEvent?,
): Store<ConsumerEvent, ConsumerState, ConsumerEffect> = apply {
scope.launch {
producerStore.link(
producer = { producerStore.states() },
collector = { stateMapper.invoke(it)?.let(this@linkTo::accept) },
)
}
scope.launch {
producerStore.link(
producer = { producerStore.effects() },
collector = { effectMapper.invoke(it)?.let(this@linkTo::accept) },
)
}
}
fun <
ConsumerEvent : Any,
ConsumerState : Any,
ConsumerEffect : Any,
ProducerEvent : Any,
ProducerState : Any,
ProducerEffect : Any,
> Store<ConsumerEvent, ConsumerState, ConsumerEffect>.linkTo(
producerStore: Store<ProducerEvent, ProducerEffect, ProducerState>,
effectMapper: (ProducerState, ProducerEffect) -> ConsumerEvent? = { _, _ -> null },
stateMapper: (oldState: ProducerState, newState: ProducerState) -> ConsumerEvent? = { _, _ ->
null
},
): Store<ConsumerEvent, ConsumerState, ConsumerEffect> = apply {
scope.launch {
producerStore.link(
producer = { producerStore.states() },
collector = { stateMapper.invoke(producerStore.currentState, it)?.let(this@linkTo::accept) },
)
}
scope.launch {
producerStore.link(
producer = { producerStore.effects() },
collector = { effectMapper.invoke(producerStore.currentState, it)?.let(this@linkTo::accept) },
)
}
}
fun <
ConsumerEvent : Any,
ConsumerState : Any,
ConsumerEffect : Any,
ProducerEvent : Any,
ProducerState : Any,
ProducerEffect : Any,
> Store<ConsumerEvent, ConsumerState, ConsumerEffect>.linkListTo(
producerStore: Store<ProducerEvent, ProducerEffect, ProducerState>,
effectMapper: (ProducerState, ProducerEffect) -> List<ConsumerEvent> = { _, _ -> emptyList() },
stateMapper: (oldState: ProducerState, newState: ProducerState) -> List<ConsumerEvent> = { _, _ ->
emptyList()
},
): Store<ConsumerEvent, ConsumerState, ConsumerEffect> = apply {
scope.launch {
producerStore.link(
producer = { producerStore.states() },
collector = { stateMapper.invoke(producerStore.currentState, it).forEach(this@linkListTo::accept) },
)
}
scope.launch {
producerStore.link(
producer = { producerStore.effects() },
collector = { effectMapper.invoke(producerStore.currentState, it).forEach(this@linkListTo::accept) },
)
}
}
@OptIn(ExperimentalCoroutinesApi::class)
private suspend fun <What, Event, State, Effect> Store<Event, State, Effect>.link(
producer: (Store<Event, State, Effect>) -> Flow<What>,
collector: (What) -> Unit,
) {
val channel = scope.produce {
producer.invoke(this@link).collect {
this.channel.send(it)
}
}
for (what in channel) {
collector.invoke(what)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment