1 /* 2 * Copyright (C) 2022 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 package com.android.systemui.bouncer.ui.viewmodel 18 19 import android.view.View 20 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor 21 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel 22 import com.android.systemui.bouncer.ui.BouncerView 23 import com.android.systemui.bouncer.ui.BouncerViewDelegate 24 import javax.inject.Inject 25 import kotlinx.coroutines.flow.Flow 26 import kotlinx.coroutines.flow.filterNotNull 27 import kotlinx.coroutines.flow.map 28 import kotlinx.coroutines.flow.merge 29 30 /** Models UI state for the lock screen bouncer; handles user input. */ 31 class KeyguardBouncerViewModel 32 @Inject 33 constructor( 34 private val view: BouncerView, 35 private val interactor: PrimaryBouncerInteractor, 36 ) { 37 /** Observe on bouncer expansion amount. */ 38 val bouncerExpansionAmount: Flow<Float> = interactor.panelExpansionAmount 39 40 /** Can the user interact with the view? */ 41 val isInteractable: Flow<Boolean> = interactor.isInteractable 42 43 /** Observe whether bouncer is showing or not. */ 44 val isShowing: Flow<Boolean> = interactor.isShowing 45 46 /** Observe whether bouncer is starting to hide. */ 47 val startingToHide: Flow<Unit> = interactor.startingToHide 48 49 /** Observe whether we want to start the disappear animation. */ 50 val startDisappearAnimation: Flow<Runnable> = interactor.startingDisappearAnimation 51 52 /** Observe whether we want to update keyguard position. */ 53 val keyguardPosition: Flow<Float> = interactor.keyguardPosition 54 55 /** Observe whether we want to update resources. */ 56 val updateResources: Flow<Boolean> = interactor.resourceUpdateRequests 57 58 /** Observe whether we want to set a keyguard message when the bouncer shows. */ 59 val bouncerShowMessage: Flow<BouncerShowMessageModel> = interactor.showMessage 60 61 /** Observe whether keyguard is authenticated already. */ 62 val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated 63 64 /** Observe whether the side fps is showing. */ 65 val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing 66 67 /** Observe whether we should update fps is showing. */ 68 val shouldUpdateSideFps: Flow<Unit> = 69 merge( 70 interactor.isShowing.map {}, 71 interactor.startingToHide, 72 interactor.startingDisappearAnimation.filterNotNull().map {} 73 ) 74 75 /** Observe whether we want to update resources. */ 76 fun notifyUpdateResources() { 77 interactor.notifyUpdatedResources() 78 } 79 80 /** Notify that keyguard authenticated was handled */ 81 fun notifyKeyguardAuthenticated() { 82 interactor.notifyKeyguardAuthenticatedHandled() 83 } 84 85 /** Notifies that the message was shown. */ 86 fun onMessageShown() { 87 interactor.onMessageShown() 88 } 89 90 fun updateSideFpsVisibility() { 91 interactor.updateSideFpsVisibility() 92 } 93 94 /** Observe whether back button is enabled. */ 95 fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> { 96 return interactor.isBackButtonEnabled.map { enabled -> 97 var vis: Int = systemUiVisibility() 98 vis = 99 if (enabled) { 100 vis and View.STATUS_BAR_DISABLE_BACK.inv() 101 } else { 102 vis or View.STATUS_BAR_DISABLE_BACK 103 } 104 vis 105 } 106 } 107 108 /** Set an abstraction that will hold reference to the ui delegate for the bouncer view. */ 109 fun setBouncerViewDelegate(delegate: BouncerViewDelegate?) { 110 view.delegate = delegate 111 } 112 } 113