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 package com.android.systemui.communal.data.repository 18 19 import com.android.compose.animation.scene.ObservableTransitionState 20 import com.android.compose.animation.scene.SceneKey 21 import com.android.compose.animation.scene.TransitionKey 22 import com.android.systemui.communal.dagger.Communal 23 import com.android.systemui.communal.shared.model.CommunalScenes 24 import com.android.systemui.dagger.SysUISingleton 25 import com.android.systemui.dagger.qualifiers.Application 26 import com.android.systemui.dagger.qualifiers.Background 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.delay 32 import kotlinx.coroutines.flow.Flow 33 import kotlinx.coroutines.flow.MutableStateFlow 34 import kotlinx.coroutines.flow.SharingStarted 35 import kotlinx.coroutines.flow.StateFlow 36 import kotlinx.coroutines.flow.flatMapLatest 37 import kotlinx.coroutines.flow.flowOf 38 import kotlinx.coroutines.flow.stateIn 39 import kotlinx.coroutines.launch 40 41 /** Encapsulates the state of communal mode. */ 42 interface CommunalSceneRepository { 43 /** 44 * Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene]. 45 */ 46 val currentScene: StateFlow<SceneKey> 47 48 /** Exposes the transition state of the communal [SceneTransitionLayout]. */ 49 val transitionState: StateFlow<ObservableTransitionState> 50 51 /** Updates the requested scene. */ 52 fun changeScene(toScene: SceneKey, transitionKey: TransitionKey? = null) 53 54 /** Immediately snaps to the desired scene. */ 55 fun snapToScene(toScene: SceneKey, delayMillis: Long = 0) 56 57 /** 58 * Updates the transition state of the hub [SceneTransitionLayout]. 59 * 60 * Note that you must call is with `null` when the UI is done or risk a memory leak. 61 */ 62 fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) 63 } 64 65 @OptIn(ExperimentalCoroutinesApi::class) 66 @SysUISingleton 67 class CommunalSceneRepositoryImpl 68 @Inject 69 constructor( 70 @Application private val applicationScope: CoroutineScope, 71 @Background backgroundScope: CoroutineScope, 72 @Communal private val sceneDataSource: SceneDataSource, 73 ) : CommunalSceneRepository { 74 75 override val currentScene: StateFlow<SceneKey> = sceneDataSource.currentScene 76 77 private val defaultTransitionState = ObservableTransitionState.Idle(CommunalScenes.Default) 78 private val _transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null) 79 override val transitionState: StateFlow<ObservableTransitionState> = 80 _transitionState innerFlowOrNullnull81 .flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) } 82 .stateIn( 83 scope = backgroundScope, 84 started = SharingStarted.Lazily, 85 initialValue = defaultTransitionState, 86 ) 87 changeScenenull88 override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) { 89 applicationScope.launch { 90 // SceneTransitionLayout state updates must be triggered on the thread the STL was 91 // created on. 92 sceneDataSource.changeScene(toScene, transitionKey) 93 } 94 } 95 snapToScenenull96 override fun snapToScene(toScene: SceneKey, delayMillis: Long) { 97 applicationScope.launch { 98 // SceneTransitionLayout state updates must be triggered on the thread the STL was 99 // created on. 100 delay(delayMillis) 101 sceneDataSource.snapToScene(toScene) 102 } 103 } 104 105 /** 106 * Updates the transition state of the hub [SceneTransitionLayout]. 107 * 108 * Note that you must call is with `null` when the UI is done or risk a memory leak. 109 */ setTransitionStatenull110 override fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) { 111 _transitionState.value = transitionState 112 } 113 } 114