Snap for 9667109 from ea57f7b5df962663311bea3db219964c5d98dec2 to tm-qpr3-release
Change-Id: I40176c43c6dd31ca205b2b4a4708285e49f6efcb
diff --git a/res/layout/color_option_with_background.xml b/res/layout/color_option_with_background.xml
index 9d3be58..67079f7 100644
--- a/res/layout/color_option_with_background.xml
+++ b/res/layout/color_option_with_background.xml
@@ -14,65 +14,80 @@
limitations under the License.
-->
<!-- Content description is set programmatically on the parent FrameLayout -->
-<FrameLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/icon_container"
- android:layout_width="@dimen/option_tile_width"
- android:layout_height="@dimen/option_tile_width"
- android:importantForAccessibility="yes">
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+ <FrameLayout
+ android:id="@+id/icon_container"
+ android:layout_width="@dimen/option_tile_width"
+ android:layout_height="@dimen/option_tile_width"
+ android:importantForAccessibility="yes">
- <ImageView
- android:id="@id/selection_border"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/option_item_border"
- android:alpha="0"
- android:importantForAccessibility="no" />
+ <ImageView
+ android:id="@id/selection_border"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/option_item_border"
+ android:alpha="0"
+ android:importantForAccessibility="no" />
- <ImageView
- android:id="@id/background"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/option_item_background"
- android:importantForAccessibility="no" />
+ <ImageView
+ android:id="@id/background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/option_item_background"
+ android:importantForAccessibility="no" />
- <ImageView
- android:id="@+id/color_preview_0"
- android:layout_width="wrap_content"
+ <ImageView
+ android:id="@+id/color_preview_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginRight="@dimen/color_seed_chip_margin"
+ android:layout_marginBottom="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled0"
+ android:importantForAccessibility="no"/>
+
+ <ImageView
+ android:id="@+id/color_preview_1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="@dimen/color_seed_chip_margin"
+ android:layout_marginBottom="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled2"
+ android:importantForAccessibility="no"/>
+
+ <ImageView
+ android:id="@+id/color_preview_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginRight="@dimen/color_seed_chip_margin"
+ android:layout_marginTop="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled1"
+ android:importantForAccessibility="no"/>
+
+ <ImageView
+ android:id="@+id/color_preview_3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="@dimen/color_seed_chip_margin"
+ android:layout_marginTop="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled3"
+ android:importantForAccessibility="no" />
+ </FrameLayout>
+
+ <TextView
+ android:id="@+id/option_title"
+ android:layout_width="@dimen/option_tile_width"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginRight="@dimen/color_seed_chip_margin"
- android:layout_marginBottom="@dimen/color_seed_chip_margin"
- android:src="@drawable/color_chip_seed_filled0"
- android:importantForAccessibility="no"/>
+ android:layout_marginTop="@dimen/option_bottom_margin"
+ android:textColor="@color/text_color_primary"
+ android:visibility="gone"
+ android:gravity="center" />
+</LinearLayout>
- <ImageView
- android:id="@+id/color_preview_1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginLeft="@dimen/color_seed_chip_margin"
- android:layout_marginBottom="@dimen/color_seed_chip_margin"
- android:src="@drawable/color_chip_seed_filled2"
- android:importantForAccessibility="no"/>
-
- <ImageView
- android:id="@+id/color_preview_2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginRight="@dimen/color_seed_chip_margin"
- android:layout_marginTop="@dimen/color_seed_chip_margin"
- android:src="@drawable/color_chip_seed_filled1"
- android:importantForAccessibility="no"/>
-
- <ImageView
- android:id="@+id/color_preview_3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginLeft="@dimen/color_seed_chip_margin"
- android:layout_marginTop="@dimen/color_seed_chip_margin"
- android:src="@drawable/color_chip_seed_filled3"
- android:importantForAccessibility="no"/>
-</FrameLayout>
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index c5f0b76..306ef04 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -67,5 +67,8 @@
fun getClockViewFactory(activity: Activity): ClockViewFactory
- fun getClockSettingsViewModelFactory(context: Context): ClockSettingsViewModel.Factory
+ fun getClockSettingsViewModelFactory(
+ context: Context,
+ wallpaperColorsViewModel: WallpaperColorsViewModel,
+ ): ClockSettingsViewModel.Factory
}
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index 3d02c84..e166f2c 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -418,11 +418,16 @@
override fun getClockSettingsViewModelFactory(
context: Context,
+ wallpaperColorsViewModel: WallpaperColorsViewModel,
): ClockSettingsViewModel.Factory {
return clockSettingsViewModelFactory
?: ClockSettingsViewModel.Factory(
context,
getClockPickerInteractor(context),
+ getColorPickerInteractor(
+ context,
+ wallpaperColorsViewModel,
+ ),
)
.also { clockSettingsViewModelFactory = it }
}
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 2ba03bd..9b6d737 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -105,7 +105,10 @@
view,
ViewModelProvider(
requireActivity(),
- injector.getClockSettingsViewModelFactory(context),
+ injector.getClockSettingsViewModelFactory(
+ context,
+ injector.getWallpaperColorsViewModel(),
+ ),
)
.get(),
this@ClockSettingsFragment,
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 41b4010..f33cb4f 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
@@ -16,13 +16,15 @@
package com.android.customization.picker.clock.ui.viewmodel
import android.content.Context
-import android.graphics.Color
import androidx.core.graphics.ColorUtils
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
+import com.android.customization.model.color.ColorSeedOption
import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
+import com.android.customization.picker.color.shared.model.ColorType
import com.android.customization.picker.color.ui.viewmodel.ColorOptionViewModel
import com.android.wallpaper.R
import kotlin.math.abs
@@ -34,6 +36,7 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.shareIn
@@ -42,7 +45,11 @@
/** View model for the clock settings screen. */
class ClockSettingsViewModel
-private constructor(context: Context, private val interactor: ClockPickerInteractor) : ViewModel() {
+private constructor(
+ context: Context,
+ private val clockPickerInteractor: ClockPickerInteractor,
+ private val colorPickerInteractor: ColorPickerInteractor,
+) : ViewModel() {
enum class Tab {
COLOR,
@@ -58,7 +65,7 @@
* level of the system theme color.
*/
private val saturationLevel: Flow<Float?> =
- interactor.selectedClockColor
+ clockPickerInteractor.selectedClockColor
.map { selectedColor ->
if (selectedColor == null) {
null
@@ -95,38 +102,48 @@
selectedOption?.let { option ->
ColorUtils.colorToHSL(option.color0, helperColorHsl)
helperColorHsl[1] = saturation
- interactor.setClockColor(ColorUtils.HSLToColor(helperColorHsl))
+ clockPickerInteractor.setClockColor(ColorUtils.HSLToColor(helperColorHsl))
}
}
@OptIn(ExperimentalCoroutinesApi::class)
val colorOptions: StateFlow<List<ColorOptionViewModel>> =
- interactor.selectedClockColor
- .mapLatest { selectedColor ->
+ combine(
+ colorPickerInteractor.colorOptions,
+ clockPickerInteractor.selectedClockColor,
+ ::Pair,
+ )
+ .mapLatest { (colorOptions, selectedColor) ->
// 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)
buildList {
- // TODO (b/241966062) Change design of the placeholder for default theme color
- add(
- ColorOptionViewModel(
- color0 = Color.TRANSPARENT,
- color1 = Color.TRANSPARENT,
- color2 = Color.TRANSPARENT,
- color3 = Color.TRANSPARENT,
- contentDescription =
- context.getString(
- R.string.content_description_color_option,
- ),
- isSelected = selectedColor == null,
- onClick =
- if (selectedColor == null) {
- null
- } else {
- { interactor.setClockColor(null) }
- },
+ val defaultThemeColor =
+ colorOptions[ColorType.WALLPAPER_COLOR]?.find { it.isSelected }
+ ?: colorOptions[ColorType.BASIC_COLOR]?.find { it.isSelected }
+ if (defaultThemeColor != null) {
+ val colorSeedOption: ColorSeedOption =
+ defaultThemeColor.colorOption as ColorSeedOption
+ val colors = colorSeedOption.previewInfo.resolveColors(context.resources)
+ add(
+ ColorOptionViewModel(
+ color0 = colors[0],
+ color1 = colors[1],
+ color2 = colors[2],
+ color3 = colors[3],
+ contentDescription =
+ colorSeedOption.getContentDescription(context).toString(),
+ title = context.getString(R.string.default_theme_title),
+ isSelected = selectedColor == null,
+ onClick =
+ if (selectedColor == null) {
+ null
+ } else {
+ { clockPickerInteractor.setClockColor(null) }
+ },
+ )
)
- )
+ }
if (selectedColor != null) {
ColorUtils.colorToHSL(selectedColor, helperColorHsl)
@@ -174,7 +191,7 @@
if (isSelected) {
null
} else {
- { interactor.setClockColor(colorToSet) }
+ { clockPickerInteractor.setClockColor(colorToSet) }
},
)
)
@@ -187,10 +204,10 @@
initialValue = emptyList(),
)
- val selectedClockSize: Flow<ClockSize> = interactor.selectedClockSize
+ val selectedClockSize: Flow<ClockSize> = clockPickerInteractor.selectedClockSize
fun setClockSize(size: ClockSize) {
- viewModelScope.launch { interactor.setClockSize(size) }
+ viewModelScope.launch { clockPickerInteractor.setClockSize(size) }
}
private val _selectedTabPosition = MutableStateFlow(Tab.COLOR)
@@ -241,13 +258,15 @@
class Factory(
private val context: Context,
- private val interactor: ClockPickerInteractor,
+ private val clockPickerInteractor: ClockPickerInteractor,
+ private val colorPickerInteractor: ColorPickerInteractor,
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return ClockSettingsViewModel(
context = context,
- interactor = interactor,
+ clockPickerInteractor = clockPickerInteractor,
+ colorPickerInteractor = colorPickerInteractor,
)
as T
}
diff --git a/src/com/android/customization/picker/color/ui/adapter/ColorOptionAdapter.kt b/src/com/android/customization/picker/color/ui/adapter/ColorOptionAdapter.kt
index 791811d..0e53766 100644
--- a/src/com/android/customization/picker/color/ui/adapter/ColorOptionAdapter.kt
+++ b/src/com/android/customization/picker/color/ui/adapter/ColorOptionAdapter.kt
@@ -23,6 +23,8 @@
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
+import android.widget.TextView
+import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.android.customization.picker.color.ui.viewmodel.ColorOptionViewModel
import com.android.wallpaper.R
@@ -35,10 +37,12 @@
class ColorOptionAdapter : RecyclerView.Adapter<ColorOptionAdapter.ViewHolder>() {
private val items = mutableListOf<ColorOptionViewModel>()
+ private var isTitleVisible = false
fun setItems(items: List<ColorOptionViewModel>) {
this.items.clear()
this.items.addAll(items)
+ isTitleVisible = items.any { item -> item.title != null }
notifyDataSetChanged()
}
@@ -49,6 +53,7 @@
val color1View: ImageView = itemView.requireViewById(R.id.color_preview_1)
val color2View: ImageView = itemView.requireViewById(R.id.color_preview_2)
val color3View: ImageView = itemView.requireViewById(R.id.color_preview_3)
+ val optionTitleView: TextView = itemView.requireViewById(R.id.option_title)
}
override fun getItemCount(): Int {
@@ -92,5 +97,7 @@
holder.color2View.drawable.colorFilter = BlendModeColorFilter(item.color2, BlendMode.SRC)
holder.color3View.drawable.colorFilter = BlendModeColorFilter(item.color3, BlendMode.SRC)
holder.itemView.contentDescription = item.contentDescription
+ holder.optionTitleView.isVisible = isTitleVisible
+ holder.optionTitleView.text = item.title
}
}
diff --git a/src/com/android/customization/picker/color/ui/viewmodel/ColorOptionViewModel.kt b/src/com/android/customization/picker/color/ui/viewmodel/ColorOptionViewModel.kt
index 0ebc74b..784ec2e 100644
--- a/src/com/android/customization/picker/color/ui/viewmodel/ColorOptionViewModel.kt
+++ b/src/com/android/customization/picker/color/ui/viewmodel/ColorOptionViewModel.kt
@@ -30,6 +30,9 @@
/** A content description for the color. */
val contentDescription: String,
+ /** Nullable option title. Null by default. */
+ val title: String? = null,
+
/** Whether this color is selected. */
val isSelected: Boolean,
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt
index 215e178..8f61d8b 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt
@@ -6,11 +6,16 @@
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.color.data.repository.FakeColorPickerRepository
+import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
+import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
+import com.android.wallpaper.testing.FakeSnapshotStore
import com.android.wallpaper.testing.collectLastValue
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.resetMain
@@ -28,7 +33,8 @@
class ClockSettingsViewModelTest {
private lateinit var underTest: ClockSettingsViewModel
-
+ private lateinit var colorPickerInteractor: ColorPickerInteractor
+ private lateinit var store: FakeSnapshotStore
private lateinit var context: Context
@Before
@@ -36,10 +42,20 @@
val testDispatcher = StandardTestDispatcher()
Dispatchers.setMain(testDispatcher)
context = InstrumentationRegistry.getInstrumentation().targetContext
+ colorPickerInteractor =
+ ColorPickerInteractor(
+ repository = FakeColorPickerRepository(context = context),
+ snapshotRestorer = {
+ ColorPickerSnapshotRestorer(interactor = colorPickerInteractor).apply {
+ runBlocking { setUpSnapshotRestorer(store = store) }
+ }
+ },
+ )
underTest =
ClockSettingsViewModel.Factory(
context = context,
- interactor = ClockPickerInteractor(FakeClockPickerRepository()),
+ clockPickerInteractor = ClockPickerInteractor(FakeClockPickerRepository()),
+ colorPickerInteractor = colorPickerInteractor,
)
.create(ClockSettingsViewModel::class.java)
}
diff --git a/tests/src/com/android/customization/testing/TestCustomizationInjector.kt b/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
index 98cbe68..af0be95 100644
--- a/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
+++ b/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
@@ -218,11 +218,16 @@
override fun getClockSettingsViewModelFactory(
context: Context,
+ wallpaperColorsViewModel: WallpaperColorsViewModel,
): ClockSettingsViewModel.Factory {
return clockSettingsViewModelFactory
?: ClockSettingsViewModel.Factory(
context,
getClockPickerInteractor(context),
+ getColorPickerInteractor(
+ context,
+ wallpaperColorsViewModel,
+ ),
)
.also { clockSettingsViewModelFactory = it }
}