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

Commit fa2e562a authored by Bryce Lee's avatar Bryce Lee
Browse files

Make Glanceable Hub selection and drag & drop RTL compatible.

This changelist adjust Glanceable Hub logic to treat offset from the
layout start location on selection. This changelist also adjust drag
logic to treat offset in the layout direction.

Bug: 320786721
Test: manual - verified selection and drag and drop worked in RTL
Flag: com.android.systemui.scene_container
Change-Id: Ibbf68aa96973c620b10e332cd6a85ccfec356de1
parent c84c71b5
Loading
Loading
Loading
Loading
+33 −5
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -127,6 +128,7 @@ import androidx.compose.ui.layout.positionInWindow
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.platform.testTag
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
@@ -209,6 +211,11 @@ fun CommunalHub(

    ObserveScrollEffect(gridState, viewModel)

    val context = LocalContext.current
    val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
    val screenWidth = windowMetrics.bounds.width()
    val layoutDirection = LocalLayoutDirection.current

    if (!viewModel.isEditMode) {
        ScrollOnUpdatedLiveContentEffect(communalContent, gridState)
    }
@@ -230,7 +237,7 @@ fun CommunalHub(
                .testTag(COMMUNAL_HUB_TEST_TAG)
                .fillMaxSize()
                .nestedScroll(nestedScrollConnection)
                .pointerInput(gridState, contentOffset, contentListState) {
                .pointerInput(layoutDirection, gridState, contentOffset, contentListState) {
                    awaitPointerEventScope {
                        while (true) {
                            var event = awaitFirstDown(requireUnconsumed = false)
@@ -261,7 +268,13 @@ fun CommunalHub(
                    // If not in edit mode, don't allow selecting items.
                    if (!viewModel.isEditMode) return@pointerInput
                    observeTaps { offset ->
                        val adjustedOffset = offset - contentOffset
                        // if RTL, flip offset direction from Left side to Right
                        val adjustedOffset =
                            Offset(
                                if (layoutDirection == LayoutDirection.Rtl) screenWidth - offset.x
                                else offset.x,
                                offset.y
                            ) - contentOffset
                        val index = firstIndexAtOffset(gridState, adjustedOffset)
                        val key = index?.let { keyAtIndexIfEditable(contentListState.list, index) }
                        viewModel.setSelectedKey(key)
@@ -279,7 +292,12 @@ fun CommunalHub(
                            // offset.
                            val adjustedOffset =
                                gridCoordinates?.let {
                                    offset - it.positionInWindow() - contentOffset
                                    Offset(
                                        if (layoutDirection == LayoutDirection.Rtl)
                                            screenWidth - offset.x
                                        else offset.x,
                                        offset.y
                                    ) - it.positionInWindow() - contentOffset
                                }
                            val index = adjustedOffset?.let { firstIndexAtOffset(gridState, it) }
                            val key = index?.let { keyAtIndexIfEditable(communalContent, index) }
@@ -330,6 +348,7 @@ fun CommunalHub(
                            viewModel = viewModel,
                            contentPadding = contentPadding,
                            contentOffset = contentOffset,
                            screenWidth = screenWidth,
                            setGridCoordinates = { gridCoordinates = it },
                            updateDragPositionForRemove = { offset ->
                                isPointerWithinEnabledRemoveButton(
@@ -535,6 +554,7 @@ private fun BoxScope.CommunalHubLazyGrid(
    viewModel: BaseCommunalViewModel,
    contentPadding: PaddingValues,
    selectedKey: State<String?>,
    screenWidth: Int,
    contentOffset: Offset,
    gridState: LazyGridState,
    contentListState: ContentListState,
@@ -557,7 +577,15 @@ private fun BoxScope.CommunalHubLazyGrid(
                updateDragPositionForRemove = updateDragPositionForRemove
            )
        gridModifier =
            gridModifier.fillMaxSize().dragContainer(dragDropState, contentOffset, viewModel)
            gridModifier
                .fillMaxSize()
                .dragContainer(
                    dragDropState,
                    LocalLayoutDirection.current,
                    screenWidth,
                    contentOffset,
                    viewModel
                )
        // for widgets dropped from other activities
        val dragAndDropTargetState =
            rememberDragAndDropTargetState(
@@ -1371,7 +1399,7 @@ private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): Padd
private fun beforeContentPadding(paddingValues: PaddingValues): ContentPaddingInPx {
    return with(LocalDensity.current) {
        ContentPaddingInPx(
            start = paddingValues.calculateLeftPadding(LayoutDirection.Ltr).toPx(),
            start = paddingValues.calculateStartPadding(LocalLayoutDirection.current).toPx(),
            top = paddingValues.calculateTopPadding().toPx()
        )
    }
+36 −8
Original line number Diff line number Diff line
@@ -37,7 +37,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.toOffset
import androidx.compose.ui.unit.toSize
import com.android.systemui.communal.ui.compose.extensions.firstItemAtOffset
@@ -47,6 +49,9 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch

private fun Float.directional(origin: LayoutDirection, current: LayoutDirection): Float =
    if (origin == current) this else -this

@Composable
fun rememberGridDragDropState(
    gridState: LazyGridState,
@@ -113,14 +118,24 @@ internal constructor(
     *
     * @return {@code True} if dragging a grid item, {@code False} otherwise.
     */
    internal fun onDragStart(offset: Offset, contentOffset: Offset): Boolean {
    internal fun onDragStart(
        offset: Offset,
        screenWidth: Int,
        layoutDirection: LayoutDirection,
        contentOffset: Offset
    ): Boolean {
        val normalizedOffset =
            Offset(
                if (layoutDirection == LayoutDirection.Ltr) offset.x else screenWidth - offset.x,
                offset.y
            )
        state.layoutInfo.visibleItemsInfo
            .filter { item -> contentListState.isItemEditable(item.index) }
            // grid item offset is based off grid content container so we need to deduct
            // before content padding from the initial pointer position
            .firstItemAtOffset(offset - contentOffset)
            .firstItemAtOffset(normalizedOffset - contentOffset)
            ?.apply {
                dragStartPointerOffset = offset - this.offset.toOffset()
                dragStartPointerOffset = normalizedOffset - this.offset.toOffset()
                draggingItemIndex = index
                draggingItemInitialOffset = this.offset.toOffset()
                return true
@@ -145,8 +160,10 @@ internal constructor(
        dragStartPointerOffset = Offset.Zero
    }

    internal fun onDrag(offset: Offset) {
        draggingItemDraggedDelta += offset
    internal fun onDrag(offset: Offset, layoutDirection: LayoutDirection) {
        // Adjust offset to match the layout direction
        draggingItemDraggedDelta +=
            Offset(offset.x.directional(LayoutDirection.Ltr, layoutDirection), offset.y)

        val draggingItem = draggingItemLayoutInfo ?: return
        val startOffset = draggingItem.offset.toOffset() + draggingItemOffset
@@ -213,6 +230,8 @@ internal constructor(

fun Modifier.dragContainer(
    dragDropState: GridDragDropState,
    layoutDirection: LayoutDirection,
    screenWidth: Int,
    contentOffset: Offset,
    viewModel: BaseCommunalViewModel,
): Modifier {
@@ -221,10 +240,17 @@ fun Modifier.dragContainer(
            detectDragGesturesAfterLongPress(
                onDrag = { change, offset ->
                    change.consume()
                    dragDropState.onDrag(offset = offset)
                    dragDropState.onDrag(offset, layoutDirection)
                },
                onDragStart = { offset ->
                    if (dragDropState.onDragStart(offset, contentOffset)) {
                    if (
                        dragDropState.onDragStart(
                            offset,
                            screenWidth,
                            layoutDirection,
                            contentOffset
                        )
                    ) {
                        viewModel.onReorderWidgetStart()
                    }
                },
@@ -262,10 +288,12 @@ fun LazyGridItemScope.DraggableItem(
            targetValue = if (dragDropState.isDraggingToRemove) 0.5f else 1f,
            label = "DraggableItemAlpha"
        )
    val direction = LocalLayoutDirection.current
    val draggingModifier =
        if (dragging) {
            Modifier.graphicsLayer {
                translationX = dragDropState.draggingItemOffset.x
                translationX =
                    dragDropState.draggingItemOffset.x.directional(LayoutDirection.Ltr, direction)
                translationY = dragDropState.draggingItemOffset.y
                alpha = itemAlpha
            }