Merge "Fix clock size tap target height" into main
diff --git a/res/layout/clock_host_view.xml b/res/layout/clock_host_view.xml
index 33cca01..d6f5275 100644
--- a/res/layout/clock_host_view.xml
+++ b/res/layout/clock_host_view.xml
@@ -13,7 +13,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<com.android.customization.picker.clock.ui.view.ClockHostView2
+<com.android.customization.picker.clock.ui.view.ClockConstraintLayoutHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/clock_host_view"
     android:importantForAccessibility="noHideDescendants"
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 3d9288a..2f88265 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -40,7 +40,7 @@
     <string name="clock_size" msgid="5028923902364418263">"Hajmi"</string>
     <string name="clock_size_dynamic" msgid="1023930312455061642">"Dinamik"</string>
     <string name="clock_size_dynamic_description" msgid="2776620745774561662">"Soat hajmi ekran qulfidagi kontent asosida oʻzgaradi"</string>
-    <string name="clock_size_large" msgid="3143248715744138979">"Yirik"</string>
+    <string name="clock_size_large" msgid="3143248715744138979">"Katta"</string>
     <string name="clock_size_small" msgid="2280449912094164133">"Kichik"</string>
     <string name="clock_size_small_description" msgid="4089511196955732480">"Ekran chekkasida kichik soat chiqishi"</string>
     <string name="clock_font_editor_apply" msgid="5965611025879105293">"Soat shrifti oʻzgarishlarini qoʻllash"</string>
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 99dfc26..764c671 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
@@ -41,10 +41,10 @@
 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.ClockCarouselView
-import com.android.customization.picker.clock.ui.view.ClockHostView
 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.binder.ColorOptionIconBinder
+import com.android.systemui.shared.Flags
 import com.android.themepicker.R
 import com.android.wallpaper.picker.common.ui.view.ItemSpacing
 import com.android.wallpaper.picker.option.ui.binder.OptionItemBinder
@@ -64,7 +64,10 @@
         clockViewFactory: ClockViewFactory,
         lifecycleOwner: LifecycleOwner,
     ) {
-        val clockHostView: ClockHostView = view.requireViewById(R.id.clock_host_view)
+        if (Flags.newCustomizationPickerUi()) {
+            return
+        }
+        val clockHostView: ViewGroup = view.requireViewById(R.id.clock_host_view)
         val tabView: RecyclerView = view.requireViewById(R.id.tabs)
         val tabAdapter = ClockSettingsTabAdapter()
         tabView.adapter = tabAdapter
@@ -204,10 +207,11 @@
                                     ClockSize.DYNAMIC -> clockViewFactory.getLargeView(clockId)
                                     ClockSize.SMALL -> clockViewFactory.getSmallView(clockId)
                                 }
-                            // The clock view might still be attached to an existing parent. Detach
-                            // before adding to another parent.
+                            // The clock view might still be attached to an existing parent.
+                            // Detach before adding to another parent.
                             (clockView.parent as? ViewGroup)?.removeView(clockView)
                             clockHostView.addView(clockView)
