• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.FromAlternateBouncerTransitionInteractor
22 import com.android.systemui.keyguard.shared.model.Edge
23 import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
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 kotlinx.coroutines.flow.Flow
34 import kotlinx.coroutines.flow.emptyFlow
35 
36 /**
37  * Breaks down ALTERNATE BOUNCER->PRIMARY BOUNCER transition into discrete steps for corresponding
38  * views to consume.
39  */
40 @SysUISingleton
41 class AlternateBouncerToPrimaryBouncerTransitionViewModel
42 @Inject
43 constructor(
44     animationFlow: KeyguardTransitionAnimationFlow,
45     blurConfig: BlurConfig,
46     shadeDependentFlows: ShadeDependentFlows,
47 ) : DeviceEntryIconTransition, PrimaryBouncerTransition {
48     private val transitionAnimation =
49         animationFlow
50             .setup(
51                 duration = FromAlternateBouncerTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
52                 edge = Edge.create(from = ALTERNATE_BOUNCER, to = Overlays.Bouncer),
53             )
54             .setupWithoutSceneContainer(
55                 edge = Edge.create(from = ALTERNATE_BOUNCER, to = PRIMARY_BOUNCER)
56             )
57 
58     private val alphaForAnimationStep: (Float) -> Float =
59         when {
60             SceneContainerFlag.isEnabled -> { step ->
61                     1f - Math.min((step / TO_BOUNCER_FADE_FRACTION), 1f)
62                 }
63             else -> { step -> 1f - step }
64         }
65 
66     private val alphaFlow =
67         transitionAnimation.sharedFlow(
68             duration = FromAlternateBouncerTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
69             onStep = alphaForAnimationStep,
70         )
71 
72     val lockscreenAlpha: Flow<Float> = if (Flags.bouncerUiRevamp()) alphaFlow else emptyFlow()
73 
74     val notificationAlpha: Flow<Float> =
75         if (Flags.bouncerUiRevamp()) {
76             shadeDependentFlows.transitionFlow(
77                 flowWhenShadeIsNotExpanded = lockscreenAlpha,
78                 flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(1f),
79             )
80         } else {
81             alphaFlow
82         }
83 
84     override val notificationBlurRadius: Flow<Float> =
85         if (Flags.bouncerUiRevamp()) {
86             shadeDependentFlows.transitionFlow(
87                 flowWhenShadeIsNotExpanded = emptyFlow(),
88                 flowWhenShadeIsExpanded =
89                     transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
90             )
91         } else {
92             emptyFlow<Float>()
93         }
94 
95     override val deviceEntryParentViewAlpha: Flow<Float> =
96         transitionAnimation.immediatelyTransitionTo(0f)
97 
98     override val windowBlurRadius: Flow<Float> =
99         shadeDependentFlows.transitionFlow(
100             flowWhenShadeIsExpanded =
101                 if (Flags.notificationShadeBlur()) {
102                     transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
103                 } else {
104                     transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx)
105                 },
106             flowWhenShadeIsNotExpanded =
107                 transitionAnimation.sharedFlow(
108                     duration = FromAlternateBouncerTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
109                     onStep = { step ->
110                         transitionProgressToBlurRadius(
111                             starBlurRadius = blurConfig.minBlurRadiusPx,
112                             endBlurRadius = blurConfig.maxBlurRadiusPx,
113                             transitionProgress = step,
114                         )
115                     },
116                     onFinish = { blurConfig.maxBlurRadiusPx },
117                 ),
118         )
119 }
120