• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.systemui.keyguard.ui.viewmodel
18 
19 import com.android.systemui.Flags
20 import com.android.systemui.dagger.SysUISingleton
21 import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
22 import com.android.systemui.keyguard.shared.model.Edge
23 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
24 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
25 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
26 import com.android.systemui.keyguard.ui.transitions.BlurConfig
27 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
28 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
29 import com.android.systemui.scene.shared.flag.SceneContainerFlag
30 import com.android.systemui.scene.shared.model.Overlays
31 import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION
32 import javax.inject.Inject
33 import kotlin.time.Duration.Companion.milliseconds
34 import kotlinx.coroutines.flow.Flow
35 import kotlinx.coroutines.flow.emptyFlow
36 
37 /**
38  * Breaks down LOCKSCREEN->PRIMARY BOUNCER transition into discrete steps for corresponding views to
39  * consume.
40  */
41 @SysUISingleton
42 class LockscreenToPrimaryBouncerTransitionViewModel
43 @Inject
44 constructor(
45     private val blurConfig: BlurConfig,
46     shadeDependentFlows: ShadeDependentFlows,
47     animationFlow: KeyguardTransitionAnimationFlow,
48 ) : DeviceEntryIconTransition, PrimaryBouncerTransition {
49     private val transitionAnimation =
50         animationFlow
51             .setup(
52                 duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
53                 edge = Edge.create(from = LOCKSCREEN, to = Overlays.Bouncer),
54             )
55             .setupWithoutSceneContainer(edge = Edge.create(from = LOCKSCREEN, to = PRIMARY_BOUNCER))
56 
57     private val alphaForAnimationStep: (Float) -> Float =
58         when {
59             SceneContainerFlag.isEnabled -> { step ->
60                     1f - Math.min((step / TO_BOUNCER_FADE_FRACTION), 1f)
61                 }
62             else -> { step -> 1f - step }
63         }
64 
65     val shortcutsAlpha: Flow<Float> =
66         transitionAnimation.sharedFlow(
67             duration = 200.milliseconds,
68             onStep = alphaForAnimationStep,
69             // Rapid swipes to bouncer, and may end up skipping intermediate values that would've
70             // caused a complete fade out of lockscreen elements. Ensure it goes to 0f.
71             onFinish = { 0f },
72         )
73 
74     val lockscreenAlpha: Flow<Float> = shortcutsAlpha
75 
76     val notificationAlpha: Flow<Float> =
77         if (Flags.bouncerUiRevamp()) {
78             shadeDependentFlows.transitionFlow(
79                 flowWhenShadeIsNotExpanded = lockscreenAlpha,
80                 flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(1f),
81             )
82         } else {
83             lockscreenAlpha
84         }
85 
86     override val notificationBlurRadius: Flow<Float> =
87         if (Flags.bouncerUiRevamp()) {
88             shadeDependentFlows.transitionFlow(
89                 flowWhenShadeIsNotExpanded = emptyFlow(),
90                 flowWhenShadeIsExpanded =
91                     transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
92             )
93         } else {
94             emptyFlow()
95         }
96 
97     override val deviceEntryParentViewAlpha: Flow<Float> =
98         shadeDependentFlows.transitionFlow(
99             flowWhenShadeIsNotExpanded =
100                 transitionAnimation.sharedFlow(
101                     duration = 250.milliseconds,
102                     onStep = { 1f - it },
103                     onCancel = { 0f },
104                     onFinish = { 0f },
105                 ),
106             flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
107         )
108     override val windowBlurRadius: Flow<Float> =
109         shadeDependentFlows.transitionFlow(
110             flowWhenShadeIsExpanded =
111                 if (Flags.notificationShadeBlur()) {
112                     transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
113                 } else {
114                     emptyFlow()
115                 },
116             flowWhenShadeIsNotExpanded =
117                 transitionAnimation.sharedFlow(
118                     duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
119                     onStep = {
120                         transitionProgressToBlurRadius(
121                             starBlurRadius = blurConfig.minBlurRadiusPx,
122                             endBlurRadius = blurConfig.maxBlurRadiusPx,
123                             transitionProgress = it,
124                         )
125                     },
126                 ),
127         )
128 }
129