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

Commit 0a8961a7 authored by Coco Duan's avatar Coco Duan Committed by Android (Google) Code Review
Browse files

Merge changes from topic "hub-edit-mode-display-cutout-fix" into main

* changes:
  Fix toolbar overlapping with display cutout on hub in edit mode
  Fix hub in edit mode overlapping with display cutout
parents a4fc9ffb 7de33898
Loading
Loading
Loading
Loading
+160 −54
Original line number Diff line number Diff line
@@ -95,7 +95,6 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButtonColors
@@ -202,6 +201,7 @@ import com.android.systemui.communal.ui.viewmodel.ResizeInfo
import com.android.systemui.communal.ui.viewmodel.ResizeableItemFrameViewModel
import com.android.systemui.communal.util.DensityUtils.Companion.adjustedDp
import com.android.systemui.communal.util.ResizeUtils.resizeOngoingItems
import com.android.systemui.communal.util.WindowSizeUtils
import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.lifecycle.rememberViewModel
@@ -765,24 +765,62 @@ fun calculateWidgetSize(
    }
}

/**
 * Calculates the padding needed to center widgets within the window. It dynamically adjusts for
 * orientation and window insets.
 */
@Composable
private fun horizontalPaddingWithInsets(padding: Dp): Dp {
private fun responsiveGridPaddingsWithInsets(
    horizontalPadding: Dp = 0.dp,
    verticalPadding: Dp = 0.dp,
    isEditMode: Boolean = false,
): PaddingValues {
    val orientation = LocalConfiguration.current.orientation
    val displayCutoutPaddings = WindowInsets.displayCutout.asPaddingValues()
    val horizontalDisplayCutoutPadding =
        remember(orientation, displayCutoutPaddings) {
    val layoutDirection = LocalLayoutDirection.current

    return remember(
        orientation,
        displayCutoutPaddings,
        isEditMode,
        horizontalPadding,
        verticalPadding,
    ) {
        if (isEditMode) {
            PaddingValues(
                horizontal =
                    horizontalPadding +
                        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                            // In edit mode activity, display cutout location changes with
                            // orientation.
                            maxOf(
                                displayCutoutPaddings.calculateLeftPadding(layoutDirection),
                                displayCutoutPaddings.calculateRightPadding(layoutDirection),
                            )
                        } else {
                            0.dp
                        },
                vertical = verticalPadding,
            )
        } else {
            PaddingValues(
                horizontal =
                    horizontalPadding +
                        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                            maxOf(
                                // Top in portrait becomes startPadding (or endPadding) in landscape
                                displayCutoutPaddings.calculateTopPadding(),
                    // Bottom in portrait becomes endPadding (or startPadding) in landscape
                                // Bottom in portrait becomes endPadding (or startPadding) in
                                // landscape
                                displayCutoutPaddings.calculateBottomPadding(),
                            )
                        } else {
                            0.dp
                        },
                vertical = verticalPadding,
            )
        }
    }
    return padding + horizontalDisplayCutoutPadding
}

