Separate lock and home tab (2/2)

Separate the lock and home tab. This way, when swtiching tabs, we no
longer need to remove and create sections.
The major benefit is that there's no flash effect from removing/adding
sections.

Test: https://drive.google.com/file/d/1ZcOUVD5EXA0ZNIhY8mVsMmgBoakSpXwt/view?usp=sharing&resourcekey=0-qKSuCEB9G2gMRV4ltnncSA
Bug: 275724650
Change-Id: Icc5d85919005157cc27edfd7dda43d7436a274d2
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 cf80dc1..925e293 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
@@ -30,14 +30,6 @@
 import kotlinx.coroutines.launch
 
 object ClockCarouselViewBinder {
-    /**
-     * The binding is used by the view where there is an action executed from another view, e.g.
-     * toggling show/hide of the view that the binder is holding.
-     */
-    interface Binding {
-        fun show()
-        fun hide()
-    }
 
     @JvmStatic
     fun bind(
@@ -46,7 +38,7 @@
         viewModel: ClockCarouselViewModel,
         clockViewFactory: ClockViewFactory,
         lifecycleOwner: LifecycleOwner,
-    ): Binding {
+    ) {
         val singleClockHostView =
             singleClockView.requireViewById<FrameLayout>(R.id.single_clock_host_view)
         lifecycleOwner.lifecycleScope.launch {
@@ -106,15 +98,5 @@
                 }
             }
         )
-
-        return object : Binding {
-            override fun show() {
-                viewModel.showClockCarousel(true)
-            }
-
-            override fun hide() {
-                viewModel.showClockCarousel(false)
-            }
-        }
     }
 }
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 b5e7c18..dd4c968 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -66,51 +66,50 @@
         val colorViewModel = injector.getWallpaperColorsViewModel()
         val displayUtils = injector.getDisplayUtils(context)
         ScreenPreviewBinder.bind(
-                activity = activity,
-                previewView = lockScreenView,
-                viewModel =
-                    ScreenPreviewViewModel(
-                        previewUtils =
-                            PreviewUtils(
-                                context = context,
-                                authority =
-                                    resources.getString(
-                                        R.string.lock_screen_preview_provider_authority,
-                                    ),
-                            ),
-                        wallpaperInfoProvider = {
-                            suspendCancellableCoroutine { continuation ->
-                                injector
-                                    .getCurrentWallpaperInfoFactory(context)
-                                    .createCurrentWallpaperInfos(
-                                        { homeWallpaper, lockWallpaper, _ ->
-                                            continuation.resume(
-                                                homeWallpaper ?: lockWallpaper,
-                                                null,
-                                            )
-                                        },
-                                        /* forceRefresh= */ true,
-                                    )
-                            }
-                        },
-                        onWallpaperColorChanged = { colors ->
-                            colorViewModel.setLockWallpaperColors(colors)
-                        },
-                        initialExtrasProvider = {
-                            Bundle().apply {
-                                // Hide the clock from the system UI rendered preview so we can
-                                // place the carousel on top of it.
-                                putBoolean(
-                                    ClockPreviewConstants.KEY_HIDE_CLOCK,
-                                    true,
+            activity = activity,
+            previewView = lockScreenView,
+            viewModel =
+                ScreenPreviewViewModel(
+                    previewUtils =
+                        PreviewUtils(
+                            context = context,
+                            authority =
+                                resources.getString(
+                                    R.string.lock_screen_preview_provider_authority,
+                                ),
+                        ),
+                    wallpaperInfoProvider = {
+                        suspendCancellableCoroutine { continuation ->
+                            injector
+                                .getCurrentWallpaperInfoFactory(context)
+                                .createCurrentWallpaperInfos(
+                                    { homeWallpaper, lockWallpaper, _ ->
+                                        continuation.resume(
+                                            homeWallpaper ?: lockWallpaper,
+                                            null,
+                                        )
+                                    },
+                                    /* forceRefresh= */ true,
                                 )
-                            }
-                        },
-                    ),
-                lifecycleOwner = this,
-                offsetToStart = displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(activity),
-            )
-            .show()
+                        }
+                    },
+                    onWallpaperColorChanged = { colors ->
+                        colorViewModel.setLockWallpaperColors(colors)
+                    },
+                    initialExtrasProvider = {
+                        Bundle().apply {
+                            // Hide the clock from the system UI rendered preview so we can
+                            // place the carousel on top of it.
+                            putBoolean(
+                                ClockPreviewConstants.KEY_HIDE_CLOCK,
+                                true,
+                            )
+                        }
+                    },
+                ),
+            lifecycleOwner = this,
+            offsetToStart = displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(activity),
+        )
 
         ClockSettingsBinder.bind(
             view,
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 60a9e85..c01f56a 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -19,8 +19,6 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.map
@@ -44,14 +42,7 @@
 
     val seedColor: Flow<Int?> = interactor.seedColor
 
-    private val shouldShowCarousel = MutableStateFlow(false)
-    val isCarouselVisible: Flow<Boolean> =
-        combine(allClockIds.map { it.size > 1 }.distinctUntilChanged(), shouldShowCarousel) {
-                hasMoreThanOneClock,
-                shouldShowCarousel ->
-                hasMoreThanOneClock && shouldShowCarousel
-            }
-            .distinctUntilChanged()
+    val isCarouselVisible: Flow<Boolean> = allClockIds.map { it.size > 1 }.distinctUntilChanged()
 
     @OptIn(ExperimentalCoroutinesApi::class)
     val selectedIndex: Flow<Int> =
@@ -69,14 +60,8 @@
             .mapNotNull { it }
 
     // Handle the case when there is only one clock in the carousel
-    private val shouldShowSingleClock = MutableStateFlow(false)
     val isSingleClockViewVisible: Flow<Boolean> =
-        combine(allClockIds.map { it.size == 1 }.distinctUntilChanged(), shouldShowSingleClock) {
-                hasOneClock,
-                shouldShowSingleClock ->
-                hasOneClock && shouldShowSingleClock
-            }
-            .distinctUntilChanged()
+        allClockIds.map { it.size == 1 }.distinctUntilChanged()
 
     val clockId: Flow<String> =
         allClockIds
@@ -87,11 +72,6 @@
         interactor.setSelectedClock(clockId)
     }
 
