1 /* 2 * 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.systemui.dagger.qualifiers.Application 22 import com.android.systemui.scene.shared.model.ObservableTransitionState 23 import com.android.systemui.scene.shared.model.SceneContainerConfig 24 import com.android.systemui.scene.shared.model.SceneKey 25 import com.android.systemui.scene.shared.model.SceneModel 26 import javax.inject.Inject 27 import kotlinx.coroutines.CoroutineScope 28 import kotlinx.coroutines.ExperimentalCoroutinesApi 29 import kotlinx.coroutines.flow.Flow 30 import kotlinx.coroutines.flow.MutableStateFlow 31 import kotlinx.coroutines.flow.SharingStarted 32 import kotlinx.coroutines.flow.StateFlow 33 import kotlinx.coroutines.flow.asStateFlow 34 import kotlinx.coroutines.flow.flatMapLatest 35 import kotlinx.coroutines.flow.flowOf 36 import kotlinx.coroutines.flow.stateIn 37 38 /** Source of truth for scene framework application state. */ 39 class SceneContainerRepository 40 @Inject 41 constructor( 42 @Application applicationScope: CoroutineScope, 43 private val config: SceneContainerConfig, 44 ) { 45 private val _desiredScene = MutableStateFlow(SceneModel(config.initialSceneKey)) 46 val desiredScene: StateFlow<SceneModel> = _desiredScene.asStateFlow() 47 48 private val _isVisible = MutableStateFlow(true) 49 val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow() 50 51 private val defaultTransitionState = ObservableTransitionState.Idle(config.initialSceneKey) 52 private val _transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null) 53 val transitionState: StateFlow<ObservableTransitionState> = 54 _transitionState 55 .flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) } 56 .stateIn( 57 scope = applicationScope, 58 started = SharingStarted.Eagerly, 59 initialValue = defaultTransitionState, 60 ) 61 62 /** 63 * Returns the keys to all scenes in the container. 64 * 65 * The scenes will be sorted in z-order such that the last one is the one that should be 66 * rendered on top of all previous ones. 67 */ 68 fun allSceneKeys(): List<SceneKey> { 69 return config.sceneKeys 70 } 71 72 fun setDesiredScene(scene: SceneModel) { 73 check(allSceneKeys().contains(scene.key)) { 74 """ 75 Cannot set the desired scene key to "${scene.key}". The configuration does not 76 contain a scene with that key. 77 """ 78 .trimIndent() 79 } 80 81 _desiredScene.value = scene 82 } 83 84 /** Sets whether the container is visible. */ 85 fun setVisible(isVisible: Boolean) { 86 _isVisible.value = isVisible 87 } 88 89 /** 90 * Binds the given flow so the system remembers it. 91 * 92 * Note that you must call is with `null` when the UI is done or risk a memory leak. 93 */ 94 fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) { 95 _transitionState.value = transitionState 96 } 97 } 98