Loading packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt +48 −5 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import androidx.compose.ui.input.pointer.PointerEventPass import androidx.compose.ui.input.pointer.PointerInputChange import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.approachLayout import androidx.compose.ui.layout.layout import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInRoot Loading Loading @@ -250,10 +251,23 @@ constructor( private fun Content() { PlatformTheme(isDarkTheme = true) { ProvideShortcutHelperIndication(interactionsConfig = interactionsConfig()) { if (viewModel.isQsVisibleAndAnyShadeExpanded) { // TODO(b/389985793): Make sure that there is no coroutine work or recompositions // happening when alwaysCompose is true but isQsVisibleAndAnyShadeExpanded is false. if (alwaysCompose || viewModel.isQsVisibleAndAnyShadeExpanded) { Box( modifier = Modifier.graphicsLayer { alpha = viewModel.viewAlpha } Modifier.thenIf(alwaysCompose) { Modifier.layout { measurable, constraints -> measurable.measure(constraints).run { layout(width, height) { if (viewModel.isQsVisibleAndAnyShadeExpanded) { place(0, 0) } } } } } .graphicsLayer { alpha = viewModel.viewAlpha } .thenIf(notificationScrimClippingParams.isEnabled) { Modifier.notificationScrimClip { notificationScrimClippingParams.params Loading Loading @@ -331,12 +345,12 @@ constructor( } SceneTransitionLayout(state = sceneState, modifier = Modifier.fillMaxSize()) { scene(QuickSettings) { scene(QuickSettings, alwaysCompose = alwaysCompose) { LaunchedEffect(Unit) { viewModel.onQSOpen() } Element(QuickSettings.rootElementKey, Modifier) { QuickSettingsElement() } } scene(QuickQuickSettings) { scene(QuickQuickSettings, alwaysCompose = alwaysCompose) { LaunchedEffect(Unit) { viewModel.onQQSOpen() } // Cannot pass the element modifier in because the top element has a `testTag` // and this would overwrite it. Loading Loading @@ -626,7 +640,20 @@ constructor( ) { val Tiles = @Composable { QuickQuickSettings(viewModel = viewModel.quickQuickSettingsViewModel) QuickQuickSettings( viewModel = viewModel.quickQuickSettingsViewModel, listening = { /* * When always compose is false, this will always be true, and we'll be * listening whenever this is composed. * When always compose is true, we listen if we are visible and not * fully expanded */ !alwaysCompose || (viewModel.isQsVisibleAndAnyShadeExpanded && viewModel.expansionState.progress < 1f) }, ) } val Media = @Composable { Loading Loading @@ -726,6 +753,18 @@ constructor( TileGrid( viewModel = containerViewModel.tileGridViewModel, modifier = Modifier.fillMaxWidth(), listening = { /* * When always compose is false, this will always be true, * and we'll be listening whenever this is composed. * When always compose is true, we look a the second * condition and we'll listen if QS is visible AND we are * not fully collapsed. */ !alwaysCompose || (viewModel.isQsVisibleAndAnyShadeExpanded && viewModel.expansionState.progress > 0f) }, ) } } Loading Loading @@ -830,6 +869,7 @@ constructor( println("qqsPositionOnScreen", rect) } println("QQS visible", qqsVisible.value) println("Always composed", alwaysCompose) if (::viewModel.isInitialized) { printSection("View Model") { viewModel.dump(this@run, args) } } Loading Loading @@ -1177,3 +1217,6 @@ private fun interactionsConfig() = // we are OK using this as our content is clipped and all corner radius are larger than this surfaceCornerRadius = 28.dp, ) private inline val alwaysCompose get() = Flags.alwaysComposeQsUiFragment() packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt +11 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,17 @@ import com.android.systemui.qs.pipeline.shared.TileSpec /** A layout of tiles, indicating how they should be composed when showing in QS or in edit mode. */ interface GridLayout { @Composable fun ContentScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) /** * [listening] can be used to compose the grid but limit when tiles should be listening. It * should be a function tracking a snapshot state. */ @Composable fun ContentScope.TileGrid( tiles: List<TileViewModel>, modifier: Modifier, listening: () -> Boolean, ) @Composable fun EditTileGrid( Loading packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt +6 −8 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.CornerSize import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.runtime.snapshotFlow Loading Loading @@ -65,17 +64,16 @@ constructor( @PaginatedBaseLayoutType private val delegateGridLayout: PaginatableGridLayout, ) : GridLayout by delegateGridLayout { @Composable override fun ContentScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) { override fun ContentScope.TileGrid( tiles: List<TileViewModel>, modifier: Modifier, listening: () -> Boolean, ) { val viewModel = rememberViewModel(traceName = "PaginatedGridLayout-TileGrid") { viewModelFactory.create() } DisposableEffect(tiles) { val token = Any() tiles.forEach { it.startListening(token) } onDispose { tiles.forEach { it.stopListening(token) } } } val columns = viewModel.columns val rows = integerResource(R.integer.quick_settings_paginated_grid_num_rows) Loading Loading @@ -122,7 +120,7 @@ constructor( ) { val page = pages[it] with(delegateGridLayout) { TileGrid(tiles = page, modifier = Modifier) } with(delegateGridLayout) { TileGrid(tiles = page, modifier = Modifier, listening) } } FooterBar( buildNumberViewModelFactory = viewModel.buildNumberViewModelFactory, Loading packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt +3 −6 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.qs.panels.ui.compose import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember Loading @@ -41,6 +40,7 @@ import com.android.systemui.res.R fun ContentScope.QuickQuickSettings( viewModel: QuickQuickSettingsViewModel, modifier: Modifier = Modifier, listening: () -> Boolean, ) { val sizedTiles = viewModel.tileViewModels Loading @@ -51,11 +51,6 @@ fun ContentScope.QuickQuickSettings( val spans by remember(sizedTiles) { derivedStateOf { sizedTiles.fastMap { it.width } } } DisposableEffect(tiles) { val token = Any() tiles.forEach { it.startListening(token) } onDispose { tiles.forEach { it.stopListening(token) } } } val columns = viewModel.columns Box(modifier = modifier) { GridAnchor() Loading Loading @@ -91,4 +86,6 @@ fun ContentScope.QuickQuickSettings( } } } TileListener(tiles, listening) } packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt +6 −2 Original line number Diff line number Diff line Loading @@ -22,9 +22,13 @@ import com.android.compose.animation.scene.ContentScope import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel @Composable fun ContentScope.TileGrid(viewModel: TileGridViewModel, modifier: Modifier = Modifier) { fun ContentScope.TileGrid( viewModel: TileGridViewModel, modifier: Modifier = Modifier, listening: () -> Boolean = { true }, ) { val gridLayout = viewModel.gridLayout val tiles = viewModel.tileViewModels with(gridLayout) { TileGrid(tiles, modifier) } with(gridLayout) { TileGrid(tiles, modifier, listening) } } Loading
packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt +48 −5 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import androidx.compose.ui.input.pointer.PointerEventPass import androidx.compose.ui.input.pointer.PointerInputChange import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.approachLayout import androidx.compose.ui.layout.layout import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInRoot Loading Loading @@ -250,10 +251,23 @@ constructor( private fun Content() { PlatformTheme(isDarkTheme = true) { ProvideShortcutHelperIndication(interactionsConfig = interactionsConfig()) { if (viewModel.isQsVisibleAndAnyShadeExpanded) { // TODO(b/389985793): Make sure that there is no coroutine work or recompositions // happening when alwaysCompose is true but isQsVisibleAndAnyShadeExpanded is false. if (alwaysCompose || viewModel.isQsVisibleAndAnyShadeExpanded) { Box( modifier = Modifier.graphicsLayer { alpha = viewModel.viewAlpha } Modifier.thenIf(alwaysCompose) { Modifier.layout { measurable, constraints -> measurable.measure(constraints).run { layout(width, height) { if (viewModel.isQsVisibleAndAnyShadeExpanded) { place(0, 0) } } } } } .graphicsLayer { alpha = viewModel.viewAlpha } .thenIf(notificationScrimClippingParams.isEnabled) { Modifier.notificationScrimClip { notificationScrimClippingParams.params Loading Loading @@ -331,12 +345,12 @@ constructor( } SceneTransitionLayout(state = sceneState, modifier = Modifier.fillMaxSize()) { scene(QuickSettings) { scene(QuickSettings, alwaysCompose = alwaysCompose) { LaunchedEffect(Unit) { viewModel.onQSOpen() } Element(QuickSettings.rootElementKey, Modifier) { QuickSettingsElement() } } scene(QuickQuickSettings) { scene(QuickQuickSettings, alwaysCompose = alwaysCompose) { LaunchedEffect(Unit) { viewModel.onQQSOpen() } // Cannot pass the element modifier in because the top element has a `testTag` // and this would overwrite it. Loading Loading @@ -626,7 +640,20 @@ constructor( ) { val Tiles = @Composable { QuickQuickSettings(viewModel = viewModel.quickQuickSettingsViewModel) QuickQuickSettings( viewModel = viewModel.quickQuickSettingsViewModel, listening = { /* * When always compose is false, this will always be true, and we'll be * listening whenever this is composed. * When always compose is true, we listen if we are visible and not * fully expanded */ !alwaysCompose || (viewModel.isQsVisibleAndAnyShadeExpanded && viewModel.expansionState.progress < 1f) }, ) } val Media = @Composable { Loading Loading @@ -726,6 +753,18 @@ constructor( TileGrid( viewModel = containerViewModel.tileGridViewModel, modifier = Modifier.fillMaxWidth(), listening = { /* * When always compose is false, this will always be true, * and we'll be listening whenever this is composed. * When always compose is true, we look a the second * condition and we'll listen if QS is visible AND we are * not fully collapsed. */ !alwaysCompose || (viewModel.isQsVisibleAndAnyShadeExpanded && viewModel.expansionState.progress > 0f) }, ) } } Loading Loading @@ -830,6 +869,7 @@ constructor( println("qqsPositionOnScreen", rect) } println("QQS visible", qqsVisible.value) println("Always composed", alwaysCompose) if (::viewModel.isInitialized) { printSection("View Model") { viewModel.dump(this@run, args) } } Loading Loading @@ -1177,3 +1217,6 @@ private fun interactionsConfig() = // we are OK using this as our content is clipped and all corner radius are larger than this surfaceCornerRadius = 28.dp, ) private inline val alwaysCompose get() = Flags.alwaysComposeQsUiFragment()
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt +11 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,17 @@ import com.android.systemui.qs.pipeline.shared.TileSpec /** A layout of tiles, indicating how they should be composed when showing in QS or in edit mode. */ interface GridLayout { @Composable fun ContentScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) /** * [listening] can be used to compose the grid but limit when tiles should be listening. It * should be a function tracking a snapshot state. */ @Composable fun ContentScope.TileGrid( tiles: List<TileViewModel>, modifier: Modifier, listening: () -> Boolean, ) @Composable fun EditTileGrid( Loading
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt +6 −8 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.CornerSize import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.runtime.snapshotFlow Loading Loading @@ -65,17 +64,16 @@ constructor( @PaginatedBaseLayoutType private val delegateGridLayout: PaginatableGridLayout, ) : GridLayout by delegateGridLayout { @Composable override fun ContentScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) { override fun ContentScope.TileGrid( tiles: List<TileViewModel>, modifier: Modifier, listening: () -> Boolean, ) { val viewModel = rememberViewModel(traceName = "PaginatedGridLayout-TileGrid") { viewModelFactory.create() } DisposableEffect(tiles) { val token = Any() tiles.forEach { it.startListening(token) } onDispose { tiles.forEach { it.stopListening(token) } } } val columns = viewModel.columns val rows = integerResource(R.integer.quick_settings_paginated_grid_num_rows) Loading Loading @@ -122,7 +120,7 @@ constructor( ) { val page = pages[it] with(delegateGridLayout) { TileGrid(tiles = page, modifier = Modifier) } with(delegateGridLayout) { TileGrid(tiles = page, modifier = Modifier, listening) } } FooterBar( buildNumberViewModelFactory = viewModel.buildNumberViewModelFactory, Loading
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt +3 −6 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.qs.panels.ui.compose import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember Loading @@ -41,6 +40,7 @@ import com.android.systemui.res.R fun ContentScope.QuickQuickSettings( viewModel: QuickQuickSettingsViewModel, modifier: Modifier = Modifier, listening: () -> Boolean, ) { val sizedTiles = viewModel.tileViewModels Loading @@ -51,11 +51,6 @@ fun ContentScope.QuickQuickSettings( val spans by remember(sizedTiles) { derivedStateOf { sizedTiles.fastMap { it.width } } } DisposableEffect(tiles) { val token = Any() tiles.forEach { it.startListening(token) } onDispose { tiles.forEach { it.stopListening(token) } } } val columns = viewModel.columns Box(modifier = modifier) { GridAnchor() Loading Loading @@ -91,4 +86,6 @@ fun ContentScope.QuickQuickSettings( } } } TileListener(tiles, listening) }
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt +6 −2 Original line number Diff line number Diff line Loading @@ -22,9 +22,13 @@ import com.android.compose.animation.scene.ContentScope import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel @Composable fun ContentScope.TileGrid(viewModel: TileGridViewModel, modifier: Modifier = Modifier) { fun ContentScope.TileGrid( viewModel: TileGridViewModel, modifier: Modifier = Modifier, listening: () -> Boolean = { true }, ) { val gridLayout = viewModel.gridLayout val tiles = viewModel.tileViewModels with(gridLayout) { TileGrid(tiles, modifier) } with(gridLayout) { TileGrid(tiles, modifier, listening) } }