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.data.repository
18
19 import com.android.compose.animation.scene.ObservableTransitionState
20 import com.android.compose.animation.scene.OverlayKey
21 import com.android.compose.animation.scene.SceneKey
22 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
23 import com.android.systemui.keyguard.shared.model.KeyguardState
24 import com.android.systemui.keyguard.shared.model.TransitionStep
25 import com.android.systemui.kosmos.Kosmos
26 import com.android.systemui.kosmos.testScope
27 import com.android.systemui.scene.shared.flag.SceneContainerFlag
28 import com.android.systemui.scene.shared.model.Scenes
29 import kotlinx.coroutines.flow.Flow
30 import kotlinx.coroutines.flow.MutableStateFlow
31 import kotlinx.coroutines.flow.flowOf
32 import kotlinx.coroutines.test.TestScope
33
34 private val mutableTransitionState =
35 MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(Scenes.Lockscreen))
36
setTransitionnull37 suspend fun Kosmos.setTransition(
38 sceneTransition: ObservableTransitionState,
39 stateTransition: TransitionStep? = null,
40 fillInStateSteps: Boolean = true,
41 scope: TestScope = testScope,
42 repository: SceneContainerRepository = sceneContainerRepository,
43 ) {
44 var state: TransitionStep? = stateTransition
45 if (SceneContainerFlag.isEnabled) {
46 setSceneTransition(sceneTransition, scope, repository)
47
48 if (state != null) {
49 state = getStateWithUndefined(sceneTransition, state)
50 }
51 }
52
53 if (state == null) return
54 fakeKeyguardTransitionRepository.sendTransitionSteps(
55 step = state,
56 testScope = scope,
57 fillInSteps = fillInStateSteps,
58 )
59 scope.testScheduler.runCurrent()
60 }
61
setSceneTransitionnull62 fun Kosmos.setSceneTransition(
63 transition: ObservableTransitionState,
64 scope: TestScope = testScope,
65 repository: SceneContainerRepository = sceneContainerRepository,
66 ) {
67 repository.setTransitionState(mutableTransitionState)
68 mutableTransitionState.value = transition
69 scope.testScheduler.runCurrent()
70 }
71
Transitionnull72 fun Transition(
73 from: SceneKey,
74 to: SceneKey,
75 currentScene: Flow<SceneKey> = flowOf(to),
76 progress: Flow<Float> = flowOf(0f),
77 isInitiatedByUserInput: Boolean = false,
78 isUserInputOngoing: Flow<Boolean> = flowOf(false),
79 previewProgress: Flow<Float> = flowOf(0f),
80 isInPreviewStage: Flow<Boolean> = flowOf(false),
81 ): ObservableTransitionState.Transition {
82 return ObservableTransitionState.Transition(
83 fromScene = from,
84 toScene = to,
85 currentScene = currentScene,
86 progress = progress,
87 isInitiatedByUserInput = isInitiatedByUserInput,
88 isUserInputOngoing = isUserInputOngoing,
89 previewProgress = previewProgress,
90 isInPreviewStage = isInPreviewStage,
91 )
92 }
93
ShowOverlaynull94 fun ShowOverlay(
95 overlay: OverlayKey,
96 fromScene: SceneKey,
97 currentOverlays: Flow<Set<OverlayKey>> = flowOf(setOf(overlay)),
98 progress: Flow<Float> = flowOf(0f),
99 isInitiatedByUserInput: Boolean = false,
100 isUserInputOngoing: Flow<Boolean> = flowOf(false),
101 previewProgress: Flow<Float> = flowOf(0f),
102 isInPreviewStage: Flow<Boolean> = flowOf(false),
103 ): ObservableTransitionState.Transition {
104 return ObservableTransitionState.Transition.showOverlay(
105 overlay = overlay,
106 fromScene = fromScene,
107 currentOverlays = currentOverlays,
108 progress = progress,
109 isInitiatedByUserInput = isInitiatedByUserInput,
110 isUserInputOngoing = isUserInputOngoing,
111 previewProgress = previewProgress,
112 isInPreviewStage = isInPreviewStage,
113 )
114 }
115
HideOverlaynull116 fun HideOverlay(
117 overlay: OverlayKey,
118 toScene: SceneKey,
119 currentOverlays: Flow<Set<OverlayKey>> = flowOf(setOf(overlay)),
120 progress: Flow<Float> = flowOf(0f),
121 isInitiatedByUserInput: Boolean = false,
122 isUserInputOngoing: Flow<Boolean> = flowOf(false),
123 previewProgress: Flow<Float> = flowOf(0f),
124 isInPreviewStage: Flow<Boolean> = flowOf(false),
125 ): ObservableTransitionState.Transition {
126 return ObservableTransitionState.Transition.hideOverlay(
127 overlay = overlay,
128 toScene = toScene,
129 currentOverlays = currentOverlays,
130 progress = progress,
131 isInitiatedByUserInput = isInitiatedByUserInput,
132 isUserInputOngoing = isUserInputOngoing,
133 previewProgress = previewProgress,
134 isInPreviewStage = isInPreviewStage,
135 )
136 }
137
Idlenull138 fun Idle(
139 currentScene: SceneKey,
140 currentOverlays: Set<OverlayKey> = emptySet(),
141 ): ObservableTransitionState.Idle {
142 return ObservableTransitionState.Idle(currentScene, currentOverlays)
143 }
144
getStateWithUndefinednull145 private fun getStateWithUndefined(
146 sceneTransition: ObservableTransitionState,
147 state: TransitionStep,
148 ): TransitionStep {
149 return when (sceneTransition) {
150 is ObservableTransitionState.Idle -> {
151 TransitionStep(
152 from = state.from,
153 to =
154 if (sceneTransition.currentScene != Scenes.Lockscreen) {
155 KeyguardState.UNDEFINED
156 } else {
157 state.to
158 },
159 value = state.value,
160 transitionState = state.transitionState,
161 )
162 }
163 is ObservableTransitionState.Transition -> {
164 TransitionStep(
165 from =
166 if (sceneTransition.fromContent != Scenes.Lockscreen) {
167 KeyguardState.UNDEFINED
168 } else {
169 state.from
170 },
171 to =
172 if (sceneTransition.toContent != Scenes.Lockscreen) {
173 KeyguardState.UNDEFINED
174 } else {
175 state.from
176 },
177 value = state.value,
178 transitionState = state.transitionState,
179 )
180 }
181 else -> state
182 }
183 }
184