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

Commit 9a302637 authored by Justin Weir's avatar Justin Weir
Browse files

Add ability to make transitions not replaceable

On the lockscreen, if the user swipes down to expand the shade then
swipes up past the origin of the swipe without lifting their finger,
it will not only collapse the shade but also unlock the phone. This
happens because when the finger passes the origin point of the swipe,
it switches from the down action (i.e. shade expand) to the up action
(i.e. unlock the phone). This CL adds the ability to mark some swipe
action results as irreversable and sets that parameter for the
lockscreen swipe down actions.

Fixes: 359876433
Test: added new tests
Test: manually verified
Flag: com.android.systemui.scene_container
Change-Id: If841ed9b1b4484d767db114b16226c4411cf7f16
parent 9aeb5612
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -226,7 +226,6 @@ internal class DraggableHandlerImpl(
        val fromSource = resolveSwipeSource(startedPosition)
        val upOrLeft = resolveSwipe(pointersDown, fromSource, isUpOrLeft = true)
        val downOrRight = resolveSwipe(pointersDown, fromSource, isUpOrLeft = false)

        return if (fromSource == null) {
            Swipes(
                upOrLeft = null,
@@ -366,10 +365,18 @@ private class DragControllerImpl(
            return 0f
        }

        val currentTransitionIrreversible =
            if (swipeAnimation.isUpOrLeft) {
                swipes.upOrLeftResult?.isIrreversible ?: false
            } else {
                swipes.downOrRightResult?.isIrreversible ?: false
            }

        val needNewTransition =
            hasReachedToContent ||
            !currentTransitionIrreversible &&
                (hasReachedToContent ||
                    result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
                result.transitionKey != swipeAnimation.contentTransition.key
                    result.transitionKey != swipeAnimation.contentTransition.key)

        if (needNewTransition) {
            // Make sure the current transition will finish to the right current scene.
+16 −1
Original line number Diff line number Diff line
@@ -498,6 +498,12 @@ sealed class UserActionResult(
     * bigger than 100% when the user released their finger. `
     */
    open val requiresFullDistanceSwipe: Boolean,

    /**
     * Whether swiping back in the opposite direction past the origin point of the swipe can replace
     * the action with the action for the opposite direction.
     */
    open val isIrreversible: Boolean = false,
) {
    internal abstract fun toContent(currentScene: SceneKey): ContentKey

@@ -507,6 +513,7 @@ sealed class UserActionResult(
        val toScene: SceneKey,
        override val transitionKey: TransitionKey? = null,
        override val requiresFullDistanceSwipe: Boolean = false,
        override val isIrreversible: Boolean = false,
    ) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
        override fun toContent(currentScene: SceneKey): ContentKey = toScene
    }
@@ -516,6 +523,7 @@ sealed class UserActionResult(
        val overlay: OverlayKey,
        override val transitionKey: TransitionKey? = null,
        override val requiresFullDistanceSwipe: Boolean = false,
        override val isIrreversible: Boolean = false,
    ) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
        override fun toContent(currentScene: SceneKey): ContentKey = overlay
    }
@@ -558,7 +566,14 @@ sealed class UserActionResult(
             * the user released their finger.
             */
            requiresFullDistanceSwipe: Boolean = false,
        ): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe)

            /**
             * Whether swiping back in the opposite direction past the origin point of the swipe can
             * replace the action with the action for the opposite direction.
             */
            isIrreversible: Boolean = false,
        ): UserActionResult =
            ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe, isIrreversible)

        /** A [UserActionResult] that shows [toOverlay]. */
        operator fun invoke(
+48 −0
Original line number Diff line number Diff line
@@ -506,6 +506,54 @@ class DraggableHandlerTest {
        )
    }

    @Test
    fun onDragWithActionsInBothDirections_dragToOppositeDirectionReplacesAction() = runGestureTest {
        // We are on SceneA. UP -> B, DOWN-> C.
        val dragController = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
        assertTransition(
            currentScene = SceneA,
            fromScene = SceneA,
            toScene = SceneB,
            progress = 0.2f,
        )

        // Reverse drag direction, it will replace the previous transition
        dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
        assertTransition(
            currentScene = SceneA,
            fromScene = SceneA,
            toScene = SceneC,
            progress = 0.3f,
        )
    }

    @Test
    fun onDragWithActionsInBothDirections_dragToOppositeDirectionNotReplaceable() = runGestureTest {
        // We are on SceneA. UP -> B, DOWN-> C. The up swipe is not replaceable though.
        mutableUserActionsA =
            mapOf(Swipe.Up to UserActionResult(SceneB, isIrreversible = true), Swipe.Down to SceneC)
        val dragController =
            onDragStarted(
                startedPosition = Offset(SCREEN_SIZE * 0.5f, SCREEN_SIZE * 0.5f),
                overSlop = up(fractionOfScreen = 0.2f),
            )
        assertTransition(
            currentScene = SceneA,
            fromScene = SceneA,
            toScene = SceneB,
            progress = 0.2f,
        )

        // Reverse drag direction, it cannot replace the previous transition
        dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
        assertTransition(
            currentScene = SceneA,
            fromScene = SceneA,
            toScene = SceneB,
            progress = -0.3f,
        )
    }

    @Test
    fun onDragFromEdge_startTransitionToEdgeAction() = runGestureTest {
        navigateToSceneC()
+12 −6
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
            assertThat(actions).isNotEmpty()
            assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
            assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
            assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
            assertThat(actions?.get(Swipe.Down))
                .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))

            setUpState(
                isShadeTouchable = false,
@@ -102,7 +103,8 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
            assertThat(actions).isNotEmpty()
            assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
            assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
            assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
            assertThat(actions?.get(Swipe.Down))
                .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
        }

    @Test
@@ -120,7 +122,7 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
            assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
            assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
            assertThat(actions?.get(Swipe.Down))
                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))

            setUpState(
                isShadeTouchable = false,
@@ -138,7 +140,7 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
            assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
            assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
            assertThat(actions?.get(Swipe.Down))
                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
        }

    @Test
@@ -156,7 +158,9 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
            assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
            assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
            assertThat(actions?.get(Swipe.Down))
                .isEqualTo(UserActionResult(Overlays.NotificationsShade))
                .isEqualTo(
                    UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
                )

            setUpState(
                isShadeTouchable = false,
@@ -170,7 +174,9 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
            assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
            assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
            assertThat(actions?.get(Swipe.Down))
                .isEqualTo(UserActionResult(Overlays.NotificationsShade))
                .isEqualTo(
                    UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
                )
        }

    private fun TestScope.setUpState(
+3 −2
Original line number Diff line number Diff line
@@ -303,7 +303,8 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() {
                // Top edge is not applicable in dual shade, as well as two-finger swipe.
                assertThat(downDestination).isNull()
            } else {
                assertThat(downDestination).isEqualTo(ShowOverlay(Overlays.NotificationsShade))
                assertThat(downDestination)
                    .isEqualTo(ShowOverlay(Overlays.NotificationsShade, isIrreversible = true))
                assertThat(downDestination?.transitionKey).isNull()
            }

@@ -320,7 +321,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() {
                downWithTwoPointers -> assertThat(downFromTopRightDestination).isNull()
                else -> {
                    assertThat(downFromTopRightDestination)
                        .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade))
                        .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true))
                    assertThat(downFromTopRightDestination?.transitionKey).isNull()
                }
            }
Loading