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.fragment 17 18 import android.content.Context 19 import android.os.Bundle 20 import android.view.LayoutInflater 21 import android.view.SurfaceView 22 import android.view.View 23 import android.view.ViewGroup 24 import androidx.cardview.widget.CardView 25 import androidx.core.content.ContextCompat 26 import androidx.core.view.ViewCompat 27 import androidx.core.view.isVisible 28 import androidx.fragment.app.activityViewModels 29 import androidx.navigation.NavController 30 import androidx.navigation.fragment.findNavController 31 import androidx.transition.Transition 32 import com.android.wallpaper.R 33 import com.android.wallpaper.picker.AppbarFragment 34 import com.android.wallpaper.picker.di.modules.MainDispatcher 35 import com.android.wallpaper.picker.preview.ui.binder.CropWallpaperButtonBinder 36 import com.android.wallpaper.picker.preview.ui.binder.FullWallpaperPreviewBinder 37 import com.android.wallpaper.picker.preview.ui.binder.PreviewTooltipBinder 38 import com.android.wallpaper.picker.preview.ui.binder.WorkspacePreviewBinder 39 import com.android.wallpaper.picker.preview.ui.transition.ChangeScaleAndPosition 40 import com.android.wallpaper.picker.preview.ui.util.AnimationUtil 41 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel 42 import com.android.wallpaper.util.DisplayUtils 43 import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils 44 import dagger.hilt.android.AndroidEntryPoint 45 import dagger.hilt.android.qualifiers.ApplicationContext 46 import javax.inject.Inject 47 import kotlinx.coroutines.CompletableDeferred 48 import kotlinx.coroutines.CoroutineScope 49 50 /** Shows full preview of user selected wallpaper for cropping, zooming and positioning. */ 51 @AndroidEntryPoint(AppbarFragment::class) 52 class FullPreviewFragment : Hilt_FullPreviewFragment() { 53 54 @Inject @ApplicationContext lateinit var appContext: Context 55 @Inject @MainDispatcher lateinit var mainScope: CoroutineScope 56 @Inject lateinit var displayUtils: DisplayUtils 57 @Inject lateinit var wallpaperConnectionUtils: WallpaperConnectionUtils 58 59 private lateinit var currentView: View 60 61 private val wallpaperPreviewViewModel by activityViewModels<WallpaperPreviewViewModel>() 62 private val isFirstBindingDeferred = CompletableDeferred<Boolean>() 63 64 private var useLightToolbarOverride = false 65 private var navigateUpListener: NavController.OnDestinationChangedListener? = null 66 67 override fun onCreate(savedInstanceState: Bundle?) { 68 super.onCreate(savedInstanceState) 69 enterTransition = AnimationUtil.getFastFadeInTransition() 70 returnTransition = AnimationUtil.getFastFadeOutTransition() 71 sharedElementEnterTransition = ChangeScaleAndPosition() 72 } 73 74 override fun onCreateView( 75 inflater: LayoutInflater, 76 container: ViewGroup?, 77 savedInstanceState: Bundle?, 78 ): View { 79 currentView = inflater.inflate(R.layout.fragment_full_preview, container, false) 80 81 navigateUpListener = 82 NavController.OnDestinationChangedListener { _, destination, _ -> 83 if (destination.id == R.id.smallPreviewFragment) { 84 wallpaperPreviewViewModel.handleBackPressed() 85 currentView.findViewById<View>(R.id.crop_wallpaper_button)?.isVisible = false 86 currentView.findViewById<View>(R.id.full_preview_tooltip_stub)?.isVisible = 87 false 88 // When navigate up back to small preview, move previews up app window for 89 // smooth shared element transition. It's the earliest timing to do this, it'll 90 // be to late in transition started callback. 91 currentView 92 .requireViewById<SurfaceView>(R.id.wallpaper_surface) 93 .setZOrderOnTop(true) 94 currentView 95 .requireViewById<SurfaceView>(R.id.workspace_surface) 96 .setZOrderOnTop(true) 97 } 98 } 99 navigateUpListener?.let { findNavController().addOnDestinationChangedListener(it) } 100 101 setUpToolbar(currentView, true, true) 102 103 val previewCard: CardView = currentView.requireViewById(R.id.preview_card) 104 ViewCompat.setTransitionName( 105 previewCard, 106 SmallPreviewFragment.FULL_PREVIEW_SHARED_ELEMENT_ID, 107 ) 108 109 FullWallpaperPreviewBinder.bind( 110 applicationContext = appContext, 111 view = currentView, 112 viewModel = wallpaperPreviewViewModel, 113 transition = sharedElementEnterTransition as? Transition, 114 displayUtils = displayUtils, 115 mainScope = mainScope, 116 lifecycleOwner = viewLifecycleOwner, 117 savedInstanceState = savedInstanceState, 118 wallpaperConnectionUtils = wallpaperConnectionUtils, 119 isFirstBindingDeferred = isFirstBindingDeferred, 120 ) { isFullScreen -> 121 useLightToolbarOverride = isFullScreen 122 setUpToolbar(view) 123 } 124 125 CropWallpaperButtonBinder.bind( 126 button = currentView.requireViewById(R.id.crop_wallpaper_button), 127 viewModel = wallpaperPreviewViewModel, 128 lifecycleOwner = viewLifecycleOwner, 129 ) { 130 wallpaperPreviewViewModel.handleBackPressed() 131 findNavController().popBackStack() 132 } 133 134 WorkspacePreviewBinder.bindFullWorkspacePreview( 135 surface = currentView.requireViewById(R.id.workspace_surface), 136 viewModel = wallpaperPreviewViewModel, 137 lifecycleOwner = viewLifecycleOwner, 138 ) 139 140 PreviewTooltipBinder.bindFullPreviewTooltip( 141 tooltipStub = currentView.requireViewById(R.id.full_preview_tooltip_stub), 142 viewModel = wallpaperPreviewViewModel.fullTooltipViewModel, 143 lifecycleOwner = viewLifecycleOwner, 144 ) 145 146 return currentView 147 } 148 149 override fun onViewStateRestored(savedInstanceState: Bundle?) { 150 super.onViewStateRestored(savedInstanceState) 151 isFirstBindingDeferred.complete(savedInstanceState == null) 152 } 153 154 override fun onDestroyView() { 155 super.onDestroyView() 156 navigateUpListener?.let { findNavController().removeOnDestinationChangedListener(it) } 157 } 158 159 // TODO(b/291761856): Use real string 160 override fun getDefaultTitle(): CharSequence { 161 return "" 162 } 163 164 override fun getToolbarTextColor(): Int { 165 return if (useLightToolbarOverride) { 166 ContextCompat.getColor(requireContext(), android.R.color.system_on_primary_light) 167 } else { 168 ContextCompat.getColor(requireContext(), R.color.system_on_surface) 169 } 170 } 171 172 override fun isStatusBarLightText(): Boolean { 173 return requireContext().resources.getBoolean(R.bool.isFragmentStatusBarLightText) or 174 useLightToolbarOverride 175 } 176 } 177