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

Commit 5d64a6fb authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Introduce Content, ContentKey and ContentScope (1/2)" into main

parents 126d0c32 259a4f34
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
@@ -70,7 +71,7 @@ object Communal {
}

object AllElements : ElementMatcher {
    override fun matches(key: ElementKey, scene: SceneKey) = true
    override fun matches(key: ElementKey, content: ContentKey) = true
}

private object TransitionDuration {
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ constructor(
    fun SceneScope.Notifications(burnInParams: BurnInParameters?, modifier: Modifier = Modifier) {
        val areNotificationsVisible by
            lockscreenContentViewModel
                .areNotificationsVisible(sceneKey)
                .areNotificationsVisible(contentKey)
                .collectAsStateWithLifecycle(initialValue = false)
        if (!areNotificationsVisible) {
            return
+48 −26
Original line number Diff line number Diff line
@@ -67,15 +67,15 @@ interface AnimatedState<T> : State<T> {
/**
 * Animate a scene Int value.
 *
 * @see SceneScope.animateSceneValueAsState
 * @see ContentScope.animateContentValueAsState
 */
@Composable
fun SceneScope.animateSceneIntAsState(
fun ContentScope.animateContentIntAsState(
    value: Int,
    key: ValueKey,
    canOverflow: Boolean = true,
): AnimatedState<Int> {
    return animateSceneValueAsState(value, key, SharedIntType, canOverflow)
    return animateContentValueAsState(value, key, SharedIntType, canOverflow)
}

/**
@@ -107,17 +107,28 @@ private object SharedIntType : SharedValueType<Int, Int> {
/**
 * Animate a scene Float value.
 *
 * @see SceneScope.animateSceneValueAsState
 * @see ContentScope.animateContentValueAsState
 */
@Composable
fun SceneScope.animateSceneFloatAsState(
fun ContentScope.animateContentFloatAsState(
    value: Float,
    key: ValueKey,
    canOverflow: Boolean = true,
): AnimatedState<Float> {
    return animateSceneValueAsState(value, key, SharedFloatType, canOverflow)
    return animateContentValueAsState(value, key, SharedFloatType, canOverflow)
}

@Deprecated(
    "Use animateSceneFloatAsState() instead",
    replaceWith = ReplaceWith("animateContentFloatAsState(value, key, canOverflow)")
)
@Composable
fun ContentScope.animateSceneFloatAsState(
    value: Float,
    key: ValueKey,
    canOverflow: Boolean = true,
) = animateContentFloatAsState(value, key, canOverflow)

/**
 * Animate a shared element Float value.
 *
@@ -147,17 +158,28 @@ private object SharedFloatType : SharedValueType<Float, Float> {
/**
 * Animate a scene Dp value.
 *
 * @see SceneScope.animateSceneValueAsState
 * @see ContentScope.animateContentValueAsState
 */
@Composable
fun SceneScope.animateSceneDpAsState(
fun ContentScope.animateContentDpAsState(
    value: Dp,
    key: ValueKey,
    canOverflow: Boolean = true,
): AnimatedState<Dp> {
    return animateSceneValueAsState(value, key, SharedDpType, canOverflow)
    return animateContentValueAsState(value, key, SharedDpType, canOverflow)
}

@Deprecated(
    "Use animateSceneDpAsState() instead",
    replaceWith = ReplaceWith("animateContentDpAsState(value, key, canOverflow)")
)
@Composable
fun ContentScope.animateSceneDpAsState(
    value: Dp,
    key: ValueKey,
    canOverflow: Boolean = true,
) = animateContentDpAsState(value, key, canOverflow)

/**
 * Animate a shared element Dp value.
 *
@@ -188,14 +210,14 @@ private object SharedDpType : SharedValueType<Dp, Dp> {
/**
 * Animate a scene Color value.
 *
 * @see SceneScope.animateSceneValueAsState
 * @see ContentScope.animateContentValueAsState
 */
@Composable
fun SceneScope.animateSceneColorAsState(
fun ContentScope.animateContentColorAsState(
    value: Color,
    key: ValueKey,
): AnimatedState<Color> {
    return animateSceneValueAsState(value, key, SharedColorType, canOverflow = false)
    return animateContentValueAsState(value, key, SharedColorType, canOverflow = false)
}

/**
@@ -261,24 +283,24 @@ private class ColorDelta(
@Composable
internal fun <T> animateSharedValueAsState(
    layoutImpl: SceneTransitionLayoutImpl,
    scene: SceneKey,
    content: ContentKey,
    element: ElementKey?,
    key: ValueKey,
    value: T,
    type: SharedValueType<T, *>,
    canOverflow: Boolean,
): AnimatedState<T> {
    DisposableEffect(layoutImpl, scene, element, key) {
        // Create the associated maps that hold the current value for each (element, scene) pair.
    DisposableEffect(layoutImpl, content, element, key) {
        // Create the associated maps that hold the current value for each (element, content) pair.
        val valueMap = layoutImpl.sharedValues.getOrPut(key) { mutableMapOf() }
        val sharedValue = valueMap.getOrPut(element) { SharedValue(type) } as SharedValue<T, *>
        val targetValues = sharedValue.targetValues
        targetValues[scene] = value
        targetValues[content] = value

        onDispose {
            // Remove the value associated to the current scene, and eventually remove the maps if
            // they are empty.
            targetValues.remove(scene)
            targetValues.remove(content)

            if (targetValues.isEmpty() && valueMap[element] === sharedValue) {
                valueMap.remove(element)
@@ -297,11 +319,11 @@ internal fun <T> animateSharedValueAsState(
            error("value is equal to $value, which is the undefined value for this type.")
        }

        sharedValue<T, Any>(layoutImpl, key, element).targetValues[scene] = value
        sharedValue<T, Any>(layoutImpl, key, element).targetValues[content] = value
    }

    return remember(layoutImpl, scene, element, canOverflow) {
        AnimatedStateImpl<T, Any>(layoutImpl, scene, element, key, canOverflow)
    return remember(layoutImpl, content, element, canOverflow) {
        AnimatedStateImpl<T, Any>(layoutImpl, content, element, key, canOverflow)
    }
}

@@ -322,8 +344,8 @@ private fun valueReadTooEarlyMessage(key: ValueKey) =
internal class SharedValue<T, Delta>(
    val type: SharedValueType<T, Delta>,
) {
    /** The target value of this shared value for each scene. */
    val targetValues = SnapshotStateMap<SceneKey, T>()
    /** The target value of this shared value for each content. */
    val targetValues = SnapshotStateMap<ContentKey, T>()

    /** The last value of this shared value. */
    var lastValue: T = type.unspecifiedValue
@@ -340,7 +362,7 @@ internal class SharedValue<T, Delta>(

private class AnimatedStateImpl<T, Delta>(
    private val layoutImpl: SceneTransitionLayoutImpl,
    private val scene: SceneKey,
    private val content: ContentKey,
    private val element: ElementKey?,
    private val key: ValueKey,
    private val canOverflow: Boolean,
@@ -356,14 +378,14 @@ private class AnimatedStateImpl<T, Delta>(
                // 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.
                ?: sharedValue[scene]
                ?: sharedValue[content]
                ?: error(valueReadTooEarlyMessage(key))
        val interruptedValue = computeInterruptedValue(sharedValue, transition, value)
        sharedValue.lastValue = interruptedValue
        return interruptedValue
    }

    private operator fun SharedValue<T, *>.get(scene: SceneKey): T? = targetValues[scene]
    private operator fun SharedValue<T, *>.get(content: ContentKey): T? = targetValues[content]

    private fun valueOrNull(
        sharedValue: SharedValue<T, *>,
@@ -401,7 +423,7 @@ private class AnimatedStateImpl<T, Delta>(
        val targetValues = sharedValue.targetValues
        val transition =
            if (element != null) {
                layoutImpl.elements[element]?.sceneStates?.let { sceneStates ->
                layoutImpl.elements[element]?.stateByContent?.let { sceneStates ->
                    layoutImpl.state.currentTransitions.fastLastOrNull { transition ->
                        transition.fromScene in sceneStates || transition.toScene in sceneStates
                    }
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
import com.android.compose.animation.scene.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified
import com.android.compose.animation.scene.content.Scene
import com.android.compose.nestedscroll.PriorityNestedScrollConnection
import kotlin.math.absoluteValue
import kotlinx.coroutines.CoroutineScope
+201 −187

File changed.

Preview size limit exceeded, changes collapsed.

Loading