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