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

Commit 73e56ea3 authored by Olivier St-Onge's avatar Olivier St-Onge Committed by Android (Google) Code Review
Browse files

Merge "Stop the tile grid from automatically reflowing during a resizing movement." into main

parents 502c895b 4da82456
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -85,12 +85,12 @@ class IconTilesInteractorTest : SysuiTestCase() {
                runCurrent()

                // Assert that the tile is removed from the large tiles after resizing
                underTest.resize(largeTile)
                underTest.resize(largeTile, toIcon = true)
                runCurrent()
                assertThat(latest).doesNotContain(largeTile)

                // Assert that the tile is added to the large tiles after resizing
                underTest.resize(largeTile)
                underTest.resize(largeTile, toIcon = false)
                runCurrent()
                assertThat(latest).contains(largeTile)
            }
@@ -122,7 +122,7 @@ class IconTilesInteractorTest : SysuiTestCase() {
                val newTile = TileSpec.create("newTile")

                // Remove the large tile from the current tiles
                underTest.resize(newTile)
                underTest.resize(newTile, toIcon = false)
                runCurrent()

                // Assert that it's still small
+0 −18
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import com.android.systemui.common.shared.model.Icon
import com.android.systemui.qs.panels.shared.model.SizedTile
import com.android.systemui.qs.panels.shared.model.SizedTileImpl
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
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
@@ -38,13 +37,6 @@ import org.junit.runner.RunWith
class EditTileListStateTest : SysuiTestCase() {
    private val underTest = EditTileListState(TestEditTiles, 4)

    @Test
    fun noDrag_listUnchanged() {
        underTest.tiles.forEach { assertThat(it).isNotInstanceOf(SpacerGridCell::class.java) }
        assertThat(underTest.tiles.map { (it as TileGridCell).tile.tileSpec })
            .containsExactly(*TestEditTiles.map { it.tile.tileSpec }.toTypedArray())
    }

    @Test
    fun startDrag_listHasSpacers() {
        underTest.onStarted(TestEditTiles[0])
@@ -108,16 +100,6 @@ class EditTileListStateTest : SysuiTestCase() {
            )
    }

    @Test
    fun droppedNewTile_spacersDisappear() {
        underTest.onStarted(TestEditTiles[0])
        underTest.onDrop()

        assertThat(underTest.tiles.toStrings()).isEqualTo(listOf("a", "b", "c", "d", "e"))
        assertThat(underTest.isMoving(TestEditTiles[0].tile.tileSpec)).isFalse()
        assertThat(underTest.dragInProgress).isFalse()
    }

    @Test
    fun movedTileOutOfBounds_tileDisappears() {
        underTest.onStarted(TestEditTiles[0])
+58 −21
Original line number Diff line number Diff line
@@ -27,23 +27,25 @@ import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
class MutableSelectionStateTest : SysuiTestCase() {
    private val underTest = MutableSelectionState()
    private val underTest = MutableSelectionState({}, {})

    @Test
    fun selectTile_isCorrectlySelected() {
        assertThat(underTest.isSelected(TEST_SPEC)).isFalse()
        assertThat(underTest.selection?.tileSpec).isNotEqualTo(TEST_SPEC)

        underTest.select(TEST_SPEC)
        assertThat(underTest.isSelected(TEST_SPEC)).isTrue()
        underTest.select(TEST_SPEC, manual = true)
        assertThat(underTest.selection?.tileSpec).isEqualTo(TEST_SPEC)
        assertThat(underTest.selection?.manual).isTrue()

        underTest.unSelect()
        assertThat(underTest.isSelected(TEST_SPEC)).isFalse()
        assertThat(underTest.selection).isNull()

        val newSpec = TileSpec.create("newSpec")
        underTest.select(TEST_SPEC)
        underTest.select(newSpec)
        assertThat(underTest.isSelected(TEST_SPEC)).isFalse()
        assertThat(underTest.isSelected(newSpec)).isTrue()
        underTest.select(TEST_SPEC, manual = true)
        underTest.select(newSpec, manual = false)
        assertThat(underTest.selection?.tileSpec).isNotEqualTo(TEST_SPEC)
        assertThat(underTest.selection?.tileSpec).isEqualTo(newSpec)
        assertThat(underTest.selection?.manual).isFalse()
    }

    @Test
@@ -51,12 +53,12 @@ class MutableSelectionStateTest : SysuiTestCase() {
        assertThat(underTest.resizingState).isNull()

        // Resizing starts but no tile is selected
        underTest.onResizingDragStart(TileWidths(0, 0, 1)) {}
        underTest.onResizingDragStart(TileWidths(0, 0, 1))
        assertThat(underTest.resizingState).isNull()

        // Resizing starts with a selected tile
        underTest.select(TEST_SPEC)
        underTest.onResizingDragStart(TileWidths(0, 0, 1)) {}
        underTest.select(TEST_SPEC, manual = true)
        underTest.onResizingDragStart(TileWidths(0, 0, 1))

        assertThat(underTest.resizingState).isNotNull()
    }
@@ -66,8 +68,8 @@ class MutableSelectionStateTest : SysuiTestCase() {
        val spec = TileSpec.create("testSpec")

        // Resizing starts with a selected tile
        underTest.select(spec)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) {}
        underTest.select(spec, manual = true)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10))
        assertThat(underTest.resizingState).isNotNull()

        underTest.onResizingDragEnd()
@@ -77,8 +79,8 @@ class MutableSelectionStateTest : SysuiTestCase() {
    @Test
    fun unselect_clearsResizingState() {
        // Resizing starts with a selected tile
        underTest.select(TEST_SPEC)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) {}
        underTest.select(TEST_SPEC, manual = true)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10))
        assertThat(underTest.resizingState).isNotNull()

        underTest.unSelect()
@@ -88,8 +90,8 @@ class MutableSelectionStateTest : SysuiTestCase() {
    @Test
    fun onResizingDrag_updatesResizingState() {
        // Resizing starts with a selected tile
        underTest.select(TEST_SPEC)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) {}
        underTest.select(TEST_SPEC, manual = true)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10))
        assertThat(underTest.resizingState).isNotNull()

        underTest.onResizingDrag(5f)
