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

Commit 151c0f2b authored by Danny Burakov's avatar Danny Burakov Committed by Android (Google) Code Review
Browse files

Merge "[Dual Shade] Limit the shade panel width to half the screen width." into main

parents d84b3e5a 1b0c0b60
Loading
Loading
Loading
Loading
+34 −4
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

package com.android.systemui.shade.ui.composable

import android.annotation.SuppressLint
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
@@ -39,10 +41,13 @@ import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexContentPicker
@@ -77,7 +82,8 @@ fun ContentScope.OverlayShade(
        Scrim(showBackgroundColor = enableTransparency, onClicked = onScrimClicked)

        Box(
            modifier = Modifier.fillMaxSize().panelContainerPadding(isFullWidth),
            modifier =
                Modifier.fillMaxSize().panelContainerPadding(isFullWidth, alignmentOnWideScreens),
            contentAlignment = if (isFullWidth) Alignment.TopCenter else alignmentOnWideScreens,
        ) {
            Panel(
@@ -156,7 +162,7 @@ private fun Modifier.panelWidth(isFullWidthPanel: Boolean): Modifier {
    return if (isFullWidthPanel) {
        fillMaxWidth()
    } else {
        width(dimensionResource(id = R.dimen.shade_panel_width))
        width(dimensionResource(R.dimen.shade_panel_width))
    }
}

@@ -167,14 +173,38 @@ internal fun isFullWidthShade(): Boolean {
}

@Composable
private fun Modifier.panelContainerPadding(isFullWidthPanel: Boolean): Modifier {
@ReadOnlyComposable
@SuppressLint("ConfigurationScreenWidthHeight")
private fun getHalfScreenWidth(): Dp {
    return LocalConfiguration.current.screenWidthDp.dp / 2
}

@Composable
private fun Modifier.panelContainerPadding(
    isFullWidthPanel: Boolean,
    alignment: Alignment,
): Modifier {
    if (isFullWidthPanel) {
        return this
    }
    // On wide screens, the shade panel width is limited to half the screen width.
    val halfScreenWidth = getHalfScreenWidth()
    val horizontalPaddingDp = dimensionResource(R.dimen.shade_panel_margin_horizontal)

    val (startPadding, endPadding) =
        when (alignment) {
            Alignment.TopStart -> horizontalPaddingDp to halfScreenWidth
            Alignment.TopEnd -> halfScreenWidth to horizontalPaddingDp
            else -> horizontalPaddingDp to horizontalPaddingDp
        }
    val paddings = PaddingValues(start = startPadding, end = endPadding)
    val layoutDirection = LocalLayoutDirection.current
    return windowInsetsPadding(
        WindowInsets.safeContent.union(
            WindowInsets(left = horizontalPaddingDp, right = horizontalPaddingDp)
            WindowInsets(
                left = paddings.calculateLeftPadding(layoutDirection),
                right = paddings.calculateRightPadding(layoutDirection),
            )
        )
    )
}
+2 −2
Original line number Diff line number Diff line
@@ -240,8 +240,8 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
            val dimens by collectLastValue(underTest.configurationBasedDimensions)

            val horizontalPosition = checkNotNull(dimens).horizontalPosition
            assertIs<HorizontalPosition.FloatAtStart>(horizontalPosition)
            assertThat(horizontalPosition.width).isEqualTo(200)
            assertIs<HorizontalPosition.EdgeToMiddle>(horizontalPosition)
            assertThat(horizontalPosition.maxWidth).isEqualTo(200)
        }

    @Test
+15 −10
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import androidx.constraintlayout.widget.ConstraintSet.VERTICAL
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.HorizontalPosition
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.HorizontalPosition.EdgeToMiddle
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.HorizontalPosition.MiddleToEdge

/**
 * Container for the stack scroller, so that the bounds can be externally specified, such as from
@@ -66,7 +68,10 @@ class SharedNotificationContainer(context: Context, attrs: AttributeSet?) :
        constraintSet.clone(baseConstraintSet)

        val startConstraintId =
            if (horizontalPosition is HorizontalPosition.MiddleToEdge) {
            if (horizontalPosition is MiddleToEdge) R.id.nssl_guideline else PARENT_ID

        val endConstraintId =
            if (SceneContainerFlag.isEnabled && horizontalPosition is EdgeToMiddle) {
                R.id.nssl_guideline
            } else {
                PARENT_ID
@@ -76,9 +81,14 @@ class SharedNotificationContainer(context: Context, attrs: AttributeSet?) :
        constraintSet.apply {
            if (SceneContainerFlag.isEnabled) {
                when (horizontalPosition) {
                    is HorizontalPosition.FloatAtStart ->
                        constrainWidth(nsslId, horizontalPosition.width)
                    is HorizontalPosition.MiddleToEdge ->
                    is EdgeToMiddle -> {
                        setGuidelinePercent(R.id.nssl_guideline, horizontalPosition.ratio)
                        constrainMaxWidth(nsslId, horizontalPosition.maxWidth)
                        // Ensure START alignment in case the maxWidth is smaller than half the
                        // parent width.
                        constraintSet.setHorizontalBias(nsslId, 0f)
                    }
                    is MiddleToEdge ->
                        setGuidelinePercent(R.id.nssl_guideline, horizontalPosition.ratio)
                    else -> Unit
                }
@@ -89,12 +99,7 @@ class SharedNotificationContainer(context: Context, attrs: AttributeSet?) :
            // animations.
            setAlpha(nsslId, nsslAlpha)
            connect(nsslId, START, startConstraintId, START, marginStart)
            if (
                !SceneContainerFlag.isEnabled ||
                    horizontalPosition !is HorizontalPosition.FloatAtStart
            ) {
                connect(nsslId, END, PARENT_ID, END, marginEnd)
            }
            connect(nsslId, END, endConstraintId, END, marginEnd)
            connect(nsslId, BOTTOM, PARENT_ID, BOTTOM, marginBottom)
            connect(nsslId, TOP, PARENT_ID, TOP, marginTop)
        }
+11 −9
Original line number Diff line number Diff line
@@ -273,8 +273,10 @@ constructor(
                                Split -> HorizontalPosition.MiddleToEdge(ratio = 0.5f)
                                Dual ->
                                    if (isShadeLayoutWide) {
                                        HorizontalPosition.FloatAtStart(
                                            width = getDimensionPixelSize(R.dimen.shade_panel_width)
                                        HorizontalPosition.EdgeToMiddle(
                                            ratio = 0.5f,
                                            maxWidth =
                                                getDimensionPixelSize(R.dimen.shade_panel_width),
                                        )
                                    } else {
                                        HorizontalPosition.EdgeToEdge
@@ -284,7 +286,7 @@ constructor(
                        ConfigurationBasedDimensions(
                            horizontalPosition = horizontalPosition,
                            marginStart = if (shadeMode is Split) 0 else marginHorizontal,
                            marginEnd = marginHorizontal,
                            marginEnd = if (shadeMode is Dual) 0 else marginHorizontal,
                            marginBottom =
                                getDimensionPixelSize(R.dimen.notification_panel_margin_bottom),
                            // y position of the NSSL in the window needs to be 0 under scene
@@ -971,14 +973,14 @@ constructor(
        /** The container is using the full width of the screen (minus any margins). */
        data object EdgeToEdge : HorizontalPosition

        /** The container is laid out from the given [ratio] of the screen width to the end edge. */
        data class MiddleToEdge(val ratio: Float = 0.5f) : HorizontalPosition

        /**
         * The container has a fixed [width] and is aligned to the start of the screen. In this
         * layout, the end edge of the container is floating, i.e. unconstrained.
         * The container is laid out from the start edge to the given [ratio] of the screen width,
         * or to [maxWidth], whichever dimension is smaller.
         */
        data class FloatAtStart(val width: Int) : HorizontalPosition
        data class EdgeToMiddle(val ratio: Float = 0.5f, val maxWidth: Int) : HorizontalPosition

        /** The container is laid out from the given [ratio] of the screen width to the end edge. */
        data class MiddleToEdge(val ratio: Float = 0.5f) : HorizontalPosition
    }

    /**