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

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

Fix Drag and drop bug when moving a tile within the current list

The moving operation requires removing the tile first before inserting it again at a new position

Test: manually moving tiles whithin the current list
Test: EditModeViewModelTest
Bug: 346991759
Flag: EXEMPT bug fix

Change-Id: Iea4435cfdd061853910506dde11203be15ed9127
parent 685b186c
Loading
Loading
Loading
Loading
+77 −21
Original line number Original line Diff line number Diff line
@@ -54,8 +54,10 @@ import com.android.systemui.qs.tiles.viewmodel.qSTileConfigProvider
import com.android.systemui.settings.userTracker
import com.android.systemui.settings.userTracker
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
@@ -103,9 +105,7 @@ class EditModeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
            appName2,
            appName2,
        )
        )


    private val underTest: EditModeViewModel by lazy {
    private val underTest: EditModeViewModel by lazy { kosmos.editModeViewModel }
        kosmos.editModeViewModel
    }


    @Before
    @Before
    fun setUp() {
    fun setUp() {
@@ -461,14 +461,17 @@ class EditModeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
        }
        }


    @Test
    @Test
    fun tileNotAvailable_notShowing() = with(kosmos) {
    fun tileNotAvailable_notShowing() =
        with(kosmos) {
            testScope.runTest {
            testScope.runTest {
                val unavailableTile = "work"
                val unavailableTile = "work"
                qsTileFactory = FakeQSFactory { spec ->
                qsTileFactory = FakeQSFactory { spec ->
                    FakeQSTile(userTracker.userId, spec != unavailableTile)
                    FakeQSTile(userTracker.userId, spec != unavailableTile)
                }
                }
            tileAvailabilityInteractorsMap = mapOf(
                tileAvailabilityInteractorsMap =
                    unavailableTile to FakeTileAvailabilityInteractor(
                    mapOf(
                        unavailableTile to
                            FakeTileAvailabilityInteractor(
                                emptyMap<Int, Flow<Boolean>>().withDefault { flowOf(false) }
                                emptyMap<Int, Flow<Boolean>>().withDefault { flowOf(false) }
                            )
                            )
                    )
                    )
@@ -483,7 +486,60 @@ class EditModeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {


                underTest.startEditing()
                underTest.startEditing()


            assertThat(tiles!!.none { it.tileSpec == TileSpec.create(unavailableTile) }).isTrue()
                assertThat(tiles!!.none { it.tileSpec == TileSpec.create(unavailableTile) })
                    .isTrue()
            }
        }

    @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"),
                    )
                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("internet"),
                        TileSpec.create("alarm"),
                    )
                currentTilesInteractor.setTiles(currentTiles)
                underTest.startEditing()
                runCurrent()

                // Move alarm tile to index 0
                underTest.addTile(TileSpec.create("alarm"), 0)

                assertThat(tiles!!.filter { it.isCurrent }.map { it.tileSpec.spec })
                    .containsExactly("alarm", "flashlight", "airplane", "internet")
                    .inOrder()
            }
            }
        }
        }


+44 −39
Original line number Original line Diff line number Diff line
@@ -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.CurrentTilesInteractor.Companion.POSITION_AT_END
import com.android.systemui.qs.pipeline.domain.interactor.MinimumTilesInteractor
import com.android.systemui.qs.pipeline.domain.interactor.MinimumTilesInteractor
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.pipeline.shared.TileSpec
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -37,8 +39,6 @@ import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.stateIn
import javax.inject.Inject
import javax.inject.Named


@SysUISingleton
@SysUISingleton
@OptIn(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
@@ -93,8 +93,10 @@ constructor(
                val editTilesData = editTilesListInteractor.getTilesToEdit()
                val editTilesData = editTilesListInteractor.getTilesToEdit()
                // Query only the non current platform tiles, as any current tile is clearly
                // Query only the non current platform tiles, as any current tile is clearly
                // available
                // available
                val unavailable = tilesAvailabilityInteractor.getUnavailableTiles(
                val unavailable =
                        editTilesData.stockTiles.map { it.tileSpec }
                    tilesAvailabilityInteractor.getUnavailableTiles(
                        editTilesData.stockTiles
                            .map { it.tileSpec }
                            .minus(currentTilesInteractor.currentTilesSpecs.toSet())
                            .minus(currentTilesInteractor.currentTilesSpecs.toSet())
                    )
                    )
                currentTilesInteractor.currentTiles.map { tiles ->
                currentTilesInteractor.currentTiles.map { tiles ->
@@ -144,13 +146,16 @@ constructor(
        _isEditing.value = false
        _isEditing.value = false
    }
    }


    /** Immediately moves [tileSpec] to [position]. */
    /**
    fun moveTile(tileSpec: TileSpec, position: Int) {
     * Immediately adds [tileSpec] to the current tiles at [position]. If the [tileSpec] was already
        throw NotImplementedError("This is not supported yet")
     * 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)
        }
        }


    /** Immediately adds [tileSpec] to the current tiles at [position]. */
    fun addTile(tileSpec: TileSpec, position: Int = POSITION_AT_END) {
        currentTilesInteractor.addTile(tileSpec, position)
        currentTilesInteractor.addTile(tileSpec, position)
    }
    }