summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Justin Weir <justinweir@google.com> 2024-10-03 20:07:58 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-10-03 20:07:58 +0000
commitb885520ee23ba3b08b40e719eaeedddeb987c3bf (patch)
tree8cb1fad00b1ad9b1a12532c5f445a828749fe268
parent66c96334c962091f3e7d90c8b9924ec1c0fe34d6 (diff)
parent9a302637d1751cb274069c170d7b0e637e3c6c3a (diff)
Merge "Add ability to make transitions not replaceable" into main
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt15
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt17
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt48
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt18
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt30
7 files changed, 110 insertions, 27 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 5fa5db880cce..085157ac72b9 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -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 ||
- result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
- result.transitionKey != swipeAnimation.contentTransition.key
+ !currentTransitionIrreversible &&
+ (hasReachedToContent ||
+ result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
+ result.transitionKey != swipeAnimation.contentTransition.key)
if (needNewTransition) {
// Make sure the current transition will finish to the right current scene.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index cec888380513..c9a4d5808cac 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -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(
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 302f207fd0bf..ecef6be49df8 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -507,6 +507,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()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
index 58b59ffd8894..755c4ebf5016 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
@@ -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(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
index fb1bf281715d..6397979d9627 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
@@ -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()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index 5c47f552e400..47fae9f0629f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -106,7 +106,7 @@ class GoneUserActionsViewModelTest : SysuiTestCase() {
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
- .isEqualTo(UserActionResult(Scenes.QuickSettings))
+ .isEqualTo(UserActionResult(Scenes.QuickSettings, isIrreversible = true))
}
@Test
@@ -118,7 +118,7 @@ class GoneUserActionsViewModelTest : SysuiTestCase() {
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
}
@Test
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
index 65b6231705d4..e5f684635ac7 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
@@ -30,41 +30,47 @@ import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
fun singleShadeActions(
requireTwoPointersForTopEdgeForQs: Boolean = false
): Array<Pair<UserAction, UserActionResult>> {
+ val shadeUserActionResult = UserActionResult(Scenes.Shade, isIrreversible = true)
+ val qsSceneUserActionResult = UserActionResult(Scenes.QuickSettings, isIrreversible = true)
return arrayOf(
// Swiping down, not from the edge, always goes to shade.
- Swipe.Down to Scenes.Shade,
- swipeDown(pointerCount = 2) to Scenes.Shade,
+ Swipe.Down to shadeUserActionResult,
+ swipeDown(pointerCount = 2) to shadeUserActionResult,
// Swiping down from the top edge.
swipeDownFromTop(pointerCount = 1) to
if (requireTwoPointersForTopEdgeForQs) {
- Scenes.Shade
+ shadeUserActionResult
} else {
- Scenes.QuickSettings
+ qsSceneUserActionResult
},
- swipeDownFromTop(pointerCount = 2) to Scenes.QuickSettings,
+ swipeDownFromTop(pointerCount = 2) to qsSceneUserActionResult,
)
}
/** Returns collection of [UserAction] to [UserActionResult] pairs for opening the split shade. */
fun splitShadeActions(): Array<Pair<UserAction, UserActionResult>> {
- val splitShadeSceneKey = UserActionResult(Scenes.Shade, ToSplitShade)
+ val shadeUserActionResult = UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)
return arrayOf(
// Swiping down, not from the edge, always goes to shade.
- Swipe.Down to splitShadeSceneKey,
- swipeDown(pointerCount = 2) to splitShadeSceneKey,
+ Swipe.Down to shadeUserActionResult,
+ swipeDown(pointerCount = 2) to shadeUserActionResult,
// Swiping down from the top edge goes to QS.
- swipeDownFromTop(pointerCount = 1) to splitShadeSceneKey,
- swipeDownFromTop(pointerCount = 2) to splitShadeSceneKey,
+ swipeDownFromTop(pointerCount = 1) to shadeUserActionResult,
+ swipeDownFromTop(pointerCount = 2) to shadeUserActionResult,
)
}
/** Returns collection of [UserAction] to [UserActionResult] pairs for opening the dual shade. */
fun dualShadeActions(): Array<Pair<UserAction, UserActionResult>> {
+ val notifShadeUserActionResult =
+ UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
+ val qsShadeuserActionResult =
+ UserActionResult.ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true)
return arrayOf(
- Swipe.Down to Overlays.NotificationsShade,
+ Swipe.Down to notifShadeUserActionResult,
Swipe(direction = SwipeDirection.Down, fromSource = SceneContainerEdge.TopRight) to
- Overlays.QuickSettingsShade,
+ qsShadeuserActionResult,
)
}