@@ -105,11 +107,15 @@ class MutableSelectionStateTest : SysuiTestCase() {
    @Test
    fun onResizingDrag_receivesResizeCallback() {
        var resized = false
        val onResize: () -> Unit = { resized = !resized }
        val onResize: (TileSpec) -> Unit = {
            assertThat(it).isEqualTo(TEST_SPEC)
            resized = !resized
        }
        val underTest = MutableSelectionState(onResize = onResize, {})

        // Resizing starts with a selected tile
        underTest.select(TEST_SPEC)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10), onResize)
        underTest.select(TEST_SPEC, true)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10))
        assertThat(underTest.resizingState).isNotNull()

        // Drag under the threshold
@@ -125,6 +131,37 @@ class MutableSelectionStateTest : SysuiTestCase() {
        assertThat(resized).isFalse()
    }

    @Test
    fun onResizingEnded_receivesResizeEndCallback() {
        var resizeEnded = false
        val onResizeEnd: (TileSpec) -> Unit = { resizeEnded = true }
        val underTest = MutableSelectionState({}, onResizeEnd = onResizeEnd)

        // Resizing starts with a selected tile
        underTest.select(TEST_SPEC, true)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10))

        underTest.onResizingDragEnd()
        assertThat(resizeEnded).isTrue()
    }

    @Test
    fun onResizingEnded_setsSelectionAutomatically() {
        val underTest = MutableSelectionState({}, {})

        // Resizing starts with a selected tile
        underTest.select(TEST_SPEC, manual = true)
        underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10))

        // Assert the selection was manual
        assertThat(underTest.selection?.manual).isTrue()

        underTest.onResizingDragEnd()

        // Assert the selection is no longer manual due to the resizing
        assertThat(underTest.selection?.manual).isFalse()
    }

    companion object {
        private val TEST_SPEC = TileSpec.create("testSpec")
    }
