diff options
2 files changed, 121 insertions, 60 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModelTest.kt index 8b49d4361d48..601779f8fb02 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModelTest.kt @@ -54,8 +54,10 @@ import com.android.systemui.qs.tiles.viewmodel.qSTileConfigProvider import com.android.systemui.settings.userTracker import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -103,9 +105,7 @@ class EditModeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { appName2, ) - private val underTest: EditModeViewModel by lazy { - kosmos.editModeViewModel - } + private val underTest: EditModeViewModel by lazy { kosmos.editModeViewModel } @Before fun setUp() { @@ -461,31 +461,87 @@ class EditModeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { } @Test - fun tileNotAvailable_notShowing() = with(kosmos) { - testScope.runTest { - val unavailableTile = "work" - qsTileFactory = FakeQSFactory { spec -> - FakeQSTile(userTracker.userId, spec != unavailableTile) + fun tileNotAvailable_notShowing() = + with(kosmos) { + testScope.runTest { + val unavailableTile = "work" + qsTileFactory = FakeQSFactory { spec -> + FakeQSTile(userTracker.userId, spec != unavailableTile) + } + tileAvailabilityInteractorsMap = + mapOf( + unavailableTile to + FakeTileAvailabilityInteractor( + emptyMap<Int, Flow<Boolean>>().withDefault { flowOf(false) } + ) + ) + val tiles by collectLastValue(underTest.tiles) + val currentTiles = + mutableListOf( + TileSpec.create("flashlight"), + TileSpec.create("airplane"), + TileSpec.create("alarm"), + ) + currentTilesInteractor.setTiles(currentTiles) + + underTest.startEditing() + + assertThat(tiles!!.none { it.tileSpec == TileSpec.create(unavailableTile) }) + .isTrue() } - tileAvailabilityInteractorsMap = mapOf( - unavailableTile to FakeTileAvailabilityInteractor( - emptyMap<Int, Flow<Boolean>>().withDefault { flowOf(false) } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun currentTiles_moveTileDown() = + with(kosmos) { + testScope.runTest { + val tiles by collectLastValue(underTest.tiles) + val currentTiles = + mutableListOf( + TileSpec.create("flashlight"), + TileSpec.create("airplane"), + TileSpec.create("internet"), + TileSpec.create("alarm"), ) - ) - val tiles by collectLastValue(underTest.tiles) - val currentTiles = + currentTilesInteractor.setTiles(currentTiles) + underTest.startEditing() + runCurrent() + + // Move flashlight tile to index 3 + underTest.addTile(TileSpec.create("flashlight"), 3) + + assertThat(tiles!!.filter { it.isCurrent }.map { it.tileSpec.spec }) + .containsExactly("airplane", "internet", "alarm", "flashlight") + .inOrder() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun currentTiles_moveTileUp() = + with(kosmos) { + testScope.runTest { + val tiles by collectLastValue(underTest.tiles) + val currentTiles = mutableListOf( - TileSpec.create("flashlight"), - TileSpec.create("airplane"), - TileSpec.create("alarm"), + TileSpec.create("flashlight"), + TileSpec.create("airplane"), + TileSpec.create("internet"), + TileSpec.create("alarm"), ) - currentTilesInteractor.setTiles(currentTiles) + currentTilesInteractor.setTiles(currentTiles) + underTest.startEditing() + runCurrent() - underTest.startEditing() + // Move alarm tile to index 0 + underTest.addTile(TileSpec.create("alarm"), 0) - assertThat(tiles!!.none { it.tileSpec == TileSpec.create(unavailableTile) }).isTrue() + assertThat(tiles!!.filter { it.isCurrent }.map { it.tileSpec.spec }) + .containsExactly("alarm", "flashlight", "airplane", "internet") + .inOrder() + } } - } companion object { private val drawable1 = TestStubDrawable("drawable1") diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt index 19b8c66983f9..62bfc72f07f2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt @@ -27,6 +27,8 @@ import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor.Companion.POSITION_AT_END import com.android.systemui.qs.pipeline.domain.interactor.MinimumTilesInteractor import com.android.systemui.qs.pipeline.shared.TileSpec +import javax.inject.Inject +import javax.inject.Named import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow @@ -37,22 +39,20 @@ import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn -import javax.inject.Inject -import javax.inject.Named @SysUISingleton @OptIn(ExperimentalCoroutinesApi::class) class EditModeViewModel @Inject constructor( - private val editTilesListInteractor: EditTilesListInteractor, - private val currentTilesInteractor: CurrentTilesInteractor, - private val tilesAvailabilityInteractor: TilesAvailabilityInteractor, - private val minTilesInteractor: MinimumTilesInteractor, - @Named("Default") private val defaultGridLayout: GridLayout, - @Application private val applicationScope: CoroutineScope, - gridLayoutTypeInteractor: GridLayoutTypeInteractor, - gridLayoutMap: Map<GridLayoutType, @JvmSuppressWildcards GridLayout>, + private val editTilesListInteractor: EditTilesListInteractor, + private val currentTilesInteractor: CurrentTilesInteractor, + private val tilesAvailabilityInteractor: TilesAvailabilityInteractor, + private val minTilesInteractor: MinimumTilesInteractor, + @Named("Default") private val defaultGridLayout: GridLayout, + @Application private val applicationScope: CoroutineScope, + gridLayoutTypeInteractor: GridLayoutTypeInteractor, + gridLayoutMap: Map<GridLayoutType, @JvmSuppressWildcards GridLayout>, ) { private val _isEditing = MutableStateFlow(false) @@ -93,10 +93,12 @@ constructor( val editTilesData = editTilesListInteractor.getTilesToEdit() // Query only the non current platform tiles, as any current tile is clearly // available - val unavailable = tilesAvailabilityInteractor.getUnavailableTiles( - editTilesData.stockTiles.map { it.tileSpec } - .minus(currentTilesInteractor.currentTilesSpecs.toSet()) - ) + val unavailable = + tilesAvailabilityInteractor.getUnavailableTiles( + editTilesData.stockTiles + .map { it.tileSpec } + .minus(currentTilesInteractor.currentTilesSpecs.toSet()) + ) currentTilesInteractor.currentTiles.map { tiles -> val currentSpecs = tiles.map { it.spec } val canRemoveTiles = currentSpecs.size > minimumTiles @@ -106,28 +108,28 @@ constructor( val nonCurrentTiles = allTiles.filter { it.tileSpec !in currentSpecs } (currentTiles + nonCurrentTiles) - .filterNot { it.tileSpec in unavailable } - .map { - val current = it.tileSpec in currentSpecs - val availableActions = buildSet { - if (current) { - add(AvailableEditActions.MOVE) - if (canRemoveTiles) { - add(AvailableEditActions.REMOVE) - } - } else { - add(AvailableEditActions.ADD) + .filterNot { it.tileSpec in unavailable } + .map { + val current = it.tileSpec in currentSpecs + val availableActions = buildSet { + if (current) { + add(AvailableEditActions.MOVE) + if (canRemoveTiles) { + add(AvailableEditActions.REMOVE) } + } else { + add(AvailableEditActions.ADD) } - EditTileViewModel( - it.tileSpec, - it.icon, - it.label, - it.appName, - current, - availableActions - ) } + EditTileViewModel( + it.tileSpec, + it.icon, + it.label, + it.appName, + current, + availableActions + ) + } } } else { emptyFlow() @@ -144,13 +146,16 @@ constructor( _isEditing.value = false } - /** Immediately moves [tileSpec] to [position]. */ - fun moveTile(tileSpec: TileSpec, position: Int) { - throw NotImplementedError("This is not supported yet") - } - - /** Immediately adds [tileSpec] to the current tiles at [position]. */ + /** + * Immediately adds [tileSpec] to the current tiles at [position]. If the [tileSpec] was already + * present, it will be moved to the new position. + */ fun addTile(tileSpec: TileSpec, position: Int = POSITION_AT_END) { + // Removing tile if it's already present to insert it at the new index. + if (currentTilesInteractor.currentTilesSpecs.contains(tileSpec)) { + removeTile(tileSpec) + } + currentTilesInteractor.addTile(tileSpec, position) } |