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.wallpaper.picker.common.preview.ui.binder 18 19 import android.os.Bundle 20 import android.os.Message 21 import androidx.core.os.bundleOf 22 import androidx.lifecycle.Lifecycle 23 import androidx.lifecycle.LifecycleOwner 24 import androidx.lifecycle.lifecycleScope 25 import androidx.lifecycle.repeatOnLifecycle 26 import com.android.customization.model.grid.DefaultShapeGridManager.Companion.COL_GRID_NAME 27 import com.android.customization.model.grid.DefaultShapeGridManager.Companion.COL_SHAPE_KEY 28 import com.android.customization.picker.clock.shared.ClockSize 29 import com.android.customization.picker.clock.ui.view.ClockViewFactory 30 import com.android.customization.picker.color.data.util.MaterialColorsGenerator 31 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END 32 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START 33 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.CLOCK_SIZE_DYNAMIC 34 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.CLOCK_SIZE_SMALL 35 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_CLOCK_SIZE 36 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE 37 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID 38 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_QUICK_AFFORDANCE_ID 39 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_SLOT_ID 40 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_DEFAULT_PREVIEW 41 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE 42 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_PREVIEW_CLOCK_SIZE 43 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED 44 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED 45 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES 46 import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerLockCustomizationOption 47 import com.android.wallpaper.customization.ui.viewmodel.ThemePickerCustomizationOptionsViewModel 48 import com.android.wallpaper.model.Screen 49 import com.android.wallpaper.picker.common.preview.ui.binder.WorkspaceCallbackBinder.Companion.sendMessage 50 import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel 51 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModel 52 import javax.inject.Inject 53 import javax.inject.Singleton 54 import kotlinx.coroutines.flow.combine 55 import kotlinx.coroutines.launch 56 57 @Singleton 58 class ThemePickerWorkspaceCallbackBinder 59 @Inject 60 constructor( 61 private val defaultWorkspaceCallbackBinder: DefaultWorkspaceCallbackBinder, 62 private val materialColorsGenerator: MaterialColorsGenerator, 63 ) : WorkspaceCallbackBinder { 64 65 override fun bind( 66 workspaceCallback: Message, 67 viewModel: CustomizationOptionsViewModel, 68 colorUpdateViewModel: ColorUpdateViewModel, 69 screen: Screen, 70 lifecycleOwner: LifecycleOwner, 71 clockViewFactory: ClockViewFactory, 72 ) { 73 defaultWorkspaceCallbackBinder.bind( 74 workspaceCallback = workspaceCallback, 75 viewModel = viewModel, 76 colorUpdateViewModel = colorUpdateViewModel, 77 screen = screen, 78 lifecycleOwner = lifecycleOwner, 79 clockViewFactory = clockViewFactory, 80 ) 81 82 if (viewModel !is ThemePickerCustomizationOptionsViewModel) { 83 throw IllegalArgumentException( 84 "viewModel $viewModel is not a ThemePickerCustomizationOptionsViewModel." 85 ) 86 } 87 88 when (screen) { 89 Screen.LOCK_SCREEN -> 90 lifecycleOwner.lifecycleScope.launch { 91 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 92 launch { 93 viewModel.selectedOption.collect { 94 when (it) { 95 ThemePickerLockCustomizationOption.SHORTCUTS -> 96 workspaceCallback.sendMessage( 97 MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES, 98 Bundle().apply { 99 putString( 100 KEY_INITIALLY_SELECTED_SLOT_ID, 101 SLOT_ID_BOTTOM_START, 102 ) 103 }, 104 ) 105 else -> 106 workspaceCallback.sendMessage( 107 MESSAGE_ID_DEFAULT_PREVIEW, 108 Bundle.EMPTY, 109 ) 110 } 111 } 112 } 113 114 launch { 115 viewModel.keyguardQuickAffordancePickerViewModel2.selectedSlotId 116 .collect { 117 workspaceCallback.sendMessage( 118 MESSAGE_ID_SLOT_SELECTED, 119 Bundle().apply { putString(KEY_SLOT_ID, it) }, 120 ) 121 } 122 } 123 124 launch { 125 viewModel.keyguardQuickAffordancePickerViewModel2 126 .previewingQuickAffordances 127 .collect { 128 it[SLOT_ID_BOTTOM_START]?.let { 129 workspaceCallback.sendMessage( 130 MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED, 131 Bundle().apply { 132 putString(KEY_SLOT_ID, SLOT_ID_BOTTOM_START) 133 putString(KEY_QUICK_AFFORDANCE_ID, it) 134 }, 135 ) 136 } 137 it[SLOT_ID_BOTTOM_END]?.let { 138 workspaceCallback.sendMessage( 139 MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED, 140 Bundle().apply { 141 putString(KEY_SLOT_ID, SLOT_ID_BOTTOM_END) 142 putString(KEY_QUICK_AFFORDANCE_ID, it) 143 }, 144 ) 145 } 146 } 147 } 148 149 launch { 150 combine( 151 viewModel.clockPickerViewModel.previewingClock, 152 viewModel.clockPickerViewModel.previewingClockSize, 153 ::Pair, 154 ) 155 .collect { (previewingClock, previewingClockSize) -> 156 val hideSmartspace = 157 clockViewFactory 158 .getController(previewingClock.clockId) 159 .let { 160 when (previewingClockSize) { 161 ClockSize.DYNAMIC -> 162 it.largeClock.config 163 .hasCustomWeatherDataDisplay 164 ClockSize.SMALL -> 165 it.smallClock.config 166 .hasCustomWeatherDataDisplay 167 } 168 } 169 workspaceCallback.sendMessage( 170 MESSAGE_ID_HIDE_SMART_SPACE, 171 Bundle().apply { 172 putBoolean(KEY_HIDE_SMART_SPACE, hideSmartspace) 173 }, 174 ) 175 176 workspaceCallback.sendMessage( 177 MESSAGE_ID_PREVIEW_CLOCK_SIZE, 178 Bundle().apply { 179 putString( 180 KEY_CLOCK_SIZE, 181 when (previewingClockSize) { 182 ClockSize.DYNAMIC -> CLOCK_SIZE_DYNAMIC 183 ClockSize.SMALL -> CLOCK_SIZE_SMALL 184 }, 185 ) 186 }, 187 ) 188 } 189 } 190 } 191 } 192 Screen.HOME_SCREEN -> 193 lifecycleOwner.lifecycleScope.launch { 194 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 195 launch { 196 viewModel.shapeGridPickerViewModel.previewingShapeKey.collect { 197 workspaceCallback.sendMessage( 198 MESSAGE_ID_UPDATE_SHAPE, 199 bundleOf(COL_SHAPE_KEY to it), 200 ) 201 } 202 } 203 204 launch { 205 viewModel.shapeGridPickerViewModel.previewingGridKey.collect { 206 workspaceCallback.sendMessage( 207 MESSAGE_ID_UPDATE_GRID, 208 bundleOf(COL_GRID_NAME to it), 209 ) 210 } 211 } 212 213 launch { 214 colorUpdateViewModel.systemColorsUpdated.collect { 215 viewModel.colorPickerViewModel2.onApplyComplete() 216 } 217 } 218 219 launch { 220 combine( 221 viewModel.colorPickerViewModel2.previewingColorOption, 222 viewModel.darkModeViewModel.overridingIsDarkMode, 223 ::Pair, 224 ) 225 .collect { (colorModel, darkMode) -> 226 val bundle = 227 Bundle().apply { 228 if (colorModel != null) { 229 val (ids, colors) = 230 materialColorsGenerator.generate( 231 colorModel.colorOption.seedColor, 232 colorModel.colorOption.style, 233 ) 234 putIntArray(KEY_COLOR_RESOURCE_IDS, ids) 235 putIntArray(KEY_COLOR_VALUES, colors) 236 } 237 238 if (darkMode != null) { 239 putBoolean(KEY_DARK_MODE, darkMode) 240 } 241 } 242 workspaceCallback.sendMessage(MESSAGE_ID_UPDATE_COLOR, bundle) 243 } 244 } 245 } 246 } 247 } 248 } 249 250 companion object { 251 const val MESSAGE_ID_UPDATE_SHAPE = 2586 252 const val MESSAGE_ID_UPDATE_GRID = 7414 253 254 const val MESSAGE_ID_UPDATE_COLOR = 856 255 const val KEY_COLOR_RESOURCE_IDS: String = "color_resource_ids" 256 const val KEY_COLOR_VALUES: String = "color_values" 257 const val KEY_DARK_MODE: String = "use_dark_mode" 258 } 259 } 260