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