+
                             when (size) {
                                 ClockSize.DYNAMIC -> {
                                     // When clock size data flow emits clock size signal, we want
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockConstraintLayoutHostView.kt b/src/com/android/customization/picker/clock/ui/view/ClockConstraintLayoutHostView.kt
new file mode 100644
index 0000000..de5fbd5
--- /dev/null
+++ b/src/com/android/customization/picker/clock/ui/view/ClockConstraintLayoutHostView.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 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.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.view.View.MeasureSpec.EXACTLY
+import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintLayout
+import com.android.customization.picker.clock.shared.ClockSize
+import com.android.systemui.plugins.clocks.ClockController
+import com.android.wallpaper.util.ScreenSizeCalculator
+
+/**
+ * Parent view for the clock view. We will calculate the current display size and the preview size
+ * and scale down the clock view to fit in the preview.
+ */
+class ClockConstraintLayoutHostView(context: Context, attrs: AttributeSet?) :
+    ConstraintLayout(context, attrs) {
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        val screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display)
+        super.onMeasure(
+            MeasureSpec.makeMeasureSpec(screenSize.x, EXACTLY),
+            MeasureSpec.makeMeasureSpec(screenSize.y, EXACTLY),
+        )
+        val ratio = MeasureSpec.getSize(widthMeasureSpec) / screenSize.x.toFloat()
+        scaleX = ratio
+        scaleY = ratio
+    }
+
+    companion object {
+        fun addClockViews(
+            clockController: ClockController,
+            rootView: ClockConstraintLayoutHostView,
+            size: ClockSize,
+        ) {
+            clockController.let { clock ->
+                when (size) {
+                    ClockSize.DYNAMIC -> {
+                        clock.largeClock.layout.views.forEach {
+                            if (it.parent != null) {
+                                (it.parent as ViewGroup).removeView(it)
+                            }
+                            rootView.addView(it).apply { it.visibility = View.VISIBLE }
+                        }
+                    }
+
+                    ClockSize.SMALL -> {
+                        clock.smallClock.layout.views.forEach {
+                            if (it.parent != null) {
+                                (it.parent as ViewGroup).removeView(it)
+                            }
+                            rootView.addView(it).apply { it.visibility = View.VISIBLE }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockHostView.kt b/src/com/android/customization/picker/clock/ui/view/ClockHostView.kt
index 512fcd1..2db52f1 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockHostView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockHostView.kt
@@ -12,10 +12,7 @@
  * same size of lockscreen to layout clock and scale down it to the size in picker carousel
  * according to ratio of preview to LS
  */
-class ClockHostView(
-    context: Context,
-    attrs: AttributeSet?,
-) : FrameLayout(context, attrs) {
+class ClockHostView(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
     private var previewRatio: Float = 1F
         set(value) {
             if (field != value) {
@@ -41,15 +38,16 @@
         parentWidthMeasureSpec: Int,
         widthUsed: Int,
         parentHeightMeasureSpec: Int,
-        heightUsed: Int
+        heightUsed: Int,
     ) {
+
         val screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display)
         super.measureChildWithMargins(
             child,
             MeasureSpec.makeMeasureSpec(screenSize.x, EXACTLY),
             widthUsed,
             MeasureSpec.makeMeasureSpec(screenSize.y, EXACTLY),
-            heightUsed
+            heightUsed,
         )
     }
 }
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockHostView2.kt b/src/com/android/customization/picker/clock/ui/view/ClockHostView2.kt
deleted file mode 100644
index be2e53d..0000000
--- a/src/com/android/customization/picker/clock/ui/view/ClockHostView2.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2024 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.view
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.View
-import android.view.View.MeasureSpec.EXACTLY
-import android.widget.FrameLayout
-import com.android.customization.picker.clock.shared.ClockSize
-import com.android.wallpaper.util.ScreenSizeCalculator
-
-/**
- * Parent view for the clock view. We will calculate the current display size and the preview size
- * and scale down the clock view to fit in the preview.
- */
-class ClockHostView2(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
-
-    var clockSize: ClockSize = ClockSize.DYNAMIC
-        set(value) {
-            if (field != value) {
-                field = value
-                updatePivotAndScale()
-                invalidate()
-            }
-        }
-
-    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
-        super.onLayout(changed, left, top, right, bottom)
-        updatePivotAndScale()
-    }
-
-    override fun measureChildWithMargins(
-        child: View?,
-        parentWidthMeasureSpec: Int,
-        widthUsed: Int,
-        parentHeightMeasureSpec: Int,
-        heightUsed: Int,
-    ) {
-        val screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display)
-        super.measureChildWithMargins(
-            child,
-            MeasureSpec.makeMeasureSpec(screenSize.x, EXACTLY),
-            widthUsed,
-            MeasureSpec.makeMeasureSpec(screenSize.y, EXACTLY),
-            heightUsed,
-        )
-    }
-
-    private fun updatePivotAndScale() {
-        when (clockSize) {
-            ClockSize.DYNAMIC -> {
-                resetPivot()
-            }
-            ClockSize.SMALL -> {
-                pivotX = getCenteredHostViewPivotX(this)
-                pivotY = 0F
-            }
-        }
-        val screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display)
-        val ratio = measuredWidth / screenSize.x.toFloat()
-        scaleX = ratio
-        scaleY = ratio
-    }
-
-    companion object {
-        fun getCenteredHostViewPivotX(hostView: View): Float {
-            return if (hostView.isLayoutRtl) hostView.width.toFloat() else 0F
-        }
-    }
-}
diff --git a/src/com/android/customization/picker/clock/ui/view/ThemePickerClockViewFactory.kt b/src/com/android/customization/picker/clock/ui/view/ThemePickerClockViewFactory.kt
index 6cb9acb..72b0f19 100644
--- a/src/com/android/customization/picker/clock/ui/view/ThemePickerClockViewFactory.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ThemePickerClockViewFactory.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.plugins.clocks.ClockFontAxisSetting
 import com.android.systemui.plugins.clocks.WeatherData
+import com.android.systemui.shared.Flags
 import com.android.systemui.shared.clocks.ClockRegistry
 import com.android.wallpaper.util.ScreenSizeCalculator
 import com.android.wallpaper.util.TimeUtils.TimeTicker
@@ -64,6 +65,7 @@
      * configs, e.g. animation state, might change during the reuse of the clock view in the app.
      */
     override fun getLargeView(clockId: String): View {
+        assert(!Flags.newCustomizationPickerUi())
         return getController(clockId).largeClock.let {
             it.animations.onPickerCarouselSwiping(1F)
             it.view
@@ -75,6 +77,7 @@
      * configs, e.g. translation X, might change during the reuse of the clock view in the app.
      */
     override fun getSmallView(clockId: String): View {
+        assert(!Flags.newCustomizationPickerUi())
         val smallClockFrame =
             smallClockFrames[clockId]
                 ?: createSmallClockFrame().also {
diff --git a/src/com/android/customization/picker/mode/ui/viewmodel/DarkModeViewModel.kt b/src/com/android/customization/picker/mode/ui/viewmodel/DarkModeViewModel.kt
index 2bcb644..f51d966 100644
--- a/src/com/android/customization/picker/mode/ui/viewmodel/DarkModeViewModel.kt
+++ b/src/com/android/customization/picker/mode/ui/viewmodel/DarkModeViewModel.kt
@@ -22,6 +22,7 @@
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
 
 @ViewModelScoped
@@ -31,7 +32,8 @@
     private val isDarkMode = interactor.isDarkMode
     val isEnabled = interactor.isEnabled
 
-    private val overridingIsDarkMode = MutableStateFlow<Boolean?>(null)
+    private val _overridingIsDarkMode = MutableStateFlow<Boolean?>(null)
+    val overridingIsDarkMode = _overridingIsDarkMode.asStateFlow()
     val previewingIsDarkMode =
         combine(overridingIsDarkMode, isDarkMode, isEnabled) { override, current, isEnabled ->
             if (isEnabled) {
@@ -41,7 +43,8 @@
 
     val toggleDarkMode =
         combine(overridingIsDarkMode, isDarkMode) { override, current ->
-            { overridingIsDarkMode.value = override?.not() ?: !current }
+            // Only set override if its value is different from current, else set to null
+            { _overridingIsDarkMode.value = if (override == null) !current else null }
         }
 
     val onApply: Flow<(suspend () -> Unit)?> =
@@ -55,6 +58,6 @@
         }
 
     fun resetPreview() {
-        overridingIsDarkMode.value = null
+        _overridingIsDarkMode.value = null
     }
 }
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 db43f4b..32b28ad 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -97,11 +97,7 @@
     ) {
 
     private val viewModel =
-        ViewModelProvider(
-                activity,
-                clockCarouselViewModelFactory,
-            )
-            .get() as ClockCarouselViewModel
+        ViewModelProvider(activity, clockCarouselViewModelFactory).get() as ClockCarouselViewModel
 
     private var clockColorAndSizeButton: View? = null
 
@@ -184,7 +180,7 @@
                                 )
                                 if (onAttachStateChangeListener != null) {
                                     carouselView.carousel.removeOnAttachStateChangeListener(
-                                        onAttachStateChangeListener,
+                                        onAttachStateChangeListener
                                     )
                                 }
                             }
diff --git a/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
index dd283c2..6bdd6ce 100644
--- a/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
+++ b/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
@@ -16,10 +16,12 @@
 
 package com.android.wallpaper.customization.ui.binder
 
+import android.content.Context
 import android.view.View
 import android.view.ViewGroup
 import android.widget.ImageView
 import android.widget.TextView
+import androidx.constraintlayout.widget.ConstraintSet
 import androidx.core.content.ContextCompat
 import androidx.core.view.isVisible
 import androidx.lifecycle.Lifecycle
@@ -27,10 +29,12 @@
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.customization.picker.clock.shared.ClockSize
-import com.android.customization.picker.clock.ui.view.ClockHostView2
+import com.android.customization.picker.clock.ui.view.ClockConstraintLayoutHostView
+import com.android.customization.picker.clock.ui.view.ClockConstraintLayoutHostView.Companion.addClockViews
 import com.android.customization.picker.clock.ui.view.ClockViewFactory
 import com.android.customization.picker.grid.ui.binder.GridIconViewBinder
 import com.android.systemui.plugins.clocks.ClockFontAxisSetting
+import com.android.systemui.shared.Flags
 import com.android.themepicker.R
 import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerHomeCustomizationOption
 import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerLockCustomizationOption
@@ -231,12 +235,14 @@
     }
 
     override fun bindClockPreview(
+        context: Context,
         clockHostView: View,
         viewModel: CustomizationPickerViewModel2,
+        colorUpdateViewModel: ColorUpdateViewModel,
         lifecycleOwner: LifecycleOwner,
         clockViewFactory: ClockViewFactory,
     ) {
-        clockHostView as ClockHostView2
+        clockHostView as ClockConstraintLayoutHostView
         val clockPickerViewModel =
             (viewModel.customizationOptionsViewModel as ThemePickerCustomizationOptionsViewModel)
                 .clockPickerViewModel
@@ -252,17 +258,36 @@
                         }
                         .collect { (clock, size) ->
                             clockHostView.removeAllViews()
-                            val clockView =
-                                when (size) {
-                                    ClockSize.DYNAMIC ->
-                                        clockViewFactory.getLargeView(clock.clockId)
-                                    ClockSize.SMALL -> clockViewFactory.getSmallView(clock.clockId)
+                            // For new customization picker, we should get views from clocklayout
+                            if (Flags.newCustomizationPickerUi()) {
+                                clockViewFactory.getController(clock.clockId).let { clockController
+                                    ->
+                                    addClockViews(clockController, clockHostView, size)
+                                    val cs = ConstraintSet()
+                                    clockController.largeClock.layout.applyPreviewConstraints(
+                                        context,
+                                        cs,
+                                    )
+                                    clockController.smallClock.layout.applyPreviewConstraints(
+                                        context,
+                                        cs,
+                                    )
+                                    cs.applyTo(clockHostView)
                                 }
-                            // The clock view might still be attached to an existing parent. Detach
-                            // before adding to another parent.
-                            (clockView.parent as? ViewGroup)?.removeView(clockView)
-                            clockHostView.addView(clockView)
-                            clockHostView.clockSize = size
+                            } else {
+                                val clockView =
+                                    when (size) {
+                                        ClockSize.DYNAMIC ->
+                                            clockViewFactory.getLargeView(clock.clockId)
+                                        ClockSize.SMALL ->
+                                            clockViewFactory.getSmallView(clock.clockId)
+                                    }
+                                // The clock view might still be attached to an existing parent.
+                                // Detach
+                                // before adding to another parent.
+                                (clockView.parent as? ViewGroup)?.removeView(clockView)
+                                clockHostView.addView(clockView)
+                            }
                         }
                 }
 
@@ -271,12 +296,12 @@
                             clockPickerViewModel.previewingSeedColor,
                             clockPickerViewModel.previewingClock,
                             clockPickerViewModel.previewingFontAxisMap,
-                            ::Triple,
+                            colorUpdateViewModel.systemColorsUpdated,
+                            ::Quadruple,
                         )
-                        .collect { triple ->
-                            val (color, clock, axisMap) = triple
+                        .collect { quadruple ->
+                            val (color, clock, axisMap, _) = quadruple
                             clockViewFactory.updateColor(clock.clockId, color)
-
                             val axisList = axisMap.map { ClockFontAxisSetting(it.key, it.value) }
                             clockViewFactory.updateFontAxes(clock.clockId, axisList)
                         }
@@ -284,4 +309,6 @@
             }
         }
     }
+
+    data class Quadruple<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D)
 }
diff --git a/src/com/android/wallpaper/picker/common/preview/ui/binder/ThemePickerWorkspaceCallbackBinder.kt b/src/com/android/wallpaper/picker/common/preview/ui/binder/ThemePickerWorkspaceCallbackBinder.kt
index 0656696..6952d91 100644
--- a/src/com/android/wallpaper/picker/common/preview/ui/binder/ThemePickerWorkspaceCallbackBinder.kt
+++ b/src/com/android/wallpaper/picker/common/preview/ui/binder/ThemePickerWorkspaceCallbackBinder.kt
@@ -39,6 +39,7 @@
 import com.android.wallpaper.customization.ui.viewmodel.ThemePickerCustomizationOptionsViewModel
 import com.android.wallpaper.model.Screen
 import com.android.wallpaper.picker.common.preview.ui.binder.WorkspaceCallbackBinder.Companion.sendMessage
+import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel
 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModel
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -56,12 +57,14 @@
     override fun bind(
         workspaceCallback: Message,
         viewModel: CustomizationOptionsViewModel,
+        colorUpdateViewModel: ColorUpdateViewModel,
         screen: Screen,
         lifecycleOwner: LifecycleOwner,
     ) {
         defaultWorkspaceCallbackBinder.bind(
             workspaceCallback = workspaceCallback,
             viewModel = viewModel,
+            colorUpdateViewModel = colorUpdateViewModel,
             screen = screen,
             lifecycleOwner = lifecycleOwner,
         )
@@ -158,10 +161,11 @@
                         launch {
                             combine(
                                     viewModel.colorPickerViewModel2.previewingColorOption,
-                                    viewModel.darkModeViewModel.previewingIsDarkMode,
-                                    ::Pair,
+                                    viewModel.darkModeViewModel.overridingIsDarkMode,
+                                    colorUpdateViewModel.systemColorsUpdated,
+                                    ::Triple,
                                 )
-                                .collect { (colorModel, darkMode) ->
+                                .collect { (colorModel, darkMode, _) ->
                                     val bundle =
                                         Bundle().apply {
                                             if (colorModel != null) {
@@ -174,7 +178,9 @@
                                                 putIntArray(KEY_COLOR_VALUES, colors)
                                             }
 
-                                            putBoolean(KEY_DARK_MODE, darkMode)
+                                            if (darkMode != null) {
+                                                putBoolean(KEY_DARK_MODE, darkMode)
+                                            }
                                         }
                                     workspaceCallback.sendMessage(MESSAGE_ID_UPDATE_COLOR, bundle)
                                 }