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 17 package com.android.wallpaper.picker.preview.ui.binder 18 19 import android.graphics.Point 20 import android.view.View 21 import android.widget.Button 22 import android.widget.FrameLayout 23 import androidx.core.view.isVisible 24 import androidx.lifecycle.Lifecycle 25 import androidx.lifecycle.LifecycleOwner 26 import androidx.lifecycle.lifecycleScope 27 import androidx.lifecycle.repeatOnLifecycle 28 import com.android.wallpaper.R 29 import com.android.wallpaper.model.Screen 30 import com.android.wallpaper.model.wallpaper.DeviceDisplayType 31 import com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout 32 import com.android.wallpaper.picker.preview.ui.view.DualDisplayAspectRatioLayout.Companion.getViewId 33 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel 34 import kotlinx.coroutines.CoroutineScope 35 import kotlinx.coroutines.launch 36 37 /** Binds the dialog on small preview confirming and setting wallpaper with destination. */ 38 object SetWallpaperDialogBinder { 39 private val PreviewScreenIds = 40 mapOf( 41 Screen.LOCK_SCREEN to R.id.lock_preview_selector, 42 Screen.HOME_SCREEN to R.id.home_preview_selector 43 ) 44 45 fun bind( 46 dialogContent: View, 47 wallpaperPreviewViewModel: WallpaperPreviewViewModel, 48 isFoldable: Boolean, 49 handheldDisplaySize: Point, 50 lifecycleOwner: LifecycleOwner, 51 mainScope: CoroutineScope, 52 currentNavDestId: Int, 53 onFinishActivity: () -> Unit, 54 onDismissDialog: () -> Unit, 55 isFirstBinding: Boolean, 56 navigate: ((View) -> Unit)?, 57 ) { 58 val previewLayout: View = 59 if (isFoldable) dialogContent.requireViewById(R.id.foldable_previews) 60 else dialogContent.requireViewById(R.id.handheld_previews) 61 if (isFoldable) 62 bindFoldablePreview( 63 previewLayout, 64 wallpaperPreviewViewModel, 65 lifecycleOwner, 66 currentNavDestId, 67 isFirstBinding, 68 navigate, 69 ) 70 else 71 bindHandheldPreview( 72 previewLayout, 73 wallpaperPreviewViewModel, 74 handheldDisplaySize, 75 lifecycleOwner, 76 currentNavDestId, 77 isFirstBinding, 78 navigate, 79 ) 80 81 val cancelButton = dialogContent.requireViewById<Button>(R.id.button_cancel) 82 cancelButton.setOnClickListener { onDismissDialog() } 83 84 val confirmButton = dialogContent.requireViewById<Button>(R.id.button_set) 85 lifecycleOwner.lifecycleScope.launch { 86 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 87 launch { 88 wallpaperPreviewViewModel.showSetWallpaperDialog.collect { show -> 89 if (!show) { 90 onDismissDialog() 91 } 92 } 93 } 94 95 launch { 96 wallpaperPreviewViewModel.setWallpaperDialogOnConfirmButtonClicked.collect { 97 onClicked -> 98 confirmButton.setOnClickListener { 99 mainScope.launch { 100 onClicked() 101 onFinishActivity() 102 } 103 } 104 } 105 } 106 107 launch { 108 wallpaperPreviewViewModel.setWallpaperDialogSelectedScreens.collect { 109 selectedScreens -> 110 confirmButton.isEnabled = selectedScreens.isNotEmpty() 111 PreviewScreenIds.forEach { screenId -> 112 bindPreviewSelector( 113 previewLayout.requireViewById(screenId.value), 114 screenId.key, 115 selectedScreens, 116 wallpaperPreviewViewModel, 117 ) 118 } 119 } 120 } 121 } 122 } 123 } 124 125 private fun bindFoldablePreview( 126 previewLayout: View, 127 wallpaperPreviewViewModel: WallpaperPreviewViewModel, 128 lifecycleOwner: LifecycleOwner, 129 currentNavDestId: Int, 130 isFirstBinding: Boolean, 131 navigate: ((View) -> Unit)?, 132 ) { 133 previewLayout.isVisible = true 134 PreviewScreenIds.forEach { screenId -> 135 val dualDisplayAspectRatioLayout: DualDisplayAspectRatioLayout = 136 previewLayout 137 .requireViewById<FrameLayout>(screenId.value) 138 .requireViewById(R.id.dual_preview) 139 140 dualDisplayAspectRatioLayout.setDisplaySizes( 141 mapOf( 142 DeviceDisplayType.FOLDED to wallpaperPreviewViewModel.smallerDisplaySize, 143 DeviceDisplayType.UNFOLDED to 144 wallpaperPreviewViewModel.wallpaperDisplaySize.value, 145 ) 146 ) 147 DeviceDisplayType.FOLDABLE_DISPLAY_TYPES.forEach { display -> 148 val previewDisplaySize = dualDisplayAspectRatioLayout.getPreviewDisplaySize(display) 149 val view: View = dualDisplayAspectRatioLayout.requireViewById(display.getViewId()) 150 previewDisplaySize?.let { 151 SmallPreviewBinder.bind( 152 applicationContext = previewLayout.context.applicationContext, 153 view = view, 154 viewModel = wallpaperPreviewViewModel, 155 viewLifecycleOwner = lifecycleOwner, 156 screen = screenId.key, 157 displaySize = it, 158 deviceDisplayType = display, 159 currentNavDestId = currentNavDestId, 160 isFirstBinding = isFirstBinding, 161 navigate = navigate, 162 ) 163 } 164 } 165 } 166 } 167 168 private fun bindHandheldPreview( 169 previewLayout: View, 170 wallpaperPreviewViewModel: WallpaperPreviewViewModel, 171 displaySize: Point, 172 lifecycleOwner: LifecycleOwner, 173 currentNavDestId: Int, 174 isFirstBinding: Boolean, 175 navigate: ((View) -> Unit)?, 176 ) { 177 previewLayout.isVisible = true 178 PreviewScreenIds.forEach { screenId -> 179 val view: View = 180 previewLayout 181 .requireViewById<FrameLayout>(screenId.value) 182 .requireViewById(R.id.preview) 183 SmallPreviewBinder.bind( 184 applicationContext = previewLayout.context.applicationContext, 185 view = view, 186 viewModel = wallpaperPreviewViewModel, 187 screen = screenId.key, 188 displaySize = displaySize, 189 deviceDisplayType = DeviceDisplayType.SINGLE, 190 viewLifecycleOwner = lifecycleOwner, 191 currentNavDestId = currentNavDestId, 192 isFirstBinding = isFirstBinding, 193 navigate = navigate, 194 ) 195 } 196 } 197 198 private fun bindPreviewSelector( 199 selector: View, 200 screen: Screen, 201 selectedScreens: Set<Screen>, 202 dialogViewModel: WallpaperPreviewViewModel, 203 ) { 204 selector.isActivated = selectedScreens.contains(screen) 205 selector.isSelected = selector.isActivated 206 selector.setOnClickListener { dialogViewModel.onSetWallpaperDialogScreenSelected(screen) } 207 } 208 } 209