Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fc4c870 authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

[Flexiglass] Extract QS layout to use slots

This simplifies the portrait vs landscape layouts.

Test: manual, expand QS
Test: atest android.platform.test.scenario.sysui.quicksettings
Test: atest android.platform.test.scenario.sysui.media
Bug: 420960164
Flag: com.android.systemui.scene_container
Change-Id: I3228c6e28bd723fab35fc252f44fe36fa03e3231
parent b0884015
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.ui.composable

import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

@Composable
fun QuickSettingsPanelLayout(
    brightness: @Composable () -> Unit,
    tiles: @Composable () -> Unit,
    media: @Composable () -> Unit,
    mediaInRow: Boolean,
    modifier: Modifier = Modifier,
) {
    if (mediaInRow) {
        Column(
            verticalArrangement = spacedBy(QuickSettingsShade.Dimensions.Padding),
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = modifier,
        ) {
            brightness()
            Row(
                horizontalArrangement = spacedBy(QuickSettingsShade.Dimensions.Padding),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Box(modifier = Modifier.weight(1f)) { tiles() }
                Box(modifier = Modifier.weight(1f)) { media() }
            }
        }
    } else {
        Column(
            verticalArrangement = spacedBy(QuickSettingsShade.Dimensions.Padding),
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = modifier,
        ) {
            brightness()
            tiles()
            media()
        }
    }
}
+45 −56
Original line number Diff line number Diff line
@@ -47,8 +47,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLifecycleOwner
@@ -275,15 +273,9 @@ private fun ContentScope.QuickSettingsScene(
                            CollapsedShadeHeader(viewModel = headerViewModel, isSplitShade = false)
                    }
                    Spacer(modifier = Modifier.height(16.dp))
                    Column(
                        modifier =
                            Modifier.element(ElementKeys.QuickSettingsContent)
                                .padding(
                                    horizontal =
                                        dimensionResource(id = R.dimen.qs_horizontal_margin)
                                )
                                .sysuiResTag("quick_settings_panel")
                    ) {
                    QuickSettingsPanelLayout(
                        brightness =
                            @Composable {
                                BrightnessSliderContainer(
                                    viewModel.qsContainerViewModel.brightnessSliderViewModel,
                                    containerColors =
@@ -294,47 +286,44 @@ private fun ContentScope.QuickSettingsScene(
                                    modifier =
                                        Modifier.padding(
                                            vertical =
                                        dimensionResource(id = R.dimen.qs_brightness_margin_top)
                                                dimensionResource(
                                                    id = R.dimen.qs_brightness_margin_top
                                                )
                                        ),
                                )
                            },
                        tiles =
                            @Composable {
                                Box {
                                    GridAnchor()
                        // This view has its own horizontal padding
                        val content: @Composable () -> Unit = {
                            TileGrid(
                                viewModel.qsContainerViewModel.tileGridViewModel,
                                modifier = Modifier.layoutId(QSMediaMeasurePolicy.LayoutId.QS),
                            )

                                    TileGrid(viewModel.qsContainerViewModel.tileGridViewModel)
                                }
                            },
                        media =
                            @Composable {
                                MediaCarousel(
                                    isVisible = isMediaVisible,
                                    mediaHost = mediaHost,
                                    modifier =
                                        Modifier.fillMaxWidth()
                                        .layoutId(QSMediaMeasurePolicy.LayoutId.Media)
                                            .padding(
                                                horizontal =
                                                dimensionResource(id = R.dimen.qs_horizontal_margin)
                                                    dimensionResource(
                                                        id = R.dimen.qs_horizontal_margin
                                                    )
                                            ),
                                    carouselController = mediaCarouselController,
                                )
                        }
                        val landscapeQsMediaMeasurePolicy = remember {
                            QSMediaMeasurePolicy(
                                { viewModel.qsSceneAdapter.qsHeight },
                                { mediaOffset.roundToPx() },
                            },
                        mediaInRow = mediaInRow,
                        modifier =
                            Modifier.element(ElementKeys.QuickSettingsContent)
                                .padding(
                                    horizontal =
                                        dimensionResource(id = R.dimen.qs_horizontal_margin)
                                )
                        }
                        Column(modifier = Modifier.padding(horizontal = shadeHorizontalPadding)) {
                            if (mediaInRow) {
                                Layout(
                                    content = content,
                                    measurePolicy = landscapeQsMediaMeasurePolicy,
                                .sysuiResTag("quick_settings_panel"),
                    )
                            } else {
                                content()
                            }
                        }
                    }
                }
            }

+0 −1
Original line number Diff line number Diff line
@@ -78,7 +78,6 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
            underTest =
                QuickSettingsSceneContentViewModel(
                    shadeHeaderViewModelFactory = shadeHeaderViewModelFactory,
                    qsSceneAdapter = fakeQsSceneAdapter,
                    qsContainerViewModelFactory = kosmos.quickSettingsContainerViewModelFactory,
                    footerActionsViewModelFactory = footerActionsViewModelFactory,
                    footerActionsController = footerActionsController,
+0 −2
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneFamilies
@@ -53,7 +52,6 @@ class QuickSettingsSceneContentViewModel
@AssistedInject
constructor(
    val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
    val qsSceneAdapter: QSSceneAdapter,
    qsContainerViewModelFactory: QuickSettingsContainerViewModel.Factory,
    private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
    private val footerActionsController: FooterActionsController,
+0 −24
Original line number Diff line number Diff line
@@ -16,43 +16,19 @@

package com.android.systemui.qs.ui.viewmodel

import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
import com.android.systemui.qs.footerActionsController
import com.android.systemui.qs.footerActionsViewModelFactory
import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub

val Kosmos.quickSettingsSceneContentViewModel by Fixture {
    QuickSettingsSceneContentViewModel(
        shadeHeaderViewModelFactory = shadeHeaderViewModelFactory,
        qsSceneAdapter =
            FakeQSSceneAdapter({
                // The Quick Settings content installs this view as a child of FrameLayout so its
                // layout
                // params are required.
                val view = mock<View>()
                view.stub {
                    on { layoutParams } doReturn
                        FrameLayout.LayoutParams(
                            ViewGroup.MarginLayoutParams(
                                ViewGroup.LayoutParams.MATCH_PARENT,
                                ViewGroup.LayoutParams.MATCH_PARENT,
                            )
                        )
                }
                view
            }),
        qsContainerViewModelFactory = quickSettingsContainerViewModelFactory,
        footerActionsViewModelFactory = footerActionsViewModelFactory,
        footerActionsController = footerActionsController,