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 18 package com.android.systemui.keyguard.ui.binder 19 20 import android.graphics.Rect 21 import android.view.View 22 import androidx.core.view.isVisible 23 import androidx.lifecycle.Lifecycle 24 import androidx.lifecycle.repeatOnLifecycle 25 import com.android.app.tracing.coroutines.launch 26 import com.android.systemui.animation.ActivityTransitionAnimator 27 import com.android.systemui.common.ui.binder.IconViewBinder 28 import com.android.systemui.common.ui.binder.TextViewBinder 29 import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel 30 import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel 31 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSettingsMenuViewModel 32 import com.android.systemui.keyguard.util.WallpaperPickerIntentUtils 33 import com.android.systemui.keyguard.util.WallpaperPickerIntentUtils.LAUNCH_SOURCE_KEYGUARD 34 import com.android.systemui.lifecycle.repeatWhenAttached 35 import com.android.systemui.plugins.ActivityStarter 36 import com.android.systemui.res.R 37 import com.android.systemui.statusbar.VibratorHelper 38 import kotlinx.coroutines.DisposableHandle 39 import kotlinx.coroutines.flow.distinctUntilChanged 40 import kotlinx.coroutines.flow.filter 41 import kotlinx.coroutines.flow.filterNotNull 42 43 object KeyguardSettingsViewBinder { 44 fun bind( 45 view: View, 46 viewModel: KeyguardSettingsMenuViewModel, 47 longPressViewModel: KeyguardLongPressViewModel, 48 rootViewModel: KeyguardRootViewModel?, 49 vibratorHelper: VibratorHelper, 50 activityStarter: ActivityStarter 51 ): DisposableHandle { 52 val disposableHandle = 53 view.repeatWhenAttached { 54 repeatOnLifecycle(Lifecycle.State.STARTED) { 55 launch("$TAG#viewModel.isVisible") { 56 viewModel.isVisible.distinctUntilChanged().collect { isVisible -> 57 view.animateVisibility(visible = isVisible) 58 if (isVisible) { 59 vibratorHelper.vibrate(KeyguardBottomAreaVibrations.Activated) 60 view.setOnTouchListener( 61 KeyguardSettingsButtonOnTouchListener( 62 viewModel = viewModel, 63 ) 64 ) 65 IconViewBinder.bind( 66 icon = viewModel.icon, 67 view = view.requireViewById(R.id.icon), 68 ) 69 TextViewBinder.bind( 70 view = view.requireViewById(R.id.text), 71 viewModel = viewModel.text, 72 ) 73 } 74 } 75 } 76 77 // activityStarter will only be null when rendering the preview that 78 // shows up in the Wallpaper Picker app. If we do that, then the 79 // settings menu should never be visible. 80 if (activityStarter != null) { 81 launch("$TAG#viewModel.shouldOpenSettings") { 82 viewModel.shouldOpenSettings 83 .filter { it } 84 .collect { 85 navigateToLockScreenSettings( 86 activityStarter = activityStarter, 87 view = view, 88 ) 89 viewModel.onSettingsShown() 90 } 91 } 92 } 93 94 launch("$TAG#rootViewModel?.lastRootViewTapPosition") { 95 rootViewModel?.lastRootViewTapPosition?.filterNotNull()?.collect { point -> 96 if (view.isVisible) { 97 val hitRect = Rect() 98 view.getHitRect(hitRect) 99 if (!hitRect.contains(point.x, point.y)) { 100 longPressViewModel.onTouchedOutside() 101 } 102 } 103 } 104 } 105 } 106 } 107 return disposableHandle 108 } 109 110 /** Opens the wallpaper picker screen after the device is unlocked by the user. */ 111 private fun navigateToLockScreenSettings( 112 activityStarter: ActivityStarter, 113 view: View, 114 ) { 115 activityStarter.postStartActivityDismissingKeyguard( 116 WallpaperPickerIntentUtils.getIntent(view.context, LAUNCH_SOURCE_KEYGUARD), 117 /* delay= */ 0, 118 /* animationController= */ ActivityTransitionAnimator.Controller.fromView(view), 119 /* customMessage= */ view.context.getString(R.string.keyguard_unlock_to_customize_ls) 120 ) 121 } 122 123 private fun View.animateVisibility(visible: Boolean) { 124 animate() 125 .withStartAction { 126 if (visible) { 127 alpha = 0f 128 isVisible = true 129 } 130 } 131 .alpha(if (visible) 1f else 0f) 132 .withEndAction { 133 if (!visible) { 134 isVisible = false 135 } 136 } 137 .start() 138 } 139 140 private const val TAG = "KeyguardSettingsViewBinder" 141 } 142