1 /* <lambda>null2 * 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.qs.ui.composable 18 19 import androidx.compose.animation.core.animateFloatAsState 20 import androidx.compose.foundation.layout.Box 21 import androidx.compose.foundation.layout.fillMaxHeight 22 import androidx.compose.foundation.layout.offset 23 import androidx.compose.foundation.layout.wrapContentWidth 24 import androidx.compose.runtime.Composable 25 import androidx.compose.runtime.getValue 26 import androidx.compose.ui.Alignment 27 import androidx.compose.ui.Modifier 28 import androidx.compose.ui.graphics.graphicsLayer 29 import androidx.compose.ui.unit.IntOffset 30 import androidx.compose.ui.viewinterop.AndroidView 31 import androidx.lifecycle.compose.collectAsStateWithLifecycle 32 import com.android.compose.modifiers.height 33 import com.android.compose.modifiers.width 34 import com.android.systemui.qs.ui.adapter.QSSceneAdapter 35 import com.android.systemui.settings.brightness.ui.binder.BrightnessMirrorInflater 36 import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel 37 38 @Composable 39 fun BrightnessMirror( 40 viewModel: BrightnessMirrorViewModel, 41 qsSceneAdapter: QSSceneAdapter, 42 modifier: Modifier = Modifier, 43 measureFromContainer: Boolean = false, 44 ) { 45 val isShowing by viewModel.isShowing.collectAsStateWithLifecycle() 46 val mirrorAlpha by 47 animateFloatAsState( 48 targetValue = if (isShowing) 1f else 0f, 49 label = "alphaAnimationBrightnessMirrorShowing", 50 ) 51 val mirrorOffsetAndSize by viewModel.locationAndSize.collectAsStateWithLifecycle() 52 val yOffset = 53 if (measureFromContainer) { 54 mirrorOffsetAndSize.yOffsetFromContainer 55 } else { 56 mirrorOffsetAndSize.yOffsetFromWindow 57 } 58 val offset = IntOffset(0, yOffset) 59 60 // Use unbounded=true as the full mirror (with paddings and background offset) may be larger 61 // than the space we have (but it will fit, because the brightness slider fits). 62 Box( 63 modifier = 64 modifier.fillMaxHeight().wrapContentWidth(unbounded = true).graphicsLayer { 65 alpha = mirrorAlpha 66 } 67 ) { 68 QuickSettingsTheme { 69 // The assumption for using this AndroidView is that there will be only one in view at 70 // a given time (which is a reasonable assumption). Because `QSSceneAdapter` (actually 71 // `BrightnessSliderController` only supports a single mirror). 72 // The benefit of doing it like this is that if the configuration changes or QSImpl is 73 // re-inflated, it's not relevant to the composable, as we'll always get a new one. 74 AndroidView( 75 modifier = 76 Modifier.align(Alignment.TopCenter) 77 .offset { offset } 78 .width { mirrorOffsetAndSize.width } 79 .height { mirrorOffsetAndSize.height }, 80 factory = { context -> 81 val (view, controller) = 82 BrightnessMirrorInflater.inflate(context, viewModel.sliderControllerFactory) 83 viewModel.setToggleSlider(controller) 84 view 85 }, 86 update = { qsSceneAdapter.setBrightnessMirrorController(viewModel) }, 87 onRelease = { qsSceneAdapter.setBrightnessMirrorController(null) } 88 ) 89 } 90 } 91 } 92