• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.keyguard.ui.viewmodel
18 
19 import android.util.MathUtils
20 import com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN
21 import com.android.systemui.dagger.SysUISingleton
22 import com.android.systemui.keyguard.domain.interactor.FromAodTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
23 import com.android.systemui.keyguard.shared.model.Edge
24 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
25 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
26 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
27 import com.android.systemui.keyguard.ui.StateToValue
28 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
29 import com.android.systemui.shade.domain.interactor.ShadeInteractor
30 import javax.inject.Inject
31 import kotlin.time.Duration.Companion.milliseconds
32 import kotlinx.coroutines.flow.Flow
33 
34 /**
35  * Breaks down AOD->LOCKSCREEN transition into discrete steps for corresponding views to consume.
36  */
37 @SysUISingleton
38 class AodToLockscreenTransitionViewModel
39 @Inject
40 constructor(shadeInteractor: ShadeInteractor, animationFlow: KeyguardTransitionAnimationFlow) :
41     DeviceEntryIconTransition {
42 
43     private val transitionAnimation =
44         animationFlow.setup(
45             duration = TO_LOCKSCREEN_DURATION,
46             edge = Edge.create(from = AOD, to = LOCKSCREEN),
47         )
48 
49     private var isShadeExpanded = false
50 
51     /**
52      * Begin the transition from wherever the y-translation value is currently. This helps ensure a
53      * smooth transition if the prior transition was canceled.
54      */
translationYnull55     fun translationY(currentTranslationY: () -> Float?): Flow<StateToValue> {
56         var startValue = 0f
57         return transitionAnimation.sharedFlowWithState(
58             duration = 500.milliseconds,
59             onStart = { startValue = currentTranslationY() ?: 0f },
60             onStep = { MathUtils.lerp(startValue, 0f, FAST_OUT_SLOW_IN.getInterpolation(it)) },
61         )
62     }
63 
64     /**
65      * Begin the transition from wherever the x-translation value is currently. This helps ensure a
66      * smooth transition if the prior transition was canceled.
67      */
translationXnull68     fun translationX(currentTranslationX: () -> Float?): Flow<StateToValue> {
69         var startValue = 0f
70         return transitionAnimation.sharedFlowWithState(
71             duration = 500.milliseconds,
72             onStart = { startValue = currentTranslationX() ?: 0f },
73             onStep = { MathUtils.lerp(startValue, 0f, FAST_OUT_SLOW_IN.getInterpolation(it)) },
74         )
75     }
76 
77     /** Ensure alpha is set to be visible */
lockscreenAlphanull78     fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> {
79         var startAlpha = 1f
80         return transitionAnimation.sharedFlow(
81             duration = 500.milliseconds,
82             onStart = { startAlpha = viewState.alpha() },
83             onStep = { MathUtils.lerp(startAlpha, 1f, it) },
84         )
85     }
86 
87     val notificationAlpha: Flow<Float> =
88         transitionAnimation.sharedFlow(
89             duration = 500.milliseconds,
<lambda>null90             onStart = {
91                 isShadeExpanded =
92                     shadeInteractor.shadeExpansion.value > 0f ||
93                         shadeInteractor.qsExpansion.value > 0f
94             },
<lambda>null95             onStep = {
96                 if (isShadeExpanded) {
97                     1f
98                 } else {
99                     it
100                 }
101             },
102         )
103 
104     val shortcutsAlpha: Flow<Float> =
105         transitionAnimation.sharedFlow(
106             duration = 167.milliseconds,
107             startTime = 67.milliseconds,
<lambda>null108             onStep = { it },
<lambda>null109             onCancel = { 0f },
110         )
111 
112     val deviceEntryBackgroundViewAlpha: Flow<Float> =
113         transitionAnimation.sharedFlow(
114             duration = 250.milliseconds,
<lambda>null115             onStep = { it },
<lambda>null116             onCancel = { 1f },
<lambda>null117             onFinish = { 1f },
118         )
119 
120     override val deviceEntryParentViewAlpha: Flow<Float> =
121         transitionAnimation.immediatelyTransitionTo(1f)
122 }
123