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.EMPHASIZED_ACCELERATE 21 import com.android.systemui.Flags 22 import com.android.systemui.dagger.SysUISingleton 23 import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor 24 import com.android.systemui.keyguard.shared.model.Edge 25 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN 26 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER 27 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow 28 import com.android.systemui.keyguard.ui.transitions.BlurConfig 29 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition 30 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition 31 import com.android.systemui.scene.shared.model.Overlays 32 import javax.inject.Inject 33 import kotlin.time.Duration.Companion.milliseconds 34 import kotlinx.coroutines.flow.Flow 35 36 /** 37 * Breaks down PRIMARY BOUNCER->LOCKSCREEN transition into discrete steps for corresponding views to 38 * consume. 39 */ 40 @SysUISingleton 41 class PrimaryBouncerToLockscreenTransitionViewModel 42 @Inject 43 constructor( 44 private val blurConfig: BlurConfig, 45 animationFlow: KeyguardTransitionAnimationFlow, 46 shadeDependentFlows: ShadeDependentFlows, 47 ) : DeviceEntryIconTransition, PrimaryBouncerTransition { 48 private val transitionAnimation = 49 animationFlow 50 .setup( 51 duration = FromPrimaryBouncerTransitionInteractor.TO_LOCKSCREEN_DURATION, 52 edge = Edge.create(from = Overlays.Bouncer, to = LOCKSCREEN), 53 ) 54 .setupWithoutSceneContainer(edge = Edge.create(from = PRIMARY_BOUNCER, to = LOCKSCREEN)) 55 56 val shortcutsAlpha: Flow<Float> = 57 transitionAnimation.sharedFlow( 58 duration = 250.milliseconds, 59 interpolator = EMPHASIZED_ACCELERATE, <lambda>null60 onStep = { it }, 61 ) 62 lockscreenAlphanull63 fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> { 64 var currentAlpha = 0f 65 return transitionAnimation.sharedFlow( 66 duration = 250.milliseconds, 67 onStart = { currentAlpha = viewState.alpha() }, 68 onStep = { MathUtils.lerp(currentAlpha, 1f, it) }, 69 ) 70 } 71 72 val deviceEntryBackgroundViewAlpha: Flow<Float> = 73 transitionAnimation.immediatelyTransitionTo(1f) 74 override val deviceEntryParentViewAlpha: Flow<Float> = 75 transitionAnimation.immediatelyTransitionTo(1f) 76 77 override val windowBlurRadius: Flow<Float> = 78 shadeDependentFlows.transitionFlow( 79 flowWhenShadeIsExpanded = 80 if (Flags.notificationShadeBlur()) { 81 transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx) 82 } else { 83 transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx) 84 }, 85 flowWhenShadeIsNotExpanded = 86 transitionAnimation.sharedFlow( 87 duration = FromPrimaryBouncerTransitionInteractor.TO_LOCKSCREEN_DURATION, <lambda>null88 onStep = { 89 transitionProgressToBlurRadius( 90 starBlurRadius = blurConfig.maxBlurRadiusPx, 91 endBlurRadius = blurConfig.minBlurRadiusPx, 92 transitionProgress = it, 93 ) 94 }, 95 ), 96 ) 97 98 override val notificationBlurRadius: Flow<Float> = 99 transitionAnimation.immediatelyTransitionTo(0.0f) 100 } 101