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 }