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 package com.android.systemui.communal.ui.viewmodel 18 19 import android.content.ComponentName 20 import android.os.UserHandle 21 import android.view.View 22 import com.android.compose.animation.scene.ObservableTransitionState 23 import com.android.compose.animation.scene.SceneKey 24 import com.android.compose.animation.scene.TransitionKey 25 import com.android.systemui.communal.domain.interactor.CommunalInteractor 26 import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor 27 import com.android.systemui.communal.domain.model.CommunalContentModel 28 import com.android.systemui.communal.shared.model.EditModeState 29 import com.android.systemui.communal.widgets.WidgetConfigurator 30 import com.android.systemui.media.controls.ui.view.MediaHost 31 import kotlinx.coroutines.flow.Flow 32 import kotlinx.coroutines.flow.MutableStateFlow 33 import kotlinx.coroutines.flow.StateFlow 34 import kotlinx.coroutines.flow.flowOf 35 36 /** The base view model for the communal hub. */ 37 abstract class BaseCommunalViewModel( 38 val communalSceneInteractor: CommunalSceneInteractor, 39 private val communalInteractor: CommunalInteractor, 40 val mediaHost: MediaHost, 41 ) { 42 val currentScene: Flow<SceneKey> = communalSceneInteractor.currentScene 43 44 /** Used to animate showing or hiding the communal content. */ 45 open val isCommunalContentVisible: Flow<Boolean> = MutableStateFlow(false) 46 47 /** Whether communal hub should be focused by accessibility tools. */ 48 open val isFocusable: Flow<Boolean> = MutableStateFlow(false) 49 50 /** Whether widgets are currently being re-ordered. */ 51 open val reorderingWidgets: StateFlow<Boolean> = MutableStateFlow(false) 52 53 private val _selectedKey: MutableStateFlow<String?> = MutableStateFlow(null) 54 55 /** The key of the currently selected item, or null if no item selected. */ 56 val selectedKey: StateFlow<String?> 57 get() = _selectedKey 58 59 /** Accessibility delegate to be set on CommunalAppWidgetHostView. */ 60 open val widgetAccessibilityDelegate: View.AccessibilityDelegate? = null 61 signalUserInteractionnull62 fun signalUserInteraction() { 63 communalInteractor.signalUserInteraction() 64 } 65 changeScenenull66 fun changeScene(scene: SceneKey, transitionKey: TransitionKey? = null) { 67 communalSceneInteractor.changeScene(scene, transitionKey) 68 } 69 setEditModeStatenull70 fun setEditModeState(state: EditModeState?) = communalSceneInteractor.setEditModeState(state) 71 72 /** 73 * Updates the transition state of the hub [SceneTransitionLayout]. 74 * 75 * Note that you must call is with `null` when the UI is done or risk a memory leak. 76 */ 77 fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) { 78 communalSceneInteractor.setTransitionState(transitionState) 79 } 80 81 /** 82 * Called when a widget is added via drag and drop from the widget picker into the communal hub. 83 */ onAddWidgetnull84 open fun onAddWidget( 85 componentName: ComponentName, 86 user: UserHandle, 87 priority: Int, 88 configurator: WidgetConfigurator? = null 89 ) { 90 communalInteractor.addWidget(componentName, user, priority, configurator) 91 } 92 onOpenEnableWidgetDialognull93 open fun onOpenEnableWidgetDialog() {} 94 onOpenEnableWorkProfileDialognull95 open fun onOpenEnableWorkProfileDialog() {} 96 97 /** A list of all the communal content to be displayed in the communal hub. */ 98 abstract val communalContent: Flow<List<CommunalContentModel>> 99 100 /** 101 * Whether to freeze the emission of the communalContent flow to prevent recomposition. Defaults 102 * to false, indicating that the flow will emit new update. 103 */ 104 open val isCommunalContentFlowFrozen: Flow<Boolean> = flowOf(false) 105 106 /** Whether in edit mode for the communal hub. */ 107 open val isEditMode = false 108 109 /** Whether the type of popup currently showing */ 110 open val currentPopup: Flow<PopupType?> = flowOf(null) 111 112 /** Whether the communal hub is empty with no widget available. */ 113 open val isEmptyState: Flow<Boolean> = flowOf(false) 114 115 /** Called as the UI request to dismiss the any displaying popup */ onHidePopupnull116 open fun onHidePopup() {} 117 118 /** Called as the UI requests deleting a widget. */ onDeleteWidgetnull119 open fun onDeleteWidget(id: Int) {} 120 121 /** 122 * Called as the UI requests reordering widgets. 123 * 124 * @param widgetIdToPriorityMap mapping of the widget ids to its priority. When re-ordering to 125 * add a new item in the middle, provide the priorities of existing widgets as if the new item 126 * existed, and then, call [onAddWidget] to add the new item at intended order. 127 */ onReorderWidgetsnull128 open fun onReorderWidgets(widgetIdToPriorityMap: Map<Int, Int>) {} 129 130 /** Called as the UI requests opening the widget editor with an optional preselected widget. */ onOpenWidgetEditornull131 open fun onOpenWidgetEditor( 132 preselectedKey: String? = null, 133 shouldOpenWidgetPickerOnStart: Boolean = false, 134 ) {} 135 136 /** Called as the UI requests to dismiss the CTA tile. */ onDismissCtaTilenull137 open fun onDismissCtaTile() {} 138 139 /** Called as the user starts dragging a widget to reorder. */ onReorderWidgetStartnull140 open fun onReorderWidgetStart() {} 141 142 /** Called as the user finishes dragging a widget to reorder. */ onReorderWidgetEndnull143 open fun onReorderWidgetEnd() {} 144 145 /** Called as the user cancels dragging a widget to reorder. */ onReorderWidgetCancelnull146 open fun onReorderWidgetCancel() {} 147 148 /** Called as the user request to show the customize widget button. */ onShowCustomizeWidgetButtonnull149 open fun onShowCustomizeWidgetButton() {} 150 151 /** Set the key of the currently selected item */ setSelectedKeynull152 fun setSelectedKey(key: String?) { 153 _selectedKey.value = key 154 } 155 } 156