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