commonMain.com.eygraber.vice.ViceContainer.kt Maven / Gradle / Ivy
package com.eygraber.vice
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.launch
public interface ViceContainer
where V : ViceView, C : ViceCompositor, E : ViceEffects {
public val view: V
public val intents: SharedFlow
public val compositor: C
public val effects: E
@Composable
public fun OnBackPressedHandler(enabled: Boolean, onBackPressed: () -> Unit)
@Composable
public fun Vice() {
RunVice(
view = view,
intents = intents as MutableSharedFlow,
compositor = compositor,
effects = effects,
onBackPressedHandler = { enabled, onBackPressed ->
OnBackPressedHandler(enabled, onBackPressed)
},
)
}
}
@Composable
private fun RunVice(
view: ViceView,
intents: MutableSharedFlow,
compositor: ViceCompositor,
effects: ViceEffects,
onBackPressedHandler: @Composable (Boolean, () -> Unit) -> Unit,
) {
val scope = rememberCoroutineScope {
Dispatchers.Main.immediate
}
onBackPressedHandler(compositor.internalIsBackHandlerEnabled()) {
compositor.internalOnBackPressed { intent ->
// this is synchronous because the dispatcher is Main.immediate
scope.launch {
compositor.internalOnIntent(intent)
}
intents.tryEmit(intent)
}
}
ViceUdf(
view,
intents,
compositor,
effects,
scope,
)
}
@Suppress("NOTHING_TO_INLINE")
@Composable
private inline fun ViceUdf(
view: ViceView,
intents: SharedFlow,
compositor: ViceCompositor,
effects: ViceEffects,
scope: CoroutineScope,
) {
effects.Launch()
val state = compositor.internalComposite(intents)
val intentHandler: (I) -> Unit = remember(scope, compositor, intents) {
{ intent: I ->
// this is synchronous because the dispatcher is Main.immediate
scope.launch {
compositor.internalOnIntent(intent)
}
(intents as MutableSharedFlow).tryEmit(intent)
}
}
view.Render(state, intentHandler)
}