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.composable.section
18 
19 import android.widget.FrameLayout
20 import androidx.compose.foundation.layout.Column
21 import androidx.compose.foundation.layout.IntrinsicSize
22 import androidx.compose.foundation.layout.Row
23 import androidx.compose.foundation.layout.Spacer
24 import androidx.compose.foundation.layout.fillMaxWidth
25 import androidx.compose.foundation.layout.height
26 import androidx.compose.foundation.layout.padding
27 import androidx.compose.foundation.layout.width
28 import androidx.compose.runtime.Composable
29 import androidx.compose.runtime.getValue
30 import androidx.compose.ui.Alignment
31 import androidx.compose.ui.Modifier
32 import androidx.compose.ui.platform.LocalContext
33 import androidx.compose.ui.res.dimensionResource
34 import androidx.compose.ui.unit.dp
35 import androidx.compose.ui.viewinterop.AndroidView
36 import androidx.lifecycle.compose.collectAsStateWithLifecycle
37 import com.android.compose.animation.scene.SceneScope
38 import com.android.compose.modifiers.padding
39 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
40 import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys
41 import com.android.systemui.keyguard.ui.composable.modifier.burnInAware
42 import com.android.systemui.keyguard.ui.composable.modifier.onTopPlacementChanged
43 import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
44 import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
45 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
46 import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
47 import com.android.systemui.res.R
48 import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
49 import javax.inject.Inject
50 
51 class SmartSpaceSection
52 @Inject
53 constructor(
54     private val lockscreenSmartspaceController: LockscreenSmartspaceController,
55     private val keyguardUnlockAnimationController: KeyguardUnlockAnimationController,
56     private val keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel,
57     private val aodBurnInViewModel: AodBurnInViewModel,
58     private val lockscreenContentViewModel: LockscreenContentViewModel,
59 ) {
60     @Composable
61     fun SceneScope.SmartSpace(
62         burnInParams: BurnInParameters,
63         onTopChanged: (top: Float?) -> Unit,
64         modifier: Modifier = Modifier,
65     ) {
66         val resources = LocalContext.current.resources
67 
68         MovableElement(key = ClockElementKeys.smartspaceElementKey, modifier = modifier) {
69             Column(
70                 modifier =
71                     modifier
72                         .onTopPlacementChanged(onTopChanged)
73                         .padding(
74                             top = { lockscreenContentViewModel.getSmartSpacePaddingTop(resources) },
75                             bottom = {
76                                 resources.getDimensionPixelSize(
77                                     R.dimen.keyguard_status_view_bottom_margin
78                                 )
79                             }
80                         )
81             ) {
82                 if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) {
83                     return@Column
84                 }
85 
86                 val paddingBelowClockStart = dimensionResource(R.dimen.below_clock_padding_start)
87                 val paddingBelowClockEnd = dimensionResource(R.dimen.below_clock_padding_end)
88 
89                 if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
90                     Row(
91                         verticalAlignment = Alignment.CenterVertically,
92                         modifier =
93                             Modifier.fillMaxWidth()
94                                 // All items will be constrained to be as tall as the shortest item.
95                                 .height(IntrinsicSize.Min)
96                                 .padding(
97                                     start = paddingBelowClockStart,
98                                 ),
99                     ) {
100                         Date(
101                             modifier =
102                                 Modifier.burnInAware(
103                                     viewModel = aodBurnInViewModel,
104                                     params = burnInParams,
105                                 ),
106                         )
107                         Spacer(modifier = Modifier.width(4.dp))
108                         Weather(
109                             modifier =
110                                 Modifier.burnInAware(
111                                     viewModel = aodBurnInViewModel,
112                                     params = burnInParams,
113                                 ),
114                         )
115                     }
116                 }
117 
118                 Card(
119                     modifier =
120                         Modifier.fillMaxWidth()
121                             .padding(
122                                 start = paddingBelowClockStart,
123                                 end = paddingBelowClockEnd,
124                             )
125                             .burnInAware(
126                                 viewModel = aodBurnInViewModel,
127                                 params = burnInParams,
128                             ),
129                 )
130             }
131         }
132     }
133 
134     @Composable
135     private fun Card(
136         modifier: Modifier = Modifier,
137     ) {
138         AndroidView(
139             factory = { context ->
140                 FrameLayout(context).apply {
141                     addView(
142                         lockscreenSmartspaceController.buildAndConnectView(this).apply {
143                             layoutParams =
144                                 FrameLayout.LayoutParams(
145                                     FrameLayout.LayoutParams.MATCH_PARENT,
146                                     FrameLayout.LayoutParams.WRAP_CONTENT,
147                                 )
148 
149                             keyguardUnlockAnimationController.lockscreenSmartspace = this
150                         }
151                     )
152                 }
153             },
154             onRelease = { keyguardUnlockAnimationController.lockscreenSmartspace = null },
155             modifier = modifier,
156         )
157     }
158 
159     @Composable
160     private fun Weather(
161         modifier: Modifier = Modifier,
162     ) {
163         val isVisible by keyguardSmartspaceViewModel.isWeatherVisible.collectAsStateWithLifecycle()
164         if (!isVisible) {
165             return
166         }
167 
168         AndroidView(
169             factory = { context ->
170                 FrameLayout(context).apply {
171                     addView(
172                         lockscreenSmartspaceController.buildAndConnectWeatherView(this).apply {
173                             layoutParams =
174                                 FrameLayout.LayoutParams(
175                                     FrameLayout.LayoutParams.WRAP_CONTENT,
176                                     FrameLayout.LayoutParams.WRAP_CONTENT,
177                                 )
178                         }
179                     )
180                 }
181             },
182             modifier = modifier,
183         )
184     }
185 
186     @Composable
187     private fun Date(
188         modifier: Modifier = Modifier,
189     ) {
190         val isVisible by keyguardSmartspaceViewModel.isDateVisible.collectAsStateWithLifecycle()
191         if (!isVisible) {
192             return
193         }
194 
195         AndroidView(
196             factory = { context ->
197                 FrameLayout(context).apply {
198                     addView(
199                         lockscreenSmartspaceController.buildAndConnectDateView(this).apply {
200                             layoutParams =
201                                 FrameLayout.LayoutParams(
202                                     FrameLayout.LayoutParams.WRAP_CONTENT,
203                                     FrameLayout.LayoutParams.WRAP_CONTENT,
204                                 )
205                         }
206                     )
207                 }
208             },
209             modifier = modifier,
210         )
211     }
212 }
213