Merge "Only allow current tiles to be resized." into main
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorTest.kt
index 661d4b0..e58cf15 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorTest.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepository
 import com.android.systemui.qs.panels.data.repository.defaultLargeTilesRepository
 import com.android.systemui.qs.panels.data.repository.qsPreferencesRepository
+import com.android.systemui.qs.pipeline.domain.interactor.currentTilesInteractor
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -40,15 +41,16 @@
         testKosmos().apply {
             defaultLargeTilesRepository =
                 object : DefaultLargeTilesRepository {
-                    override val defaultLargeTiles: Set<TileSpec> = setOf(TileSpec.create("large"))
+                    override val defaultLargeTiles: Set<TileSpec> = setOf(largeTile)
                 }
+            currentTilesInteractor.setTiles(listOf(largeTile, smallTile))
         }
     private val underTest = with(kosmos) { iconTilesInteractor }
 
     @Test
     fun isIconTile_returnsCorrectValue() {
-        assertThat(underTest.isIconTile(TileSpec.create("large"))).isFalse()
-        assertThat(underTest.isIconTile(TileSpec.create("small"))).isTrue()
+        assertThat(underTest.isIconTile(largeTile)).isFalse()
+        assertThat(underTest.isIconTile(smallTile)).isTrue()
     }
 
     @OptIn(ExperimentalCoroutinesApi::class)
@@ -56,14 +58,21 @@
     fun isIconTile_updatesFromSharedPreferences() =
         with(kosmos) {
             testScope.runTest {
-                // Assert that new tile defaults to icon
-                assertThat(underTest.isIconTile(TileSpec.create("newTile"))).isTrue()
+                val spec = TileSpec.create("newTile")
 
-                qsPreferencesRepository.setLargeTilesSpecs(setOf(TileSpec.create("newTile")))
+                // Assert that new tile defaults to icon
+                assertThat(underTest.isIconTile(spec)).isTrue()
+
+                // Add the tile
+                currentTilesInteractor.addTile(spec)
+                runCurrent()
+
+                // Resize it to large
+                qsPreferencesRepository.setLargeTilesSpecs(setOf(spec))
                 runCurrent()
 
                 // Assert that the new tile was added to the large tiles set
-                assertThat(underTest.isIconTile(TileSpec.create("newTile"))).isFalse()
+                assertThat(underTest.isIconTile(spec)).isFalse()
             }
         }
 
@@ -72,21 +81,57 @@
     fun resize_updatesSharedPreferences() =
         with(kosmos) {
             testScope.runTest {
-                qsPreferencesRepository.setLargeTilesSpecs(setOf())
-                runCurrent()
-
                 val latest by collectLastValue(qsPreferencesRepository.largeTilesSpecs)
-                val spec = TileSpec.create("large")
-
-                // Assert that the tile is added to the large tiles after resizing
-                underTest.resize(spec)
                 runCurrent()
-                assertThat(latest).contains(spec)
 
                 // Assert that the tile is removed from the large tiles after resizing
-                underTest.resize(spec)
+                underTest.resize(largeTile)
                 runCurrent()
-                assertThat(latest).doesNotContain(spec)
+                assertThat(latest).doesNotContain(largeTile)
+
+                // Assert that the tile is added to the large tiles after resizing
+                underTest.resize(largeTile)
+                runCurrent()
+                assertThat(latest).contains(largeTile)
             }
         }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun removingTile_updatesSharedPreferences() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(qsPreferencesRepository.largeTilesSpecs)