-    fun showClockCarousel(shouldShow: Boolean) {
-        shouldShowCarousel.value = shouldShow
-        shouldShowSingleClock.value = shouldShow
-    }
-
     companion object {
         const val CLOCKS_EVENT_UPDATE_DELAY_MILLIS: Long = 100
     }
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 0303b41..43fb85b 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -22,7 +22,6 @@
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewStub
-import androidx.core.view.isVisible
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import com.android.customization.picker.clock.ui.binder.ClockCarouselViewBinder
@@ -46,7 +45,7 @@
 class PreviewWithClockCarouselSectionController(
     activity: Activity,
     private val lifecycleOwner: LifecycleOwner,
-    private val initialScreen: CustomizationSections.Screen,
+    private val screen: CustomizationSections.Screen,
     wallpaperInfoFactory: CurrentWallpaperInfoFactory,
     colorViewModel: WallpaperColorsViewModel,
     displayUtils: DisplayUtils,
@@ -59,7 +58,7 @@
     ScreenPreviewSectionController(
         activity,
         lifecycleOwner,
-        initialScreen,
+        screen,
         wallpaperInfoFactory,
         colorViewModel,
         displayUtils,
@@ -67,32 +66,31 @@
         wallpaperInteractor,
     ) {
 
-    private var clockCarouselBinding: ClockCarouselViewBinder.Binding? = null
     private var clockColorAndSizeButton: View? = null
 
     override val hideLockScreenClockPreview = true
 
     override fun createView(context: Context): ScreenPreviewView {
         val view = super.createView(context)
+        if (screen == CustomizationSections.Screen.LOCK_SCREEN) {
+            val clockColorAndSizeButtonStub: ViewStub =
+                view.requireViewById(R.id.clock_color_and_size_button)
+            clockColorAndSizeButtonStub.layoutResource = R.layout.clock_color_and_size_button
+            clockColorAndSizeButton = clockColorAndSizeButtonStub.inflate() as View
+            clockColorAndSizeButton?.setOnClickListener {
+                navigationController.navigateTo(ClockSettingsFragment())
+            }
 
-        val clockColorAndSizeButtonStub: ViewStub =
-            view.requireViewById(R.id.clock_color_and_size_button)
-        clockColorAndSizeButtonStub.layoutResource = R.layout.clock_color_and_size_button
-        clockColorAndSizeButton = clockColorAndSizeButtonStub.inflate() as View
-        clockColorAndSizeButton?.setOnClickListener {
-            navigationController.navigateTo(ClockSettingsFragment())
-        }
+            val carouselViewStub: ViewStub = view.requireViewById(R.id.clock_carousel_view_stub)
+            carouselViewStub.layoutResource = R.layout.clock_carousel_view
+            val carouselView = carouselViewStub.inflate() as ClockCarouselView
 
-        val carouselViewStub: ViewStub = view.requireViewById(R.id.clock_carousel_view_stub)
-        carouselViewStub.layoutResource = R.layout.clock_carousel_view
-        val carouselView = carouselViewStub.inflate() as ClockCarouselView
-
-        // 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
-        lifecycleOwner.lifecycleScope.launch {
-            clockCarouselBinding =
+            // 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
+            lifecycleOwner.lifecycleScope.launch {
                 ClockCarouselViewBinder.bind(
                     carouselView = carouselView,
                     singleClockView = singleClockView,
@@ -100,20 +98,9 @@
                     clockViewFactory = clockViewFactory,
                     lifecycleOwner = lifecycleOwner,
                 )
-            onScreenSwitched(
-                isOnLockScreen = initialScreen == CustomizationSections.Screen.LOCK_SCREEN
-            )
+            }
         }
-        return view
-    }
 
-    override fun onScreenSwitched(isOnLockScreen: Boolean) {
-        super.onScreenSwitched(isOnLockScreen)
-        clockColorAndSizeButton?.isVisible = isOnLockScreen
-        if (isOnLockScreen) {
-            clockCarouselBinding?.show()
-        } else {
-            clockCarouselBinding?.hide()
-        }
+        return view
     }
 }
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
index 63f77bd..5bc7461 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -75,46 +75,22 @@
     }
 
     @Test
-    fun setShouldShowCarousel() = runTest {
+    fun multipleClockCase() = runTest {
         underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithMultipleClocks))
         val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
+        val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
         advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsCarouselVisible()).isFalse()
