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

Commit 25506a4f authored by Andreas Miko's avatar Andreas Miko
Browse files

Make TransitionLinks match more flexible

TransitionLinks can be initialized with `null` to indicate matching any
Scene in this slot.

Test: SceneTransitionLayoutStateTest
Bug: b/320257219
Flag: NONE
Change-Id: I3b3cf18cab4b8cc177c314f8401f8384b655876b
parent d25d0d8d
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -251,12 +251,15 @@ internal abstract class BaseSceneTransitionLayoutState(
    private fun setupTransitionLinks(transitionState: TransitionState) {
        if (transitionState !is TransitionState.Transition) return
        stateLinks.fastForEach { stateLink ->
            val matchingLink =
                stateLink.transitionLinks.firstOrNull() { it.isMatchingLink(transitionState) } ?: return@fastForEach
            val matchingLinks =
                stateLink.transitionLinks.fastFilter { it.isMatchingLink(transitionState) }
            if (matchingLinks.isEmpty()) return@fastForEach
            if (matchingLinks.size > 1) error("More than one link matched.")

            val targetCurrentScene = stateLink.target.transitionState.currentScene
            val matchingLink = matchingLinks[0]

            if (targetCurrentScene != matchingLink.targetFrom) return@fastForEach
            if (!matchingLink.targetIsInValidState(targetCurrentScene)) return@fastForEach

            val linkedTransition =
                LinkedTransition(
+6 −6
Original line number Diff line number Diff line
@@ -35,9 +35,9 @@ class StateLink(target: SceneTransitionLayoutState, val transitionLinks: List<Tr
     * target to `SceneA` from any current scene.
     */
    class TransitionLink(
        val sourceFrom: SceneKey,
        val sourceTo: SceneKey,
        val targetFrom: SceneKey,
        val sourceFrom: SceneKey?,
        val sourceTo: SceneKey?,
        val targetFrom: SceneKey?,
        val targetTo: SceneKey,
        val targetTransitionKey: TransitionKey? = null,
    ) {
@@ -50,12 +50,12 @@ class StateLink(target: SceneTransitionLayoutState, val transitionLinks: List<Tr
        }

        internal fun isMatchingLink(transition: TransitionState.Transition): Boolean {
            return (sourceFrom == transition.fromScene) &&
                (sourceTo == transition.toScene)
            return (sourceFrom == null || sourceFrom == transition.fromScene) &&
                (sourceTo == null || sourceTo == transition.toScene)
        }

        internal fun targetIsInValidState(targetCurrentScene: SceneKey): Boolean {
            return (targetFrom == targetCurrentScene) &&
            return (targetFrom == null || targetFrom == targetCurrentScene) &&
                targetTo != targetCurrentScene
        }
    }
+52 −5
Original line number Diff line number Diff line
@@ -130,17 +130,23 @@ class SceneTransitionLayoutStateTest {
        assertThat(state.transitionState).isEqualTo(TransitionState.Idle(SceneB))
    }

    private fun setupLinkedStates():
            Pair<BaseSceneTransitionLayoutState, BaseSceneTransitionLayoutState> {
        val parentState = MutableSceneTransitionLayoutState(SceneC)
    private fun setupLinkedStates(
        parentInitialScene: SceneKey = SceneC,
        childInitialScene: SceneKey = SceneA,
        sourceFrom: SceneKey? = SceneA,
        sourceTo: SceneKey? = SceneB,
        targetFrom: SceneKey? = SceneC,
        targetTo: SceneKey = SceneD
    ): Pair<BaseSceneTransitionLayoutState, BaseSceneTransitionLayoutState> {
        val parentState = MutableSceneTransitionLayoutState(parentInitialScene)
        val link =
            listOf(
                StateLink(
                    parentState,
                    listOf(StateLink.TransitionLink(SceneA, SceneB, SceneC, SceneD))
                    listOf(StateLink.TransitionLink(sourceFrom, sourceTo, targetFrom, targetTo))
                )
            )
        val childState = MutableSceneTransitionLayoutState(SceneA, stateLinks = link)
        val childState = MutableSceneTransitionLayoutState(childInitialScene, stateLinks = link)
        return Pair(
            parentState as BaseSceneTransitionLayoutState,
            childState as BaseSceneTransitionLayoutState
@@ -342,4 +348,45 @@ class SceneTransitionLayoutStateTest {
        assertThat(state.isTransitioning()).isFalse()
        assertThat(state.transitionState).isEqualTo(TransitionState.Idle(TestScenes.SceneB))
    }

    @Test
    fun linkedTransition_fuzzyLinksAreMatchedAndStarted() {
        val (parentState, childState) = setupLinkedStates(SceneC, SceneA, null, null, null, SceneD)
        val childTransition = TestableTransition(SceneA, SceneB)

        childState.startTransition(childTransition, null)
        assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue()
        assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue()

        childState.finishTransition(childTransition, SceneB)
        assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneB))
        assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneD))
    }

    @Test
    fun linkedTransition_fuzzyLinksAreMatchedAndResetToProperPreviousScene() {
        val (parentState, childState) =
            setupLinkedStates(SceneC, SceneA, SceneA, null, null, SceneD)

        val childTransition = TestableTransition(SceneA, SceneB)

        childState.startTransition(childTransition, null)
        assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue()
        assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue()

        childState.finishTransition(childTransition, SceneA)
        assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneA))
        assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneC))
    }

    @Test
    fun linkedTransition_fuzzyLinksAreNotMatched() {
        val (parentState, childState) =
            setupLinkedStates(SceneC, SceneA, SceneB, null, SceneC, SceneD)
        val childTransition = TestableTransition(SceneA, SceneB)

        childState.startTransition(childTransition, null)
        assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue()
        assertThat(parentState.isTransitioning(SceneC, SceneD)).isFalse()
    }
}