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

Commit 5cb61d04 authored by Johannes Gallmann's avatar Johannes Gallmann
Browse files

Expose previewProgress and isInPreviewStage in ObservableTransitionState

Bug: 350705972
Test: ObservableTransitionStateTest
Flag: com.android.systemui.scene_container
Change-Id: I708eb96d81ea75e2bb264b054d3a215a5f30c7e9
parent 0c96ea06
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,12 @@ sealed interface ObservableTransitionState {
         * the transition completes/settles.
         * the transition completes/settles.
         */
         */
        val isUserInputOngoing: Flow<Boolean>,
        val isUserInputOngoing: Flow<Boolean>,

        /** Current progress of the preview part of the transition */
        val previewProgress: Flow<Float> = flowOf(0f),

        /** Whether the transition is currently in the preview stage or not */
        val isInPreviewStage: Flow<Boolean> = flowOf(false),
    ) : ObservableTransitionState {
    ) : ObservableTransitionState {
        override fun toString(): String =
        override fun toString(): String =
            """Transition
            """Transition
@@ -113,6 +119,8 @@ fun SceneTransitionLayoutState.observableTransitionState(): Flow<ObservableTrans
                        progress = snapshotFlow { state.progress },
                        progress = snapshotFlow { state.progress },
                        isInitiatedByUserInput = state.isInitiatedByUserInput,
                        isInitiatedByUserInput = state.isInitiatedByUserInput,
                        isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
                        isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
                        previewProgress = snapshotFlow { state.previewProgress },
                        isInPreviewStage = snapshotFlow { state.isInPreviewStage }
                    )
                    )
                }
                }
            }
            }
+92 −2
Original line number Original line Diff line number Diff line
@@ -16,11 +16,16 @@


package com.android.compose.animation.scene
package com.android.compose.animation.scene


import androidx.activity.BackEventCompat
import androidx.activity.ComponentActivity
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.getValue
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.Modifier
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.TestScenes.SceneB
@@ -36,7 +41,7 @@ import org.junit.runner.RunWith


@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
class ObservableTransitionStateTest {
class ObservableTransitionStateTest {
    @get:Rule val rule = createComposeRule()
    @get:Rule val rule = createAndroidComposeRule<ComponentActivity>()


    @Test
    @Test
    fun testObservableTransitionState() = runTest {
    fun testObservableTransitionState() = runTest {
@@ -145,6 +150,82 @@ class ObservableTransitionStateTest {
        assertThat(currentScene.value).isEqualTo(SceneA)
        assertThat(currentScene.value).isEqualTo(SceneA)
    }
    }


    @Test
    fun testObservablePreviewTransitionState() = runTest {
        val layoutState =
            rule.runOnUiThread {
                MutableSceneTransitionLayoutState(
                    SceneA,
                    transitions = transitions { from(SceneA, to = SceneB, preview = {}) }
                )
            }
        rule.setContent {
            SceneTransitionLayout(layoutState) {
                scene(SceneA, mapOf(Back to SceneB)) { Box(Modifier.fillMaxSize()) }
                scene(SceneB) { Box(Modifier.fillMaxSize()) }
            }
        }

        var observableState: ObservableTransitionState? = null
        backgroundScope.launch {
            layoutState.observableTransitionState().collect { observableState = it }
        }

        fun observableState(): ObservableTransitionState {
            runCurrent()
            return observableState!!
        }

        fun ObservableTransitionState.Transition.previewProgress(): Float {
            var lastProgress = -1f
            backgroundScope.launch { previewProgress.collect { lastProgress = it } }
            runCurrent()
            return lastProgress
        }

        fun ObservableTransitionState.Transition.isInPreviewStage(): Boolean {
            var lastIsInPreviewStage = false
            backgroundScope.launch { isInPreviewStage.collect { lastIsInPreviewStage = it } }
            runCurrent()
            return lastIsInPreviewStage
        }

        // Start back.
        val dispatcher = rule.activity.onBackPressedDispatcher
        rule.runOnUiThread {
            dispatcher.dispatchOnBackStarted(backEvent())
            dispatcher.dispatchOnBackProgressed(backEvent(progress = 0.4f))
        }

        var state = observableState()
        assertThat(state).isInstanceOf(ObservableTransitionState.Transition::class.java)
        assertThat((state as ObservableTransitionState.Transition).fromScene).isEqualTo(SceneA)
        assertThat(state.previewProgress()).isEqualTo(0.4f)
        assertThat(state.isInPreviewStage()).isEqualTo(true)

        // Cancel it.
        rule.runOnUiThread { dispatcher.dispatchOnBackCancelled() }
        rule.waitForIdle()
        state = observableState()
        assertThat(state).isInstanceOf(ObservableTransitionState.Idle::class.java)

        // Start again and commit it.
        rule.runOnUiThread {
            dispatcher.dispatchOnBackStarted(backEvent())
            dispatcher.dispatchOnBackProgressed(backEvent(progress = 0.4f))
            dispatcher.onBackPressed()
        }
        state = observableState()
        assertThat(state).isInstanceOf(ObservableTransitionState.Transition::class.java)
        assertThat((state as ObservableTransitionState.Transition).fromScene).isEqualTo(SceneA)
        assertThat(state.previewProgress()).isEqualTo(0.4f)
        assertThat(state.isInPreviewStage()).isEqualTo(false)

        rule.waitForIdle()
        state = observableState()
        assertThat(state).isInstanceOf(ObservableTransitionState.Idle::class.java)
    }

    // See http://shortn/_hj4Mhikmos for inspiration.
    // See http://shortn/_hj4Mhikmos for inspiration.
    private fun runTestWithSnapshots(testBody: suspend TestScope.() -> Unit) {
    private fun runTestWithSnapshots(testBody: suspend TestScope.() -> Unit) {
        val globalWriteObserverHandle =
        val globalWriteObserverHandle =
@@ -159,4 +240,13 @@ class ObservableTransitionStateTest {
            globalWriteObserverHandle.dispose()
            globalWriteObserverHandle.dispose()
        }
        }
    }
    }

    private fun backEvent(progress: Float = 0f): BackEventCompat {
        return BackEventCompat(
            touchX = 0f,
            touchY = 0f,
            progress = progress,
            swipeEdge = BackEventCompat.EDGE_LEFT,
        )
    }
}
}
+5 −1
Original line number Original line Diff line number Diff line
@@ -69,6 +69,8 @@ fun Transition(
    progress: Flow<Float> = flowOf(0f),
    progress: Flow<Float> = flowOf(0f),
    isInitiatedByUserInput: Boolean = false,
    isInitiatedByUserInput: Boolean = false,
    isUserInputOngoing: Flow<Boolean> = flowOf(false),
    isUserInputOngoing: Flow<Boolean> = flowOf(false),
    previewProgress: Flow<Float> = flowOf(0f),
    isInPreviewStage: Flow<Boolean> = flowOf(false)
): ObservableTransitionState.Transition {
): ObservableTransitionState.Transition {
    return ObservableTransitionState.Transition(
    return ObservableTransitionState.Transition(
        fromScene = from,
        fromScene = from,
@@ -76,7 +78,9 @@ fun Transition(
        currentScene = currentScene,
        currentScene = currentScene,
        progress = progress,
        progress = progress,
        isInitiatedByUserInput = isInitiatedByUserInput,
        isInitiatedByUserInput = isInitiatedByUserInput,
        isUserInputOngoing = isUserInputOngoing
        isUserInputOngoing = isUserInputOngoing,
        previewProgress = previewProgress,
        isInPreviewStage = isInPreviewStage
    )
    )
}
}