Merge "[Custom Clock Color] Disable slider" into udc-dev
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index 306ef04..479bca2 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -70,5 +70,6 @@
     fun getClockSettingsViewModelFactory(
         context: Context,
         wallpaperColorsViewModel: WallpaperColorsViewModel,
+        clockViewFactory: ClockViewFactory,
     ): ClockSettingsViewModel.Factory
 }
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index b35de75..1d2b4c9 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -460,6 +460,7 @@
     override fun getClockSettingsViewModelFactory(
         context: Context,
         wallpaperColorsViewModel: WallpaperColorsViewModel,
+        clockViewFactory: ClockViewFactory,
     ): ClockSettingsViewModel.Factory {
         return clockSettingsViewModelFactory
             ?: ClockSettingsViewModel.Factory(
@@ -469,7 +470,10 @@
                         context,
                         wallpaperColorsViewModel,
                     ),
-                )
+                ) { clockId ->
+                    clockId?.let { clockViewFactory.getController(clockId).events.isReactiveToTone }
+                        ?: false
+                }
                 .also { clockSettingsViewModelFactory = it }
     }
 
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 1bbb965..b358873 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
@@ -43,6 +43,9 @@
 
 /** Bind between the clock settings screen and its view model. */
 object ClockSettingsBinder {
+    private const val SLIDER_ENABLED_ALPHA = 1f
+    private const val SLIDER_DISABLED_ALPHA = .3f
+
     fun bind(
         view: View,
         viewModel: ClockSettingsViewModel,
@@ -176,7 +179,11 @@
                 }
 
                 launch {
-                    viewModel.isSliderEnabled.collect { isEnabled -> slider.isEnabled = isEnabled }
+                    viewModel.isSliderEnabled.collect { isEnabled ->
+                        slider.isEnabled = isEnabled
+                        slider.alpha =
+                            if (isEnabled) SLIDER_ENABLED_ALPHA else SLIDER_DISABLED_ALPHA
+                    }
                 }
             }
         }
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 c5cde53..b5e7c18 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -115,10 +115,11 @@
         ClockSettingsBinder.bind(
             view,
             ViewModelProvider(
-                    requireActivity(),
+                    activity,
                     injector.getClockSettingsViewModelFactory(
                         context,
                         injector.getWallpaperColorsViewModel(),
+                        injector.getClockViewFactory(activity),
                     ),
                 )
                 .get(),
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 1514f1b..b66f977 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
@@ -53,6 +53,7 @@
     context: Context,
     private val clockPickerInteractor: ClockPickerInteractor,
     private val colorPickerInteractor: ColorPickerInteractor,
+    private val getIsReactiveToTone: (clockId: String?) -> Boolean,
 ) : ViewModel() {
 
     enum class Tab {
@@ -60,20 +61,27 @@
         SIZE,
     }
 
-    val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+    private val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
 
     val selectedClockId: StateFlow<String?> =
         clockPickerInteractor.selectedClockId
             .distinctUntilChanged()
             .stateIn(viewModelScope, SharingStarted.Eagerly, null)
 
-    val selectedColorId: StateFlow<String?> =
+    private 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.selectedColorId.map { it != null }.distinctUntilChanged()
+        combine(selectedClockId, clockPickerInteractor.selectedColorId) { clockId, colorId ->
+                if (colorId == null) {
+                    false
+                } else {
+                    getIsReactiveToTone(clockId)
+                }
+            }
+            .distinctUntilChanged()
     val sliderProgress: Flow<Int> =
         merge(clockPickerInteractor.colorToneProgress, sliderColorToneProgress)
 
@@ -286,6 +294,7 @@
         private val context: Context,
         private val clockPickerInteractor: ClockPickerInteractor,
         private val colorPickerInteractor: ColorPickerInteractor,
+        private val getIsReactiveToTone: (clockId: String?) -> Boolean,
     ) : ViewModelProvider.Factory {
         override fun <T : ViewModel> create(modelClass: Class<T>): T {
             @Suppress("UNCHECKED_CAST")
@@ -293,6 +302,7 @@
                 context = context,
                 clockPickerInteractor = clockPickerInteractor,
                 colorPickerInteractor = colorPickerInteractor,
+                getIsReactiveToTone = getIsReactiveToTone,
             )
                 as T
         }
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 2ef4e97..2b0b47f 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
@@ -75,12 +75,16 @@
     }
 
     companion object {
+        const val CLOCK_ID_0 = "clock0"
+        const val CLOCK_ID_1 = "clock1"
+        const val CLOCK_ID_2 = "clock2"
+        const val CLOCK_ID_3 = "clock3"
         val fakeClocks =
             listOf(
-                ClockMetadataModel("clock0", "clock0", null, 50, null),
-                ClockMetadataModel("clock1", "clock1", null, 50, null),
-                ClockMetadataModel("clock2", "clock2", null, 50, null),
-                ClockMetadataModel("clock3", "clock3", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_0, "clock0", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_1, "clock1", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_2, "clock2", null, 50, null),
+                ClockMetadataModel(CLOCK_ID_3, "clock3", null, 50, null),
             )
         const val CLOCK_COLOR_ID = "RED"
         const val CLOCK_COLOR_TONE_PROGRESS = 87
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
index a959a46..92059e3 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
@@ -34,14 +34,26 @@
 
     private lateinit var context: Context
     private lateinit var colorPickerInteractor: ColorPickerInteractor
+    private lateinit var clockPickerInteractor: ClockPickerInteractor
     private lateinit var underTest: ClockSettingsViewModel
     private lateinit var colorMap: Map<String, ClockColorViewModel>
+    // We make the condition that CLOCK_ID_3 is not reactive to tone
+    private val getIsReactiveToTone: (clockId: String?) -> Boolean = { clockId ->
+        when (clockId) {
+            FakeClockPickerRepository.CLOCK_ID_0 -> true
+            FakeClockPickerRepository.CLOCK_ID_1 -> true
+            FakeClockPickerRepository.CLOCK_ID_2 -> true
+            FakeClockPickerRepository.CLOCK_ID_3 -> false
+            else -> false
+        }
+    }
 
     @Before
     fun setUp() {
         val testDispatcher = StandardTestDispatcher()
         Dispatchers.setMain(testDispatcher)
         context = InstrumentationRegistry.getInstrumentation().targetContext
+        clockPickerInteractor = ClockPickerInteractor(FakeClockPickerRepository())
         colorPickerInteractor =
             ColorPickerInteractor(
                 repository = FakeColorPickerRepository(context = context),
@@ -54,11 +66,14 @@
         underTest =
             ClockSettingsViewModel.Factory(
                     context = context,
-                    clockPickerInteractor = ClockPickerInteractor(FakeClockPickerRepository()),
+                    clockPickerInteractor = clockPickerInteractor,
                     colorPickerInteractor = colorPickerInteractor,
+                    getIsReactiveToTone = getIsReactiveToTone,
                 )
                 .create(ClockSettingsViewModel::class.java)
         colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+
+        clockPickerInteractor.setSelectedClock(FakeClockPickerRepository.CLOCK_ID_0)
     }
 
     @After
@@ -160,4 +175,21 @@
         underTest.setClockSize(ClockSize.SMALL)
         assertThat(observedClockSize()).isEqualTo(ClockSize.SMALL)
     }
+
+    @Test
+    fun getIsReactiveToTone() = runTest {
+        val observedClockColorOptions = collectLastValue(underTest.colorOptions)
+        val isSliderEnabled = collectLastValue(underTest.isSliderEnabled)
+        // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
+        advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
+        val option1OnClicked = collectLastValue(observedClockColorOptions()!![1].onClicked)
+        option1OnClicked()?.invoke()
+
+        clockPickerInteractor.setSelectedClock(FakeClockPickerRepository.CLOCK_ID_0)
+        assertThat(isSliderEnabled()).isTrue()
+
+        // We make the condition that CLOCK_ID_0 is not reactive to tone
+        clockPickerInteractor.setSelectedClock(FakeClockPickerRepository.CLOCK_ID_3)
+        assertThat(isSliderEnabled()).isFalse()
+    }
 }