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

Commit 4e81ba44 authored by Omar Miatello's avatar Omar Miatello Committed by Android (Google) Code Review
Browse files

Merge "Moved NestedScrollConnection into SwipeToScene" into main

parents 9ec83fe1 43de60f2
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -913,9 +913,9 @@ private class Swipes(
internal class NestedScrollHandlerImpl(
    private val layoutImpl: SceneTransitionLayoutImpl,
    private val orientation: Orientation,
    private val topOrLeftBehavior: NestedScrollBehavior,
    private val bottomOrRightBehavior: NestedScrollBehavior,
    private val isExternalOverscrollGesture: () -> Boolean,
    internal var topOrLeftBehavior: NestedScrollBehavior,
    internal var bottomOrRightBehavior: NestedScrollBehavior,
    internal var isExternalOverscrollGesture: () -> Boolean,
    private val pointersInfoOwner: PointersInfoOwner,
) {
    private val layoutState = layoutImpl.state
+1 −6
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import androidx.compose.ui.node.DelegatingNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.node.ObserverModifierNode
import androidx.compose.ui.node.PointerInputModifierNode
import androidx.compose.ui.node.TraversableNode
import androidx.compose.ui.node.currentValueOf
import androidx.compose.ui.node.findNearestAncestor
import androidx.compose.ui.node.observeReads
@@ -139,16 +138,12 @@ internal class MultiPointerDraggableNode(
    DelegatingNode(),
    PointerInputModifierNode,
    CompositionLocalConsumerModifierNode,
    TraversableNode,
    PointersInfoOwner,
    ObserverModifierNode {
    private val pointerInputHandler: suspend PointerInputScope.() -> Unit = { pointerInput() }
    private val delegate = delegate(SuspendingPointerInputModifierNode(pointerInputHandler))
    private val velocityTracker = VelocityTracker()
    private var previousEnabled: Boolean = false

    override val traverseKey: Any = TRAVERSE_KEY

    var enabled: () -> Boolean = enabled
        set(value) {
            // Reset the pointer input whenever enabled changed.
@@ -208,7 +203,7 @@ internal class MultiPointerDraggableNode(
    private var startedPosition: Offset? = null
    private var pointersDown: Int = 0

    override fun pointersInfo(): PointersInfo {
    internal fun pointersInfo(): PointersInfo {
        return PointersInfo(
            startedPosition = startedPosition,
            // Note: We could have 0 pointers during fling or for other reasons.
+8 −72
Original line number Diff line number Diff line
@@ -22,11 +22,9 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScrollModifierNode
import androidx.compose.ui.node.DelegatableNode
import androidx.compose.ui.node.DelegatingNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.InspectorInfo
import com.android.compose.nestedscroll.PriorityNestedScrollConnection

/**
 * Defines the behavior of the [SceneTransitionLayout] when a scrollable component is scrolled.
@@ -70,7 +68,11 @@ enum class NestedScrollBehavior(val canStartOnPostFling: Boolean) {
     * In addition, during scene transitions, scroll events are consumed by the
     * [SceneTransitionLayout] instead of the scrollable component.
     */
    EdgeAlways(canStartOnPostFling = true),
    EdgeAlways(canStartOnPostFling = true);

    companion object {
        val Default = EdgeNoPreview
    }
}

internal fun Modifier.nestedScrollToScene(
@@ -131,7 +133,6 @@ private class NestedScrollToSceneNode(
    private var bottomOrRightBehavior: NestedScrollBehavior,
    private var isExternalOverscrollGesture: () -> Boolean,
) : DelegatingNode() {
    lateinit var pointersInfoOwner: PointersInfoOwner
    private var scrollBehaviorOwner: ScrollBehaviorOwner? = null

    private fun requireScrollBehaviorOwner(): ScrollBehaviorOwner {
@@ -143,7 +144,7 @@ private class NestedScrollToSceneNode(
        return behaviorOwner
    }

    val updateScrollBehaviorsConnection =
    private val updateScrollBehaviorsConnection =
        object : NestedScrollConnection {
            /**
             * When using [NestedScrollConnection.onPostScroll], we can specify the desired behavior
@@ -174,37 +175,11 @@ private class NestedScrollToSceneNode(
            }
        }

    private var priorityNestedScrollConnection: PriorityNestedScrollConnection =
        scenePriorityNestedScrollConnection(
            layoutImpl = layoutImpl,
            orientation = orientation,
            topOrLeftBehavior = topOrLeftBehavior,
            bottomOrRightBehavior = bottomOrRightBehavior,
            isExternalOverscrollGesture = isExternalOverscrollGesture,
            pointersInfoOwner = { pointersInfoOwner.pointersInfo() }
        )

    private var nestedScrollNode: DelegatableNode =
        nestedScrollModifierNode(
            connection = priorityNestedScrollConnection,
            dispatcher = null,
        )

    private var updateScrollBehaviorsNestedScrollNode: DelegatableNode =
        nestedScrollModifierNode(
            connection = updateScrollBehaviorsConnection,
            dispatcher = null,
        )

    override fun onAttach() {
        pointersInfoOwner = requireAncestorPointersInfoOwner()
        delegate(nestedScrollNode)
        delegate(updateScrollBehaviorsNestedScrollNode)
    init {
        delegate(nestedScrollModifierNode(updateScrollBehaviorsConnection, dispatcher = null))
    }

    override fun onDetach() {
        // Make sure we reset the scroll connection when this modifier is removed from composition
        priorityNestedScrollConnection.reset()
        scrollBehaviorOwner = null
    }

@@ -220,44 +195,5 @@ private class NestedScrollToSceneNode(
        this.topOrLeftBehavior = topOrLeftBehavior
        this.bottomOrRightBehavior = bottomOrRightBehavior
        this.isExternalOverscrollGesture = isExternalOverscrollGesture

        // Clean up the old nested scroll connection
        priorityNestedScrollConnection.reset()
        undelegate(nestedScrollNode)

        // Create a new nested scroll connection
        priorityNestedScrollConnection =
            scenePriorityNestedScrollConnection(
                layoutImpl = layoutImpl,
                orientation = orientation,
                topOrLeftBehavior = topOrLeftBehavior,
                bottomOrRightBehavior = bottomOrRightBehavior,
                isExternalOverscrollGesture = isExternalOverscrollGesture,
                pointersInfoOwner = pointersInfoOwner,
            )
        nestedScrollNode =
            nestedScrollModifierNode(
                connection = priorityNestedScrollConnection,
                dispatcher = null,
            )
        delegate(nestedScrollNode)
    }
}

private fun scenePriorityNestedScrollConnection(
    layoutImpl: SceneTransitionLayoutImpl,
    orientation: Orientation,
    topOrLeftBehavior: NestedScrollBehavior,
    bottomOrRightBehavior: NestedScrollBehavior,
    isExternalOverscrollGesture: () -> Boolean,
    pointersInfoOwner: PointersInfoOwner,
) =
    NestedScrollHandlerImpl(
            layoutImpl = layoutImpl,
            orientation = orientation,
            topOrLeftBehavior = topOrLeftBehavior,
            bottomOrRightBehavior = bottomOrRightBehavior,
            isExternalOverscrollGesture = isExternalOverscrollGesture,
            pointersInfoOwner = pointersInfoOwner,
        )
        .connection
+4 −4
Original line number Diff line number Diff line
@@ -207,8 +207,8 @@ interface BaseSceneScope : ElementStateScope {
     * @param rightBehavior when we should perform the overscroll animation at the right.
     */
    fun Modifier.horizontalNestedScrollToScene(
        leftBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
        rightBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
        leftBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
        rightBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
        isExternalOverscrollGesture: () -> Boolean = { false },
    ): Modifier

@@ -220,8 +220,8 @@ interface BaseSceneScope : ElementStateScope {
     * @param bottomBehavior when we should perform the overscroll animation at the bottom.
     */
    fun Modifier.verticalNestedScrollToScene(
        topBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
        bottomBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
        topBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
        bottomBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
        isExternalOverscrollGesture: () -> Boolean = { false },
    ): Modifier

+26 −5
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import androidx.compose.foundation.gestures.Orientation
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.nestedScrollModifierNode
import androidx.compose.ui.input.pointer.PointerEvent
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.node.DelegatableNode
@@ -81,8 +82,24 @@ private class SwipeToSceneNode(
            }
        }

    override fun onAttach() {
        delegate(ScrollBehaviorOwnerNode(draggableHandler.nestedScrollKey))
    private val nestedScrollHandlerImpl =
        NestedScrollHandlerImpl(
            layoutImpl = draggableHandler.layoutImpl,
            orientation = draggableHandler.orientation,
            topOrLeftBehavior = NestedScrollBehavior.Default,
            bottomOrRightBehavior = NestedScrollBehavior.Default,
            isExternalOverscrollGesture = { false },
            pointersInfoOwner = { multiPointerDraggableNode.pointersInfo() },
        )

    init {
        delegate(nestedScrollModifierNode(nestedScrollHandlerImpl.connection, dispatcher = null))
        delegate(ScrollBehaviorOwnerNode(draggableHandler.nestedScrollKey, nestedScrollHandlerImpl))
    }

    override fun onDetach() {
        // Make sure we reset the scroll connection when this modifier is removed from composition
        nestedScrollHandlerImpl.connection.reset()
    }

    override fun onPointerEvent(
@@ -151,13 +168,17 @@ internal fun interface ScrollBehaviorOwner {
 *
 * TODO(b/353234530) move this logic into [SwipeToSceneNode]
 */
private class ScrollBehaviorOwnerNode(override val traverseKey: Any) :
    Modifier.Node(), TraversableNode, ScrollBehaviorOwner {
private class ScrollBehaviorOwnerNode(
    override val traverseKey: Any,
    val nestedScrollHandlerImpl: NestedScrollHandlerImpl
) : Modifier.Node(), TraversableNode, ScrollBehaviorOwner {
    override fun updateScrollBehaviors(
        topOrLeftBehavior: NestedScrollBehavior,
        bottomOrRightBehavior: NestedScrollBehavior,
        isExternalOverscrollGesture: () -> Boolean
    ) {
        // This method will be used to update the desired behavior in a following CL.
        nestedScrollHandlerImpl.topOrLeftBehavior = topOrLeftBehavior
        nestedScrollHandlerImpl.bottomOrRightBehavior = bottomOrRightBehavior
        nestedScrollHandlerImpl.isExternalOverscrollGesture = isExternalOverscrollGesture
    }
}
Loading