+                runCurrent()
+
+                // Remove the large tile from the current tiles
+                currentTilesInteractor.removeTiles(listOf(largeTile))
+                runCurrent()
+
+                // Assert that it resized to small
+                assertThat(latest).doesNotContain(largeTile)
+            }
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun resizingNonCurrentTile_doesNothing() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(qsPreferencesRepository.largeTilesSpecs)
+                val newTile = TileSpec.create("newTile")
+
+                // Remove the large tile from the current tiles
+                underTest.resize(newTile)
+                runCurrent()
+
+                // Assert that it's still small
+                assertThat(latest).doesNotContain(newTile)
+            }
+        }
+
+    private companion object {
+        private val largeTile = TileSpec.create("large")
+        private val smallTile = TileSpec.create("small")
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QuickQuickSettingsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QuickQuickSettingsViewModelTest.kt
index 56156a8..ef85302 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QuickQuickSettingsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QuickQuickSettingsViewModelTest.kt
@@ -24,8 +24,7 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testCase
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepository
-import com.android.systemui.qs.panels.data.repository.defaultLargeTilesRepository
+import com.android.systemui.qs.panels.domain.interactor.qsPreferencesInteractor
 import com.android.systemui.qs.pipeline.domain.interactor.currentTilesInteractor
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.res.R
@@ -56,11 +55,9 @@
 
     private val kosmos =
         testKosmos().apply {
-            defaultLargeTilesRepository =
-                object : DefaultLargeTilesRepository {
-                    override val defaultLargeTiles: Set<TileSpec> =
-                        tiles.filter { it.spec.startsWith(PREFIX_LARGE) }.toSet()
-                }
+            qsPreferencesInteractor.setLargeTilesSpecs(
+                tiles.filter { it.spec.startsWith(PREFIX_LARGE) }.toSet()
+            )
         }
 
     private val underTest = kosmos.quickQuickSettingsViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
index 6dcdea9..02a607d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
@@ -22,10 +22,12 @@
 import com.android.systemui.log.core.LogLevel
 import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepository
 import com.android.systemui.qs.panels.shared.model.PanelsLog
+import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 
@@ -35,19 +37,38 @@
 @Inject
 constructor(
     repo: DefaultLargeTilesRepository,
+    private val currentTilesInteractor: CurrentTilesInteractor,
     private val preferencesInteractor: QSPreferencesInteractor,
     @PanelsLog private val logBuffer: LogBuffer,
     @Application private val applicationScope: CoroutineScope
 ) {
 
     val largeTilesSpecs =
-        preferencesInteractor.largeTilesSpecs
+        combine(preferencesInteractor.largeTilesSpecs, currentTilesInteractor.currentTiles) {
+                largeTiles,
+                currentTiles ->
+                if (currentTiles.isEmpty()) {
+                    largeTiles
+                } else {
+                    // Only current tiles can be resized, so observe the current tiles and find the
+                    // intersection between them and the large tiles.
+                    val newLargeTiles = largeTiles intersect currentTiles.map { it.spec }.toSet()
+                    if (newLargeTiles != largeTiles) {
+                        preferencesInteractor.setLargeTilesSpecs(newLargeTiles)
+                    }
+                    newLargeTiles
+                }
+            }
             .onEach { logChange(it) }
             .stateIn(applicationScope, SharingStarted.Eagerly, repo.defaultLargeTiles)
 
     fun isIconTile(spec: TileSpec): Boolean = !largeTilesSpecs.value.contains(spec)
 
     fun resize(spec: TileSpec) {
+        if (!isCurrent(spec)) {
+            return
+        }
+
         if (largeTilesSpecs.value.contains(spec)) {
             preferencesInteractor.setLargeTilesSpecs(largeTilesSpecs.value - spec)
         } else {
@@ -55,6 +76,10 @@
         }
     }
 
+    private fun isCurrent(spec: TileSpec): Boolean {
+        return currentTilesInteractor.currentTilesSpecs.contains(spec)
+    }
+
     private fun logChange(specs: Set<TileSpec>) {
         logBuffer.log(
             LOG_BUFFER_LARGE_TILES_SPECS_CHANGE_TAG,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
index 76dccdb..0c62d0e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
@@ -20,11 +20,13 @@
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.log.core.FakeLogBuffer
 import com.android.systemui.qs.panels.data.repository.defaultLargeTilesRepository
+import com.android.systemui.qs.pipeline.domain.interactor.currentTilesInteractor
 
 val Kosmos.iconTilesInteractor by
     Kosmos.Fixture {
         IconTilesInteractor(
             defaultLargeTilesRepository,
+            currentTilesInteractor,
             qsPreferencesInteractor,
             FakeLogBuffer.Factory.create(),
             applicationCoroutineScope