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.common.ui.domain.interactor.ConfigurationInteractor
20 import com.android.systemui.dagger.qualifiers.Background
21 import com.android.systemui.dagger.qualifiers.Main
22 import com.android.systemui.doze.util.BurnInHelperWrapper
23 import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
24 import com.android.systemui.keyguard.MigrateClocksToBlueprint
25 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
26 import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
27 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
28 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
29 import com.android.systemui.keyguard.shared.model.BurnInModel
30 import com.android.systemui.keyguard.shared.model.KeyguardState
31 import com.android.systemui.res.R
32 import javax.inject.Inject
33 import kotlin.coroutines.CoroutineContext
34 import kotlinx.coroutines.CoroutineDispatcher
35 import kotlinx.coroutines.ExperimentalCoroutinesApi
36 import kotlinx.coroutines.flow.Flow
37 import kotlinx.coroutines.flow.combine
38 import kotlinx.coroutines.flow.distinctUntilChanged
39 import kotlinx.coroutines.flow.flowOn
40 import kotlinx.coroutines.flow.map
41 
42 /** View-model for the keyguard indication area view */
43 class KeyguardIndicationAreaViewModel
44 @Inject
45 constructor(
46     private val keyguardInteractor: KeyguardInteractor,
47     private val bottomAreaInteractor: KeyguardBottomAreaInteractor,
48     keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel,
49     private val burnInHelperWrapper: BurnInHelperWrapper,
50     private val burnInInteractor: BurnInInteractor,
51     private val shortcutsCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel,
52     configurationInteractor: ConfigurationInteractor,
53     keyguardTransitionInteractor: KeyguardTransitionInteractor,
54     @Background private val backgroundCoroutineContext: CoroutineContext,
55     @Main private val mainDispatcher: CoroutineDispatcher,
56 ) {
57 
58     /** Notifies when a new configuration is set */
59     val configurationChange: Flow<Unit> = configurationInteractor.onAnyConfigurationChange
60 
61     /** An observable for the alpha level for the entire bottom area. */
62     val alpha: Flow<Float> = keyguardBottomAreaViewModel.alpha
63 
64     /** An observable for whether the indication area should be padded. */
65     val isIndicationAreaPadded: Flow<Boolean> =
66         if (KeyguardBottomAreaRefactor.isEnabled) {
67             combine(shortcutsCombinedViewModel.startButton, shortcutsCombinedViewModel.endButton) {
68                     startButtonModel,
69                     endButtonModel ->
70                     startButtonModel.isVisible || endButtonModel.isVisible
71                 }
72                 .distinctUntilChanged()
73         } else {
74             combine(
75                     keyguardBottomAreaViewModel.startButton,
76                     keyguardBottomAreaViewModel.endButton
77                 ) { startButtonModel, endButtonModel ->
78                     startButtonModel.isVisible || endButtonModel.isVisible
79                 }
80                 .distinctUntilChanged()
81         }
82 
83     @OptIn(ExperimentalCoroutinesApi::class)
84     private val burnIn: Flow<BurnInModel> =
85         combine(
86                 burnInInteractor.burnIn(
87                     xDimenResourceId = R.dimen.burn_in_prevention_offset_x,
88                     yDimenResourceId = R.dimen.default_burn_in_prevention_offset,
89                 ),
90                 keyguardTransitionInteractor.transitionValue(KeyguardState.AOD),
91             ) { burnIn, aodTransitionValue ->
92                 BurnInModel(
93                     (burnIn.translationX * aodTransitionValue).toInt(),
94                     (burnIn.translationY * aodTransitionValue).toInt(),
95                     burnIn.scale,
96                     burnIn.scaleClockOnly,
97                 )
98             }
99             .distinctUntilChanged()
100             .flowOn(backgroundCoroutineContext)
101 
102     /** An observable for the x-offset by which the indication area should be translated. */
103     val indicationAreaTranslationX: Flow<Float> =
104         if (MigrateClocksToBlueprint.isEnabled || KeyguardBottomAreaRefactor.isEnabled) {
105             burnIn.map { it.translationX.toFloat() }.flowOn(mainDispatcher)
106         } else {
107             bottomAreaInteractor.clockPosition.map { it.x.toFloat() }.distinctUntilChanged()
108         }
109 
110     /** Returns an observable for the y-offset by which the indication area should be translated. */
111     fun indicationAreaTranslationY(defaultBurnInOffset: Int): Flow<Float> {
112         return if (MigrateClocksToBlueprint.isEnabled) {
113             burnIn.map { it.translationY.toFloat() }.flowOn(mainDispatcher)
114         } else {
115             keyguardInteractor.dozeAmount
116                 .map { dozeAmount ->
117                     dozeAmount *
118                         (burnInHelperWrapper.burnInOffset(
119                             /* amplitude = */ defaultBurnInOffset * 2,
120                             /* xAxis= */ false,
121                         ) - defaultBurnInOffset)
122                 }
123                 .distinctUntilChanged()
124         }
125     }
126 }
127