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 package com.android.systemui.statusbar.notification.stack.ui.viewmodel 18 19 import com.android.systemui.dagger.SysUISingleton 20 import com.android.systemui.dump.DumpManager 21 import com.android.systemui.flags.FeatureFlagsClassic 22 import com.android.systemui.flags.Flags 23 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor 24 import com.android.systemui.scene.shared.flag.SceneContainerFlag 25 import com.android.systemui.shade.domain.interactor.ShadeInteractor 26 import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor 27 import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds 28 import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding 29 import com.android.systemui.util.kotlin.FlowDumperImpl 30 import javax.inject.Inject 31 import kotlinx.coroutines.flow.Flow 32 33 /** 34 * ViewModel used by the Notification placeholders inside the scene container to update the 35 * [NotificationStackAppearanceInteractor], and by extension control the NSSL. 36 */ 37 @SysUISingleton 38 class NotificationsPlaceholderViewModel 39 @Inject 40 constructor( 41 dumpManager: DumpManager, 42 private val interactor: NotificationStackAppearanceInteractor, 43 shadeInteractor: ShadeInteractor, 44 featureFlags: FeatureFlagsClassic, 45 private val keyguardInteractor: KeyguardInteractor, 46 ) : FlowDumperImpl(dumpManager) { 47 /** DEBUG: whether the placeholder should be made slightly visible for positional debugging. */ 48 val isVisualDebuggingEnabled: Boolean = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES) 49 50 /** DEBUG: whether the debug logging should be output. */ 51 val isDebugLoggingEnabled: Boolean = SceneContainerFlag.isEnabled 52 53 /** Notifies that the bounds of the notification scrim have changed. */ onScrimBoundsChangednull54 fun onScrimBoundsChanged(bounds: ShadeScrimBounds?) { 55 interactor.setShadeScrimBounds(bounds) 56 } 57 58 /** Sets the available space */ onConstrainedAvailableSpaceChangednull59 fun onConstrainedAvailableSpaceChanged(height: Int) { 60 interactor.setConstrainedAvailableSpace(height) 61 } 62 63 /** Sets the content alpha for the current state of the brightness mirror */ setAlphaForBrightnessMirrornull64 fun setAlphaForBrightnessMirror(alpha: Float) { 65 interactor.setAlphaForBrightnessMirror(alpha) 66 } 67 68 /** Corner rounding of the stack */ 69 val shadeScrimRounding: Flow<ShadeScrimRounding> = 70 interactor.shadeScrimRounding.dumpWhileCollecting("shadeScrimRounding") 71 72 /** 73 * The amount [0-1] that the shade or quick settings has been opened. At 0, the shade is closed; 74 * at 1, either the shade or quick settings is open. 75 */ 76 val expandFraction: Flow<Float> = shadeInteractor.anyExpansion.dumpValue("expandFraction") 77 78 /** 79 * The amount in px that the notification stack should scroll due to internal expansion. This 80 * should only happen when a notification expansion hits the bottom of the screen, so it is 81 * necessary to scroll up to keep expanding the notification. 82 */ 83 val syntheticScroll: Flow<Float> = 84 interactor.syntheticScroll.dumpWhileCollecting("syntheticScroll") 85 86 /** 87 * Whether the current touch gesture is overscroll. If true, it means the NSSL has already 88 * consumed part of the gesture. 89 */ 90 val isCurrentGestureOverscroll: Flow<Boolean> = 91 interactor.isCurrentGestureOverscroll.dumpWhileCollecting("isCurrentGestureOverScroll") 92 93 /** Sets whether the notification stack is scrolled to the top. */ setScrolledToTopnull94 fun setScrolledToTop(scrolledToTop: Boolean) { 95 interactor.setScrolledToTop(scrolledToTop) 96 } 97 } 98 99 // Expansion fraction thresholds (between 0-1f) at which the corresponding value should be 100 // at its maximum, given they are at their minimum value at expansion = 0f. 101 object NotificationTransitionThresholds { 102 const val EXPANSION_FOR_MAX_CORNER_RADIUS = 0.1f 103 const val EXPANSION_FOR_MAX_SCRIM_ALPHA = 0.3f 104 const val EXPANSION_FOR_DELAYED_STACK_FADE_IN = 0.5f 105 } 106