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

Commit 7099f815 authored by Olivier St-Onge's avatar Olivier St-Onge
Browse files

Polish edit mode UI for BC25

Changes are:
 - Subtitles ("hold to move tile...")
 - A remove zone with animated visibility
 - Hides available tiles when dragging
 - Removes small tiles labels in the current tile list
 - Show all available tiles as small tiles with labels

Bug: 337021579
Flag: com.android.systemui.qs_ui_refactor
Test: manually with QSActivity
Test: DragAndDropStateTest
Change-Id: Ibb6359fc33f38d1b922aa5e984249805192c84c3
parent 77b2e9ab
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -82,6 +82,20 @@ class DragAndDropStateTest : SysuiTestCase() {
        TestEditTiles.forEach { assertThat(underTest.isMoving(it.tileSpec)).isFalse() }
    }

    @Test
    fun onMoveOutOfBounds_removeMovingTileFromCurrentList() {
        val movingTileSpec = TestEditTiles[0].tileSpec

        // Start the drag movement
        underTest.onStarted(movingTileSpec)

        // Move the tile outside of the list
        underTest.movedOutOfBounds()

        // Asserts the moving tile is not current
        assertThat(listState.tiles.first { it.tileSpec == movingTileSpec }.isCurrent).isFalse()
    }

    companion object {
        private fun createEditTile(tileSpec: String): EditTileViewModel {
            return EditTileViewModel(
+49 −0
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ class DragAndDropState(
    val sourceSpec: MutableState<TileSpec?>,
    private val listState: EditTileListState
) {
    val dragInProgress: Boolean
        get() = sourceSpec.value != null

    /** Returns index of the dragged tile if it's present in the list. Returns -1 if not. */
    fun currentPosition(): Int {
        return sourceSpec.value?.let { listState.indexOf(it) } ?: -1
@@ -65,6 +68,12 @@ class DragAndDropState(
        sourceSpec.value?.let { listState.move(it, targetSpec) }
    }

    fun movedOutOfBounds() {
        // Removing the tiles from the current tile grid if it moves out of bounds. This clears
        // the spacer and makes it apparent that dropping the tile at that point would remove it.
        sourceSpec.value?.let { listState.removeFromCurrent(it) }
    }

    fun onDrop() {
        sourceSpec.value = null
    }
@@ -111,6 +120,42 @@ fun Modifier.dragAndDropTile(
    )
}

/**
 * Registers a composable as a [DragAndDropTarget] to receive drop events. Use this outside the tile
 * grid to catch out of bounds drops.
 *
 * @param dragAndDropState The [DragAndDropState] using the tiles list
 * @param onDrop Action to be executed when a [TileSpec] is dropped on the composable
 */
@Composable
fun Modifier.dragAndDropRemoveZone(
    dragAndDropState: DragAndDropState,
    onDrop: (TileSpec) -> Unit,
): Modifier {
    val target =
        remember(dragAndDropState) {
            object : DragAndDropTarget {
                override fun onDrop(event: DragAndDropEvent): Boolean {
                    return dragAndDropState.sourceSpec.value?.let {
                        onDrop(it)
                        dragAndDropState.onDrop()
                        true
                    } ?: false
                }

                override fun onEntered(event: DragAndDropEvent) {
                    dragAndDropState.movedOutOfBounds()
                }
            }
        }
    return dragAndDropTarget(
        shouldStartDragAndDrop = { event ->
            event.mimeTypes().contains(QsDragAndDrop.TILESPEC_MIME_TYPE)
        },
        target = target,
    )
}

/**
 * Registers a tile list as a [DragAndDropTarget] to receive drop events. Use this on list
 * containers to catch drops outside of tiles.
@@ -128,6 +173,10 @@ fun Modifier.dragAndDropTileList(
    val target =
        remember(dragAndDropState) {
            object : DragAndDropTarget {
                override fun onEnded(event: DragAndDropEvent) {
                    dragAndDropState.onDrop()
                }

                override fun onDrop(event: DragAndDropEvent): Boolean {
                    return dragAndDropState.sourceSpec.value?.let {
                        onDrop(it, dragAndDropState.currentPosition())
+12 −0
Original line number Diff line number Diff line
@@ -46,6 +46,18 @@ class EditTileListState(tiles: List<EditTileViewModel>) {
        tiles.apply { add(toIndex, removeAt(fromIndex).copy(isCurrent = isMovingToCurrent)) }
    }

    /**
     * Sets the [TileSpec] as a non-current tile. Use this when a tile is dragged out of the current
     * tile grid.
     */
    fun removeFromCurrent(tileSpec: TileSpec) {
        val fromIndex = indexOf(tileSpec)
        if (fromIndex >= 0 && fromIndex < tiles.size) {
            // Mark the moving tile as non-current
            tiles[fromIndex] = tiles[fromIndex].copy(isCurrent = false)
        }
    }

    fun indexOf(tileSpec: TileSpec): Int {
        return tiles.indexOfFirst { it.tileSpec == tileSpec }
    }
+1 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ constructor(
        DefaultEditTileGrid(
            tiles = tiles,
            isIconOnly = isIcon,
            columns = GridCells.Fixed(columns),
            columns = columns,
            modifier = modifier,
            onAddTile = onAddTile,
            onRemoveTile = onRemoveTile,
+5 −10
Original line number Diff line number Diff line
@@ -305,9 +305,9 @@ class PartitionedGridLayout @Inject constructor(private val viewModel: Partition
                    largeTiles,
                    ClickAction.ADD,
                    addTileToEnd,
                    onDoubleTap,
                    isIconOnly,
                    dragAndDropState,
                    onDoubleTap = onDoubleTap,
                    acceptDrops = { true },
                    onDrop = onDrop,
                )
@@ -318,10 +318,10 @@ class PartitionedGridLayout @Inject constructor(private val viewModel: Partition
                    smallTiles,
                    ClickAction.ADD,
                    addTileToEnd,
                    onDoubleTap,
                    isIconOnly,
                    dragAndDropState,
                    onDoubleTap = onDoubleTap,
                    showLabels = showLabels,
                    dragAndDropState = dragAndDropState,
                    acceptDrops = { true },
                    onDrop = onDrop,
                )
@@ -332,10 +332,10 @@ class PartitionedGridLayout @Inject constructor(private val viewModel: Partition
                    tilesCustom,
                    ClickAction.ADD,
                    addTileToEnd,
                    onDoubleTap,
                    isIconOnly,
                    dragAndDropState,
                    onDoubleTap = onDoubleTap,
                    showLabels = showLabels,
                    dragAndDropState = dragAndDropState,
                    acceptDrops = { true },
                    onDrop = onDrop,
                )
@@ -372,11 +372,6 @@ class PartitionedGridLayout @Inject constructor(private val viewModel: Partition
        }
    }

    private fun gridHeight(nTiles: Int, tileHeight: Dp, columns: Int, padding: Dp): Dp {
        val rows = (nTiles + columns - 1) / columns
        return ((tileHeight + padding) * rows) - padding
    }

    /** Fill up the rest of the row if it's not complete. */
    private fun LazyGridScope.fillUpRow(nTiles: Int, columns: Int) {
        if (nTiles % columns != 0) {
Loading