@Composable
@@ -866,6 +904,7 @@ private fun BoxScope.CommunalHubLazyGrid(
    var list = communalContent
    var dragDropState: GridDragDropState? = null
    var arrangementSpacing = Dimensions.ItemSpacing
    val windowSize = WindowSizeUtils.getWindowSizeCategory(LocalContext.current)
    if (viewModel.isEditMode && viewModel is CommunalEditModeViewModel) {
        list = contentListState.list
        // for drag & drop operations within the communal hub grid
@@ -942,7 +981,10 @@ private fun BoxScope.CommunalHubLazyGrid(
            val size = SizeF(dpSize.width.value, dpSize.height.value)
            val selected = item.key == selectedKey.value
            val isResizable =
                if (item is CommunalContentModel.WidgetContent.Widget) {
                if (
                    item is CommunalContentModel.WidgetContent.Widget &&
                        windowSize != WindowSizeUtils.WindowSizeCategory.MOBILE_LANDSCAPE
                ) {
                    item.providerInfo.resizeMode and AppWidgetProviderInfo.RESIZE_VERTICAL != 0
                } else {
                    false
@@ -955,6 +997,16 @@ private fun BoxScope.CommunalHubLazyGrid(
                ) {
                    ResizeableItemFrameViewModel()
                }
            val itemAlpha =
                if (communalResponsiveGrid()) {
                    val percentVisible by
                        remember(gridState, index) {
                            derivedStateOf { calculatePercentVisible(gridState, index) }
                        }
                    animateFloatAsState(percentVisible)
                } else {
                    null
                }
            if (viewModel.isEditMode && dragDropState != null) {
                val isItemDragging = dragDropState.draggingItemKey == item.key
                val outlineAlpha by
@@ -1005,7 +1057,13 @@ private fun BoxScope.CommunalHubLazyGrid(
                        key = item.key,
                    ) { isDragging ->
                        CommunalContent(
                            modifier = Modifier.requiredSize(dpSize),
                            modifier =
                                Modifier.requiredSize(dpSize).thenIf(
                                    item !is CommunalContentModel.WidgetPlaceholder &&
                                        !isItemDragging
                                ) {
                                    Modifier.graphicsLayer { alpha = itemAlpha?.value ?: 1f }
                                },
                            model = item,
                            viewModel = viewModel,
                            size = size,
@@ -1020,17 +1078,6 @@ private fun BoxScope.CommunalHubLazyGrid(
                    }
                }
            } else {
                val itemAlpha =
                    if (communalResponsiveGrid()) {
                        val percentVisible by
                            remember(gridState, index) {
                                derivedStateOf { calculatePercentVisible(gridState, index) }
                            }
                        animateFloatAsState(percentVisible)
                    } else {
                        null
                    }

                CommunalContent(
                    model = item,
                    viewModel = viewModel,
@@ -1126,7 +1173,6 @@ private fun EmptyStateCta(contentPadding: PaddingValues, viewModel: BaseCommunal
 * 2) remove a widget from the grid and
 * 3) exit the edit mode.
 */
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
private fun Toolbar(
    removeEnabled: Boolean,
@@ -1145,16 +1191,10 @@ private fun Toolbar(
            targetValue = if (removeEnabled) 1f else 0.5f,
            label = "RemoveButtonAlphaAnimation",
        )

    val toolbarPadding = toolbarPadding()
    Box(
        modifier =
            Modifier.fillMaxWidth()
                .padding(
                    top = Dimensions.ToolbarPaddingTop,
                    start = Dimensions.ToolbarPaddingHorizontal,
                    end = Dimensions.ToolbarPaddingHorizontal,
                )
                .onSizeChanged { setToolbarSize(it) }
            Modifier.fillMaxWidth().padding(toolbarPadding).onSizeChanged { setToolbarSize(it) }
    ) {
        val addWidgetText = stringResource(R.string.hub_mode_add_widget_button_text)

@@ -1350,7 +1390,7 @@ fun HighlightedItem(modifier: Modifier = Modifier, alpha: Float = 1.0f) {
            // resize grid items to account for the border.
            modifier.drawBehind {
                // 8dp of padding between the widget and the highlight on every side.
                val padding = 8.adjustedDp.toPx()
                val padding = Dimensions.WidgetOutlinePadding.toPx()
                drawRoundRect(
                    brush,
                    alpha = alpha,
@@ -1891,13 +1931,11 @@ private fun nonScalableTextSize(sizeInDp: Dp) = with(LocalDensity.current) { siz
private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): PaddingValues {
    if (!isEditMode || toolbarSize == null) {
        return if (communalResponsiveGrid()) {
            val horizontalPaddings: Dp =
            if (isCompactWindow()) {
                    horizontalPaddingWithInsets(Dimensions.ItemSpacingCompact)
                responsiveGridPaddingsWithInsets(Dimensions.ItemSpacingCompact)
            } else {
                    Dimensions.ItemSpacing
                PaddingValues(horizontal = Dimensions.ItemSpacing)
            }
            PaddingValues(start = horizontalPaddings, end = horizontalPaddings)
        } else {
            PaddingValues(
                start = Dimensions.ItemSpacing,
@@ -1910,16 +1948,31 @@ private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): Padd
    val density = LocalDensity.current
    val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
    val screenHeight = with(density) { windowMetrics.bounds.height().toDp() }
    val toolbarHeight = with(density) { Dimensions.ToolbarPaddingTop + toolbarSize.height.toDp() }
    val toolbarHeight = with(density) { toolbarSize.height.toDp() }
    return if (communalResponsiveGrid()) {
        PaddingValues(
            start = Dimensions.ToolbarPaddingHorizontal,
            end = Dimensions.ToolbarPaddingHorizontal,
            top = hubDimensions.GridTopSpacing,
        // In edit mode, grid spans full screen so min top padding of the grid should include space
        // taken by toolbar.
        val toolbarPadding = toolbarPadding()
        // Add extra padding to render the widget outline which draws behind the selected widget.
        val topPadding =
            toolbarPadding.calculateTopPadding() +
                toolbarHeight +
                toolbarPadding.calculateBottomPadding() +
                Dimensions.WidgetOutlinePadding
        responsiveGridPaddingsWithInsets(
            horizontalPadding =
                if (isCompactWindow()) {
                    Dimensions.ItemSpacingCompact + Dimensions.WidgetOutlinePadding
                } else {
                    Dimensions.ItemSpacing
                },
            verticalPadding = topPadding,
            isEditMode = true,
        )
    } else {
        val toolbarHeightWithTopPadding = toolbarHeight + Dimensions.ToolbarPaddingTop
        val verticalPadding =
            ((screenHeight - toolbarHeight - hubDimensions.GridHeight +
            ((screenHeight - toolbarHeightWithTopPadding - hubDimensions.GridHeight +
                    hubDimensions.GridTopSpacing) / 2)
                .coerceAtLeast(Dimensions.Spacing)
        PaddingValues(
@@ -1949,6 +2002,33 @@ private fun CommunalContentSize.FixedSize.dp(): Dp {
    }
}

@Composable
private fun toolbarPadding(): PaddingValues {
    if (!communalResponsiveGrid()) {
        return PaddingValues(
            top = Dimensions.ToolbarPaddingTop,
            start = Dimensions.ToolbarPaddingHorizontal,
            end = Dimensions.ToolbarPaddingHorizontal,
        )
    }
    val displayCutoutPaddings = WindowInsets.displayCutout.asPaddingValues()
    val horizontalPadding = hubDimensions.toolbarHorizontalPadding
    val bottomPadding = hubDimensions.toolbarBottomPadding

    return remember(displayCutoutPaddings, horizontalPadding, bottomPadding) {
        // Depending on camera location, there can be no cutout paddings, set a min value
        val topPadding =
            displayCutoutPaddings.calculateTopPadding().coerceAtLeast(Dimensions.ToolbarPaddingTop)

        PaddingValues(
            start = horizontalPadding,
            top = topPadding,
            end = horizontalPadding,
            bottom = bottomPadding,
        )
    }
}

private fun firstIndexAtOffset(gridState: LazyGridState, offset: Offset): Int? =
    gridState.layoutInfo.visibleItemsInfo.firstItemAtOffset(offset)?.index

@@ -1978,6 +2058,32 @@ class Dimensions(val context: Context, val config: Configuration) {
    val GridHeight: Dp
        get() = CardHeightFull + GridTopSpacing

    /** Responsive grid toolbar bottom padding. */
    val toolbarBottomPadding: Dp
        get() {
            val windowSizeCategory = WindowSizeUtils.getWindowSizeCategory(context)
            return if (windowSizeCategory == WindowSizeUtils.WindowSizeCategory.MOBILE_LANDSCAPE) {
                6.adjustedDp
            } else {
                0.adjustedDp
            }
        }

    /** Responsive grid toolbar horizontal padding. */
    val toolbarHorizontalPadding: Dp
        get() {
            val windowSizeCategory = WindowSizeUtils.getWindowSizeCategory(context)
            return if (windowSizeCategory == WindowSizeUtils.WindowSizeCategory.TABLET) {
                if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    18.adjustedDp
                } else {
                    12.adjustedDp
                }
            } else {
                9.adjustedDp
            }
        }

    companion object {
        val CardHeightFull
            get() = 530.adjustedDp
@@ -1997,15 +2103,15 @@ class Dimensions(val context: Context, val config: Configuration) {
        val CardWidth
            get() = 360.adjustedDp

        val CardOutlineWidth
            get() = 3.adjustedDp
        val WidgetOutlinePadding
            get() = 8.adjustedDp

        val Spacing
            get() = ItemSpacing / 2

        // The sizing/padding of the toolbar in glanceable hub edit mode
        val ToolbarPaddingTop
            get() = 27.adjustedDp
            get() = if (communalResponsiveGrid()) 12.adjustedDp else 27.adjustedDp

        val ToolbarPaddingHorizontal
            get() = ItemSpacing