1 /*
<lambda>null2  * 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.customization.picker.color.data.repository
18 
19 import android.content.Context
20 import android.graphics.Color
21 import android.text.TextUtils
22 import com.android.customization.model.ResourceConstants
23 import com.android.customization.model.color.ColorOptionImpl
24 import com.android.customization.model.color.ColorOptionsProvider
25 import com.android.customization.model.color.ColorUtils.toColorString
26 import com.android.customization.picker.color.shared.model.ColorOptionModel
27 import com.android.customization.picker.color.shared.model.ColorType
28 import com.android.systemui.monet.Style
29 import kotlinx.coroutines.flow.MutableStateFlow
30 import kotlinx.coroutines.flow.StateFlow
31 import kotlinx.coroutines.flow.asStateFlow
32 
33 class FakeColorPickerRepository(private val context: Context) : ColorPickerRepository {
34 
35     private val _isApplyingSystemColor = MutableStateFlow(false)
36     override val isApplyingSystemColor = _isApplyingSystemColor.asStateFlow()
37 
38     private lateinit var selectedColorOption: ColorOptionModel
39 
40     private val _colorOptions =
41         MutableStateFlow(
42             mapOf<ColorType, List<ColorOptionModel>>(
43                 ColorType.WALLPAPER_COLOR to listOf(),
44                 ColorType.PRESET_COLOR to listOf(),
45             )
46         )
47     override val colorOptions: StateFlow<Map<ColorType, List<ColorOptionModel>>> =
48         _colorOptions.asStateFlow()
49 
50     init {
51         setOptions(4, 4, ColorType.WALLPAPER_COLOR, 0)
52     }
53 
54     fun setOptions(
55         wallpaperOptions: List<ColorOptionImpl>,
56         presetOptions: List<ColorOptionImpl>,
57         selectedColorOptionType: ColorType,
58         selectedColorOptionIndex: Int,
59     ) {
60         _colorOptions.value =
61             mapOf(
62                 ColorType.WALLPAPER_COLOR to
63                     buildList {
64                         for ((index, colorOption) in wallpaperOptions.withIndex()) {
65                             val isSelected =
66                                 selectedColorOptionType == ColorType.WALLPAPER_COLOR &&
67                                     selectedColorOptionIndex == index
68                             val colorOptionModel =
69                                 ColorOptionModel(
70                                     key = "${ColorType.WALLPAPER_COLOR}::$index",
71                                     colorOption = colorOption,
72                                     isSelected = isSelected,
73                                 )
74                             if (isSelected) {
75                                 selectedColorOption = colorOptionModel
76                             }
77                             add(colorOptionModel)
78                         }
79                     },
80                 ColorType.PRESET_COLOR to
81                     buildList {
82                         for ((index, colorOption) in presetOptions.withIndex()) {
83                             val isSelected =
84                                 selectedColorOptionType == ColorType.PRESET_COLOR &&
85                                     selectedColorOptionIndex == index
86                             val colorOptionModel =
87                                 ColorOptionModel(
88                                     key = "${ColorType.PRESET_COLOR}::$index",
89                                     colorOption = colorOption,
90                                     isSelected = isSelected,
91                                 )
92                             if (isSelected) {
93                                 selectedColorOption = colorOptionModel
94                             }
95                             add(colorOptionModel)
96                         }
97                     },
98             )
99     }
100 
101     fun setOptions(
102         numWallpaperOptions: Int,
103         numPresetOptions: Int,
104         selectedColorOptionType: ColorType,
105         selectedColorOptionIndex: Int,
106     ) {
107         _colorOptions.value =
108             mapOf(
109                 ColorType.WALLPAPER_COLOR to
110                     buildList {
111                         repeat(times = numWallpaperOptions) { index ->
112                             val isSelected =
113                                 selectedColorOptionType == ColorType.WALLPAPER_COLOR &&
114                                     selectedColorOptionIndex == index
115                             val colorOption =
116                                 ColorOptionModel(
117                                     key = "${ColorType.WALLPAPER_COLOR}::$index",
118                                     colorOption = buildWallpaperOption(index),
119                                     isSelected = isSelected,
120                                 )
121                             if (isSelected) {
122                                 selectedColorOption = colorOption
123                             }
124                             add(colorOption)
125                         }
126                     },
127                 ColorType.PRESET_COLOR to
128                     buildList {
129                         repeat(times = numPresetOptions) { index ->
130                             val isSelected =
131                                 selectedColorOptionType == ColorType.PRESET_COLOR &&
132                                     selectedColorOptionIndex == index
133                             val colorOption =
134                                 ColorOptionModel(
135                                     key = "${ColorType.PRESET_COLOR}::$index",
136                                     colorOption = buildPresetOption(index),
137                                     isSelected = isSelected,
138                                 )
139                             if (isSelected) {
140                                 selectedColorOption = colorOption
141                             }
142                             add(colorOption)
143                         }
144                     },
145             )
146     }
147 
148     private fun buildPresetOption(index: Int): ColorOptionImpl {
149         val builder = ColorOptionImpl.Builder()
150         builder.lightColors =
151             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
152         builder.darkColors =
153             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
154         builder.index = index
155         builder.type = ColorType.PRESET_COLOR
156         builder.source = ColorOptionsProvider.COLOR_SOURCE_PRESET
157         builder.title = "Preset"
158         builder
159             .addOverlayPackage("TEST_PACKAGE_TYPE", "preset_color")
160             .addOverlayPackage("TEST_PACKAGE_INDEX", "$index")
161         return builder.build()
162     }
163 
164     fun buildPresetOption(@Style.Type style: Int, seedColor: Int): ColorOptionImpl {
165         val builder = ColorOptionImpl.Builder()
166         builder.lightColors =
167             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
168         builder.darkColors =
169             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
170         builder.type = ColorType.PRESET_COLOR
171         builder.source = ColorOptionsProvider.COLOR_SOURCE_PRESET
172         builder.style = style
173         builder.title = "Preset"
174         builder.seedColor = seedColor
175         builder
176             .addOverlayPackage("TEST_PACKAGE_TYPE", "preset_color")
177             .addOverlayPackage(
178                 ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE,
179                 toColorString(seedColor),
180             )
181         return builder.build()
182     }
183 
184     private fun buildWallpaperOption(index: Int): ColorOptionImpl {
185         val builder = ColorOptionImpl.Builder()
186         builder.lightColors =
187             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
188         builder.darkColors =
189             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
190         builder.index = index
191         builder.type = ColorType.WALLPAPER_COLOR
192         builder.source = ColorOptionsProvider.COLOR_SOURCE_HOME
193         builder.title = "Dynamic"
194         builder
195             .addOverlayPackage("TEST_PACKAGE_TYPE", "wallpaper_color")
196             .addOverlayPackage("TEST_PACKAGE_INDEX", "$index")
197         return builder.build()
198     }
199 
200     fun buildWallpaperOption(
201         source: String,
202         @Style.Type style: Int,
203         seedColor: Int,
204     ): ColorOptionImpl {
205         val builder = ColorOptionImpl.Builder()
206         builder.lightColors =
207             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
208         builder.darkColors =
209             intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
210         builder.type = ColorType.WALLPAPER_COLOR
211         builder.source = source
212         builder.style = style
213         builder.title = "Dynamic"
214         builder.seedColor = seedColor
215         builder
216             .addOverlayPackage("TEST_PACKAGE_TYPE", "wallpaper_color")
217             .addOverlayPackage(
218                 ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE,
219                 toColorString(seedColor),
220             )
221         return builder.build()
222     }
223 
224     override suspend fun select(colorOptionModel: ColorOptionModel) {
225         val colorOptions = _colorOptions.value
226         val wallpaperColorOptions = colorOptions[ColorType.WALLPAPER_COLOR]!!
227         val newWallpaperColorOptions = buildList {
228             wallpaperColorOptions.forEach { option ->
229                 add(
230                     ColorOptionModel(
231                         key = option.key,
232                         colorOption = option.colorOption,
233                         isSelected = option.testEquals(colorOptionModel),
234                     )
235                 )
236             }
237         }
238         val basicColorOptions = colorOptions[ColorType.PRESET_COLOR]!!
239         val newBasicColorOptions = buildList {
240             basicColorOptions.forEach { option ->
241                 add(
242                     ColorOptionModel(
243                         key = option.key,
244                         colorOption = option.colorOption,
245                         isSelected = option.testEquals(colorOptionModel),
246                     )
247                 )
248             }
249         }
250         _colorOptions.value =
251             mapOf(
252                 ColorType.WALLPAPER_COLOR to newWallpaperColorOptions,
253                 ColorType.PRESET_COLOR to newBasicColorOptions,
254             )
255     }
256 
257     override fun getCurrentColorOption(): ColorOptionModel = selectedColorOption
258 
259     override fun getCurrentColorSource(): String? =
260         when ((selectedColorOption.colorOption as ColorOptionImpl).type) {
261             ColorType.WALLPAPER_COLOR -> ColorOptionsProvider.COLOR_SOURCE_HOME
262             ColorType.PRESET_COLOR -> ColorOptionsProvider.COLOR_SOURCE_PRESET
263             else -> null
264         }
265 
266     private fun ColorOptionModel.testEquals(other: Any?): Boolean {
267         if (other == null) {
268             return false
269         }
270         return if (other is ColorOptionModel) {
271             TextUtils.equals(this.key, other.key)
272         } else {
273             false
274         }
275     }
276 }
277