-        underTest.showClockCarousel(true)
         assertThat(observedIsCarouselVisible()).isTrue()
+        assertThat(observedIsSingleClockViewVisible()).isFalse()
     }
 
     @Test
-    fun shouldNotShowCarouselWhenSingleClock() = runTest {
+    fun singleClockCase() = runTest {
         underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithSingleClock))
         val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
-        advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsCarouselVisible()).isFalse()
-        underTest.showClockCarousel(true)
-        assertThat(observedIsCarouselVisible()).isFalse()
-    }
-
-    @Test
-    fun setShouldShowSingleClock() = runTest {
-        underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithSingleClock))
         val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
         advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsSingleClockViewVisible()).isFalse()
-        underTest.showClockCarousel(true)
+        assertThat(observedIsCarouselVisible()).isFalse()
         assertThat(observedIsSingleClockViewVisible()).isTrue()
     }
-
-    @Test
-    fun shouldNotShowSingleClockWhenMultipleClocks() = runTest {
-        underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithMultipleClocks))
-        val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
-        advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-        underTest.showClockCarousel(false)
-        assertThat(observedIsSingleClockViewVisible()).isFalse()
-        underTest.showClockCarousel(true)
-        assertThat(observedIsSingleClockViewVisible()).isFalse()
-    }
 }