[TP] Use design clock colors
Use the clock colors approved from the designers. For each color, we
have its min and max tone to tune.
1. Create ClockColorViewModel to represents a clock color config
2. Use string id to identify the selected color
3. Rename COLOR_TONE to COLOR_TONE_PROGRESS
Test: manually test that the color tone works as expected
Bug: 241966062
Change-Id: Iadb9ae773478008137413ad5873bb88f9a63b4b1
diff --git a/res/values/clock_colors.xml b/res/values/clock_colors.xml
new file mode 100644
index 0000000..1539a92
--- /dev/null
+++ b/res/values/clock_colors.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string-array name="clock_color_ids">
+ <item>RED</item>
+ <item>ORANGE</item>
+ <item>YELLOW</item>
+ <item>GREEN</item>
+ <item>BLUE</item>
+ <item>INDIGO</item>
+ <item>VIOLET</item>
+ <item>GRAY</item>
+ <item>TEAL</item>
+ </string-array>
+ <array name="clock_color_names">
+ <item>@string/clock_color_red</item>
+ <item>@string/clock_color_orange</item>
+ <item>@string/clock_color_yellow</item>
+ <item>@string/clock_color_green</item>
+ <item>@string/clock_color_blue</item>
+ <item>@string/clock_color_indigo</item>
+ <item>@string/clock_color_violet</item>
+ <item>@string/clock_color_gray</item>
+ <item>@string/clock_color_teal</item>
+ </array>
+ <array name="clock_colors">
+ <item>#FFA3A7</item>
+ <item>#F7AC69</item>
+ <item>#FFC951</item>
+ <item>#88D86A</item>
+ <item>#8EC8FF</item>
+ <item>#B9AAFF</item>
+ <item>#F6A2FF</item>
+ <item>#B9B9B9</item>
+ <item>#40D9CF</item>
+ </array>
+ <array name="clock_color_tone_min">
+ <item>20</item>
+ <item>20</item>
+ <item>50</item>
+ <item>20</item>
+ <item>20</item>
+ <item>10</item>
+ <item>20</item>
+ <item>0</item>
+ <item>20</item>
+ </array>
+ <array name="clock_color_tone_max">
+ <item>95</item>
+ <item>95</item>
+ <item>95</item>
+ <item>99</item>
+ <item>95</item>
+ <item>95</item>
+ <item>97</item>
+ <item>100</item>
+ <item>99</item>
+ </array>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3bd9e84..18c0103 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -45,6 +45,33 @@
<!-- Title of a tab to change the clock color. [CHAR LIMIT=15] -->
<string name="clock_color">Color</string>
+ <!-- Title of a clock color red option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_red">Red</string>
+
+ <!-- Title of a clock color orange option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_orange">Orange</string>
+
+ <!-- Title of a clock color yellow option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_yellow">Yellow</string>
+
+ <!-- Title of a clock color green option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_green">Green</string>
+
+ <!-- Title of a clock color blue option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_blue">Blue</string>
+
+ <!-- Title of a clock color indigo option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_indigo">Indigo</string>
+
+ <!-- Title of a clock color violet option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_violet">Violet</string>
+
+ <!-- Title of a clock color grey option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_gray">Grey</string>
+
+ <!-- Title of a clock color teal option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+ <string name="clock_color_teal">Teal</string>
+
<!-- Title of a tab to change the clock size. [CHAR LIMIT=15] -->
<string name="clock_size">Size</string>
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
index 3474858..ae66ce3 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
@@ -39,12 +39,12 @@
* Set clock color to the settings.
*
* @param selectedColor selected color in the color option list.
- * @param colorTone color tone from 0 to 100 to apply to the selected color
+ * @param colorToneProgress color tone from 0 to 100 to apply to the selected color
* @param seedColor the actual clock color after blending the selected color and color tone
*/
fun setClockColor(
- @ColorInt selectedColor: Int?,
- @IntRange(from = 0, to = 100) colorTone: Int,
+ selectedColorId: String?,
+ @IntRange(from = 0, to = 100) colorToneProgress: Int,
@ColorInt seedColor: Int?,
)
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
index e96649b..880a00b 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -86,9 +86,9 @@
.getClocks()
.find { clockMetadata -> clockMetadata.clockId == currentClockId }
?.toModel(
- selectedColor = metadata?.getSelectedColor(),
+ selectedColorId = metadata?.getSelectedColorId(),
colorTone = metadata?.getColorTone()
- ?: ClockMetadataModel.DEFAULT_COLOR_TONE,
+ ?: ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
seedColor = registry.seedColor
)
trySend(model)
@@ -119,16 +119,16 @@
}
override fun setClockColor(
- @ColorInt selectedColor: Int?,
- @IntRange(from = 0, to = 100) colorTone: Int,
+ selectedColorId: String?,
+ @IntRange(from = 0, to = 100) colorToneProgress: Int,
@ColorInt seedColor: Int?,
) {
registry.mutateSetting { oldSettings ->
val newSettings = oldSettings.copy(seedColor = seedColor)
newSettings.metadata =
oldSettings.metadata
- .put(KEY_METADATA_SELECTED_COLOR, selectedColor)
- .put(KEY_METADATA_COLOR_TONE, colorTone)
+ .put(KEY_METADATA_SELECTED_COLOR_ID, selectedColorId)
+ .put(KEY_METADATA_COLOR_TONE_PROGRESS, colorToneProgress)
newSettings
}
}
@@ -153,38 +153,41 @@
)
}
- private fun JSONObject.getSelectedColor(): Int? {
- return if (this.isNull(KEY_METADATA_SELECTED_COLOR)) {
+ private fun JSONObject.getSelectedColorId(): String? {
+ return if (this.isNull(KEY_METADATA_SELECTED_COLOR_ID)) {
null
} else {
- this.getInt(KEY_METADATA_SELECTED_COLOR)
+ this.getString(KEY_METADATA_SELECTED_COLOR_ID)
}
}
private fun JSONObject.getColorTone(): Int {
- return this.optInt(KEY_METADATA_COLOR_TONE, ClockMetadataModel.DEFAULT_COLOR_TONE)
+ return this.optInt(
+ KEY_METADATA_COLOR_TONE_PROGRESS,
+ ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS
+ )
}
/** By default, [ClockMetadataModel] has no color information unless specified. */
private fun ClockMetadata.toModel(
- @ColorInt selectedColor: Int? = null,
+ selectedColorId: String? = null,
@IntRange(from = 0, to = 100) colorTone: Int = 0,
@ColorInt seedColor: Int? = null,
): ClockMetadataModel {
return ClockMetadataModel(
clockId = clockId,
name = name,
- selectedColor = selectedColor,
- colorTone = colorTone,
+ selectedColorId = selectedColorId,
+ colorToneProgress = colorTone,
seedColor = seedColor,
)
}
companion object {
// The selected color in the color option list
- private const val KEY_METADATA_SELECTED_COLOR = "metadataSelectedColor"
+ private const val KEY_METADATA_SELECTED_COLOR_ID = "metadataSelectedColorId"
// The color tone to apply to the selected color
- private const val KEY_METADATA_COLOR_TONE = "metadataColorTone"
+ private const val KEY_METADATA_COLOR_TONE_PROGRESS = "metadataColorToneProgress"
}
}
diff --git a/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt b/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
index 794706f..6f3657a 100644
--- a/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
+++ b/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
@@ -17,6 +17,8 @@
package com.android.customization.picker.clock.domain.interactor
+import androidx.annotation.ColorInt
+import androidx.annotation.IntRange
import com.android.customization.picker.clock.data.repository.ClockPickerRepository
import com.android.customization.picker.clock.shared.ClockSize
import com.android.customization.picker.clock.shared.model.ClockMetadataModel
@@ -35,10 +37,11 @@
val selectedClockId: Flow<String> =
repository.selectedClock.map { clock -> clock.clockId }.distinctUntilChanged()
- val selectedColor: Flow<Int?> =
- repository.selectedClock.map { clock -> clock.selectedColor }.distinctUntilChanged()
+ val selectedColorId: Flow<String?> =
+ repository.selectedClock.map { clock -> clock.selectedColorId }.distinctUntilChanged()
- val colorTone: Flow<Int> = repository.selectedClock.map { clock -> clock.colorTone }
+ val colorToneProgress: Flow<Int> =
+ repository.selectedClock.map { clock -> clock.colorToneProgress }
val seedColor: Flow<Int?> = repository.selectedClock.map { clock -> clock.seedColor }
@@ -48,8 +51,12 @@
repository.setSelectedClock(clockId)
}
- fun setClockColor(selectedColor: Int?, colorTone: Int, seedColor: Int?) {
- repository.setClockColor(selectedColor, colorTone, seedColor)
+ fun setClockColor(
+ selectedColorId: String?,
+ @IntRange(from = 0, to = 100) colorToneProgress: Int,
+ @ColorInt seedColor: Int?,
+ ) {
+ repository.setClockColor(selectedColorId, colorToneProgress, seedColor)
}
suspend fun setClockSize(size: ClockSize) {
diff --git a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
index 72aeca6..bd87ba6 100644
--- a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
+++ b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
@@ -24,11 +24,11 @@
data class ClockMetadataModel(
val clockId: String,
val name: String,
- @ColorInt val selectedColor: Int?,
- @IntRange(from = 0, to = 100) val colorTone: Int,
+ val selectedColorId: String?,
+ @IntRange(from = 0, to = 100) val colorToneProgress: Int,
@ColorInt val seedColor: Int?,
) {
companion object {
- const val DEFAULT_COLOR_TONE = 50
+ const val DEFAULT_COLOR_TONE_PROGRESS = 75
}
}
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockColorViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockColorViewModel.kt
new file mode 100644
index 0000000..65ebc79
--- /dev/null
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockColorViewModel.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.android.customization.picker.clock.ui.viewmodel
+
+import android.annotation.ColorInt
+import android.content.res.Resources
+import android.graphics.Color
+import androidx.core.content.res.getStringOrThrow
+import com.android.wallpaper.R
+
+/** The view model that defines custom clock colors. */
+data class ClockColorViewModel(
+ val colorId: String,
+ val colorName: String?,
+ @ColorInt val color: Int,
+ private val colorToneMin: Double,
+ private val colorToneMax: Double,
+) {
+
+ fun getColorTone(progress: Int): Double {
+ return colorToneMin + (progress.toDouble() * (colorToneMax - colorToneMin)) / 100
+ }
+
+ companion object {
+ const val DEFAULT_COLOR_TONE_MIN = 0
+ const val DEFAULT_COLOR_TONE_MAX = 100
+
+ fun getPresetColorMap(resources: Resources): Map<String, ClockColorViewModel> {
+ val ids = resources.obtainTypedArray(R.array.clock_color_ids)
+ val names = resources.obtainTypedArray(R.array.clock_color_names)
+ val colors = resources.obtainTypedArray(R.array.clock_colors)
+ val colorToneMinList = resources.obtainTypedArray(R.array.clock_color_tone_min)
+ val colorToneMaxList = resources.obtainTypedArray(R.array.clock_color_tone_max)
+ return buildList {
+ for (i in 0 until ids.length()) {
+ add(
+ ClockColorViewModel(
+ ids.getStringOrThrow(i),
+ names.getString(i),
+ colors.getColor(i, Color.TRANSPARENT),
+ colorToneMinList.getInt(i, DEFAULT_COLOR_TONE_MIN).toDouble(),
+ colorToneMaxList.getInt(i, DEFAULT_COLOR_TONE_MAX).toDouble(),
+ )
+ )
+ }
+ }
+ .associateBy { it.colorId }
+ .also {
+ ids.recycle()
+ names.recycle()
+ colors.recycle()
+ colorToneMinList.recycle()
+ colorToneMaxList.recycle()
+ }
+ }
+ }
+}
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt
index 9239c0a..008a125 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt
@@ -22,15 +22,20 @@
import com.android.wallpaper.R
import java.util.Locale
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
/** View model for the clock section view on the lockscreen customization surface. */
class ClockSectionViewModel(context: Context, interactor: ClockPickerInteractor) {
val appContext: Context = context.applicationContext
+ val clockColorMap: Map<String, ClockColorViewModel> =
+ ClockColorViewModel.getPresetColorMap(appContext.resources)
val selectedClockColorAndSizeText: Flow<String> =
- interactor.selectedClockSize.map { selectedClockSize ->
- // TODO (b/241966062) Finalize the colors and their names
- val colorText = "Violet"
+ combine(interactor.selectedColorId, interactor.selectedClockSize, ::Pair).map {
+ (selectedColorId, selectedClockSize) ->
+ val colorText =
+ clockColorMap[selectedColorId]?.colorName
+ ?: context.getString(R.string.default_theme_title)
val sizeText =
when (selectedClockSize) {
ClockSize.SMALL -> appContext.getString(R.string.clock_size_small)
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
index 21d39f4..c9be43f 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
@@ -57,18 +57,22 @@
SIZE,
}
+ val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+
val selectedClockId: StateFlow<String?> =
clockPickerInteractor.selectedClockId
.distinctUntilChanged()
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
- val selectedColor: StateFlow<Int?> =
- clockPickerInteractor.selectedColor.stateIn(viewModelScope, SharingStarted.Eagerly, null)
+ val selectedColorId: StateFlow<String?> =
+ clockPickerInteractor.selectedColorId.stateIn(viewModelScope, SharingStarted.Eagerly, null)
- private val sliderProgressColorTone = MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE)
+ private val sliderColorToneProgress =
+ MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
val isSliderEnabled: Flow<Boolean> =
- clockPickerInteractor.selectedColor.map { it != null }.distinctUntilChanged()
- val sliderProgress: Flow<Int> = merge(clockPickerInteractor.colorTone, sliderProgressColorTone)
+ clockPickerInteractor.selectedColorId.map { it != null }.distinctUntilChanged()
+ val sliderProgress: Flow<Int> =
+ merge(clockPickerInteractor.colorToneProgress, sliderColorToneProgress)
private val _seedColor: MutableStateFlow<Int?> = MutableStateFlow(null)
val seedColor: Flow<Int?> = merge(clockPickerInteractor.seedColor, _seedColor)
@@ -76,29 +80,37 @@
/**
* The slider color tone updates are quick. Do not set color tone and the blended color to the
* settings until [onSliderProgressStop] is called. Update to a locally cached temporary
- * [sliderProgressColorTone] and [_seedColor] instead.
+ * [sliderColorToneProgress] and [_seedColor] instead.
*/
fun onSliderProgressChanged(progress: Int) {
- sliderProgressColorTone.value = progress
- val color = selectedColor.value
- if (color != null) {
- _seedColor.value = blendColorWithTone(color, progress)
- }
+ sliderColorToneProgress.value = progress
+ val selectedColorId = selectedColorId.value ?: return
+ val clockColorViewModel = colorMap[selectedColorId] ?: return
+ _seedColor.value =
+ blendColorWithTone(
+ color = clockColorViewModel.color,
+ colorTone = clockColorViewModel.getColorTone(progress),
+ )
}
fun onSliderProgressStop(progress: Int) {
- val color = selectedColor.value ?: return
+ val selectedColorId = selectedColorId.value ?: return
+ val clockColorViewModel = colorMap[selectedColorId] ?: return
clockPickerInteractor.setClockColor(
- selectedColor = color,
- colorTone = progress,
- seedColor = blendColorWithTone(color = color, colorTone = progress)
+ selectedColorId = selectedColorId,
+ colorToneProgress = progress,
+ seedColor =
+ blendColorWithTone(
+ color = clockColorViewModel.color,
+ colorTone = clockColorViewModel.getColorTone(progress),
+ )
)
}
@OptIn(ExperimentalCoroutinesApi::class)
val colorOptions: StateFlow<List<ColorOptionViewModel>> =
- combine(colorPickerInteractor.colorOptions, clockPickerInteractor.selectedColor, ::Pair)
- .mapLatest { (colorOptions, selectedColor) ->
+ combine(colorPickerInteractor.colorOptions, clockPickerInteractor.selectedColorId, ::Pair)
+ .mapLatest { (colorOptions, selectedColorId) ->
// Use mapLatest and delay(100) here to prevent too many selectedClockColor update
// events from ClockRegistry upstream, caused by sliding the saturation level bar.
delay(COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
@@ -109,35 +121,30 @@
?.colorOption as? ColorSeedOption)
?.toColorOptionViewModel(
context,
- selectedColor,
+ selectedColorId,
)
?: (colorOptions[ColorType.BASIC_COLOR]
?.find { it.isSelected }
?.colorOption as? ColorBundle)
?.toColorOptionViewModel(
context,
- selectedColor,
+ selectedColorId,
)
if (defaultThemeColorOptionViewModel != null) {
add(defaultThemeColorOptionViewModel)
}
- val selectedColorPosition =
- if (selectedColor != null) {
- COLOR_SET_LIST.indexOf(selectedColor)
- } else {
- -1
- }
+ val selectedColorPosition = colorMap.keys.indexOf(selectedColorId)
- COLOR_SET_LIST.forEachIndexed { index, color ->
+ colorMap.values.forEachIndexed { index, colorModel ->
val isSelected = selectedColorPosition == index
- val colorTone = ClockMetadataModel.DEFAULT_COLOR_TONE
+ val colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS
add(
ColorOptionViewModel(
- color0 = color,
- color1 = color,
- color2 = color,
- color3 = color,
+ color0 = colorModel.color,
+ color1 = colorModel.color,
+ color2 = colorModel.color,
+ color3 = colorModel.color,
contentDescription =
context.getString(
R.string.content_description_color_option,
@@ -150,12 +157,15 @@
} else {
{
clockPickerInteractor.setClockColor(
- selectedColor = color,
- colorTone = colorTone,
+ selectedColorId = colorModel.colorId,
+ colorToneProgress = colorToneProgress,
seedColor =
blendColorWithTone(
- color = color,
- colorTone = colorTone,
+ color = colorModel.color,
+ colorTone =
+ colorModel.getColorTone(
+ colorToneProgress,
+ ),
),
)
}
@@ -173,7 +183,7 @@
private fun ColorSeedOption.toColorOptionViewModel(
context: Context,
- selectedColor: Int?,
+ selectedColorId: String?,
): ColorOptionViewModel {
val colors = previewInfo.resolveColors(context.resources)
return ColorOptionViewModel(
@@ -183,15 +193,15 @@
color3 = colors[3],
contentDescription = getContentDescription(context).toString(),
title = context.getString(R.string.default_theme_title),
- isSelected = selectedColor == null,
+ isSelected = selectedColorId == null,
onClick =
- if (selectedColor == null) {
+ if (selectedColorId == null) {
null
} else {
{
clockPickerInteractor.setClockColor(
- selectedColor = null,
- colorTone = ClockMetadataModel.DEFAULT_COLOR_TONE,
+ selectedColorId = null,
+ colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
seedColor = null,
)
}
@@ -201,7 +211,7 @@
private fun ColorBundle.toColorOptionViewModel(
context: Context,
- selectedColor: Int?
+ selectedColorId: String?
): ColorOptionViewModel {
val primaryColor = previewInfo.resolvePrimaryColor(context.resources)
val secondaryColor = previewInfo.resolveSecondaryColor(context.resources)
@@ -212,15 +222,15 @@
color3 = secondaryColor,
contentDescription = getContentDescription(context).toString(),
title = context.getString(R.string.default_theme_title),
- isSelected = selectedColor == null,
+ isSelected = selectedColorId == null,
onClick =
- if (selectedColor == null) {
+ if (selectedColorId == null) {
null
} else {
{
clockPickerInteractor.setClockColor(
- selectedColor = null,
- colorTone = ClockMetadataModel.DEFAULT_COLOR_TONE,
+ selectedColorId = null,
+ colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
seedColor = null,
)
}
@@ -263,24 +273,12 @@
}
companion object {
- // TODO (b/241966062) The color integers here are temporary for dev purposes. We need to
- // finalize the overridden colors.
- val COLOR_SET_LIST =
- listOf(
- -786432,
- -3648768,
- -9273600,
- -16739840,
- -9420289,
- -6465837,
- -5032719,
- )
+ private val helperColorLab: DoubleArray by lazy { DoubleArray(3) }
- fun blendColorWithTone(color: Int, colorTone: Int): Int {
- val helperColorLab: DoubleArray by lazy { DoubleArray(3) }
+ fun blendColorWithTone(color: Int, colorTone: Double): Int {
ColorUtils.colorToLAB(color, helperColorLab)
return ColorUtils.LABToColor(
- colorTone.toDouble(),
+ colorTone,
helperColorLab[1],
helperColorLab[2],
)
diff --git a/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
index 918cfb1..2ef4e97 100644
--- a/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
+++ b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -15,6 +15,7 @@
*/
package com.android.customization.picker.clock.data.repository
+import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.IntRange
import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository.Companion.fakeClocks
@@ -31,13 +32,13 @@
override val allClocks: Flow<List<ClockMetadataModel>> = MutableStateFlow(clocks).asStateFlow()
private val selectedClockId = MutableStateFlow(fakeClocks[0].clockId)
- @ColorInt private val selectedColor = MutableStateFlow<Int?>(null)
- private val colorTone = MutableStateFlow<Int>(ClockMetadataModel.DEFAULT_COLOR_TONE)
+ @ColorInt private val selectedColorId = MutableStateFlow<String?>(null)
+ private val colorTone = MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
@ColorInt private val seedColor = MutableStateFlow<Int?>(null)
override val selectedClock: Flow<ClockMetadataModel> =
combine(
selectedClockId,
- selectedColor,
+ selectedColorId,
colorTone,
seedColor,
) { selectedClockId, selectedColor, colorTone, seedColor ->
@@ -60,12 +61,12 @@
}
override fun setClockColor(
- @ColorInt selectedColor: Int?,
- @IntRange(from = 0, to = 100) colorTone: Int,
+ selectedColorId: String?,
+ @IntRange(from = 0, to = 100) colorToneProgress: Int,
@ColorInt seedColor: Int?,
) {
- this.selectedColor.value = selectedColor
- this.colorTone.value = colorTone
+ this.selectedColorId.value = selectedColorId
+ this.colorTone.value = colorToneProgress
this.seedColor.value = seedColor
}
@@ -81,7 +82,8 @@
ClockMetadataModel("clock2", "clock2", null, 50, null),
ClockMetadataModel("clock3", "clock3", null, 50, null),
)
- val clockColor = 0
- val clockColorTone = 87
+ const val CLOCK_COLOR_ID = "RED"
+ const val CLOCK_COLOR_TONE_PROGRESS = 87
+ const val SEED_COLOR = Color.RED
}
}
diff --git a/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt b/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
index 01bfce1..cd41d7d 100644
--- a/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
+++ b/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
@@ -56,16 +56,18 @@
@Test
fun setColor() = runTest {
- val observedSelectedColor = collectLastValue(underTest.selectedColor)
- val observedColorTone = collectLastValue(underTest.colorTone)
+ val observedSelectedColor = collectLastValue(underTest.selectedColorId)
+ val observedColorToneProgress = collectLastValue(underTest.colorToneProgress)
val observedSeedColor = collectLastValue(underTest.seedColor)
underTest.setClockColor(
- FakeClockPickerRepository.clockColor,
- FakeClockPickerRepository.clockColorTone,
- FakeClockPickerRepository.clockColor,
+ FakeClockPickerRepository.CLOCK_COLOR_ID,
+ FakeClockPickerRepository.CLOCK_COLOR_TONE_PROGRESS,
+ FakeClockPickerRepository.SEED_COLOR,
)
- Truth.assertThat(observedSelectedColor()).isEqualTo(FakeClockPickerRepository.clockColor)
- Truth.assertThat(observedColorTone()).isEqualTo(FakeClockPickerRepository.clockColorTone)
- Truth.assertThat(observedSeedColor()).isEqualTo(FakeClockPickerRepository.clockColor)
+ Truth.assertThat(observedSelectedColor())
+ .isEqualTo(FakeClockPickerRepository.CLOCK_COLOR_ID)
+ Truth.assertThat(observedColorToneProgress())
+ .isEqualTo(FakeClockPickerRepository.CLOCK_COLOR_TONE_PROGRESS)
+ Truth.assertThat(observedSeedColor()).isEqualTo(FakeClockPickerRepository.SEED_COLOR)
}
}
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
index ea1311f..63f77bd 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -46,7 +46,7 @@
"clock0",
"clock0",
null,
- ClockMetadataModel.DEFAULT_COLOR_TONE,
+ ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
null,
),
)
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt
new file mode 100644
index 0000000..61976ad
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.customization.picker.clock.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ClockSectionViewModelTest {
+
+ private lateinit var clockColorMap: Map<String, ClockColorViewModel>
+ private lateinit var interactor: ClockPickerInteractor
+ private lateinit var underTest: ClockSectionViewModel
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ val context = InstrumentationRegistry.getInstrumentation().targetContext
+ clockColorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+ interactor = ClockPickerInteractor(FakeClockPickerRepository())
+ underTest =
+ ClockSectionViewModel(
+ context,
+ interactor,
+ )
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun setSelectedClock() = runTest {
+ val colorRed = clockColorMap.values.first()
+ val observedSelectedClockColorAndSizeText =
+ collectLastValue(underTest.selectedClockColorAndSizeText)
+ interactor.setClockColor(
+ colorRed.colorId,
+ ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
+ ClockSettingsViewModel.blendColorWithTone(
+ colorRed.color,
+ colorRed.getColorTone(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS),
+ )
+ )
+ interactor.setClockSize(ClockSize.DYNAMIC)
+ assertThat(observedSelectedClockColorAndSizeText()).isEqualTo("Red, dynamic")
+ }
+}
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
similarity index 80%
rename from tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt
rename to tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
index 10994c7..8ce9671 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
@@ -6,6 +6,7 @@
import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
import com.android.customization.picker.color.data.repository.FakeColorPickerRepository
import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
@@ -31,10 +32,10 @@
@RunWith(JUnit4::class)
class ClockSettingsViewModelTest {
- private lateinit var underTest: ClockSettingsViewModel
- private lateinit var colorPickerInteractor: ColorPickerInteractor
- private lateinit var store: FakeSnapshotStore
private lateinit var context: Context
+ private lateinit var colorPickerInteractor: ColorPickerInteractor
+ private lateinit var underTest: ClockSettingsViewModel
+ private lateinit var colorMap: Map<String, ClockColorViewModel>
@Before
fun setUp() {
@@ -46,7 +47,7 @@
repository = FakeColorPickerRepository(context = context),
snapshotRestorer = {
ColorPickerSnapshotRestorer(interactor = colorPickerInteractor).apply {
- runBlocking { setUpSnapshotRestorer(store = store) }
+ runBlocking { setUpSnapshotRestorer(store = FakeSnapshotStore()) }
}
},
)
@@ -57,6 +58,7 @@
colorPickerInteractor = colorPickerInteractor,
)
.create(ClockSettingsViewModel::class.java)
+ colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
}
@After
@@ -80,6 +82,8 @@
@Test
fun setSelectedColor() = runTest {
val observedClockColorOptions = collectLastValue(underTest.colorOptions)
+ val observedSliderProgress = collectLastValue(underTest.sliderProgress)
+ val observedSeedColor = collectLastValue(underTest.seedColor)
// Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
assertThat(observedClockColorOptions()!![0].isSelected).isTrue()
@@ -90,6 +94,18 @@
advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
assertThat(observedClockColorOptions()!![1].isSelected).isTrue()
assertThat(observedClockColorOptions()!![1].onClick).isNull()
+ assertThat(observedSliderProgress())
+ .isEqualTo(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
+ val expectedSelectedColorModel = colorMap.values.first() // RED
+ assertThat(observedSeedColor())
+ .isEqualTo(
+ ClockSettingsViewModel.blendColorWithTone(
+ expectedSelectedColorModel.color,
+ expectedSelectedColorModel.getColorTone(
+ ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS
+ ),
+ )
+ )
}
@Test
@@ -97,12 +113,14 @@
val observedClockColorOptions = collectLastValue(underTest.colorOptions)
val observedIsSliderEnabled = collectLastValue(underTest.isSliderEnabled)
val observedSliderProgress = collectLastValue(underTest.sliderProgress)
+ val observedSeedColor = collectLastValue(underTest.seedColor)
// Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
assertThat(observedClockColorOptions()!![0].isSelected).isTrue()
assertThat(observedIsSliderEnabled()).isFalse()
observedClockColorOptions()!![1].onClick?.invoke()
+
// Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
assertThat(observedIsSliderEnabled()).isTrue()
@@ -112,6 +130,14 @@
val targetProgress2 = 55
underTest.onSliderProgressStop(targetProgress2)
assertThat(observedSliderProgress()).isEqualTo(targetProgress2)
+ val expectedSelectedColorModel = colorMap.values.first() // RED
+ assertThat(observedSeedColor())
+ .isEqualTo(
+ ClockSettingsViewModel.blendColorWithTone(
+ expectedSelectedColorModel.color,
+ expectedSelectedColorModel.getColorTone(targetProgress2),
+ )
+ )
}
@Test