blob: 1f4be40602232b59d858ab9efbf7cc0a8e2ad8cd [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.communal.data.repository
import com.android.systemui.Flags.communalHub
import com.android.systemui.communal.shared.model.CommunalSceneKey
import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.scene.data.repository.SceneContainerRepository
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.SceneKey
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Encapsulates the state of communal mode. */
interface CommunalRepository {
/** Whether communal features are enabled. */
val isCommunalEnabled: Boolean
/** Whether the communal hub is showing. */
val isCommunalHubShowing: Flow<Boolean>
/**
* Target scene as requested by the underlying [SceneTransitionLayout] or through
* [setDesiredScene].
*/
val desiredScene: StateFlow<CommunalSceneKey>
/** Exposes the transition state of the communal [SceneTransitionLayout]. */
val transitionState: StateFlow<ObservableCommunalTransitionState>
/** Updates the requested scene. */
fun setDesiredScene(desiredScene: CommunalSceneKey)
/**
* Updates the transition state of the hub [SceneTransitionLayout].
*
* Note that you must call is with `null` when the UI is done or risk a memory leak.
*/
fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?)
}
@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalRepositoryImpl
@Inject
constructor(
@Background backgroundScope: CoroutineScope,
private val featureFlagsClassic: FeatureFlagsClassic,
sceneContainerFlags: SceneContainerFlags,
sceneContainerRepository: SceneContainerRepository,
) : CommunalRepository {
override val isCommunalEnabled: Boolean
get() = featureFlagsClassic.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) && communalHub()
private val _desiredScene: MutableStateFlow<CommunalSceneKey> =
MutableStateFlow(CommunalSceneKey.DEFAULT)
override val desiredScene: StateFlow<CommunalSceneKey> = _desiredScene.asStateFlow()
private val defaultTransitionState =
ObservableCommunalTransitionState.Idle(CommunalSceneKey.DEFAULT)
private val _transitionState = MutableStateFlow<Flow<ObservableCommunalTransitionState>?>(null)
override val transitionState: StateFlow<ObservableCommunalTransitionState> =
_transitionState
.flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) }
.stateIn(
scope = backgroundScope,
started = SharingStarted.Lazily,
initialValue = defaultTransitionState,
)
override fun setDesiredScene(desiredScene: CommunalSceneKey) {
_desiredScene.value = desiredScene
}
/**
* Updates the transition state of the hub [SceneTransitionLayout].
*
* Note that you must call is with `null` when the UI is done or risk a memory leak.
*/
override fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?) {
_transitionState.value = transitionState
}
override val isCommunalHubShowing: Flow<Boolean> =
if (sceneContainerFlags.isEnabled()) {
sceneContainerRepository.desiredScene.map { scene -> scene.key == SceneKey.Communal }
} else {
desiredScene.map { sceneKey -> sceneKey == CommunalSceneKey.Communal }
}
}