1 /*
2  * 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.content.Intent
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.systemui.R
26 import com.android.systemui.animation.ActivityLaunchAnimator
27 import com.android.systemui.animation.view.LaunchableLinearLayout
28 import com.android.systemui.common.ui.binder.IconViewBinder
29 import com.android.systemui.common.ui.binder.TextViewBinder
30 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSettingsMenuViewModel
31 import com.android.systemui.lifecycle.repeatWhenAttached
32 import com.android.systemui.plugins.ActivityStarter
33 import com.android.systemui.statusbar.VibratorHelper
34 import kotlinx.coroutines.DisposableHandle
35 import kotlinx.coroutines.flow.distinctUntilChanged
36 import kotlinx.coroutines.flow.filter
37 import kotlinx.coroutines.launch
38 
39 object KeyguardSettingsViewBinder {
40     fun bind(
41         parentView: View,
42         viewModel: KeyguardSettingsMenuViewModel,
43         vibratorHelper: VibratorHelper,
44         activityStarter: ActivityStarter
45     ): DisposableHandle {
46         val view = parentView.requireViewById<LaunchableLinearLayout>(R.id.keyguard_settings_button)
47 
48         val disposableHandle =
49             view.repeatWhenAttached {
50                 repeatOnLifecycle(Lifecycle.State.STARTED) {
51                     launch {
52                         viewModel.isVisible.distinctUntilChanged().collect { isVisible ->
53                             view.animateVisibility(visible = isVisible)
54                             if (isVisible) {
55                                 vibratorHelper.vibrate(KeyguardBottomAreaVibrations.Activated)
56                                 view.setOnTouchListener(
57                                     KeyguardSettingsButtonOnTouchListener(
58                                         view = view,
59                                         viewModel = viewModel,
60                                     )
61                                 )
62                                 IconViewBinder.bind(
63                                     icon = viewModel.icon,
64                                     view = view.requireViewById(R.id.icon),
65                                 )
66                                 TextViewBinder.bind(
67                                     view = view.requireViewById(R.id.text),
68                                     viewModel = viewModel.text,
69                                 )
70                             }
71                         }
72                     }
73 
74                     // activityStarter will only be null when rendering the preview that
75                     // shows up in the Wallpaper Picker app. If we do that, then the
76                     // settings menu should never be visible.
77                     if (activityStarter != null) {
78                         launch {
79                             viewModel.shouldOpenSettings
80                                 .filter { it }
81                                 .collect {
82                                     navigateToLockScreenSettings(
83                                         activityStarter = activityStarter,
84                                         view = view,
85                                     )
86                                     viewModel.onSettingsShown()
87                                 }
88                         }
89                     }
90                 }
91             }
92         return disposableHandle
93     }
94 
95     /** Opens the wallpaper picker screen after the device is unlocked by the user. */
96     private fun navigateToLockScreenSettings(
97         activityStarter: ActivityStarter,
98         view: View,
99     ) {
100         activityStarter.postStartActivityDismissingKeyguard(
101             Intent(Intent.ACTION_SET_WALLPAPER).apply {
102                 flags = Intent.FLAG_ACTIVITY_NEW_TASK
103                 view.context
104                     .getString(R.string.config_wallpaperPickerPackage)
105                     .takeIf { it.isNotEmpty() }
106                     ?.let { packageName -> setPackage(packageName) }
107             },
108             /* delay= */ 0,
109             /* animationController= */ ActivityLaunchAnimator.Controller.fromView(view),
110             /* customMessage= */ view.context.getString(R.string.keyguard_unlock_to_customize_ls)
111         )
112     }
113 
114     private fun View.animateVisibility(visible: Boolean) {
115         animate()
116             .withStartAction {
117                 if (visible) {
118                     alpha = 0f
119                     isVisible = true
120                 }
121             }
122             .alpha(if (visible) 1f else 0f)
123             .withEndAction {
124                 if (!visible) {
125                     isVisible = false
126                 }
127             }
128             .start()
129     }
130 
131 }