1 /*
<lambda>null2  * Copyright (C) 2023 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 package com.android.wallpaper.picker.preview.ui.binder
17 
18 import android.annotation.SuppressLint
19 import android.content.Context
20 import android.graphics.Point
21 import android.view.View
22 import androidx.core.view.doOnPreDraw
23 import androidx.lifecycle.Lifecycle
24 import androidx.lifecycle.LifecycleOwner
25 import androidx.lifecycle.lifecycleScope
26 import androidx.lifecycle.repeatOnLifecycle
27 import androidx.recyclerview.widget.RecyclerView
28 import androidx.transition.Transition
29 import androidx.viewpager2.widget.ViewPager2
30 import com.android.wallpaper.R
31 import com.android.wallpaper.model.wallpaper.DeviceDisplayType
32 import com.android.wallpaper.picker.preview.ui.view.adapters.SinglePreviewPagerAdapter
33 import com.android.wallpaper.picker.preview.ui.view.pagetransformers.PreviewCardPageTransformer
34 import com.android.wallpaper.picker.preview.ui.viewmodel.FullPreviewConfigViewModel
35 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
36 import kotlinx.coroutines.launch
37 
38 /** Binds single preview home screen and lock screen tabs view pager. */
39 object PreviewPagerBinder {
40 
41     @SuppressLint("WrongConstant")
42     fun bind(
43         applicationContext: Context,
44         viewLifecycleOwner: LifecycleOwner,
45         previewsViewPager: ViewPager2,
46         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
47         previewDisplaySize: Point,
48         currentNavDestId: Int,
49         transition: Transition?,
50         transitionConfig: FullPreviewConfigViewModel?,
51         isFirstBinding: Boolean,
52         navigate: (View) -> Unit,
53     ) {
54         previewsViewPager.apply {
55             adapter = SinglePreviewPagerAdapter { viewHolder, position ->
56                 PreviewTooltipBinder.bindSmallPreviewTooltip(
57                     tooltipStub = viewHolder.itemView.requireViewById(R.id.tooltip_stub),
58                     viewModel = wallpaperPreviewViewModel.smallTooltipViewModel,
59                     lifecycleOwner = viewLifecycleOwner,
60                 )
61 
62                 SmallPreviewBinder.bind(
63                     applicationContext = applicationContext,
64                     view = viewHolder.itemView.requireViewById(R.id.preview),
65                     viewModel = wallpaperPreviewViewModel,
66                     screen = wallpaperPreviewViewModel.smallPreviewTabs[position],
67                     displaySize = previewDisplaySize,
68                     deviceDisplayType = DeviceDisplayType.SINGLE,
69                     viewLifecycleOwner = viewLifecycleOwner,
70                     currentNavDestId = currentNavDestId,
71                     transition = transition,
72                     transitionConfig = transitionConfig,
73                     isFirstBinding = isFirstBinding,
74                     navigate = navigate,
75                 )
76             }
77             offscreenPageLimit = SinglePreviewPagerAdapter.PREVIEW_PAGER_ITEM_COUNT
78             setPageTransformer(PreviewCardPageTransformer(previewDisplaySize))
79         }
80 
81         // the over scroll animation needs to be disabled for the RecyclerView that is contained in
82         // the ViewPager2 rather than the ViewPager2 itself
83         val child: View = previewsViewPager.getChildAt(0)
84         if (child is RecyclerView) {
85             child.overScrollMode = View.OVER_SCROLL_NEVER
86             // Remove clip children to enable child card view to display fully during scaling shared
87             // element transition.
88             child.clipChildren = false
89         }
90 
91         // Wrap in doOnPreDraw for emoji wallpaper creation case, to make sure recycler view with
92         // previews have finished layout before calling registerOnPageChangeCallback and
93         // setCurrentItem.
94         // TODO (b/339679893): investigate to see if there is a better solution
95         previewsViewPager.doOnPreDraw {
96             previewsViewPager.registerOnPageChangeCallback(
97                 object : ViewPager2.OnPageChangeCallback() {
98                     override fun onPageSelected(position: Int) {
99                         super.onPageSelected(position)
100                         wallpaperPreviewViewModel.setSmallPreviewSelectedTabIndex(position)
101                     }
102                 }
103             )
104 
105             viewLifecycleOwner.lifecycleScope.launch {
106                 viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
107                     wallpaperPreviewViewModel.smallPreviewSelectedTabIndex.collect {
108                         if (previewsViewPager.currentItem != it) {
109                             previewsViewPager.setCurrentItem(it, /* smoothScroll= */ true)
110                         }
111                     }
112                 }
113             }
114         }
115     }
116 }
117