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

commonMain.com.arkivanov.decompose.extensions.compose.stack.Children.kt Maven / Gradle / Ivy

package com.arkivanov.decompose.extensions.compose.stack

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.extensions.compose.stack.animation.LocalStackAnimationProvider
import com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimation
import com.arkivanov.decompose.extensions.compose.stack.animation.emptyStackAnimation
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.keyHashString
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.value.Value

@Composable
fun  Children(
    stack: ChildStack,
    modifier: Modifier = Modifier,
    animation: StackAnimation? = null,
    content: @Composable (child: Child.Created) -> Unit,
) {
    val holder = rememberSaveableStateHolder()

    holder.retainStates(stack.getKeys())

    val animationProvider = LocalStackAnimationProvider.current
    val anim = animation ?: remember(animationProvider, animationProvider::provide) ?: emptyStackAnimation()

    anim(stack = stack, modifier = modifier) { child ->
        holder.SaveableStateProvider(child.keyHashString()) {
            content(child)
        }
    }
}

@Composable
fun  Children(
    stack: Value>,
    modifier: Modifier = Modifier,
    animation: StackAnimation? = null,
    content: @Composable (child: Child.Created) -> Unit,
) {
    val state = stack.subscribeAsState()

    Children(
        stack = state.value,
        modifier = modifier,
        animation = animation,
        content = content
    )
}

private fun ChildStack<*, *>.getKeys(): Set =
    items.mapTo(HashSet(), Child<*, *>::keyHashString)

@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 - 2024 Weber Informatics LLC | Privacy Policy