
commonMain.com.arkivanov.decompose.extensions.compose.jetbrains.Children.kt Maven / Gradle / Ivy
package com.arkivanov.decompose.extensions.compose.jetbrains
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.SaveableStateHolder
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.Modifier
import com.arkivanov.decompose.Child
import com.arkivanov.decompose.ExperimentalDecomposeApi
import com.arkivanov.decompose.extensions.compose.jetbrains.animation.child.ChildAnimation
import com.arkivanov.decompose.extensions.compose.jetbrains.animation.child.emptyChildAnimation
import com.arkivanov.decompose.router.RouterState
import com.arkivanov.decompose.value.Value
typealias ChildContent = @Composable (child: Child.Created) -> Unit
@OptIn(ExperimentalDecomposeApi::class)
@Composable
fun Children(
routerState: RouterState,
modifier: Modifier = Modifier,
animation: ChildAnimation = emptyChildAnimation(),
content: ChildContent
) {
val holder = rememberSaveableStateHolder()
holder.retainStates(routerState.getConfigurations())
animation(routerState, modifier) { child ->
holder.SaveableStateProvider(child.configuration.key()) {
content(child)
}
}
}
@OptIn(ExperimentalDecomposeApi::class)
@Composable
fun Children(
routerState: Value>,
modifier: Modifier = Modifier,
animation: ChildAnimation = emptyChildAnimation(),
content: ChildContent
) {
val state = routerState.subscribeAsState()
Children(
routerState = state.value,
modifier = modifier,
animation = animation,
content = content
)
}
private fun RouterState<*, *>.getConfigurations(): Set {
val set = HashSet()
backStack.forEach { set += it.configuration.key() }
set += activeChild.configuration.key()
return set
}
private fun Any.key(): String = "${this::class.simpleName}_${hashCode().toString(radix = 36)}"
@Composable
private fun SaveableStateHolder.retainStates(currentKeys: Set) {
val keys = remember(this) { Keys(currentKeys) }
DisposableEffect(this, currentKeys) {
keys.set.forEach {
if (it !in currentKeys) {
removeState(it)
}
}
keys.set = currentKeys
onDispose {}
}
}
private class Keys(
var set: Set
)
© 2015 - 2025 Weber Informatics LLC | Privacy Policy