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

Commit a70cdf69 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add support for fromSource in nested scroll" into main

parents a768d736 f0b04418
Loading
Loading
Loading
Loading
+20 −29
Original line number Diff line number Diff line
@@ -189,7 +189,7 @@ internal class DraggableHandlerImpl(
        return createSwipeAnimation(layoutImpl, result, isUpOrLeft, orientation)
    }

    private fun resolveSwipeSource(startedPosition: Offset?): SwipeSource.Resolved? {
    internal fun resolveSwipeSource(startedPosition: Offset?): SwipeSource.Resolved? {
        if (startedPosition == null) return null
        return layoutImpl.swipeSourceDetector.source(
            layoutSize = layoutImpl.lastSize,
@@ -199,7 +199,7 @@ internal class DraggableHandlerImpl(
        )
    }

    private fun resolveSwipe(
    internal fun resolveSwipe(
        pointersDown: Int,
        fromSource: SwipeSource.Resolved?,
        isUpOrLeft: Boolean,
@@ -559,6 +559,14 @@ internal class NestedScrollHandlerImpl(

    val connection: PriorityNestedScrollConnection = nestedScrollConnection()

    private fun PointersInfo.resolveSwipe(isUpOrLeft: Boolean): Swipe.Resolved {
        return draggableHandler.resolveSwipe(
            pointersDown = pointersDown,
            fromSource = draggableHandler.resolveSwipeSource(startedPosition),
            isUpOrLeft = isUpOrLeft,
        )
    }

    private fun nestedScrollConnection(): PriorityNestedScrollConnection {
        // If we performed a long gesture before entering priority mode, we would have to avoid
        // moving on to the next scene.
@@ -575,36 +583,19 @@ internal class NestedScrollHandlerImpl(
            val transitionState = layoutState.transitionState
            val scene = transitionState.currentScene
            val fromScene = layoutImpl.scene(scene)
            val nextScene =
            val resolvedSwipe =
                when {
                    amount < 0f -> {
                        val actionUpOrLeft =
                            Swipe.Resolved(
                                direction =
                                    when (orientation) {
                                        Orientation.Horizontal -> SwipeDirection.Resolved.Left
                                        Orientation.Vertical -> SwipeDirection.Resolved.Up
                                    },
                                pointerCount = pointersInfo().pointersDown,
                                fromSource = null,
                            )
                        fromScene.userActions[actionUpOrLeft]
                    }
                    amount > 0f -> {
                        val actionDownOrRight =
                            Swipe.Resolved(
                                direction =
                                    when (orientation) {
                                        Orientation.Horizontal -> SwipeDirection.Resolved.Right
                                        Orientation.Vertical -> SwipeDirection.Resolved.Down
                                    },
                                pointerCount = pointersInfo().pointersDown,
                                fromSource = null,
                            )
                        fromScene.userActions[actionDownOrRight]
                    }
                    amount < 0f -> pointersInfo().resolveSwipe(isUpOrLeft = true)
                    amount > 0f -> pointersInfo().resolveSwipe(isUpOrLeft = false)
                    else -> null
                }
            val nextScene =
                resolvedSwipe?.let {
                    fromScene.userActions[it]
                        ?: if (it.fromSource != null) {
                            fromScene.userActions[it.copy(fromSource = null)]
                        } else null
                }
            if (nextScene != null) return true

            if (transitionState !is TransitionState.Idle) return false
+2 −1
Original line number Diff line number Diff line
@@ -213,8 +213,9 @@ internal class MultiPointerDraggableNode(

    internal fun pointersInfo(): PointersInfo {
        return PointersInfo(
            // This may be null, i.e. when the user uses TalkBack
            startedPosition = startedPosition,
            // Note: We could have 0 pointers during fling or for other reasons.
            // We could have 0 pointers during fling or for other reasons.
            pointersDown = pointersDown.coerceAtLeast(1),
        )
    }
+52 −4
Original line number Diff line number Diff line
@@ -130,6 +130,10 @@ class DraggableHandlerTest {
        val draggableHandler = layoutImpl.draggableHandler(Orientation.Vertical)
        val horizontalDraggableHandler = layoutImpl.draggableHandler(Orientation.Horizontal)

        var pointerInfoOwner: () -> PointersInfo = {
            PointersInfo(startedPosition = Offset.Zero, pointersDown = 1)
        }

        fun nestedScrollConnection(
            nestedScrollBehavior: NestedScrollBehavior,
            isExternalOverscrollGesture: Boolean = false,
@@ -140,9 +144,7 @@ class DraggableHandlerTest {
                    topOrLeftBehavior = nestedScrollBehavior,
                    bottomOrRightBehavior = nestedScrollBehavior,
                    isExternalOverscrollGesture = { isExternalOverscrollGesture },
                    pointersInfoOwner = {
                        PointersInfo(startedPosition = Offset.Zero, pointersDown = 1)
                    },
                    pointersInfoOwner = { pointerInfoOwner() },
                )
                .connection

@@ -156,11 +158,18 @@ class DraggableHandlerTest {

        fun downOffset(fractionOfScreen: Float) =
            if (fractionOfScreen < 0f) {
                error("upOffset() is required, not implemented yet")
                error("use upOffset()")
            } else {
                Offset(x = 0f, y = down(fractionOfScreen))
            }

        fun upOffset(fractionOfScreen: Float) =
            if (fractionOfScreen < 0f) {
                error("use downOffset()")
            } else {
                Offset(x = 0f, y = up(fractionOfScreen))
            }

        val transitionState: TransitionState
            get() = layoutState.transitionState

@@ -1134,6 +1143,45 @@ class DraggableHandlerTest {
        assertThat(transition!!.progress).isEqualTo(-0.1f)
    }

    @Test
    fun nestedScrollUseFromSourceInfo() = runGestureTest {
        // Start at scene C.
        navigateToSceneC()
        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)

        // Drag from the **top** of the screen
        pointerInfoOwner = { PointersInfo(startedPosition = Offset(0f, 0f), pointersDown = 1) }
        assertIdle(currentScene = SceneC)

        nestedScroll.scroll(available = upOffset(fractionOfScreen = 0.1f))
        assertTransition(
            currentScene = SceneC,
            fromScene = SceneC,
            // userAction: Swipe.Up to SceneB
            toScene = SceneB,
            progress = 0.1f,
        )

        // Reset to SceneC
        nestedScroll.preFling(Velocity.Zero)
        advanceUntilIdle()

        // Drag from the **bottom** of the screen
        pointerInfoOwner = {
            PointersInfo(startedPosition = Offset(0f, SCREEN_SIZE), pointersDown = 1)
        }
        assertIdle(currentScene = SceneC)

        nestedScroll.scroll(available = upOffset(fractionOfScreen = 0.1f))
        assertTransition(
            currentScene = SceneC,
            fromScene = SceneC,
            // userAction: Swipe(SwipeDirection.Up, fromSource = Edge.Bottom) to SceneA
            toScene = SceneA,
            progress = 0.1f,
        )
    }

    @Test
    fun transitionIsImmediatelyUpdatedWhenReleasingFinger() = runGestureTest {
        // Swipe up from the middle to transition to scene B.