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

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

Merge changes Ia38a4d87,I57f2090b,I16a69a18 into main

* changes:
  Fix bug in AnimateToScene
  Only compute drag distance when necessary
  Rename (Element|Scene|Value)Key.name to .debugName
parents 712d5033 5a8ca65f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ fun SceneKey.toCommunalSceneKey(): CommunalSceneKey {

// TODO(b/315490861): Remove these conversions once Compose can be used throughout SysUI.
fun CommunalSceneKey.toTransitionSceneKey(): SceneKey {
    return SceneKey(name = toString(), identity = this)
    return SceneKey(debugName = toString(), identity = this)
}

/**
+1 −1
Original line number Diff line number Diff line
@@ -12,5 +12,5 @@ val Communal = SceneKey.Communal.toTransitionSceneKey()

// TODO(b/293899074): Remove this file once we can use the scene keys from SceneTransitionLayout.
fun SceneKey.toTransitionSceneKey(): SceneTransitionSceneKey {
    return SceneTransitionSceneKey(name = toString(), identity = this)
    return SceneTransitionSceneKey(debugName = toString(), identity = this)
}
+2 −2
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ internal fun CoroutineScope.animateToScene(
                    // The transition is already finished (progress ~= 1): no need to animate. We
                    // finish the current transition early to make sure that the current state
                    // change is committed.
                    layoutState.finishTransition(transitionState, transitionState.currentScene)
                    layoutState.finishTransition(transitionState, target)
                    null
                } else {
                    // The transition is in progress: start the canned animation at the same
@@ -78,7 +78,7 @@ internal fun CoroutineScope.animateToScene(
                if (progress.absoluteValue < ProgressVisibilityThreshold) {
                    // The transition is at progress ~= 0: no need to animate.We finish the current
                    // transition early to make sure that the current state change is committed.
                    layoutState.finishTransition(transitionState, transitionState.currentScene)
                    layoutState.finishTransition(transitionState, target)
                    null
                } else {
                    // TODO(b/290184746): Also take the current velocity into account.
+8 −8
Original line number Diff line number Diff line
@@ -42,16 +42,16 @@ sealed class Key(val debugName: String, val identity: Any) {

/** Key for a scene. */
class SceneKey(
    name: String,
    debugName: String,
    identity: Any = Object(),
) : Key(name, identity), UserActionResult {
) : Key(debugName, identity), UserActionResult {
    @VisibleForTesting
    // TODO(b/240432457): Make internal once PlatformComposeSceneTransitionLayoutTestsUtils can
    // access internal members.
    val testTag: String = "scene:$name"
    val testTag: String = "scene:$debugName"

    /** The unique [ElementKey] identifying this scene's root element. */
    val rootElementKey = ElementKey(name, identity)
    val rootElementKey = ElementKey(debugName, identity)

    // Implementation of [UserActionResult].
    override val toScene: SceneKey = this
@@ -64,7 +64,7 @@ class SceneKey(

/** Key for an element. */
class ElementKey(
    name: String,
    debugName: String,
    identity: Any = Object(),

    /**
@@ -72,11 +72,11 @@ class ElementKey(
     * or compose MovableElements.
     */
    val scenePicker: ElementScenePicker = DefaultElementScenePicker,
) : Key(name, identity), ElementMatcher {
) : Key(debugName, identity), ElementMatcher {
    @VisibleForTesting
    // TODO(b/240432457): Make internal once PlatformComposeSceneTransitionLayoutTestsUtils can
    // access internal members.
    val testTag: String = "element:$name"
    val testTag: String = "element:$debugName"

    override fun matches(key: ElementKey, scene: SceneKey): Boolean {
        return key == this
@@ -99,7 +99,7 @@ class ElementKey(
}

/** Key for a shared value of an element. */
class ValueKey(name: String, identity: Any = Object()) : Key(name, identity) {
class ValueKey(debugName: String, identity: Any = Object()) : Key(debugName, identity) {
    override fun toString(): String {
        return "ValueKey(debugName=$debugName)"
    }
+41 −47
Original line number Diff line number Diff line
@@ -146,9 +146,10 @@ internal class SceneGestureHandler(
        val fromScene = layoutImpl.scene(transitionState.currentScene)
        updateSwipes(fromScene, startedPosition, pointersDown)

        val (targetScene, distance) =
            findTargetSceneAndDistance(fromScene, overSlop, updateSwipesResults = true) ?: return
        updateTransition(SwipeTransition(fromScene, targetScene, distance), force = true)
        val result =
            findUserActionResult(fromScene, directionOffset = overSlop, updateSwipesResults = true)
                ?: return
        updateTransition(SwipeTransition(fromScene, result), force = true)
    }

    private fun updateSwipes(fromScene: Scene, startedPosition: Offset?, pointersDown: Int) {
@@ -224,8 +225,8 @@ internal class SceneGestureHandler(
            computeFromSceneConsideringAcceleratedSwipe(swipeTransition)

        val isNewFromScene = fromScene.key != swipeTransition.fromScene
        val (targetScene, distance) =
            findTargetSceneAndDistance(
        val result =
            findUserActionResult(
                fromScene,
                swipeTransition.dragOffset,
                updateSwipesResults = isNewFromScene,
@@ -236,9 +237,9 @@ internal class SceneGestureHandler(
                }
        swipeTransition.dragOffset += acceleratedOffset

        if (isNewFromScene || targetScene.key != swipeTransition.toScene) {
        if (isNewFromScene || result.toScene != swipeTransition.toScene) {
            updateTransition(
                SwipeTransition(fromScene, targetScene, distance).apply {
                SwipeTransition(fromScene, result).apply {
                    this.dragOffset = swipeTransition.dragOffset
                }
            )
@@ -306,7 +307,7 @@ internal class SceneGestureHandler(
    }

    /**
     * Returns the target scene and distance from [fromScene] in the direction [directionOffset].
     * Returns the [UserActionResult] from [fromScene] in the direction of [directionOffset].
     *
     * @param fromScene the scene from which we look for the target
     * @param directionOffset signed float that indicates the direction. Positive is down or right
@@ -322,57 +323,42 @@ internal class SceneGestureHandler(
     *   [directionOffset] is 0f and both direction are available, it will default to
     *   [upOrLeftResult].
     */
    private inline fun findTargetSceneAndDistance(
    private fun findUserActionResult(
        fromScene: Scene,
        directionOffset: Float,
        updateSwipesResults: Boolean,
    ): Pair<Scene, Float>? {
    ): UserActionResult? {
        if (updateSwipesResults) updateSwipesResults(fromScene)

        // Compute the target scene depending on the current offset.
        return when {
            upOrLeftResult == null && downOrRightResult == null -> null
            (directionOffset < 0f && upOrLeftResult != null) || downOrRightResult == null ->
                upOrLeftResult?.let { result ->
                    Pair(
                        layoutImpl.scene(result.toScene),
                        -fromScene.getAbsoluteDistance(result.distance)
                    )
                }
            else ->
                downOrRightResult?.let { result ->
                    Pair(
                        layoutImpl.scene(result.toScene),
                        fromScene.getAbsoluteDistance(result.distance)
                    )
                }
                upOrLeftResult
            else -> downOrRightResult
        }
    }

    /**
     * A strict version of [findTargetSceneAndDistance] that will return null when there is no Scene
     * in [directionOffset] direction
     * A strict version of [findUserActionResult] that will return null when there is no Scene in
     * [directionOffset] direction
     */
    private inline fun findTargetSceneAndDistanceStrict(
        fromScene: Scene,
        directionOffset: Float,
    ): Pair<Scene, Float>? {
    private fun findUserActionResultStrict(directionOffset: Float): UserActionResult? {
        return when {
            directionOffset > 0f ->
                upOrLeftResult?.let { result ->
                    Pair(
                        layoutImpl.scene(result.toScene),
                        -fromScene.getAbsoluteDistance(result.distance),
                    )
            directionOffset > 0f -> upOrLeftResult
            directionOffset < 0f -> downOrRightResult
            else -> null
        }
            directionOffset < 0f ->
                downOrRightResult?.let { result ->
                    Pair(
                        layoutImpl.scene(result.toScene),
                        fromScene.getAbsoluteDistance(result.distance),
                    )
    }
            else -> null

    private fun computeAbsoluteDistance(
        fromScene: Scene,
        result: UserActionResult,
    ): Float {
        return if (result == upOrLeftResult) {
            -fromScene.getAbsoluteDistance(result.distance)
        } else {
            check(result == downOrRightResult)
            fromScene.getAbsoluteDistance(result.distance)
        }
    }

@@ -440,8 +426,8 @@ internal class SceneGestureHandler(

            if (startFromIdlePosition) {
                // If there is a target scene, we start the overscroll animation.
                val (targetScene, distance) =
                    findTargetSceneAndDistanceStrict(fromScene, velocity)
                val result =
                    findUserActionResultStrict(velocity)
                        ?: run {
                            // We will not animate
                            layoutState.finishTransition(swipeTransition, idleScene = fromScene.key)
@@ -449,7 +435,7 @@ internal class SceneGestureHandler(
                        }

                updateTransition(
                    SwipeTransition(fromScene, targetScene, distance).apply {
                    SwipeTransition(fromScene, result).apply {
                        _currentScene = swipeTransition._currentScene
                    }
                )
@@ -496,6 +482,14 @@ internal class SceneGestureHandler(
        }
    }

    private fun SwipeTransition(fromScene: Scene, result: UserActionResult): SwipeTransition {
        return SwipeTransition(
            fromScene,
            layoutImpl.scene(result.toScene),
            computeAbsoluteDistance(fromScene, result),
        )
    }

    internal class SwipeTransition(
        val _fromScene: Scene,
        val _toScene: Scene,
Loading