Merge changes I288c3d8f,Ie6cb75ca,Iadb9ae77,Ib78058d0 into tm-qpr-dev
* changes:
[TP] Make clock previews tick
[TP] Smooth scroll to clock color option position
[TP] Use design clock colors
[TP] Handle quick update from slider
diff --git a/res/layout/fragment_clock_settings.xml b/res/layout/fragment_clock_settings.xml
index 088ec2a..5208222 100644
--- a/res/layout/fragment_clock_settings.xml
+++ b/res/layout/fragment_clock_settings.xml
@@ -41,6 +41,11 @@
android:layout_height="match_parent"
android:layout_gravity="center" />
+ <FrameLayout
+ android:id="@+id/clock_host_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center" />
</com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
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/binder/ClockCarouselViewBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
index 6c72a5b..9ad735d 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
@@ -15,7 +15,6 @@
*/
package com.android.customization.picker.clock.ui.binder
-import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.view.isVisible
@@ -24,6 +23,7 @@
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.android.customization.picker.clock.ui.view.ClockCarouselView
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.wallpaper.R
import kotlinx.coroutines.launch
@@ -43,7 +43,7 @@
carouselView: ClockCarouselView,
singleClockView: ViewGroup,
viewModel: ClockCarouselViewModel,
- clockViewFactory: (clockId: String) -> View,
+ clockViewFactory: ClockViewFactory,
lifecycleOwner: LifecycleOwner,
): Binding {
val singleClockHostView =
@@ -56,7 +56,7 @@
viewModel.allClockIds.collect { allClockIds ->
carouselView.setUpClockCarouselView(
clockIds = allClockIds,
- onGetClockPreview = clockViewFactory,
+ onGetClockPreview = { clockId -> clockViewFactory.getView(clockId) },
onClockSelected = { clockId -> viewModel.setSelectedClock(clockId) },
)
}
@@ -69,13 +69,17 @@
}
launch {
+ viewModel.seedColor.collect { clockViewFactory.updateColorForAllClocks(it) }
+ }
+
+ launch {
viewModel.isSingleClockViewVisible.collect { singleClockView.isVisible = it }
}
launch {
viewModel.clockId.collect { clockId ->
singleClockHostView.removeAllViews()
- val clockView = clockViewFactory(clockId)
+ val clockView = clockViewFactory.getView(clockId)
// The clock view might still be attached to an existing parent. Detach
// before adding to another parent.
(clockView.parent as? ViewGroup)?.removeView(clockView)
@@ -84,6 +88,15 @@
}
}
}
+
+ lifecycleOwner.lifecycleScope.launch {
+ lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
+ clockViewFactory.registerTimeTicker()
+ }
+ // When paused
+ clockViewFactory.unregisterTimeTicker()
+ }
+
return object : Binding {
override fun show() {
viewModel.showClockCarousel(true)
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
index 62d7217..66d9251 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
@@ -16,6 +16,8 @@
package com.android.customization.picker.clock.ui.binder
import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
import android.widget.SeekBar
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
@@ -28,10 +30,12 @@
import com.android.customization.picker.clock.shared.ClockSize
import com.android.customization.picker.clock.ui.adapter.ClockSettingsTabAdapter
import com.android.customization.picker.clock.ui.view.ClockSizeRadioButtonGroup
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
import com.android.customization.picker.color.ui.adapter.ColorOptionAdapter
import com.android.customization.picker.common.ui.view.ItemSpacing
import com.android.wallpaper.R
+import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.launch
/** Bind between the clock settings screen and its view model. */
@@ -39,8 +43,11 @@
fun bind(
view: View,
viewModel: ClockSettingsViewModel,
+ clockViewFactory: ClockViewFactory,
lifecycleOwner: LifecycleOwner,
) {
+ val clockHostView: FrameLayout = view.requireViewById(R.id.clock_host_view)
+
val tabView: RecyclerView = view.requireViewById(R.id.tabs)
val tabAdapter = ClockSettingsTabAdapter()
tabView.adapter = tabAdapter
@@ -82,6 +89,25 @@
val colorOptionContainer = view.requireViewById<View>(R.id.color_picker_container)
lifecycleOwner.lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+ launch {
+ viewModel.selectedClockId
+ .mapNotNull { it }
+ .collect { clockId ->
+ val clockView = clockViewFactory.getView(clockId)
+ (clockView.parent as? ViewGroup)?.removeView(clockView)
+ clockHostView.removeAllViews()
+ clockHostView.addView(clockView)
+ }
+ }
+
+ launch {
+ viewModel.seedColor.collect { seedColor ->
+ viewModel.selectedClockId.value?.let { selectedClockId ->
+ clockViewFactory.updateColor(selectedClockId, seedColor)
+ }
+ }
+ }
+
launch { viewModel.tabs.collect { tabAdapter.setItems(it) } }
launch {
@@ -106,6 +132,18 @@
}
launch {
+ viewModel.selectedColorOptionPosition.collect { selectedPosition ->
+ if (selectedPosition != -1) {
+ // We use "post" because we need to give the adapter item a pass to
+ // update the view.
+ colorOptionContainerView.post {
+ colorOptionContainerView.smoothScrollToPosition(selectedPosition)
+ }
+ }
+ }
+ }
+
+ launch {
viewModel.selectedClockSize.collect { size ->
when (size) {
ClockSize.DYNAMIC -> {
@@ -131,5 +169,13 @@
}
}
}
+
+ lifecycleOwner.lifecycleScope.launch {
+ lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
+ clockViewFactory.registerTimeTicker()
+ }
+ // When paused
+ clockViewFactory.unregisterTimeTicker()
+ }
}
}
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
index 9b6d737..ef1a5ef 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -24,6 +24,7 @@
import androidx.lifecycle.get
import com.android.customization.module.ThemePickerInjector
import com.android.customization.picker.clock.ui.binder.ClockSettingsBinder
+import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants
import com.android.wallpaper.R
import com.android.wallpaper.module.InjectorProvider
import com.android.wallpaper.picker.AppbarFragment
@@ -95,6 +96,16 @@
onWallpaperColorChanged = { colors ->
colorViewModel.setLockWallpaperColors(colors)
},
+ initialExtrasProvider = {
+ Bundle().apply {
+ // Hide the clock from the system UI rendered preview so we can
+ // place the carousel on top of it.
+ putBoolean(
+ ClockPreviewConstants.KEY_HIDE_CLOCK,
+ true,
+ )
+ }
+ },
),
lifecycleOwner = this,
offsetToStart = displayUtils.isOnWallpaperDisplay(activity),
@@ -111,6 +122,7 @@
),
)
.get(),
+ injector.getClockViewFactory(activity),
this@ClockSettingsFragment,
)
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
index 488dd08..7f480de 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
@@ -17,21 +17,45 @@
import android.app.Activity
import android.view.View
+import androidx.annotation.ColorInt
import com.android.systemui.plugins.ClockController
import com.android.systemui.shared.clocks.ClockRegistry
import com.android.wallpaper.R
import com.android.wallpaper.util.ScreenSizeCalculator
+import com.android.wallpaper.util.TimeUtils.TimeTicker
class ClockViewFactory(
private val activity: Activity,
private val registry: ClockRegistry,
) {
private val clockControllers: HashMap<String, ClockController> = HashMap()
+ private var ticker: TimeTicker? = null
fun getView(clockId: String): View {
return (clockControllers[clockId] ?: initClockController(clockId)).largeClock.view
}
+ fun updateColorForAllClocks(@ColorInt seedColor: Int?) {
+ clockControllers.values.forEach { it.events.onSeedColorChanged(seedColor = seedColor) }
+ }
+
+ fun updateColor(clockId: String, @ColorInt seedColor: Int?) {
+ return (clockControllers[clockId] ?: initClockController(clockId))
+ .events
+ .onSeedColorChanged(seedColor)
+ }
+
+ fun registerTimeTicker() {
+ ticker =
+ TimeTicker.registerNewReceiver(activity.applicationContext) {
+ clockControllers.values.forEach { it.largeClock.events.onTimeTick() }
+ }
+ }
+
+ fun unregisterTimeTicker() {
+ activity.applicationContext.unregisterReceiver(ticker)
+ }
+
private fun initClockController(clockId: String): ClockController {
val controller =
registry.createExampleClock(clockId).also { it?.initialize(activity.resources, 0f, 0f) }
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
index 8fe9dca..60a9e85 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -42,6 +42,8 @@
allClocks.map { it.clockId }
}
+ val seedColor: Flow<Int?> = interactor.seedColor
+
private val shouldShowCarousel = MutableStateFlow(false)
val isCarouselVisible: Flow<Boolean> =
combine(allClockIds.map { it.size > 1 }.distinctUntilChanged(), shouldShowCarousel) {
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 06fd2af..23fbc7e 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
@@ -57,13 +57,22 @@
SIZE,
}
- val selectedColor: StateFlow<Int?> =
- clockPickerInteractor.selectedColor.stateIn(viewModelScope, SharingStarted.Eagerly, null)
+ val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
- private val sliderProgressColorTone = MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE)
+ val selectedClockId: StateFlow<String?> =
+ clockPickerInteractor.selectedClockId
+ .distinctUntilChanged()
+ .stateIn(viewModelScope, SharingStarted.Eagerly, null)
+
+ val selectedColorId: StateFlow<String?> =
+ clockPickerInteractor.selectedColorId.stateIn(viewModelScope, SharingStarted.Eagerly, null)
+
+ 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)
@@ -71,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)
@@ -104,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,
@@ -145,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,
+ ),
),
)
}
@@ -166,9 +181,13 @@
initialValue = emptyList(),
)
+ @OptIn(ExperimentalCoroutinesApi::class)
+ val selectedColorOptionPosition: Flow<Int> =
+ colorOptions.mapLatest { it.indexOfFirst { colorOption -> colorOption.isSelected } }
+
private fun ColorSeedOption.toColorOptionViewModel(
context: Context,
- selectedColor: Int?,
+ selectedColorId: String?,
): ColorOptionViewModel {
val colors = previewInfo.resolveColors(context.resources)
return ColorOptionViewModel(
@@ -178,15 +197,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,
)
}
@@ -196,7 +215,7 @@
private fun ColorBundle.toColorOptionViewModel(
context: Context,
- selectedColor: Int?
+ selectedColorId: String?
): ColorOptionViewModel {
val primaryColor = previewInfo.resolvePrimaryColor(context.resources)
val secondaryColor = previewInfo.resolveSecondaryColor(context.resources)
@@ -207,15 +226,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,
)
}
@@ -258,24 +277,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/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
index 0b197b4..700439b 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -79,7 +79,7 @@
carouselView = carouselView,
singleClockView = singleClockView,
viewModel = clockCarouselViewModel,
- clockViewFactory = { clockId -> clockViewFactory.getView(clockId) },
+ clockViewFactory = clockViewFactory,
lifecycleOwner = lifecycleOwner,
)
onScreenSwitched(
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 77%
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..d53288d 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,16 +82,34 @@
@Test
fun setSelectedColor() = runTest {
val observedClockColorOptions = collectLastValue(underTest.colorOptions)
+ val observedSelectedColorOptionPosition =
+ collectLastValue(underTest.selectedColorOptionPosition)
+ 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(observedClockColorOptions()!![0].onClick).isNull()
+ assertThat(observedSelectedColorOptionPosition()).isEqualTo(0)
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(observedClockColorOptions()!![1].isSelected).isTrue()
assertThat(observedClockColorOptions()!![1].onClick).isNull()
+ assertThat(observedSelectedColorOptionPosition()).isEqualTo(1)
+ 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 +117,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 +134,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