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