1 /*
<lambda>null2  * Copyright (C) 2023 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 @file:OptIn(ExperimentalCoroutinesApi::class)
18 
19 package com.android.systemui.scene.data.repository
20 
21 import com.android.compose.animation.scene.ObservableTransitionState
22 import com.android.compose.animation.scene.SceneKey
23 import com.android.compose.animation.scene.TransitionKey
24 import com.android.systemui.dagger.SysUISingleton
25 import com.android.systemui.dagger.qualifiers.Application
26 import com.android.systemui.scene.shared.model.SceneContainerConfig
27 import com.android.systemui.scene.shared.model.SceneDataSource
28 import javax.inject.Inject
29 import kotlinx.coroutines.CoroutineScope
30 import kotlinx.coroutines.ExperimentalCoroutinesApi
31 import kotlinx.coroutines.flow.Flow
32 import kotlinx.coroutines.flow.MutableStateFlow
33 import kotlinx.coroutines.flow.SharingStarted
34 import kotlinx.coroutines.flow.StateFlow
35 import kotlinx.coroutines.flow.asStateFlow
36 import kotlinx.coroutines.flow.flatMapLatest
37 import kotlinx.coroutines.flow.flowOf
38 import kotlinx.coroutines.flow.stateIn
39 
40 @SysUISingleton
41 /** Source of truth for scene framework application state. */
42 class SceneContainerRepository
43 @Inject
44 constructor(
45     @Application applicationScope: CoroutineScope,
46     private val config: SceneContainerConfig,
47     private val dataSource: SceneDataSource,
48 ) {
49     val currentScene: StateFlow<SceneKey> = dataSource.currentScene
50 
51     private val _isVisible = MutableStateFlow(true)
52     val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
53 
54     /**
55      * Whether there's an ongoing remotely-initiated user interaction.
56      *
57      * For more information see the logic in `SceneInteractor` that mutates this.
58      */
59     val isRemoteUserInteractionOngoing = MutableStateFlow(false)
60 
61     private val defaultTransitionState = ObservableTransitionState.Idle(config.initialSceneKey)
62     private val _transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null)
63     val transitionState: StateFlow<ObservableTransitionState> =
64         _transitionState
65             .flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) }
66             .stateIn(
67                 scope = applicationScope,
68                 started = SharingStarted.Eagerly,
69                 initialValue = defaultTransitionState,
70             )
71 
72     /**
73      * Returns the keys to all scenes in the container.
74      *
75      * The scenes will be sorted in z-order such that the last one is the one that should be
76      * rendered on top of all previous ones.
77      */
78     fun allSceneKeys(): List<SceneKey> {
79         return config.sceneKeys
80     }
81 
82     fun changeScene(
83         toScene: SceneKey,
84         transitionKey: TransitionKey? = null,
85     ) {
86         dataSource.changeScene(
87             toScene = toScene,
88             transitionKey = transitionKey,
89         )
90     }
91 
92     fun snapToScene(
93         toScene: SceneKey,
94     ) {
95         dataSource.snapToScene(
96             toScene = toScene,
97         )
98     }
99 
100     /** Sets whether the container is visible. */
101     fun setVisible(isVisible: Boolean) {
102         _isVisible.value = isVisible
103     }
104 
105     /**
106      * Binds the given flow so the system remembers it.
107      *
108      * Note that you must call is with `null` when the UI is done or risk a memory leak.
109      */
110     fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) {
111         _transitionState.value = transitionState
112     }
113 }
114