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

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

Use the availability of a tile as a key for the grouped and sorted list in edit mode

This also passes the entire list of tiles to Edit mode instead of splitting and rejoining the list.
The AvailableTileGridCell data class is also removed as it's no longer needed.

Flag: com.android.systemui.qs_ui_refactor_compose_fragment
Fixes: 405279487
Test: DragAndDropTest.kt
Test: EditModeTest.kt
Test: ResizingTest.kt
Change-Id: Ieb085569fe4d82bc9c7f21651ef8c44474f59ca4
parent 1caf584c
Loading
Loading
Loading
Loading
+28 −47
Original line number Diff line number Diff line
@@ -85,7 +85,6 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@@ -156,7 +155,6 @@ import com.android.systemui.qs.panels.ui.compose.selection.TileState
import com.android.systemui.qs.panels.ui.compose.selection.rememberResizingState
import com.android.systemui.qs.panels.ui.compose.selection.rememberSelectionState
import com.android.systemui.qs.panels.ui.compose.selection.selectableTile
import com.android.systemui.qs.panels.ui.model.AvailableTileGridCell
import com.android.systemui.qs.panels.ui.model.GridCell
import com.android.systemui.qs.panels.ui.model.SpacerGridCell
import com.android.systemui.qs.panels.ui.model.TileGridCell
@@ -229,7 +227,7 @@ private fun EditModeTopBar(onStopEditing: () -> Unit, onReset: (() -> Unit)?) {
@Composable
fun DefaultEditTileGrid(
    listState: EditTileListState,
    otherTiles: List<EditTileViewModel>,
    allTiles: List<EditTileViewModel>,
    modifier: Modifier,
    onAddTile: (TileSpec, Int) -> Unit,
    onRemoveTile: (TileSpec) -> Unit,
@@ -331,19 +329,8 @@ fun DefaultEditTileGrid(
                                spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)),
                            modifier = modifier.fillMaxSize(),
                        ) {
                            val availableTiles = remember {
                                mutableStateListOf<AvailableTileGridCell>().apply {
                                    addAll(toAvailableTiles(listState.tiles, otherTiles))
                                }
                            }
                            LaunchedEffect(listState.tiles, otherTiles) {
                                availableTiles.apply {
                                    clear()
                                    addAll(toAvailableTiles(listState.tiles, otherTiles))
                                }
                            }
                            AvailableTileGrid(
                                availableTiles,
                                allTiles,
                                selectionState,
                                listState.columns,
                                { onAddTile(it, listState.tileSpecs().size) }, // Add to the end
@@ -544,17 +531,19 @@ private fun CurrentTilesGrid(

@Composable
private fun AvailableTileGrid(
    tiles: List<AvailableTileGridCell>,
    tiles: List<EditTileViewModel>,
    selectionState: MutableSelectionState,
    columns: Int,
    onAddTile: (TileSpec) -> Unit,
    dragAndDropState: DragAndDropState,
) {
    // Available tiles aren't visible during drag and drop, so the row/col isn't needed
    val groupedTiles =
        remember(tiles.fastMap { it.tile.category }, tiles.fastMap { it.tile.label }) {
            groupAndSort(tiles)
    // Group and sort to get the proper order tiles should be displayed in
    val groupedTileSpecs =
        remember(tiles.fastMap { it.category }, tiles.fastMap { it.label }) {
            groupAndSort(tiles).mapValues { tiles -> tiles.value.map { it.tileSpec } }
        }
    // Map of TileSpec to EditTileViewModel to use with the grouped tilespecs
    val viewModelsMap = remember(tiles) { tiles.associateBy { it.tileSpec } }

    // Available tiles
    Column(
@@ -563,7 +552,7 @@ private fun AvailableTileGrid(
        modifier =
            Modifier.fillMaxWidth().wrapContentHeight().testTag(AVAILABLE_TILES_GRID_TEST_TAG),
    ) {
        groupedTiles.forEach { (category, tiles) ->
        groupedTileSpecs.forEach { (category, tileSpecs) ->
            key(category) {
                val surfaceColor = MaterialTheme.colorScheme.surface
                Column(
@@ -582,15 +571,16 @@ private fun AvailableTileGrid(
                        category,
                        modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp),
                    )
                    tiles.chunked(columns).forEach { row ->
                    tileSpecs.chunked(columns).forEach { row ->
                        Row(
                            horizontalArrangement = spacedBy(TileArrangementPadding),
                            modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Max),
                        ) {
                            row.forEach { tileGridCell ->
                                key(tileGridCell.key) {
                            for (tileSpec in row) {
                                val viewModel = viewModelsMap[tileSpec] ?: continue
                                key(tileSpec) {
                                    AvailableTileGridCell(
                                        cell = tileGridCell,
                                        cell = viewModel,
                                        dragAndDropState = dragAndDropState,
                                        selectionState = selectionState,
                                        onAddTile = onAddTile,
@@ -855,17 +845,17 @@ private fun CategoryHeader(category: TileCategory, modifier: Modifier = Modifier

@Composable
private fun AvailableTileGridCell(
    cell: AvailableTileGridCell,
    cell: EditTileViewModel,
    dragAndDropState: DragAndDropState,
    selectionState: MutableSelectionState,
    onAddTile: (TileSpec) -> Unit,
    modifier: Modifier = Modifier,
) {
    val stateDescription: String? =
        if (cell.isAvailable) null
        else stringResource(R.string.accessibility_qs_edit_tile_already_added)
        if (cell.isCurrent) stringResource(R.string.accessibility_qs_edit_tile_already_added)
        else null

    val alpha by animateFloatAsState(if (cell.isAvailable) 1f else .38f)
    val alpha by animateFloatAsState(if (cell.isCurrent) .38f else 1f)
    val colors = EditModeTileDefaults.editTileColors()

    // Displays the tile as an icon tile with the label underneath
@@ -881,21 +871,21 @@ private fun AvailableTileGridCell(
    ) {
        Box(Modifier.fillMaxWidth().height(TileHeight)) {
            val draggableModifier =
                if (cell.isAvailable) {
                if (cell.isCurrent) {
                    Modifier
                } else {
                    Modifier.dragAndDropTileSource(
                        SizedTileImpl(cell.tile, cell.width),
                        SizedTileImpl(cell, 1), // Available tiles are fixed at a width of 1
                        dragAndDropState,
                        DragType.Add,
                    ) {
                        selectionState.unSelect()
                    }
                } else {
                    Modifier
                }
            Box(draggableModifier.fillMaxSize().tileBackground { colors.background }) {
                // Icon
                SmallTileContent(
                    iconProvider = { cell.tile.icon },
                    iconProvider = { cell.icon },
                    color = colors.icon,
                    animateToEnd = true,
                    modifier = Modifier.align(Alignment.Center),
@@ -906,15 +896,15 @@ private fun AvailableTileGridCell(
                icon = Icons.Default.Add,
                contentDescription =
                    stringResource(id = R.string.accessibility_qs_edit_tile_add_action),
                enabled = cell.isAvailable,
                enabled = !cell.isCurrent,
            ) {
                onAddTile(cell.tile.tileSpec)
                selectionState.select(cell.tile.tileSpec)
                onAddTile(cell.tileSpec)
                selectionState.select(cell.tileSpec)
            }
        }
        Box(Modifier.fillMaxSize()) {
            Text(
                cell.tile.label.text,
                cell.label.text,
                maxLines = 2,
                color = colors.label,
                overflow = TextOverflow.Ellipsis,
@@ -998,15 +988,6 @@ fun EditTile(
    }
}

private fun toAvailableTiles(
    currentTiles: List<GridCell>,
    otherTiles: List<EditTileViewModel>,
): List<AvailableTileGridCell> {
    return currentTiles.filterIsInstance<TileGridCell>().fastMap {
        AvailableTileGridCell(it.tile, isAvailable = false)
    } + otherTiles.fastMap { AvailableTileGridCell(it) }
}

private fun MeasureScope.iconHorizontalCenter(containerSize: Int): Float {
    return (containerSize - ToggleTargetSize.roundToPx()) / 2f -
        CommonTileDefaults.TileStartPadding.toPx()
+2 −2
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ constructor(
        val largeTilesSpan by iconTilesViewModel.largeTilesSpanState
        val largeTiles by iconTilesViewModel.largeTiles.collectAsStateWithLifecycle()

        val (currentTiles, otherTiles) = tiles.partition { it.isCurrent }
        val currentTiles = tiles.filter { it.isCurrent }
        val listState =
            remember(columns, largeTilesSpan) {
                EditTileListState(
@@ -176,7 +176,7 @@ constructor(

        DefaultEditTileGrid(
            listState = listState,
            otherTiles = otherTiles,
            allTiles = tiles,
            modifier = modifier,
            onAddTile = onAddTile,
            onRemoveTile = onRemoveTile,
+0 −13
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import androidx.compose.runtime.Immutable
import com.android.systemui.qs.panels.shared.model.SizedTile
import com.android.systemui.qs.panels.shared.model.splitInRowsSequence
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.shared.model.CategoryAndName

/** Represents an item from a grid associated with a row and a span */
@@ -51,18 +50,6 @@ data class TileGridCell(
    ) : this(tile = sizedTile.tile, row = row, column = column, width = sizedTile.width)
}

/**
 * Represents a [EditTileViewModel] from the edit mode available tiles grid and whether it is
 * available to add or not.
 */
@Immutable
data class AvailableTileGridCell(
    override val tile: EditTileViewModel,
    override val width: Int = 1,
    val isAvailable: Boolean = true,
    val key: TileSpec = tile.tileSpec,
) : SizedTile<EditTileViewModel>, CategoryAndName by tile

/** Represents an empty space used to fill incomplete rows. Will always display as a 1x1 tile */
@Immutable
data class SpacerGridCell(
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ class DragAndDropTest : SysuiTestCase() {
        PlatformTheme {
            DefaultEditTileGrid(
                listState = listState,
                otherTiles = listOf(),
                allTiles = listState.tiles.filterIsInstance<TileGridCell>().map { it.tile },
                modifier = Modifier.fillMaxSize(),
                onAddTile = { _, _ -> },
                onRemoveTile = {},
+6 −6
Original line number Diff line number Diff line
@@ -52,9 +52,9 @@ class EditModeTest : SysuiTestCase() {
    @get:Rule val composeRule = createComposeRule()

    @Composable
    private fun EditTileGridUnderTest(tiles: List<EditTileViewModel>) {
        val allTiles = remember { tiles.toMutableStateList() }
        val (currentTiles, otherTiles) = allTiles.partition { it.isCurrent }
    private fun EditTileGridUnderTest() {
        val allTiles = remember { TestEditTiles.toMutableStateList() }
        val currentTiles = allTiles.filter { it.isCurrent }
        val listState =
            EditTileListState(currentTiles, TestLargeTilesSpecs, columns = 4, largeTilesSpan = 2)
        LaunchedEffect(currentTiles) { listState.updateTiles(currentTiles, TestLargeTilesSpecs) }
@@ -62,7 +62,7 @@ class EditModeTest : SysuiTestCase() {
        PlatformTheme {
            DefaultEditTileGrid(
                listState = listState,
                otherTiles = otherTiles,
                allTiles = allTiles,
                modifier = Modifier.fillMaxSize(),
                onAddTile = { spec, _ ->
                    val index = allTiles.indexOfFirst { it.tileSpec == spec }
@@ -82,7 +82,7 @@ class EditModeTest : SysuiTestCase() {

    @Test
    fun clickAvailableTile_shouldAdd() {
        composeRule.setContent { EditTileGridUnderTest(TestEditTiles) }
        composeRule.setContent { EditTileGridUnderTest() }
        composeRule.waitForIdle()

        composeRule.onNodeWithContentDescription("tileF").performClick() // Tap to add
@@ -96,7 +96,7 @@ class EditModeTest : SysuiTestCase() {

    @Test
    fun placementMode_shouldRepositionTile() {
        composeRule.setContent { EditTileGridUnderTest(TestEditTiles) }
        composeRule.setContent { EditTileGridUnderTest() }
        composeRule.waitForIdle()

        // Double tap first "tileA", i.e. the one in the current grid
Loading