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

Commit 78703ead authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Enforce that onDragStarted.overSlop is != 0f

This CL ensures that the overSlop passed to
SceneGestureHandler.onDragStarter() is different than 0f if we are not
interrupting the current transition.

Bug: 291053278
Test: PlatformComposeSceneTransitionLayoutTests
Flag: N/A
Change-Id: I3300b3b2ceb51a90a15c11d9f67c9b5c10fcbb06
parent 0b21899e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -96,6 +96,9 @@ internal class SceneGestureHandler(
            return
        }

        check(overSlop != 0f) {
            "onDragStarted() called while isDrivingTransition=false overSlop=0f"
        }
        val transitionState = layoutState.transitionState
        if (transitionState is TransitionState.Transition) {
            // TODO(b/290184746): Better handle interruptions here if state != idle.
+7 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.unit.Velocity
import com.android.compose.ui.util.SpaceVectorConverter
import kotlin.math.sign

/**
 * This [NestedScrollConnection] waits for a child to scroll ([onPreScroll] or [onPostScroll]), and
@@ -117,7 +118,12 @@ class PriorityNestedScrollConnection(
            return Velocity.Zero
        }

        onPriorityStart(available = Offset.Zero)
        // The offset passed to onPriorityStart() must be != 0f, so we create a small offset of 1px
        // given the available velocity.
        // TODO(b/291053278): Remove canStartPostFling() and instead make it possible to define the
        // overscroll behavior on the Scene level.
        val smallOffset = Offset(available.x.sign, available.y.sign)
        onPriorityStart(available = smallOffset)

        // This is the last event of a scroll gesture.
        return onPriorityStop(available)
+12 −28
Original line number Diff line number Diff line
@@ -192,16 +192,14 @@ class SceneGestureHandlerTest {

    @Test
    fun onDragStarted_shouldStartATransition() = runGestureTest {
        draggable.onDragStarted()
        draggable.onDragStarted(overSlop = down(0.1f))
        assertTransition(currentScene = SceneA)
    }

    @Test
    fun afterSceneTransitionIsStarted_interceptDragEvents() = runGestureTest {
        draggable.onDragStarted()
        draggable.onDragStarted(overSlop = down(0.1f))
        assertTransition(currentScene = SceneA)

        draggable.onDelta(pixels = down(0.1f))
        assertThat(progress).isEqualTo(0.1f)

        draggable.onDelta(pixels = down(0.1f))
@@ -210,10 +208,7 @@ class SceneGestureHandlerTest {

    @Test
    fun onDragStoppedAfterDrag_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
        draggable.onDragStarted()
        assertTransition(currentScene = SceneA)

        draggable.onDelta(pixels = down(0.1f))
        draggable.onDragStarted(overSlop = down(0.1f))
        assertTransition(currentScene = SceneA)

        draggable.onDragStopped(
@@ -228,10 +223,7 @@ class SceneGestureHandlerTest {

    @Test
    fun onDragStoppedAfterDrag_velocityAtLeastThreshold_goToNextScene() = runGestureTest {
        draggable.onDragStarted()
        assertTransition(currentScene = SceneA)

        draggable.onDelta(pixels = down(0.1f))
        draggable.onDragStarted(overSlop = down(0.1f))
        assertTransition(currentScene = SceneA)

        draggable.onDragStopped(velocity = velocityThreshold)
@@ -245,7 +237,7 @@ class SceneGestureHandlerTest {

    @Test
    fun onDragStoppedAfterStarted_returnToIdle() = runGestureTest {
        draggable.onDragStarted()
        draggable.onDragStarted(overSlop = down(0.1f))
        assertTransition(currentScene = SceneA)

        draggable.onDragStopped(velocity = 0f)
@@ -256,8 +248,7 @@ class SceneGestureHandlerTest {
    @Test
    fun onDragReversedDirection_changeToScene() = runGestureTest {
        // Drag A -> B with progress 0.6
        draggable.onDragStarted()
        draggable.onDelta(up(0.6f))
        draggable.onDragStarted(overSlop = up(0.6f))
        assertTransition(
            currentScene = SceneA,
            fromScene = SceneA,
@@ -366,8 +357,7 @@ class SceneGestureHandlerTest {
    @Test
    fun onAccelaratedScroll_scrollToThirdScene() = runGestureTest {
        // Drag A -> B with progress 0.2
        draggable.onDragStarted()
        draggable.onDelta(up(0.2f))
        draggable.onDragStarted(overSlop = up(0.2f))
        assertTransition(
            currentScene = SceneA,
            fromScene = SceneA,
@@ -401,9 +391,7 @@ class SceneGestureHandlerTest {

    @Test
    fun onAccelaratedScrollBothTargetsBecomeNull_settlesToIdle() = runGestureTest {
        draggable.onDragStarted()
        draggable.onDelta(up(0.2f))

        draggable.onDragStarted(overSlop = up(0.2f))
        draggable.onDelta(up(0.2f))
        draggable.onDragStopped(velocity = -velocityThreshold)
        assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
@@ -459,16 +447,14 @@ class SceneGestureHandlerTest {
        draggable.onDragStopped(down(0.1f))

        // now target changed to C for new drag that started before previous drag settled to Idle
        draggable.onDragStarted(up(0.1f))
        draggable.onDragStarted(overSlop = 0f)
        draggable.onDelta(up(0.1f))
        assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.3f)
    }

    @Test
    fun startGestureDuringAnimatingOffset_shouldImmediatelyStopTheAnimation() = runGestureTest {
        draggable.onDragStarted()
        assertTransition(currentScene = SceneA)

        draggable.onDelta(pixels = down(0.1f))
        draggable.onDragStarted(overSlop = down(0.1f))
        assertTransition(currentScene = SceneA)

        draggable.onDragStopped(
@@ -759,10 +745,8 @@ class SceneGestureHandlerTest {
    @Test
    fun startNestedScrollWhileDragging() = runGestureTest {
        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
        draggable.onDragStarted()
        draggable.onDragStarted(overSlop = down(0.1f))
        assertTransition(currentScene = SceneA)

        draggable.onDelta(down(0.1f))
        assertThat(progress).isEqualTo(0.1f)

        // now we can intercept the scroll events