+6 −5
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ constructor(
    private val currentTilesInteractor: CurrentTilesInteractor,
    private val preferencesInteractor: QSPreferencesInteractor,
    @PanelsLog private val logBuffer: LogBuffer,
    @Application private val applicationScope: CoroutineScope
    @Application private val applicationScope: CoroutineScope,
) {

    val largeTilesSpecs =
@@ -64,14 +64,15 @@ constructor(

    fun isIconTile(spec: TileSpec): Boolean = !largeTilesSpecs.value.contains(spec)

    fun resize(spec: TileSpec) {
    fun resize(spec: TileSpec, toIcon: Boolean) {
        if (!isCurrent(spec)) {
            return
        }

        if (largeTilesSpecs.value.contains(spec)) {
        val isIcon = !largeTilesSpecs.value.contains(spec)
        if (toIcon && !isIcon) {
            preferencesInteractor.setLargeTilesSpecs(largeTilesSpecs.value - spec)
        } else {
        } else if (!toIcon && isIcon) {
            preferencesInteractor.setLargeTilesSpecs(largeTilesSpecs.value + spec)
        }
    }
@@ -85,7 +86,7 @@ constructor(
            LOG_BUFFER_LARGE_TILES_SPECS_CHANGE_TAG,
            LogLevel.DEBUG,
            { str1 = specs.toString() },
            { "Large tiles change: $str1" }
            { "Large tiles change: $str1" },
        )
    }

+50 −8
Original line number Diff line number Diff line
@@ -60,10 +60,37 @@ class EditTileListState(tiles: List<SizedTile<EditTileViewModel>>, private val c
        return _tiles.filterIsInstance<TileGridCell>().map { it.tile.tileSpec }
    }

    fun indexOf(tileSpec: TileSpec): Int {
    private fun indexOf(tileSpec: TileSpec): Int {
        return _tiles.indexOfFirst { it is TileGridCell && it.tile.tileSpec == tileSpec }
    }

    /**
     * Whether the tile with this [TileSpec] is currently an icon in the [EditTileListState]
     *
     * @return true if the tile is an icon, false if it's large, null if the tile isn't in the list
     */
    fun isIcon(tileSpec: TileSpec): Boolean? {
        val index = indexOf(tileSpec)
        return if (index != -1) {
            val cell = _tiles[index]
            cell as TileGridCell
            return cell.isIcon
        } else {
            null
        }
    }

    /** Toggle the size of the tile corresponding to the [TileSpec] */
    fun toggleSize(tileSpec: TileSpec) {
        val fromIndex = indexOf(tileSpec)
        if (fromIndex != -1) {
            val cell = _tiles.removeAt(fromIndex)
            cell as TileGridCell
            _tiles.add(fromIndex, cell.copy(width = if (cell.isIcon) 2 else 1))
            regenerateGrid(fromIndex)
        }
    }

    override fun isMoving(tileSpec: TileSpec): Boolean {
        return _draggedCell.value?.let { it.tile.tileSpec == tileSpec } ?: false
    }
@@ -71,8 +98,8 @@ class EditTileListState(tiles: List<SizedTile<EditTileViewModel>>, private val c
    override fun onStarted(cell: SizedTile<EditTileViewModel>) {
        _draggedCell.value = cell

        // Add visible spacers to the grid to indicate where the user can move a tile
        regenerateGrid(includeSpacers = true)
        // Add spacers to the grid to indicate where the user can move a tile
        regenerateGrid()
    }

    override fun onMoved(target: Int, insertAfter: Boolean) {
@@ -86,7 +113,7 @@ class EditTileListState(tiles: List<SizedTile<EditTileViewModel>>, private val c
        val insertionIndex = if (insertAfter) target + 1 else target
        if (fromIndex != -1) {
            val cell = _tiles.removeAt(fromIndex)
            regenerateGrid(includeSpacers = true)
            regenerateGrid()
            _tiles.add(insertionIndex.coerceIn(0, _tiles.size), cell)
        } else {
            // Add the tile with a temporary row which will get reassigned when
@@ -94,7 +121,7 @@ class EditTileListState(tiles: List<SizedTile<EditTileViewModel>>, private val c
            _tiles.add(insertionIndex.coerceIn(0, _tiles.size), TileGridCell(draggedTile, 0))
        }

        regenerateGrid(includeSpacers = true)
        regenerateGrid()
    }

    override fun movedOutOfBounds() {
@@ -109,12 +136,27 @@ class EditTileListState(tiles: List<SizedTile<EditTileViewModel>>, private val c
        _draggedCell.value = null

        // Remove the spacers
        regenerateGrid(includeSpacers = false)
        regenerateGrid()
    }

    private fun regenerateGrid(includeSpacers: Boolean) {
        _tiles.filterIsInstance<TileGridCell>().toGridCells(columns, includeSpacers).let {
    /** Regenerate the list of [GridCell] with their new potential rows */
    private fun regenerateGrid() {
        _tiles.filterIsInstance<TileGridCell>().toGridCells(columns).let {
            _tiles.clear()
            _tiles.addAll(it)
        }
    }

    /**
     * Regenerate the list of [GridCell] with their new potential rows from [fromIndex], leaving
     * cells before that untouched.
     */
    private fun regenerateGrid(fromIndex: Int) {
        val fromRow = _tiles[fromIndex].row
        val (pre, post) = _tiles.partition { it.row < fromRow }
        post.filterIsInstance<TileGridCell>().toGridCells(columns, startingRow = fromRow).let {
            _tiles.clear()
            _tiles.addAll(pre)
            _tiles.addAll(it)
        }
    }
Loading