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

Commit 9e47735d authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Clear interruption values when necessary

Bug: 290930950
Test: ElementTest
Flag: N/A
Change-Id: Ie509a8d744ae7392e6a49fac2dd4cac8f657e657
parent e20a8718
Loading
Loading
Loading
Loading
+21 −8
Original line number Diff line number Diff line
@@ -329,10 +329,9 @@ private fun elementTransition(

    if (transition == null && previousTransition != null) {
        // The transition was just finished.
        element.sceneStates.values.forEach { sceneState ->
            sceneState.offsetInterruptionDelta = Offset.Zero
            sceneState.scaleInterruptionDelta = Scale.Zero
            sceneState.alphaInterruptionDelta = 0f
        element.sceneStates.values.forEach {
            it.clearValuesBeforeInterruption()
            it.clearInterruptionDeltas()
        }
    }

@@ -375,12 +374,22 @@ private fun prepareInterruption(element: Element) {
        sceneState.scaleBeforeInterruption = lastScale
        sceneState.alphaBeforeInterruption = lastAlpha

        sceneState.offsetInterruptionDelta = Offset.Zero
        sceneState.scaleInterruptionDelta = Scale.Zero
        sceneState.alphaInterruptionDelta = 0f
        sceneState.clearInterruptionDeltas()
    }
}

private fun Element.SceneState.clearInterruptionDeltas() {
    offsetInterruptionDelta = Offset.Zero
    scaleInterruptionDelta = Scale.Zero
    alphaInterruptionDelta = 0f
}

private fun Element.SceneState.clearValuesBeforeInterruption() {
    offsetBeforeInterruption = Offset.Unspecified
    scaleBeforeInterruption = Scale.Unspecified
    alphaBeforeInterruption = Element.AlphaUnspecified
}

/**
 * Compute what [value] should be if we take the
 * [interruption progress][TransitionState.Transition.interruptionProgress] of [transition] into
@@ -744,7 +753,11 @@ private fun ApproachMeasureScope.place(
        // No need to place the element in this scene if we don't want to draw it anyways.
        if (!shouldPlaceElement(layoutImpl, scene, element, transition)) {
            sceneState.lastOffset = Offset.Unspecified
            sceneState.offsetBeforeInterruption = Offset.Unspecified
            sceneState.lastScale = Scale.Unspecified
            sceneState.lastAlpha = Element.AlphaUnspecified

            sceneState.clearValuesBeforeInterruption()
            sceneState.clearInterruptionDeltas()
            return
        }

+33 −10
Original line number Diff line number Diff line
@@ -1049,24 +1049,30 @@ class ElementTest {
            Box(modifier.element(TestElements.Foo).size(fooSize))
        }

        lateinit var layoutImpl: SceneTransitionLayoutImpl
        rule.setContent {
            SceneTransitionLayout(state, Modifier.size(layoutSize)) {
            SceneTransitionLayoutForTesting(
                state,
                Modifier.size(layoutSize),
                onLayoutImpl = { layoutImpl = it },
            ) {
                // In scene A, Foo is aligned at the TopStart.
                scene(SceneA) {
                    Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.TopStart)) }
                }

                // In scene C, Foo is aligned at the BottomEnd, so it moves vertically when coming
                // from B. We put it before (below) scene B so that we can check that interruptions
                // values and deltas are properly cleared once all transitions are done.
                scene(SceneC) {
                    Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.BottomEnd)) }
                }

                // In scene B, Foo is aligned at the TopEnd, so it moves horizontally when coming
                // from A.
                scene(SceneB) {
                    Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.TopEnd)) }
                }

                // In scene C, Foo is aligned at the BottomEnd, so it moves vertically when coming
                // from B.
                scene(SceneC) {
                    Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.BottomEnd)) }
                }
            }
        }

@@ -1115,7 +1121,7 @@ class ElementTest {
        // Interruption progress is at 100% and bToC is at 0%, so Foo should be at the same offset
        // as right before the interruption.
        rule
            .onNode(isElement(TestElements.Foo, SceneC))
            .onNode(isElement(TestElements.Foo, SceneB))
            .assertPositionInRootIsEqualTo(offsetInAToB.x, offsetInAToB.y)

        // Move the transition forward at 30% and set the interruption progress to 50%.
@@ -1130,7 +1136,7 @@ class ElementTest {
                )
        rule.waitForIdle()
        rule
            .onNode(isElement(TestElements.Foo, SceneC))
            .onNode(isElement(TestElements.Foo, SceneB))
            .assertPositionInRootIsEqualTo(
                offsetInBToCWithInterruption.x,
                offsetInBToCWithInterruption.y,
@@ -1140,7 +1146,24 @@ class ElementTest {
        bToCProgress = 1f
        interruptionProgress = 0f
        rule
            .onNode(isElement(TestElements.Foo, SceneC))
            .onNode(isElement(TestElements.Foo, SceneB))
            .assertPositionInRootIsEqualTo(offsetInC.x, offsetInC.y)

        // Manually finish the transition.
        state.finishTransition(aToB, SceneB)
        state.finishTransition(bToC, SceneC)
        rule.waitForIdle()
        assertThat(state.currentTransition).isNull()

        // The interruption values should be unspecified and deltas should be set to zero.
        val foo = layoutImpl.elements.getValue(TestElements.Foo)
        assertThat(foo.sceneStates.keys).containsExactly(SceneC)
        val stateInC = foo.sceneStates.getValue(SceneC)
        assertThat(stateInC.offsetBeforeInterruption).isEqualTo(Offset.Unspecified)
        assertThat(stateInC.scaleBeforeInterruption).isEqualTo(Scale.Unspecified)
        assertThat(stateInC.alphaBeforeInterruption).isEqualTo(Element.AlphaUnspecified)
        assertThat(stateInC.offsetInterruptionDelta).isEqualTo(Offset.Zero)
        assertThat(stateInC.scaleInterruptionDelta).isEqualTo(Scale.Zero)
        assertThat(stateInC.alphaInterruptionDelta).isEqualTo(0f)
    }
}