• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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.OverlayKey
20 import com.android.compose.animation.scene.SceneKey
21 import com.android.compose.animation.scene.TransitionKey
22 import kotlinx.coroutines.CoroutineScope
23 import kotlinx.coroutines.flow.MutableStateFlow
24 import kotlinx.coroutines.flow.SharingStarted
25 import kotlinx.coroutines.flow.StateFlow
26 import kotlinx.coroutines.flow.asStateFlow
27 import kotlinx.coroutines.flow.flatMapLatest
28 import kotlinx.coroutines.flow.stateIn
29 
30 /**
31  * Delegates calls to a runtime-provided [SceneDataSource] or to a no-op implementation if a
32  * delegate isn't set.
33  */
34 class SceneDataSourceDelegator(applicationScope: CoroutineScope, config: SceneContainerConfig) :
35     SceneDataSource {
36     private val noOpDelegate = NoOpSceneDataSource(config.initialSceneKey)
37     private val delegateMutable = MutableStateFlow<SceneDataSource>(noOpDelegate)
38 
39     override val currentScene: StateFlow<SceneKey> =
40         delegateMutable
41             .flatMapLatest { delegate -> delegate.currentScene }
42             .stateIn(
43                 scope = applicationScope,
44                 started = SharingStarted.WhileSubscribed(),
45                 initialValue = config.initialSceneKey,
46             )
47 
48     override val currentOverlays: StateFlow<Set<OverlayKey>> =
49         delegateMutable
50             .flatMapLatest { delegate -> delegate.currentOverlays }
51             .stateIn(
52                 scope = applicationScope,
53                 started = SharingStarted.WhileSubscribed(),
54                 initialValue = emptySet(),
55             )
56 
57     override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) {
58         delegateMutable.value.changeScene(toScene = toScene, transitionKey = transitionKey)
59     }
60 
61     override fun snapToScene(toScene: SceneKey) {
62         delegateMutable.value.snapToScene(toScene = toScene)
63     }
64 
65     override fun showOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) {
66         delegateMutable.value.showOverlay(overlay = overlay, transitionKey = transitionKey)
67     }
68 
69     override fun hideOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) {
70         delegateMutable.value.hideOverlay(overlay = overlay, transitionKey = transitionKey)
71     }
72 
73     override fun replaceOverlay(from: OverlayKey, to: OverlayKey, transitionKey: TransitionKey?) {
74         delegateMutable.value.replaceOverlay(from = from, to = to, transitionKey = transitionKey)
75     }
76 
77     override fun instantlyShowOverlay(overlay: OverlayKey) {
78         delegateMutable.value.instantlyShowOverlay(overlay)
79     }
80 
81     override fun instantlyHideOverlay(overlay: OverlayKey) {
82         delegateMutable.value.instantlyHideOverlay(overlay)
83     }
84 
85     override fun freezeAndAnimateToCurrentState() {
86         delegateMutable.value.freezeAndAnimateToCurrentState()
87     }
88 
89     /**
90      * Binds the current, dependency injection provided [SceneDataSource] to the given object.
91      *
92      * In other words: once this is invoked, the state and functionality of the [SceneDataSource]
93      * will be served by the given [delegate].
94      *
95      * If `null` is passed in, the delegator will use a no-op implementation of [SceneDataSource].
96      *
97      * This removes any previously set delegate.
98      */
99     fun setDelegate(delegate: SceneDataSource?) {
100         delegateMutable.value = delegate ?: noOpDelegate
101     }
102 
103     private class NoOpSceneDataSource(initialSceneKey: SceneKey) : SceneDataSource {
104         override val currentScene: StateFlow<SceneKey> =
105             MutableStateFlow(initialSceneKey).asStateFlow()
106 
107         override val currentOverlays: StateFlow<Set<OverlayKey>> =
108             MutableStateFlow(emptySet<OverlayKey>()).asStateFlow()
109 
110         override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = Unit
111 
112         override fun snapToScene(toScene: SceneKey) = Unit
113 
114         override fun showOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) = Unit
115 
116         override fun hideOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) = Unit
117 
118         override fun replaceOverlay(
119             from: OverlayKey,
120             to: OverlayKey,
121             transitionKey: TransitionKey?,
122         ) = Unit
123 
124         override fun instantlyShowOverlay(overlay: OverlayKey) = Unit
125 
126         override fun instantlyHideOverlay(overlay: OverlayKey) = Unit
127 
128         override fun freezeAndAnimateToCurrentState() = Unit
129     }
130 }
131