Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6dbf7c1 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Move the implementation of AnimatedState into AnimatedStateImpl

This CL is a simple move of the implementation of AnimatedState into a
separate AnimatedStateImpl class. This is just meant to make the diff of
ag/27551958 easier to parse.

Bug: 290930950
Test: atest AnimatedSharedAsStateTest
Flag: com.android.systemui.scene_container
Change-Id: Ia7cec9773eb660a2a6b168f5b22a99018feafe3d
parent 4747534b
Loading
Loading
Loading
Loading
+66 −79
Original line number Diff line number Diff line
@@ -212,22 +212,7 @@ internal fun <T> animateSharedValueAsState(
    SideEffect { sceneToValueMap<T>(layoutImpl, key, element)[scene] = value }

    return remember(layoutImpl, scene, element, lerp, canOverflow) {
        object : AnimatedState<T> {
            override val value: T
                get() = value(layoutImpl, scene, element, key, lerp, canOverflow)

            @Composable
            override fun unsafeCompositionState(initialValue: T): State<T> {
                val state = remember { mutableStateOf(initialValue) }

                val animatedState = this
                LaunchedEffect(animatedState) {
                    snapshotFlow { animatedState.value }.collect { state.value = it }
                }

                return state
            }
        }
        AnimatedStateImpl(layoutImpl, scene, element, key, lerp, canOverflow)
    }
}

@@ -245,35 +230,27 @@ private fun valueReadTooEarlyMessage(key: ValueKey) =
        "means that you are reading it during composition, which you should not do. See the " +
        "documentation of AnimatedState for more information."

private fun <T> value(
    layoutImpl: SceneTransitionLayoutImpl,
    scene: SceneKey,
    element: ElementKey?,
    key: ValueKey,
    lerp: (T, T, Float) -> T,
    canOverflow: Boolean,
): T {
    return valueOrNull(layoutImpl, scene, element, key, lerp, canOverflow)
        ?: error(valueReadTooEarlyMessage(key))
}
private class AnimatedStateImpl<T>(
    private val layoutImpl: SceneTransitionLayoutImpl,
    private val scene: SceneKey,
    private val element: ElementKey?,
    private val key: ValueKey,
    private val lerp: (T, T, Float) -> T,
    private val canOverflow: Boolean,
) : AnimatedState<T> {
    override val value: T
        get() = valueOrNull() ?: error(valueReadTooEarlyMessage(key))

private fun <T> valueOrNull(
    layoutImpl: SceneTransitionLayoutImpl,
    scene: SceneKey,
    element: ElementKey?,
    key: ValueKey,
    lerp: (T, T, Float) -> T,
    canOverflow: Boolean,
): T? {
    private fun valueOrNull(): T? {
        val sceneToValueMap = sceneToValueMap<T>(layoutImpl, key, element)
        fun sceneValue(scene: SceneKey): T? = sceneToValueMap[scene]

        val transition =
        transition(layoutImpl, element, sceneToValueMap)
            transition(sceneToValueMap)
                ?: return sceneValue(layoutImpl.state.transitionState.currentScene)
                    // TODO(b/311600838): Remove this. We should not have to fallback to the current
                // scene value, but we have to because code of removed nodes can still run if they
                // are placed with a graphics layer.
                    // scene value, but we have to because code of removed nodes can still run if
                    // they are placed with a graphics layer.
                    ?: sceneValue(scene)

        val fromValue = sceneValue(transition.fromScene)
@@ -284,8 +261,8 @@ private fun <T> valueOrNull(
                // relayout/redraw for nothing.
                fromValue
            } else {
            // In the case of bouncing, if the value remains constant during the overscroll,
            // we should use the value of the scene we are bouncing around.
                // In the case of bouncing, if the value remains constant during the overscroll, we
                // should use the value of the scene we are bouncing around.
                if (!canOverflow && transition is TransitionState.HasOverscrollProperties) {
                    val bouncingScene = transition.bouncingScene
                    if (bouncingScene != null) {
@@ -294,23 +271,20 @@ private fun <T> valueOrNull(
                }

                val progress =
                if (canOverflow) transition.progress else transition.progress.fastCoerceIn(0f, 1f)
                    if (canOverflow) transition.progress
                    else transition.progress.fastCoerceIn(0f, 1f)
                lerp(fromValue, toValue, progress)
            }
        } else
            fromValue
                ?: toValue
            // TODO(b/311600838): Remove this. We should not have to fallback to the current scene
            // value, but we have to because code of removed nodes can still run if they are placed
            // with a graphics layer.
                // TODO(b/311600838): Remove this. We should not have to fallback to the current
                // scene value, but we have to because code of removed nodes can still run if they
                // are placed with a graphics layer.
                ?: sceneValue(scene)
    }

private fun transition(
    layoutImpl: SceneTransitionLayoutImpl,
    element: ElementKey?,
    sceneToValueMap: Map<SceneKey, *>,
): TransitionState.Transition? {
    private fun transition(sceneToValueMap: Map<SceneKey, *>): TransitionState.Transition? {
        return if (element != null) {
            layoutImpl.elements[element]?.sceneStates?.let { sceneStates ->
                layoutImpl.state.currentTransitions.fastLastOrNull { transition ->
@@ -323,3 +297,16 @@ private fun transition(
            }
        }
    }

    @Composable
    override fun unsafeCompositionState(initialValue: T): State<T> {
        val state = remember { mutableStateOf(initialValue) }

        val animatedState = this
        LaunchedEffect(animatedState) {
            snapshotFlow { animatedState.value }.collect { state.value = it }
        }

        return state
    }
}