1 /* 2 * 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.composable.section 18 19 import android.view.View 20 import android.view.ViewGroup 21 import androidx.compose.foundation.layout.Box 22 import androidx.compose.foundation.layout.IntrinsicSize 23 import androidx.compose.foundation.layout.Row 24 import androidx.compose.foundation.layout.fillMaxSize 25 import androidx.compose.foundation.layout.height 26 import androidx.compose.foundation.layout.padding 27 import androidx.compose.foundation.layout.wrapContentSize 28 import androidx.compose.runtime.Composable 29 import androidx.compose.ui.Alignment 30 import androidx.compose.ui.Modifier 31 import androidx.compose.ui.res.dimensionResource 32 import androidx.compose.ui.viewinterop.AndroidView 33 import com.android.compose.animation.scene.ElementKey 34 import com.android.compose.animation.scene.SceneScope 35 import com.android.compose.modifiers.padding 36 import com.android.systemui.customization.R as customizationR 37 import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockElementKeys 38 import com.android.systemui.keyguard.ui.composable.modifier.burnInAware 39 import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel 40 import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters 41 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel 42 import com.android.systemui.plugins.clocks.ClockController 43 import javax.inject.Inject 44 45 /** Provides small clock and large clock composables for the weather clock layout. */ 46 class WeatherClockSection 47 @Inject 48 constructor( 49 private val viewModel: KeyguardClockViewModel, 50 private val aodBurnInViewModel: AodBurnInViewModel, 51 ) { 52 @Composable Timenull53 fun SceneScope.Time( 54 clock: ClockController, 55 burnInParams: BurnInParameters, 56 ) { 57 Row( 58 modifier = 59 Modifier.padding( 60 horizontal = dimensionResource(customizationR.dimen.clock_padding_start) 61 ) 62 .burnInAware(aodBurnInViewModel, burnInParams, isClock = true) 63 ) { 64 WeatherElement( 65 weatherClockElementViewId = customizationR.id.weather_clock_time, 66 clock = clock, 67 elementKey = WeatherClockElementKeys.timeElementKey, 68 ) 69 } 70 } 71 72 @Composable SceneScopenull73 private fun SceneScope.Date( 74 clock: ClockController, 75 modifier: Modifier = Modifier, 76 ) { 77 WeatherElement( 78 weatherClockElementViewId = customizationR.id.weather_clock_date, 79 clock = clock, 80 elementKey = WeatherClockElementKeys.dateElementKey, 81 modifier = modifier, 82 ) 83 } 84 85 @Composable Weathernull86 private fun SceneScope.Weather( 87 clock: ClockController, 88 modifier: Modifier = Modifier, 89 ) { 90 WeatherElement( 91 weatherClockElementViewId = customizationR.id.weather_clock_weather_icon, 92 clock = clock, 93 elementKey = WeatherClockElementKeys.weatherIconElementKey, 94 modifier = modifier.wrapContentSize(), 95 ) 96 } 97 98 @Composable SceneScopenull99 private fun SceneScope.DndAlarmStatus( 100 clock: ClockController, 101 modifier: Modifier = Modifier, 102 ) { 103 WeatherElement( 104 weatherClockElementViewId = customizationR.id.weather_clock_alarm_dnd, 105 clock = clock, 106 elementKey = WeatherClockElementKeys.dndAlarmElementKey, 107 modifier = modifier.wrapContentSize(), 108 ) 109 } 110 111 @Composable Temperaturenull112 private fun SceneScope.Temperature( 113 clock: ClockController, 114 modifier: Modifier = Modifier, 115 ) { 116 WeatherElement( 117 weatherClockElementViewId = customizationR.id.weather_clock_temperature, 118 clock = clock, 119 elementKey = WeatherClockElementKeys.temperatureElementKey, 120 modifier = modifier.wrapContentSize(), 121 ) 122 } 123 124 @Composable WeatherElementnull125 private fun SceneScope.WeatherElement( 126 weatherClockElementViewId: Int, 127 clock: ClockController, 128 elementKey: ElementKey, 129 modifier: Modifier = Modifier, 130 ) { 131 MovableElement(key = elementKey, modifier) { 132 content { 133 AndroidView( 134 factory = { 135 try { 136 val view = 137 clock.largeClock.layout.views.first { 138 it.id == weatherClockElementViewId 139 } 140 (view.parent as? ViewGroup)?.removeView(view) 141 view 142 } catch (e: NoSuchElementException) { 143 View(it) 144 } 145 }, 146 update = {}, 147 modifier = modifier 148 ) 149 } 150 } 151 } 152 153 @Composable SceneScopenull154 fun SceneScope.LargeClockSectionBelowSmartspace( 155 burnInParams: BurnInParameters, 156 clock: ClockController, 157 ) { 158 Row( 159 modifier = 160 Modifier.height(IntrinsicSize.Max) 161 .padding( 162 horizontal = dimensionResource(customizationR.dimen.clock_padding_start) 163 ) 164 .burnInAware(aodBurnInViewModel, burnInParams, isClock = true) 165 ) { 166 Date(clock = clock, modifier = Modifier.wrapContentSize()) 167 Box( 168 modifier = 169 Modifier.fillMaxSize() 170 .padding( 171 start = dimensionResource(customizationR.dimen.clock_padding_start) 172 ) 173 ) { 174 Weather(clock = clock, modifier = Modifier.align(Alignment.TopStart)) 175 Temperature(clock = clock, modifier = Modifier.align(Alignment.BottomEnd)) 176 DndAlarmStatus(clock = clock, modifier = Modifier.align(Alignment.TopEnd)) 177 } 178 } 179 } 180 } 181