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

Commit fe967c69 authored by omarmt's avatar omarmt
Browse files

STL find ScrollBehaviorOwner if present

With the introduction of ag/29699552, node `SwipeToSceneRootNode` (and
consequentially `ScrollBehaviorOwnerNode`) is removed from the
composition if there are no scenes in that orientation.

Methods `nestedScrollToScene()` previously assumed the node was always
present and deferred to the STL to decide whether to consume the gesture.

Test: atest NestedScrollToSceneTest
Bug: 373802396
Flag: com.android.systemui.scene_container
Change-Id: I8dd09e5b9dfd834effd3ec8a228f5e0bf0a16f11
parent 58613adc
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -128,10 +128,10 @@ private class NestedScrollToSceneNode(
) : DelegatingNode() {
    private var scrollBehaviorOwner: ScrollBehaviorOwner? = null

    private fun requireScrollBehaviorOwner(): ScrollBehaviorOwner {
    private fun findScrollBehaviorOwner(): ScrollBehaviorOwner? {
        var behaviorOwner = scrollBehaviorOwner
        if (behaviorOwner == null) {
            behaviorOwner = requireScrollBehaviorOwner(layoutImpl.draggableHandler(orientation))
            behaviorOwner = findScrollBehaviorOwner(layoutImpl.draggableHandler(orientation))
            scrollBehaviorOwner = behaviorOwner
        }
        return behaviorOwner
@@ -156,8 +156,8 @@ private class NestedScrollToSceneNode(
                // transition between scenes. We can assume that the behavior is only needed if
                // there is some remaining amount.
                if (available != Offset.Zero) {
                    requireScrollBehaviorOwner()
                        .updateScrollBehaviors(
                    findScrollBehaviorOwner()
                        ?.updateScrollBehaviors(
                            topOrLeftBehavior = topOrLeftBehavior,
                            bottomOrRightBehavior = bottomOrRightBehavior,
                            isExternalOverscrollGesture = isExternalOverscrollGesture,
+5 −8
Original line number Diff line number Diff line
@@ -172,15 +172,12 @@ private class SwipeToSceneNode(
}

/** Find the [ScrollBehaviorOwner] for the current orientation. */
internal fun DelegatableNode.requireScrollBehaviorOwner(
internal fun DelegatableNode.findScrollBehaviorOwner(
    draggableHandler: DraggableHandlerImpl
): ScrollBehaviorOwner {
    val ancestorNode =
        checkNotNull(findNearestAncestor(draggableHandler.nestedScrollKey)) {
            "This should never happen! Couldn't find a ScrollBehaviorOwner. " +
                "Are we inside an SceneTransitionLayout?"
        }
    return ancestorNode as ScrollBehaviorOwner
): ScrollBehaviorOwner? {
    // If there are no scenes in a particular orientation, the corresponding ScrollBehaviorOwnerNode
    // is removed from the composition.
    return findNearestAncestor(draggableHandler.nestedScrollKey) as? ScrollBehaviorOwner
}

internal fun interface ScrollBehaviorOwner {
+34 −0
Original line number Diff line number Diff line
@@ -224,6 +224,40 @@ class NestedScrollToSceneTest {
        assertThat(state.transitionState).hasCurrentScene(SceneB)
    }

    @Test
    fun stlNotConsumeUnobservedGesture() {
        val state =
            rule.runOnUiThread {
                MutableSceneTransitionLayoutState(SceneA, transitions = EmptyTestTransitions)
            }

        rule.setContent {
            touchSlop = LocalViewConfiguration.current.touchSlop
            SceneTransitionLayout(
                state = state,
                modifier = Modifier.size(layoutWidth, layoutHeight),
            ) {
                scene(SceneA) {
                    Spacer(
                        Modifier.verticalNestedScrollToScene()
                            // This scrollable will not consume the gesture.
                            .scrollable(rememberScrollableState { 0f }, Vertical)
                            .fillMaxSize()
                    )
                }
            }
        }

        rule.onRoot().performTouchInput {
            down(Offset.Zero)
            // There is no vertical scene.
            moveBy(Offset(0f, layoutWidth.toPx()), delayMillis = 1_000)
        }

        rule.waitForIdle()
        assertThat(state.transitionState).isIdle()
    }

    @Test
    fun customizeStlNestedScrollBehavior_multipleRequests() {
        var canScroll = true