Loading packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +16 −1 Original line number Diff line number Diff line Loading @@ -481,7 +481,9 @@ internal class Swipes(val upOrLeft: Swipe.Resolved, val downOrRight: Swipe.Resol actionSwipe.fromSource != swipe.fromSource) || // The action requires a specific pointerType. (actionSwipe.pointerType != null && actionSwipe.pointerType != swipe.pointerType) actionSwipe.pointerType != swipe.pointerType) || // The action is not valid in the current state. !isActionValid(actionResult) ) { // This action is not eligible. return@forEach Loading @@ -507,6 +509,19 @@ internal class Swipes(val upOrLeft: Swipe.Resolved, val downOrRight: Swipe.Resol return bestMatch } /** Whether [result] is a valid user action in the current state. */ private fun Content.isActionValid(result: UserActionResult): Boolean { val state = layoutImpl.state return when (result) { is UserActionResult.HideOverlay -> result.overlay in state.currentOverlays is UserActionResult.ReplaceByOverlay -> { val fromOverlay = key as? OverlayKey ?: return false fromOverlay in state.currentOverlays && result.overlay !in state.currentOverlays } else -> true } } /** * Update the swipes results. * Loading packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt +27 −0 Original line number Diff line number Diff line Loading @@ -1144,4 +1144,31 @@ class SwipeToSceneTest { assertThat(state.transitionState).hasCurrentScene(SceneA) assertThat(state.transitionState).hasCurrentOverlays(OverlayB) } @Test fun invalidSwipeAction() { val state = rule.runOnUiThread { MutableSceneTransitionLayoutStateForTests(initialScene = SceneA) } rule.setContent { SceneTransitionLayout(state) { scene( SceneA, userActions = mapOf(Swipe.Up to UserActionResult.HideOverlay(OverlayA)), ) { Box(Modifier.fillMaxSize()) } overlay(OverlayA) { Box(Modifier.size(100.dp)) } } } // OverlayA is not shown. // Swipe up on SceneA. This should not trigger the HideOverlay action given that OverlayA is // already hidden. rule.onRoot().performTouchInput { swipeUp() } // The state should remain unchanged. assertThat(state.transitionState).isIdle() assertThat(state.transitionState).hasCurrentScene(SceneA) } } Loading
packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +16 −1 Original line number Diff line number Diff line Loading @@ -481,7 +481,9 @@ internal class Swipes(val upOrLeft: Swipe.Resolved, val downOrRight: Swipe.Resol actionSwipe.fromSource != swipe.fromSource) || // The action requires a specific pointerType. (actionSwipe.pointerType != null && actionSwipe.pointerType != swipe.pointerType) actionSwipe.pointerType != swipe.pointerType) || // The action is not valid in the current state. !isActionValid(actionResult) ) { // This action is not eligible. return@forEach Loading @@ -507,6 +509,19 @@ internal class Swipes(val upOrLeft: Swipe.Resolved, val downOrRight: Swipe.Resol return bestMatch } /** Whether [result] is a valid user action in the current state. */ private fun Content.isActionValid(result: UserActionResult): Boolean { val state = layoutImpl.state return when (result) { is UserActionResult.HideOverlay -> result.overlay in state.currentOverlays is UserActionResult.ReplaceByOverlay -> { val fromOverlay = key as? OverlayKey ?: return false fromOverlay in state.currentOverlays && result.overlay !in state.currentOverlays } else -> true } } /** * Update the swipes results. * Loading
packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt +27 −0 Original line number Diff line number Diff line Loading @@ -1144,4 +1144,31 @@ class SwipeToSceneTest { assertThat(state.transitionState).hasCurrentScene(SceneA) assertThat(state.transitionState).hasCurrentOverlays(OverlayB) } @Test fun invalidSwipeAction() { val state = rule.runOnUiThread { MutableSceneTransitionLayoutStateForTests(initialScene = SceneA) } rule.setContent { SceneTransitionLayout(state) { scene( SceneA, userActions = mapOf(Swipe.Up to UserActionResult.HideOverlay(OverlayA)), ) { Box(Modifier.fillMaxSize()) } overlay(OverlayA) { Box(Modifier.size(100.dp)) } } } // OverlayA is not shown. // Swipe up on SceneA. This should not trigger the HideOverlay action given that OverlayA is // already hidden. rule.onRoot().performTouchInput { swipeUp() } // The state should remain unchanged. assertThat(state.transitionState).isIdle() assertThat(state.transitionState).hasCurrentScene(SceneA) } }