Remove single clock view
We can use the mInfinite flag in the carousel to handle single clock
case.
When clock faces are less than 5, we will force the clock carousel
finite.
Test: See screeshot in bug. Also made sure for clock faces >= 5, the
Test: carousel is infinite again.
Bug: 290848550
Bug: 287650278
Change-Id: I1f0d9810ee5b92efc9cfacdfe2c70c6627916628
diff --git a/res/layout/single_clock_view.xml b/res/layout/single_clock_view.xml
deleted file mode 100644
index ffc6039..0000000
--- a/res/layout/single_clock_view.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.wallpaper.picker.FixedWidthDisplayRatioFrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/screen_preview_width"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:clipChildren="false">
- <com.android.customization.picker.clock.ui.view.ClockHostView
- android:id="@+id/single_clock_host_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center" />
-</com.android.wallpaper.picker.FixedWidthDisplayRatioFrameLayout>
\ No newline at end of file
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
index 89fac89..7880d82 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
@@ -16,8 +16,6 @@
package com.android.customization.picker.clock.ui.binder
import android.content.Context
-import android.view.ViewGroup
-import android.widget.FrameLayout
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
@@ -27,7 +25,6 @@
import com.android.customization.picker.clock.ui.view.ClockCarouselView
import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
-import com.android.wallpaper.R
import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewClickView
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
@@ -38,7 +35,6 @@
fun bind(
context: Context,
carouselView: ClockCarouselView,
- singleClockView: ViewGroup,
screenPreviewClickView: ScreenPreviewClickView,
viewModel: ClockCarouselViewModel,
clockViewFactory: ClockViewFactory,
@@ -46,6 +42,7 @@
isTwoPaneAndSmallWidth: Boolean,
) {
carouselView.setClockViewFactory(clockViewFactory)
+ carouselView.isVisible = true
clockViewFactory.updateRegionDarkness()
val carouselAccessibilityDelegate =
CarouselAccessibilityDelegate(
@@ -61,12 +58,8 @@
)
screenPreviewClickView.accessibilityDelegate = carouselAccessibilityDelegate
- val singleClockHostView =
- singleClockView.requireViewById<FrameLayout>(R.id.single_clock_host_view)
lifecycleOwner.lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
- launch { viewModel.isCarouselVisible.collect { carouselView.isVisible = it } }
-
launch {
combine(viewModel.selectedClockSize, viewModel.allClocks, ::Pair).collect {
(size, allClocks) ->
@@ -98,21 +91,6 @@
launch {
viewModel.seedColor.collect { clockViewFactory.updateColorForAllClocks(it) }
}
-
- launch {
- viewModel.isSingleClockViewVisible.collect { singleClockView.isVisible = it }
- }
-
- launch {
- viewModel.clockId.collect { clockId ->
- singleClockHostView.removeAllViews()
- val clockView = clockViewFactory.getLargeView(clockId)
- // The clock view might still be attached to an existing parent. Detach
- // before adding to another parent.
- (clockView.parent as? ViewGroup)?.removeView(clockView)
- singleClockHostView.addView(clockView)
- }
- }
}
}
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
index aa6cc91..2d18ab3 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -114,6 +114,7 @@
}
adapter = ClockCarouselAdapter(clockSize, clocks, clockViewFactory, onClockSelected)
+ carousel.isInfinite = clocks.size >= MIN_CLOCKS_TO_ENABLE_INFINITE_CAROUSEL
carousel.setAdapter(adapter)
val indexOfSelectedClock =
clocks
@@ -470,6 +471,8 @@
}
companion object {
+ // The carousel needs to have at least 5 different clock faces to be infinite
+ const val MIN_CLOCKS_TO_ENABLE_INFINITE_CAROUSEL = 5
const val CLOCK_CAROUSEL_VIEW_SCALE = 0.5f
val itemViewIds =
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
index 7922054..b2dfa61 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -27,7 +27,6 @@
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
@@ -39,8 +38,7 @@
* Clock carousel view model that provides data for the carousel of clock previews. When there is
* only one item, we should show a single clock preview instead of a carousel.
*/
-class ClockCarouselViewModel
-constructor(
+class ClockCarouselViewModel(
private val interactor: ClockPickerInteractor,
private val backgroundDispatcher: CoroutineDispatcher,
) : ViewModel() {
@@ -58,8 +56,6 @@
val seedColor: Flow<Int?> = interactor.seedColor
- val isCarouselVisible: Flow<Boolean> = allClocks.map { it.size > 1 }.distinctUntilChanged()
-
@OptIn(ExperimentalCoroutinesApi::class)
val selectedIndex: Flow<Int> =
allClocks
@@ -77,15 +73,6 @@
}
.mapNotNull { it }
- // Handle the case when there is only one clock in the carousel
- val isSingleClockViewVisible: Flow<Boolean> =
- allClocks.map { it.size == 1 }.distinctUntilChanged()
-
- val clockId: Flow<String> =
- allClocks
- .map { allClockIds -> if (allClockIds.size == 1) allClockIds[0].clockId else null }
- .mapNotNull { it }
-
private var setSelectedClockJob: Job? = null
fun setSelectedClock(clockId: String) {
setSelectedClockJob?.cancel()
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 fa87029..2174ba7 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -23,7 +23,6 @@
import android.view.TouchDelegate
import android.view.View
import android.view.View.OnAttachStateChangeListener
-import android.view.ViewGroup
import android.view.ViewStub
import androidx.activity.ComponentActivity
import androidx.constraintlayout.helper.widget.Carousel
@@ -156,12 +155,6 @@
guidelineEnd.layoutParams = layoutParams
}
- // TODO (b/270716937) We should handle the single clock case in the clock carousel
- // itself
- val singleClockViewStub: ViewStub = view.requireViewById(R.id.single_clock_view_stub)
- singleClockViewStub.layoutResource = R.layout.single_clock_view
- val singleClockView = singleClockViewStub.inflate() as ViewGroup
-
/**
* Only bind after [Carousel.onAttachedToWindow]. This is to avoid the race condition
* that the flow emits before attached to window where [Carousel.mMotionLayout] is still
@@ -177,7 +170,6 @@
ClockCarouselViewBinder.bind(
context = context,
carouselView = carouselView,
- singleClockView = singleClockView,
screenPreviewClickView = screenPreviewClickView,
viewModel = viewModel,
clockViewFactory = clockViewFactory,
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 1b1eb9a..ca6f8c7 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
@@ -88,38 +88,6 @@
assertThat(observedSelectedIndex()).isEqualTo(2)
}
- @Test
- fun multipleClockCase() = runTest {
- underTest =
- ClockCarouselViewModel(
- getClockPickerInteractor(repositoryWithMultipleClocks),
- testDispatcher
- )
- val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
- val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
-
- advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-
- assertThat(observedIsCarouselVisible()).isTrue()
- assertThat(observedIsSingleClockViewVisible()).isFalse()
- }
-
- @Test
- fun singleClockCase() = runTest {
- underTest =
- ClockCarouselViewModel(
- getClockPickerInteractor(repositoryWithSingleClock),
- testDispatcher
- )
- val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
- val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
-
- advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-
- assertThat(observedIsCarouselVisible()).isFalse()
- assertThat(observedIsSingleClockViewVisible()).isTrue()
- }
-
private fun getClockPickerInteractor(repository: ClockPickerRepository): ClockPickerInteractor {
return ClockPickerInteractor(
repository = repository,