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

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

Only compute drag distance when necessary

This CL is a small refactor in SceneGestureHandler so that the drag
distance and target Scene are computed only when the target SceneKey has
changed.

Bug: 291071158
Test: PlatformComposeSceneTransitionLayoutTests
Flag: N/A
Change-Id: I57f2090bcfc711bcb3b9bd220d86b4cc0bf54a86
parent 67d8f970
Loading
Loading
Loading
Loading
+41 −47
Original line number Original line Diff line number Diff line
@@ -146,9 +146,10 @@ internal class SceneGestureHandler(
        val fromScene = layoutImpl.scene(transitionState.currentScene)
        val fromScene = layoutImpl.scene(transitionState.currentScene)
        updateSwipes(fromScene, startedPosition, pointersDown)
        updateSwipes(fromScene, startedPosition, pointersDown)


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


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


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


        if (isNewFromScene || targetScene.key != swipeTransition.toScene) {
        if (isNewFromScene || result.toScene != swipeTransition.toScene) {
            updateTransition(
            updateTransition(
                SwipeTransition(fromScene, targetScene, distance).apply {
                SwipeTransition(fromScene, result).apply {
                    this.dragOffset = swipeTransition.dragOffset
                    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 fromScene the scene from which we look for the target
     * @param directionOffset signed float that indicates the direction. Positive is down or right
     * @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
     *   [directionOffset] is 0f and both direction are available, it will default to
     *   [upOrLeftResult].
     *   [upOrLeftResult].
     */
     */
    private inline fun findTargetSceneAndDistance(
    private fun findUserActionResult(
        fromScene: Scene,
        fromScene: Scene,
        directionOffset: Float,
        directionOffset: Float,
        updateSwipesResults: Boolean,
        updateSwipesResults: Boolean,
    ): Pair<Scene, Float>? {
    ): UserActionResult? {
        if (updateSwipesResults) updateSwipesResults(fromScene)
        if (updateSwipesResults) updateSwipesResults(fromScene)


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


    /**
    /**
     * A strict version of [findTargetSceneAndDistance] that will return null when there is no Scene
     * A strict version of [findUserActionResult] that will return null when there is no Scene in
     * in [directionOffset] direction
     * [directionOffset] direction
     */
     */
    private inline fun findTargetSceneAndDistanceStrict(
    private fun findUserActionResultStrict(directionOffset: Float): UserActionResult? {
        fromScene: Scene,
        directionOffset: Float,
    ): Pair<Scene, Float>? {
        return when {
        return when {
            directionOffset > 0f ->
            directionOffset > 0f -> upOrLeftResult
                upOrLeftResult?.let { result ->
            directionOffset < 0f -> downOrRightResult
                    Pair(
            else -> null
                        layoutImpl.scene(result.toScene),
                        -fromScene.getAbsoluteDistance(result.distance),
                    )
        }
        }
            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 (startFromIdlePosition) {
                // If there is a target scene, we start the overscroll animation.
                // If there is a target scene, we start the overscroll animation.
                val (targetScene, distance) =
                val result =
                    findTargetSceneAndDistanceStrict(fromScene, velocity)
                    findUserActionResultStrict(velocity)
                        ?: run {
                        ?: run {
                            // We will not animate
                            // We will not animate
                            layoutState.finishTransition(swipeTransition, idleScene = fromScene.key)
                            layoutState.finishTransition(swipeTransition, idleScene = fromScene.key)
@@ -449,7 +435,7 @@ internal class SceneGestureHandler(
                        }
                        }


                updateTransition(
                updateTransition(
                    SwipeTransition(fromScene, targetScene, distance).apply {
                    SwipeTransition(fromScene, result).apply {
                        _currentScene = swipeTransition._currentScene
                        _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(
    internal class SwipeTransition(
        val _fromScene: Scene,
        val _fromScene: Scene,
        val _toScene: Scene,
        val _toScene: Scene,