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