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