1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.scene.shared.model
18 
19 import com.android.compose.animation.scene.SceneKey
20 import com.android.compose.animation.scene.TransitionKey
21 import kotlinx.coroutines.flow.MutableStateFlow
22 import kotlinx.coroutines.flow.StateFlow
23 import kotlinx.coroutines.flow.asStateFlow
24 
25 class FakeSceneDataSource(
26     initialSceneKey: SceneKey,
27 ) : SceneDataSource {
28 
29     private val _currentScene = MutableStateFlow(initialSceneKey)
30     override val currentScene: StateFlow<SceneKey> = _currentScene.asStateFlow()
31 
32     var isPaused = false
33         private set
34     var pendingScene: SceneKey? = null
35         private set
36 
changeScenenull37     override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) {
38         if (isPaused) {
39             pendingScene = toScene
40         } else {
41             _currentScene.value = toScene
42         }
43     }
44 
snapToScenenull45     override fun snapToScene(toScene: SceneKey) {
46         changeScene(toScene)
47     }
48 
49     /**
50      * Pauses scene changes.
51      *
52      * Any following calls to [changeScene] will be conflated and the last one will be remembered.
53      */
pausenull54     fun pause() {
55         check(!isPaused) { "Can't pause what's already paused!" }
56 
57         isPaused = true
58     }
59 
60     /**
61      * Unpauses scene changes.
62      *
63      * If there were any calls to [changeScene] since [pause] was called, the latest of the bunch
64      * will be replayed.
65      *
66      * If [force] is `true`, there will be no check that [isPaused] is true.
67      *
68      * If [expectedScene] is provided, will assert that it's indeed the latest called.
69      */
unpausenull70     fun unpause(
71         force: Boolean = false,
72         expectedScene: SceneKey? = null,
73     ) {
74         check(force || isPaused) { "Can't unpause what's already not paused!" }
75 
76         isPaused = false
77         pendingScene?.let { _currentScene.value = it }
78         pendingScene = null
79 
80         check(expectedScene == null || currentScene.value == expectedScene) {
81             """
82                 Unexpected scene while unpausing.
83                 Expected $expectedScene but was $currentScene.
84             """
85                 .trimIndent()
86         }
87     }
88 }
89