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

Commit 6f6b35d0 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] Introduces a previousScene flow.

This is needed for bugs like the attached one and potentially other bugs
where logic needs to know not only the current scene but also the
previous scene but don't need to monitor every scene-to-scene transition
state.

Bug: 330695017
Test: added unit tests at the data and domain layers
Test: manually verified the fix for the attached bug with the next CL in
the chain
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT

Change-Id: Ifb07f26f47a210d46b17fdbcc665dbc6f8c272b5
parent 9a2e20a9
Loading
Loading
Loading
Loading
+19 −0
Original line number Original line Diff line number Diff line
@@ -140,4 +140,23 @@ class SceneContainerRepositoryTest : SysuiTestCase() {
                    ObservableTransitionState.Idle(kosmos.sceneContainerConfig.initialSceneKey)
                    ObservableTransitionState.Idle(kosmos.sceneContainerConfig.initialSceneKey)
                )
                )
        }
        }

    @Test
    fun previousScene() =
        testScope.runTest {
            val underTest = kosmos.sceneContainerRepository
            val currentScene by collectLastValue(underTest.currentScene)
            val previousScene by collectLastValue(underTest.previousScene)

            assertThat(previousScene).isNull()

            val firstScene = currentScene
            underTest.changeScene(Scenes.Shade)
            assertThat(previousScene).isEqualTo(firstScene)
            assertThat(currentScene).isEqualTo(Scenes.Shade)

            underTest.changeScene(Scenes.QuickSettings)
            assertThat(previousScene).isEqualTo(Scenes.Shade)
            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
        }
}
}
+15 −0
Original line number Original line Diff line number Diff line
@@ -291,4 +291,19 @@ class SceneInteractorTest : SysuiTestCase() {


            assertThat(isVisible).isFalse()
            assertThat(isVisible).isFalse()
        }
        }

    @Test
    fun previousScene() =
        testScope.runTest {
            val currentScene by collectLastValue(underTest.currentScene)
            val previousScene by collectLastValue(underTest.previousScene)
            assertThat(previousScene).isNull()

            val firstScene = currentScene
            underTest.changeScene(toScene = Scenes.Shade, "reason")
            assertThat(previousScene).isEqualTo(firstScene)

            underTest.changeScene(toScene = Scenes.QuickSettings, "reason")
            assertThat(previousScene).isEqualTo(Scenes.Shade)
        }
}
}
+29 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@ import com.android.compose.animation.scene.TransitionKey
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneDataSource
import com.android.systemui.scene.shared.model.SceneDataSource
import com.android.systemui.util.kotlin.WithPrev
import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,6 +36,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.stateIn


/** Source of truth for scene framework application state. */
/** Source of truth for scene framework application state. */
@@ -44,7 +47,32 @@ constructor(
    private val config: SceneContainerConfig,
    private val config: SceneContainerConfig,
    private val dataSource: SceneDataSource,
    private val dataSource: SceneDataSource,
) {
) {
    val currentScene: StateFlow<SceneKey> = dataSource.currentScene
    private val previousAndCurrentScene: StateFlow<WithPrev<SceneKey?, SceneKey>> =
        dataSource.currentScene
            .pairwise()
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = WithPrev(null, dataSource.currentScene.value),
            )

    val currentScene: StateFlow<SceneKey> =
        previousAndCurrentScene
            .map { it.newValue }
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = previousAndCurrentScene.value.newValue,
            )

    val previousScene: StateFlow<SceneKey?> =
        previousAndCurrentScene
            .map { it.previousValue }
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = previousAndCurrentScene.value.previousValue,
            )


    private val _isVisible = MutableStateFlow(true)
    private val _isVisible = MutableStateFlow(true)
    val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
    val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
+8 −0
Original line number Original line Diff line number Diff line
@@ -139,6 +139,14 @@ constructor(
                initialValue = isVisibleInternal()
                initialValue = isVisibleInternal()
            )
            )


    /**
     * The previous scene.
     *
     * This is effectively the previous value of [currentScene] which means that all caveats, for
     * example regarding when in a transition the current scene changes, apply.
     */
    val previousScene: StateFlow<SceneKey?> = repository.previousScene

    /**
    /**
     * Returns the keys of all scenes in the container.
     * Returns the keys of all scenes in the container.
     *
     *