Clock font axis editor dialogue
Bug: 364673969
Test: Manual + Presumbits
Flag: com.android.systemui.shared.new_customization_picker_ui
Change-Id: I2eade33e285514423d042c3b99085ef35cd2a24a
diff --git a/res/drawable/clock_font_apply.xml b/res/drawable/clock_font_apply.xml
new file mode 100644
index 0000000..11c6f06
--- /dev/null
+++ b/res/drawable/clock_font_apply.xml
@@ -0,0 +1,24 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="72dp"
+ android:height="56dp"
+ android:viewportWidth="72"
+ android:viewportHeight="56">
+ <group>
+ <clip-path
+ android:pathData="M0,0h72v56h-72z"/>
+ <group>
+ <clip-path
+ android:pathData="M0,28C0,12.536 12.536,0 28,0H44C59.464,0 72,12.536 72,28C72,43.464 59.464,56 44,56H28C12.536,56 0,43.464 0,28Z"/>
+ <path
+ android:pathData="M0,28C0,12.536 12.536,0 28,0H44C59.464,0 72,12.536 72,28C72,43.464 59.464,56 44,56H28C12.536,56 0,43.464 0,28Z"
+ android:fillColor="@color/system_on_primary"/>
+ <group>
+ <clip-path
+ android:pathData="M24,16h24v24h-24z"/>
+ <path
+ android:pathData="M33.55,34L27.85,28.3L29.275,26.875L33.55,31.15L42.725,21.975L44.15,23.4L33.55,34Z"
+ android:fillColor="@color/system_primary"/>
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/res/drawable/clock_font_revert.xml b/res/drawable/clock_font_revert.xml
new file mode 100644
index 0000000..10a46ad
--- /dev/null
+++ b/res/drawable/clock_font_revert.xml
@@ -0,0 +1,24 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="72dp"
+ android:height="56dp"
+ android:viewportWidth="72"
+ android:viewportHeight="56">
+ <group>
+ <clip-path
+ android:pathData="M0,0h72v56h-72z"/>
+ <group>
+ <clip-path
+ android:pathData="M0,28C0,12.536 12.536,0 28,0H44C59.464,0 72,12.536 72,28C72,43.464 59.464,56 44,56H28C12.536,56 0,43.464 0,28Z"/>
+ <path
+ android:pathData="M0,28C0,12.536 12.536,0 28,0H44C59.464,0 72,12.536 72,28C72,43.464 59.464,56 44,56H28C12.536,56 0,43.464 0,28Z"
+ android:fillColor="@color/system_secondary_container"/>
+ <group>
+ <clip-path
+ android:pathData="M24,16h24v24h-24z"/>
+ <path
+ android:pathData="M30.4,35L29,33.6L34.6,28L29,22.4L30.4,21L36,26.6L41.6,21L43,22.4L37.4,28L43,33.6L41.6,35L36,29.4L30.4,35Z"
+ android:fillColor="@color/system_on_secondary_container"/>
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/res/drawable/clock_font_switch_divider.xml b/res/drawable/clock_font_switch_divider.xml
new file mode 100644
index 0000000..abaee24
--- /dev/null
+++ b/res/drawable/clock_font_switch_divider.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="6dp"
+ android:height="48dp"
+ android:viewportWidth="6"
+ android:viewportHeight="48">
+ <path
+ android:pathData="M2,11C2,10.448 2.448,10 3,10C3.552,10 4,10.448 4,11V37C4,37.552 3.552,38 3,38C2.448,38 2,37.552 2,37V11Z"
+ android:fillColor="@color/system_outline"/>
+</vector>
diff --git a/res/layout/clock_font_axis_name.xml b/res/layout/clock_font_axis_name.xml
new file mode 100644
index 0000000..dd29c6b
--- /dev/null
+++ b/res/layout/clock_font_axis_name.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/clock_axis_name"
+ android:layout_width="@dimen/clock_font_axis_name_width"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" />
\ No newline at end of file
diff --git a/res/layout/clock_font_axis_slider_row.xml b/res/layout/clock_font_axis_slider_row.xml
new file mode 100644
index 0000000..cb663b4
--- /dev/null
+++ b/res/layout/clock_font_axis_slider_row.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingVertical="@dimen/clock_axis_control_row_vertical_padding"
+ android:orientation="horizontal">
+ <include layout="@layout/clock_font_axis_name" />
+
+ <SeekBar
+ android:id="@+id/clock_axis_slider"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingStart="@dimen/clock_axis_control_padding_start"
+ android:minHeight="@dimen/touch_target_min_height"
+ android:thumb="@null"
+ android:background="@null"
+ android:splitTrack="false"
+ android:progressDrawable="@drawable/saturation_progress_drawable" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/clock_font_axis_switch.xml b/res/layout/clock_font_axis_switch.xml
new file mode 100644
index 0000000..385d105
--- /dev/null
+++ b/res/layout/clock_font_axis_switch.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+<Switch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/clock_axis_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/clock_axis_control_padding_start"
+ style="@style/Switch.SettingsLib" />
\ No newline at end of file
diff --git a/res/layout/clock_font_axis_switch_row.xml b/res/layout/clock_font_axis_switch_row.xml
new file mode 100644
index 0000000..139e5e0
--- /dev/null
+++ b/res/layout/clock_font_axis_switch_row.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingVertical="@dimen/clock_axis_control_row_vertical_padding"
+ android:orientation="horizontal">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/clock_switch_one"
+ android:orientation="horizontal">
+
+ <include layout="@layout/clock_font_axis_name" />
+ <include layout="@layout/clock_font_axis_switch" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/clock_switch_two"
+ android:orientation="horizontal"
+ android:visibility="gone">
+
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/clock_font_switch_divider"
+ android:layout_marginHorizontal="@dimen/clock_font_control_switch_padding_horizontal"
+ android:layout_gravity="center_vertical"/>
+
+ <include layout="@layout/clock_font_axis_name" />
+ <include layout="@layout/clock_font_axis_switch" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/floating_sheet_clock.xml b/res/layout/floating_sheet_clock.xml
index 7ff663f..75afce6 100644
--- a/res/layout/floating_sheet_clock.xml
+++ b/res/layout/floating_sheet_clock.xml
@@ -148,7 +148,6 @@
android:clipToPadding="false" />
</FrameLayout>
-
<SeekBar
android:id="@+id/clock_color_slider"
android:layout_width="match_parent"
@@ -162,6 +161,19 @@
android:progressDrawable="@drawable/saturation_progress_drawable"
android:splitTrack="false" />
</LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/clock_floating_sheet_font_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/floating_sheet_content_horizontal_padding"
+ android:paddingVertical="@dimen/floating_sheet_content_vertical_padding"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <!-- Populated dynamically w/ clock axis information -->
+ </LinearLayout>
</FrameLayout>
<com.android.wallpaper.picker.customization.ui.view.FloatingToolbar
@@ -170,4 +182,27 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="@dimen/floating_sheet_tab_toolbar_vertical_margin" />
+
+ <LinearLayout
+ android:id="@+id/clock_font_toolbar"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginVertical="@dimen/floating_sheet_tab_toolbar_vertical_margin">
+
+ <ImageView
+ android:id="@+id/clock_font_revert"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/clock_font_revert"
+ android:contentDescription="@string/clock_font_editor_revert" />
+ <ImageView
+ android:id="@+id/clock_font_apply"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/clock_font_apply_padding_start"
+ android:src="@drawable/clock_font_apply"
+ android:contentDescription="@string/clock_font_editor_apply" />
+ </LinearLayout>
</LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c242fe9..d8d30d3 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -194,4 +194,11 @@
<dimen name="floating_sheet_color_option_size">54dp</dimen>
<dimen name="floating_sheet_color_option_stroke_width">3dp</dimen>
<dimen name="customization_option_entry_shortcut_icon_size">20dp</dimen>
+
+ <!-- Clock font control dimensions -->
+ <dimen name="clock_font_axis_name_width">64dp</dimen>
+ <dimen name="clock_axis_control_padding_start">16dp</dimen>
+ <dimen name="clock_axis_control_row_vertical_padding">10dp</dimen>
+ <dimen name="clock_font_control_switch_padding_horizontal">38dp</dimen>
+ <dimen name="clock_font_apply_padding_start">8dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5643351..586117f 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -96,6 +96,12 @@
<!-- Description of a radio button to apply clock size small. [CHAR LIMIT=NONE] -->
<string name="clock_size_small_description">A small clock shows in the corner of your screen</string>
+ <!-- Description for clock font editor axis apply button. [CHAR LIMIT=NONE] -->
+ <string name="clock_font_editor_apply">Apply clock font changes</string>
+
+ <!-- Description for clock font editor axis revert button. [CHAR LIMIT=NONE] -->
+ <string name="clock_font_editor_revert">Undo clock font changes</string>
+
<!-- Title of a section of the customization picker where the user can select a Grid size for
the home screen. [CHAR LIMIT=15] -->
<string name="grid_title">App grid</string>
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 f3a2301..86920a3 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -22,6 +22,7 @@
import androidx.annotation.IntRange
import com.android.customization.picker.clock.shared.ClockSize
import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.systemui.plugins.clocks.ClockFontAxis
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.shared.clocks.ClockRegistry
import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
@@ -70,7 +71,7 @@
description = clockConfig.description,
thumbnail = clockConfig.thumbnail,
isReactiveToTone = clockConfig.isReactiveToTone,
- hasReactiveAxes = !clockConfig.axes.isEmpty(),
+ axes = clockConfig.axes,
)
} else {
null
@@ -116,7 +117,7 @@
description = it.description,
thumbnail = it.thumbnail,
isReactiveToTone = it.isReactiveToTone,
- hasReactiveAxes = !it.axes.isEmpty(),
+ axes = it.axes,
selectedColorId = metadata?.getSelectedColorId(),
colorTone =
metadata?.getColorTone()
@@ -206,7 +207,7 @@
description: String,
thumbnail: Drawable,
isReactiveToTone: Boolean,
- hasReactiveAxes: Boolean,
+ axes: List<ClockFontAxis>,
selectedColorId: String? = null,
@IntRange(from = 0, to = 100) colorTone: Int = 0,
@ColorInt seedColor: Int? = null,
@@ -217,7 +218,7 @@
description = description,
thumbnail = thumbnail,
isReactiveToTone = isReactiveToTone,
- hasReactiveAxes = hasReactiveAxes,
+ axes = axes,
selectedColorId = selectedColorId,
colorToneProgress = colorTone,
seedColor = seedColor,
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 ff8d85f..dfedb5d 100644
--- a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
+++ b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
@@ -20,6 +20,7 @@
import android.graphics.drawable.Drawable
import androidx.annotation.ColorInt
import androidx.annotation.IntRange
+import com.android.systemui.plugins.clocks.ClockFontAxis
/** Model for clock metadata. */
data class ClockMetadataModel(
@@ -28,7 +29,7 @@
val description: String,
val thumbnail: Drawable,
val isReactiveToTone: Boolean,
- val hasReactiveAxes: Boolean,
+ val axes: List<ClockFontAxis>,
val selectedColorId: String?,
@IntRange(from = 0, to = 100) val colorToneProgress: Int,
@ColorInt val seedColor: Int?,
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 b68edd9..09da12a 100644
--- a/src/com/android/customization/picker/clock/ui/view/ThemePickerClockViewFactory.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ThemePickerClockViewFactory.kt
@@ -26,6 +26,7 @@
import androidx.lifecycle.LifecycleOwner
import com.android.internal.policy.SystemBarUtils
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.clocks.ClockRegistry
import com.android.wallpaper.config.BaseFlags
@@ -135,6 +136,10 @@
}
}
+ override fun updateFontAxes(clockId: String, settings: List<ClockFontAxisSetting>) {
+ getController(clockId).let { it.events.onFontAxesChanged(settings) }
+ }
+
override fun updateRegionDarkness() {
val isRegionDark = isLockscreenWallpaperDark()
clockControllers.values.forEach {
diff --git a/src/com/android/wallpaper/customization/ui/binder/ClockFloatingSheetBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ClockFloatingSheetBinder.kt
index 983b897..3423617 100644
--- a/src/com/android/wallpaper/customization/ui/binder/ClockFloatingSheetBinder.kt
+++ b/src/com/android/wallpaper/customization/ui/binder/ClockFloatingSheetBinder.kt
@@ -19,11 +19,13 @@
import android.animation.ValueAnimator
import android.content.Context
import android.content.res.Configuration
+import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.SeekBar
import android.widget.Switch
+import android.widget.TextView
import androidx.core.view.doOnLayout
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
@@ -37,18 +39,22 @@
import com.android.customization.picker.color.ui.view.ColorOptionIconView
import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel
import com.android.customization.picker.common.ui.view.SingleRowListItemSpacing
+import com.android.systemui.plugins.clocks.AxisType
+import com.android.systemui.plugins.clocks.ClockFontAxis
+import com.android.systemui.plugins.clocks.ClockId
import com.android.themepicker.R
import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerLockCustomizationOption.CLOCK
import com.android.wallpaper.customization.ui.viewmodel.ClockFloatingSheetHeightsViewModel
+import com.android.wallpaper.customization.ui.viewmodel.ClockPickerViewModel
import com.android.wallpaper.customization.ui.viewmodel.ClockPickerViewModel.ClockStyleModel
-import com.android.wallpaper.customization.ui.viewmodel.ClockPickerViewModel.Tab.COLOR
-import com.android.wallpaper.customization.ui.viewmodel.ClockPickerViewModel.Tab.STYLE
+import com.android.wallpaper.customization.ui.viewmodel.ClockPickerViewModel.Tab
import com.android.wallpaper.customization.ui.viewmodel.ThemePickerCustomizationOptionsViewModel
import com.android.wallpaper.picker.customization.ui.view.FloatingToolbar
import com.android.wallpaper.picker.customization.ui.view.adapter.FloatingToolbarTabAdapter
import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel
import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter
import java.lang.ref.WeakReference
+import kotlin.math.abs
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -94,6 +100,17 @@
initStyleList(appContext, clockStyleAdapter)
}
+ // Clock font editor
+ val clockFontContent =
+ view.requireViewById<ViewGroup>(R.id.clock_floating_sheet_font_content)
+ val clockFontToolbar = view.requireViewById<ViewGroup>(R.id.clock_font_toolbar)
+ clockFontToolbar
+ .requireViewById<View>(R.id.clock_font_revert)
+ .setOnClickListener(View.OnClickListener { viewModel.revertFontAxes() })
+ clockFontToolbar
+ .requireViewById<View>(R.id.clock_font_apply)
+ .setOnClickListener(View.OnClickListener { viewModel.applyFontAxes() })
+
// Clock color
val clockColorContent = view.requireViewById<View>(R.id.clock_floating_sheet_color_content)
val clockColorAdapter =
@@ -126,6 +143,7 @@
ClockFloatingSheetHeightsViewModel(
clockStyleContentHeight = clockStyleContent.height,
clockColorContentHeight = clockColorContent.height,
+ clockFontContentHeight = clockFontContent.height,
)
}
}
@@ -135,33 +153,69 @@
launch { viewModel.tabs.collect { tabAdapter.submitList(it) } }
launch {
- combine(clockFloatingSheetHeights, viewModel.selectedTab) { heights, selectedTab
- ->
- heights to selectedTab
+ combine(clockFloatingSheetHeights, viewModel.selectedTab, ::Pair).collect {
+ (heights, selectedTab) ->
+ heights ?: return@collect
+
+ val targetHeight =
+ when (selectedTab) {
+ Tab.STYLE -> heights.clockStyleContentHeight
+ Tab.COLOR -> heights.clockColorContentHeight
+ Tab.FONT -> heights.clockFontContentHeight
+ } +
+ view.resources.getDimensionPixelSize(
+ R.dimen.floating_sheet_content_vertical_padding
+ ) * 2
+
+ val animationFloatingSheet =
+ ValueAnimator.ofInt(floatingSheetContainer.height, targetHeight)
+ animationFloatingSheet.addUpdateListener { valueAnimator ->
+ val value = valueAnimator.animatedValue as Int
+ floatingSheetContainer.layoutParams =
+ floatingSheetContainer.layoutParams.apply { height = value }
}
- .collect { (heights, selectedTab) ->
- heights ?: return@collect
- val targetHeight =
- when (selectedTab) {
- STYLE -> heights.clockStyleContentHeight
- COLOR -> heights.clockColorContentHeight
- } +
- view.resources.getDimensionPixelSize(
- R.dimen.floating_sheet_content_vertical_padding
- ) * 2
+ animationFloatingSheet.setDuration(ANIMATION_DURATION)
+ animationFloatingSheet.start()
- val animationFloatingSheet =
- ValueAnimator.ofInt(floatingSheetContainer.height, targetHeight)
- animationFloatingSheet.addUpdateListener { valueAnimator ->
- val value = valueAnimator.animatedValue as Int
- floatingSheetContainer.layoutParams =
- floatingSheetContainer.layoutParams.apply { height = value }
+ clockStyleContent.isVisible = selectedTab == Tab.STYLE
+ clockColorContent.isVisible = selectedTab == Tab.COLOR
+ clockFontContent.isVisible = selectedTab == Tab.FONT
+
+ tabs.isVisible = selectedTab != Tab.FONT
+ clockFontToolbar.isVisible = selectedTab == Tab.FONT
+ }
+ }
+
+ launch {
+ var boundClockId: ClockId? = null
+ var boundEditorViews = mapOf<String, Pair<View, ClockFontAxis>>()
+ combine(viewModel.previewingClock, viewModel.previewingFontAxes, ::Pair)
+ .collect { pair ->
+ val (clock, axisSettings) = pair
+ if (clock == null) {
+ boundClockId = null
+ boundEditorViews = mapOf()
+ clockFontContent.removeAllViews()
+ return@collect
}
- animationFloatingSheet.setDuration(ANIMATION_DURATION)
- animationFloatingSheet.start()
- clockStyleContent.isVisible = selectedTab == STYLE
- clockColorContent.isVisible = selectedTab == COLOR
+ if (boundClockId != clock.clockId) {
+ boundEditorViews =
+ initClockFontEditor(clockFontContent, clock.axes, viewModel)
+ boundClockId = clock.clockId
+ }
+
+ for ((key, value) in axisSettings) {
+ boundEditorViews[key]?.let { pair ->
+ val (view, axis) = pair
+ view.findViewById<Switch>(R.id.clock_axis_switch)?.apply {
+ isChecked = abs(value - axis.maxValue) < 0.01f
+ }
+ view.findViewById<SeekBar>(R.id.clock_axis_slider)?.apply {
+ setProgress(value.toInt(), false)
+ }
+ }
+ }
}
}
@@ -221,6 +275,76 @@
}
}
+ private fun initClockFontEditor(
+ parent: ViewGroup,
+ axes: List<ClockFontAxis>,
+ viewModel: ClockPickerViewModel,
+ ): Map<String, Pair<View, ClockFontAxis>> {
+ parent.removeAllViews()
+ val inflater = LayoutInflater.from(parent.context)
+ val axisMap = mutableMapOf<String, Pair<View, ClockFontAxis>>()
+ var nextSwitch: View? = null
+ for (axis in axes) {
+ val view =
+ when (axis.type) {
+ AxisType.Float -> {
+ val id = R.layout.clock_font_axis_slider_row
+ val row = inflater.inflate(id, parent, false)
+ parent.addView(row)
+ row
+ }
+ AxisType.Boolean ->
+ nextSwitch?.also { nextSwitch = null }
+ ?: run {
+ val id = R.layout.clock_font_axis_switch_row
+ val row = inflater.inflate(id, parent, false)
+ parent.addView(row)
+
+ nextSwitch = row.requireViewById(R.id.clock_switch_two)
+ row.requireViewById(R.id.clock_switch_one)
+ }
+ }
+
+ view.visibility = View.VISIBLE
+ axisMap[axis.key] = Pair(view, axis)
+ view.contentDescription = axis.description
+ view.requireViewById<TextView>(R.id.clock_axis_name).text = axis.name
+
+ view.findViewById<Switch>(R.id.clock_axis_switch)?.apply {
+ isChecked = abs(axis.currentValue - axis.maxValue) < 0.01f
+ setOnCheckedChangeListener { v, _ ->
+ val value = if (v.isChecked) axis.maxValue else axis.minValue
+ viewModel.updatePreviewFontAxis(axis.key, value)
+ }
+ }
+
+ view.findViewById<SeekBar>(R.id.clock_axis_slider)?.apply {
+ setMax(axis.maxValue.toInt())
+ setMin(axis.minValue.toInt())
+ setProgress(axis.currentValue.toInt(), false)
+
+ setOnSeekBarChangeListener(
+ object : SeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(
+ seekBar: SeekBar?,
+ progress: Int,
+ fromUser: Boolean,
+ ) {
+ if (fromUser) {
+ viewModel.updatePreviewFontAxis(axis.key, progress.toFloat())
+ }
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar?) {}
+
+ override fun onStopTrackingTouch(seekBar: SeekBar?) {}
+ }
+ )
+ }
+ }
+ return axisMap
+ }
+
private fun createClockStyleOptionItemAdapter(
lifecycleOwner: LifecycleOwner
): OptionItemAdapter<ClockStyleModel> =
@@ -230,6 +354,7 @@
bindIcon = { view: View, style: ClockStyleModel ->
(view.findViewById(R.id.clock_icon) as ImageView).setImageDrawable(style.thumbnail)
(view.findViewById(R.id.edit_icon) as ImageView).setVisibility(
+ // TODO(b/364673969): Route isSelected here and hide when unselected
if (style.isEditable) View.VISIBLE else View.GONE
)
},
diff --git a/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
index a92471c..528c61a 100644
--- a/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
+++ b/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
@@ -30,6 +30,7 @@
import com.android.customization.picker.clock.ui.view.ClockHostView2
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.themepicker.R
import com.android.wallpaper.config.BaseFlags
import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerHomeCustomizationOption
@@ -276,11 +277,15 @@
combine(
clockPickerViewModel.previewingSeedColor,
clockPickerViewModel.previewingClock,
- ) { color, clock ->
- color to clock
- }
- .collect { (color, clock) ->
+ clockPickerViewModel.previewingFontAxes,
+ ::Triple,
+ )
+ .collect { triple ->
+ val (color, clock, axisMap) = triple
clockViewFactory.updateColor(clock.clockId, color)
+
+ val axisList = axisMap.map { ClockFontAxisSetting(it.key, it.value) }
+ clockViewFactory.updateFontAxes(clock.clockId, axisList)
}
}
}
diff --git a/src/com/android/wallpaper/customization/ui/viewmodel/ClockFloatingSheetHeightsViewModel.kt b/src/com/android/wallpaper/customization/ui/viewmodel/ClockFloatingSheetHeightsViewModel.kt
index 913ff11..1f86533 100644
--- a/src/com/android/wallpaper/customization/ui/viewmodel/ClockFloatingSheetHeightsViewModel.kt
+++ b/src/com/android/wallpaper/customization/ui/viewmodel/ClockFloatingSheetHeightsViewModel.kt
@@ -19,4 +19,5 @@
data class ClockFloatingSheetHeightsViewModel(
val clockStyleContentHeight: Int,
val clockColorContentHeight: Int,
+ val clockFontContentHeight: Int,
)
diff --git a/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModel.kt b/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModel.kt
index 504b766..fe8a718 100644
--- a/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModel.kt
+++ b/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModel.kt
@@ -40,6 +40,7 @@
import dagger.assisted.AssistedInject
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.scopes.ViewModelScoped
+import kotlin.collections.map
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -72,6 +73,7 @@
enum class Tab {
STYLE,
COLOR,
+ FONT,
}
private val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
@@ -137,7 +139,7 @@
payload =
ClockStyleModel(
clockModel.thumbnail,
- isEditable = clockModel.hasReactiveAxes,
+ isEditable = !clockModel.axes.isEmpty(),
),
text = Text.Loaded(contentDescription),
isTextUserVisible = false,
@@ -145,9 +147,14 @@
onClicked =
isSelectedFlow.map { isSelected ->
if (isSelected) {
- null
+ fun() {
+ _selectedTab.value = Tab.FONT
+ }
} else {
- { overridingClock.value = clockModel }
+ fun() {
+ overridingClock.value = clockModel
+ overrideFontAxes.value = null
+ }
}
},
)
@@ -159,6 +166,29 @@
.flowOn(backgroundDispatcher.limitedParallelism(1))
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
+ // Clock Font Axis Editor
+ private val overrideFontAxes = MutableStateFlow<Map<String, Float>?>(null)
+ val previewingFontAxes =
+ combine(overrideFontAxes, previewingClock) { overrideAxes, previewingClock ->
+ overrideAxes ?: previewingClock.axes.associate { it.key to it.currentValue }
+ }
+ .stateIn(viewModelScope, SharingStarted.Eagerly, emptyMap())
+
+ fun updatePreviewFontAxis(key: String, value: Float) {
+ val fontAxes = previewingFontAxes.value.toMutableMap()
+ fontAxes[key] = value
+ overrideFontAxes.value = fontAxes
+ }
+
+ fun applyFontAxes() {
+ _selectedTab.value = Tab.STYLE
+ }
+
+ fun revertFontAxes() {
+ overrideFontAxes.value = null
+ _selectedTab.value = Tab.STYLE
+ }
+
// Clock size
private val overridingClockSize = MutableStateFlow<ClockSize?>(null)
val previewingClockSize =
@@ -360,6 +390,7 @@
overridingClockSize.value = null
overridingClockColorId.value = null
overridingSliderProgress.value = null
+ overrideFontAxes.value = null
_selectedTab.value = Tab.STYLE
}
diff --git a/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt b/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
index 729241f..c1a4a65 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -22,6 +22,8 @@
import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository.Companion.fakeClocks
import com.android.customization.picker.clock.shared.ClockSize
import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.systemui.plugins.clocks.AxisType
+import com.android.systemui.plugins.clocks.ClockFontAxis
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -50,7 +52,7 @@
description = "description",
thumbnail = ColorDrawable(0),
isReactiveToTone = selectedClock.isReactiveToTone,
- hasReactiveAxes = false,
+ axes = fakeAxisList,
selectedColorId = selectedColor,
colorToneProgress = colorTone,
seedColor = seedColor,
@@ -79,6 +81,19 @@
}
companion object {
+ private val fakeAxisList =
+ listOf(
+ ClockFontAxis(
+ key = "key",
+ type = AxisType.Float,
+ maxValue = 0f,
+ minValue = 100f,
+ currentValue = 50f,
+ name = "FakeAxis",
+ description = "Axis Description",
+ )
+ )
+
const val CLOCK_ID_0 = "clock0"
const val CLOCK_ID_1 = "clock1"
const val CLOCK_ID_2 = "clock2"
@@ -91,7 +106,7 @@
"description0",
ColorDrawable(0),
true,
- false,
+ fakeAxisList,
null,
50,
null,
@@ -102,7 +117,7 @@
"description1",
ColorDrawable(0),
true,
- false,
+ fakeAxisList,
null,
50,
null,
@@ -113,7 +128,7 @@
"description2",
ColorDrawable(0),
true,
- false,
+ fakeAxisList,
null,
50,
null,
@@ -124,7 +139,7 @@
"description3",
ColorDrawable(0),
false,
- false,
+ fakeAxisList,
null,
50,
null,
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
index d2acb16..bb2ad4c 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
@@ -8,6 +8,7 @@
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockEvents
import com.android.systemui.plugins.clocks.ClockFaceController
+import com.android.systemui.plugins.clocks.ClockFontAxisSetting
import java.io.PrintWriter
import javax.inject.Inject
@@ -56,6 +57,10 @@
TODO("Not yet implemented")
}
+ override fun updateFontAxes(clockId: String, settings: List<ClockFontAxisSetting>) {
+ TODO("Not yet implemented")
+ }
+
override fun updateRegionDarkness() {
TODO("Not yet implemented")
}
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
index cf1cc55..166855f 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -58,7 +58,7 @@
description = "description",
thumbnail = ColorDrawable(0),
isReactiveToTone = true,
- hasReactiveAxes = false,
+ axes = listOf(),
selectedColorId = null,
colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
seedColor = null,
diff --git a/tests/robotests/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModelTest.kt b/tests/robotests/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModelTest.kt
index 6bec3df..8b87368 100644
--- a/tests/robotests/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModelTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/customization/ui/viewmodel/ClockPickerViewModelTest.kt
@@ -138,6 +138,22 @@
}
@Test
+ fun selectedTab_fontEditorWhenClickSelectedClock() = runTest {
+ val clockStyleOptions = collectLastValue(underTest.clockStyleOptions)
+ val selectedTab = collectLastValue(underTest.selectedTab)
+ // Advance CLOCKS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from clockStyleOptions
+ advanceTimeBy(ClockPickerViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+ assertThat(selectedTab()).isEqualTo(Tab.STYLE)
+
+ val firstClock = clockStyleOptions()!![0]
+ val onClicked = collectLastValue(firstClock.onClicked)
+ if (!firstClock.isSelected.value) onClicked()?.invoke()
+ onClicked()?.invoke()
+
+ assertThat(selectedTab()).isEqualTo(Tab.FONT)
+ }
+
+ @Test
fun previewingClock_whenClickOnStyleOptions() = runTest {
val previewingClock = collectLastValue(underTest.previewingClock)
val clockStyleOptions = collectLastValue(underTest.clockStyleOptions)
@@ -165,7 +181,7 @@
val option1OnClicked = collectLastValue(clockStyleOptions()!![1].onClicked)
assertThat(option0IsSelected()).isTrue()
- assertThat(option0OnClicked()).isNull()
+ assertThat(option0OnClicked()).isNotNull()
option1OnClicked()?.invoke()
// Advance CLOCKS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from clockColorOptions
@@ -173,7 +189,7 @@
assertThat(option0IsSelected()).isFalse()
assertThat(option1IsSelected()).isTrue()
- assertThat(option1OnClicked()).isNull()
+ assertThat(option1OnClicked()).isNotNull()
}
@Test
@@ -190,6 +206,76 @@
}
@Test
+ fun previewingFontAxes_defaultWhenNoOverrides() = runTest {
+ val previewingFontAxes = collectLastValue(underTest.previewingFontAxes)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 50f))
+ }
+
+ @Test
+ fun previewingFontAxes_updateAxisChangesSetting() = runTest {
+ val previewingFontAxes = collectLastValue(underTest.previewingFontAxes)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 50f))
+
+ underTest.updatePreviewFontAxis("key", 100f)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 100f))
+
+ underTest.updatePreviewFontAxis("extra", 10f)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 100f, "extra" to 10f))
+ }
+
+ @Test
+ fun previewingFontAxes_applyFontEditorExitsTab_keepsPreviewAxis() = runTest {
+ val previewingFontAxes = collectLastValue(underTest.previewingFontAxes)
+ val clockStyleOptions = collectLastValue(underTest.clockStyleOptions)
+ val selectedTab = collectLastValue(underTest.selectedTab)
+ // Advance CLOCKS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from clockStyleOptions
+ advanceTimeBy(ClockPickerViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 50f))
+ assertThat(selectedTab()).isEqualTo(Tab.STYLE)
+
+ val firstClock = clockStyleOptions()!![0]
+ val onClicked = collectLastValue(firstClock.onClicked)
+ if (!firstClock.isSelected.value) onClicked()?.invoke()
+ onClicked()?.invoke()
+ underTest.updatePreviewFontAxis("key", 100f)
+
+ assertThat(selectedTab()).isEqualTo(Tab.FONT)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 100f))
+
+ underTest.applyFontAxes()
+
+ assertThat(selectedTab()).isEqualTo(Tab.STYLE)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 100f))
+ }
+
+ @Test
+ fun previewingFontAxes_revertFontEditorExitsTab_revertsPreviewAxis() = runTest {
+ val previewingFontAxes = collectLastValue(underTest.previewingFontAxes)
+ val clockStyleOptions = collectLastValue(underTest.clockStyleOptions)
+ val selectedTab = collectLastValue(underTest.selectedTab)
+ // Advance CLOCKS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from clockStyleOptions
+ advanceTimeBy(ClockPickerViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 50f))
+ assertThat(selectedTab()).isEqualTo(Tab.STYLE)
+
+ val firstClock = clockStyleOptions()!![0]
+ val onClicked = collectLastValue(firstClock.onClicked)
+ if (!firstClock.isSelected.value) onClicked()?.invoke()
+ onClicked()?.invoke()
+ underTest.updatePreviewFontAxis("key", 100f)
+
+ assertThat(selectedTab()).isEqualTo(Tab.FONT)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 100f))
+
+ underTest.revertFontAxes()
+
+ assertThat(selectedTab()).isEqualTo(Tab.STYLE)
+ assertThat(previewingFontAxes()).isEqualTo(mapOf("key" to 50f))
+ }
+
+ @Test
fun sliderProgress_whenOnSliderProgressChanged() = runTest {
val sliderProgress = collectLastValue(underTest.previewingSliderProgress)