1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wallpaper.picker.customization.ui.binder
18 
19 import android.view.View
20 import androidx.constraintlayout.motion.widget.MotionLayout
21 import androidx.core.view.doOnLayout
22 import androidx.lifecycle.Lifecycle
23 import androidx.lifecycle.LifecycleOwner
24 import androidx.lifecycle.lifecycleScope
25 import androidx.lifecycle.repeatOnLifecycle
26 import androidx.recyclerview.widget.RecyclerView
27 import androidx.viewpager2.widget.ViewPager2
28 import com.android.wallpaper.R
29 import com.android.wallpaper.model.Screen
30 import com.android.wallpaper.model.Screen.HOME_SCREEN
31 import com.android.wallpaper.model.Screen.LOCK_SCREEN
32 import com.android.wallpaper.picker.customization.ui.CustomizationPickerActivity2
33 import com.android.wallpaper.picker.customization.ui.util.CustomizationOptionUtil.CustomizationOption
34 import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel
35 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationPickerViewModel2
36 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationPickerViewModel2.PickerScreen.CUSTOMIZATION_OPTION
37 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationPickerViewModel2.PickerScreen.MAIN
38 import kotlinx.coroutines.launch
39 
40 object CustomizationPickerBinder2 {
41 
42     private const val ALPHA_SELECTED_PREVIEW = 1f
43     private const val ALPHA_NON_SELECTED_PREVIEW = 0.4f
44     private const val LOCK_SCREEN_PREVIEW_POSITION = 0
45     private const val HOME_SCREEN_PREVIEW_POSITION = 1
46 
47     /**
48      * @return Callback for the [CustomizationPickerActivity2] to set
49      *   [CustomizationPickerViewModel2]'s screen state to null, which infers to the main screen. We
50      *   need this callback to handle the back navigation in [CustomizationPickerActivity2].
51      */
52     fun bind(
53         view: View,
54         lockScreenCustomizationOptionEntries: List<Pair<CustomizationOption, View>>,
55         homeScreenCustomizationOptionEntries: List<Pair<CustomizationOption, View>>,
56         customizationOptionFloatingSheetViewMap: Map<CustomizationOption, View>?,
57         viewModel: CustomizationPickerViewModel2,
58         colorUpdateViewModel: ColorUpdateViewModel,
59         customizationOptionsBinder: CustomizationOptionsBinder,
60         lifecycleOwner: LifecycleOwner,
61         navigateToPrimary: () -> Unit,
62         navigateToSecondary: (screen: CustomizationOption) -> Unit,
63         navigateToCategoriesScreen: (screen: Screen) -> Unit,
64     ) {
65         val optionContainer =
66             view.requireViewById<MotionLayout>(R.id.customization_option_container)
67         val pager = view.requireViewById<ViewPager2>(R.id.preview_pager)
68         pager.registerOnPageChangeCallback(
69             object : ViewPager2.OnPageChangeCallback() {
70                 override fun onPageSelected(position: Int) {
71                     viewModel.selectPreviewScreen(
72                         if (position == LOCK_SCREEN_PREVIEW_POSITION) LOCK_SCREEN else HOME_SCREEN
73                     )
74                 }
75             }
76         )
77         val mediumAnimTimeMs =
78             view.resources.getInteger(android.R.integer.config_mediumAnimTime).toLong()
79         pager.doOnLayout {
80             // RecyclerView items can only be reliably retrieved on layout.
81             val lockScreenPreview =
82                 (pager.getChildAt(0) as? RecyclerView)
83                     ?.findViewHolderForAdapterPosition(LOCK_SCREEN_PREVIEW_POSITION)
84                     ?.itemView
85             val homeScreenPreview =
86                 (pager.getChildAt(0) as? RecyclerView)
87                     ?.findViewHolderForAdapterPosition(HOME_SCREEN_PREVIEW_POSITION)
88                     ?.itemView
89             val fadePreview = { position: Int ->
90                 lockScreenPreview?.apply {
91                     findViewById<View>(R.id.wallpaper_surface)
92                         .animate()
93                         .alpha(
94                             if (position == LOCK_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW
95                             else ALPHA_NON_SELECTED_PREVIEW
96                         )
97                         .setDuration(mediumAnimTimeMs)
98                         .start()
99                     findViewById<View>(R.id.workspace_surface)
100                         .animate()
101                         .alpha(
102                             if (position == LOCK_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW
103                             else ALPHA_NON_SELECTED_PREVIEW
104                         )
105                         .setDuration(mediumAnimTimeMs)
106                         .start()
107                 }
108                 homeScreenPreview?.apply {
109                     findViewById<View>(R.id.wallpaper_surface)
110                         .animate()
111                         .alpha(
112                             if (position == HOME_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW
113                             else ALPHA_NON_SELECTED_PREVIEW
114                         )
115                         .setDuration(mediumAnimTimeMs)
116                         .start()
117                     findViewById<View>(R.id.workspace_surface)
118                         .animate()
119                         .alpha(
120                             if (position == HOME_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW
121                             else ALPHA_NON_SELECTED_PREVIEW
122                         )
123                         .setDuration(mediumAnimTimeMs)
124                         .start()
125                 }
126             }
127             fadePreview(pager.currentItem)
128             pager.registerOnPageChangeCallback(
129                 object : ViewPager2.OnPageChangeCallback() {
130                     override fun onPageSelected(position: Int) {
131                         super.onPageSelected(position)
132                         fadePreview(position)
133                     }
134                 }
135             )
136         }
137 
138         lifecycleOwner.lifecycleScope.launch {
139             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
140                 launch {
141                     viewModel.screen.collect { (screen, option) ->
142                         when (screen) {
143                             MAIN -> navigateToPrimary()
144                             CUSTOMIZATION_OPTION -> option?.let(navigateToSecondary)
145                         }
146                     }
147                 }
148 
149                 launch {
150                     viewModel.selectedPreviewScreen.collect {
151                         when (it) {
152                             LOCK_SCREEN -> {
153                                 pager.currentItem = 0
154                                 optionContainer.transitionToStart()
155                             }
156                             HOME_SCREEN -> {
157                                 pager.currentItem = 1
158                                 optionContainer.transitionToEnd()
159                             }
160                         }
161                     }
162                 }
163             }
164         }
165 
166         customizationOptionsBinder.bind(
167             view,
168             lockScreenCustomizationOptionEntries,
169             homeScreenCustomizationOptionEntries,
170             customizationOptionFloatingSheetViewMap,
171             viewModel,
172             colorUpdateViewModel,
173             lifecycleOwner,
174             navigateToCategoriesScreen,
175         )
176     }
177 }
178