summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Olivier St-Onge <ostonge@google.com> 2024-05-28 15:05:14 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-05-28 15:05:14 +0000
commitdcb0555ffb778ecce9bfac4aaeb7bbfde1e7bec5 (patch)
treee5345bab58cf0cbb6cb5a28bf5e08633568b3daf
parent139f2e7759e02c94781b52c2705178841a7b7bf3 (diff)
parent404e8d4f5cbabc4e62760766c4c5d9d4ab2f76ce (diff)
Merge "Add optional labels to icon tiles." into main
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepository.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractor.kt61
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/IconLabelVisibilityLog.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PartitionedGridLayout.kt111
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/StretchedGridLayout.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModel.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModel.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModel.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModel.kt32
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepositoryKosmos.kt21
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorKosmos.kt31
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/PartitionedGridLayoutKosmos.kt3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModelKosmos.kt23
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModelKosmos.kt22
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModelKosmos.kt23
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModelKosmos.kt28
20 files changed, 581 insertions, 55 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
index d161c6b834c0..7b679932de3e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
@@ -28,6 +28,7 @@ import com.android.systemui.qs.panels.domain.interactor.InfiniteGridConsistencyI
import com.android.systemui.qs.panels.domain.interactor.NoopGridConsistencyInteractor
import com.android.systemui.qs.panels.shared.model.GridConsistencyLog
import com.android.systemui.qs.panels.shared.model.GridLayoutType
+import com.android.systemui.qs.panels.shared.model.IconLabelVisibilityLog
import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
import com.android.systemui.qs.panels.shared.model.PartitionedGridLayoutType
import com.android.systemui.qs.panels.shared.model.StretchedGridLayoutType
@@ -35,6 +36,12 @@ import com.android.systemui.qs.panels.ui.compose.GridLayout
import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
import com.android.systemui.qs.panels.ui.compose.PartitionedGridLayout
import com.android.systemui.qs.panels.ui.compose.StretchedGridLayout
+import com.android.systemui.qs.panels.ui.viewmodel.IconLabelVisibilityViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.IconLabelVisibilityViewModelImpl
+import com.android.systemui.qs.panels.ui.viewmodel.IconTilesViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.IconTilesViewModelImpl
+import com.android.systemui.qs.panels.ui.viewmodel.InfiniteGridSizeViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.InfiniteGridSizeViewModelImpl
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -53,6 +60,15 @@ interface PanelsModule {
impl: NoopGridConsistencyInteractor
): GridTypeConsistencyInteractor
+ @Binds fun bindIconTilesViewModel(impl: IconTilesViewModelImpl): IconTilesViewModel
+
+ @Binds fun bindGridSizeViewModel(impl: InfiniteGridSizeViewModelImpl): InfiniteGridSizeViewModel
+
+ @Binds
+ fun bindIconLabelVisibilityViewModel(
+ impl: IconLabelVisibilityViewModelImpl
+ ): IconLabelVisibilityViewModel
+
@Binds @Named("Default") fun bindDefaultGridLayout(impl: PartitionedGridLayout): GridLayout
companion object {
@@ -64,6 +80,13 @@ interface PanelsModule {
}
@Provides
+ @SysUISingleton
+ @IconLabelVisibilityLog
+ fun providesIconTileLabelVisibilityLog(factory: LogBufferFactory): LogBuffer {
+ return factory.create("IconLabelVisibilityLog", 50)
+ }
+
+ @Provides
@IntoSet
fun provideGridLayout(gridLayout: InfiniteGridLayout): Pair<GridLayoutType, GridLayout> {
return Pair(InfiniteGridLayoutType, gridLayout)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepository.kt
new file mode 100644
index 000000000000..686e5f49442b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepository.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** Repository for whether to show the labels of icon tiles. */
+@SysUISingleton
+class IconLabelVisibilityRepository @Inject constructor() {
+ // TODO(b/341735914): Persist and back up showLabels
+ private val _showLabels = MutableStateFlow(false)
+ val showLabels: StateFlow<Boolean> = _showLabels.asStateFlow()
+
+ fun setShowLabels(showLabels: Boolean) {
+ _showLabels.value = showLabels
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractor.kt
new file mode 100644
index 000000000000..a871531f283a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractor.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.qs.panels.data.repository.IconLabelVisibilityRepository
+import com.android.systemui.qs.panels.shared.model.IconLabelVisibilityLog
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.stateIn
+
+@SysUISingleton
+class IconLabelVisibilityInteractor
+@Inject
+constructor(
+ private val repo: IconLabelVisibilityRepository,
+ @IconLabelVisibilityLog private val logBuffer: LogBuffer,
+ @Application scope: CoroutineScope,
+) {
+ val showLabels: StateFlow<Boolean> =
+ repo.showLabels
+ .onEach { logChange(it) }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), repo.showLabels.value)
+
+ fun setShowLabels(showLabels: Boolean) {
+ repo.setShowLabels(showLabels)
+ }
+
+ private fun logChange(showLabels: Boolean) {
+ logBuffer.log(
+ LOG_BUFFER_ICON_TILE_LABEL_VISIBILITY_CHANGE_TAG,
+ LogLevel.DEBUG,
+ { bool1 = showLabels },
+ { "Icon tile label visibility changed: $bool1" }
+ )
+ }
+
+ private companion object {
+ const val LOG_BUFFER_ICON_TILE_LABEL_VISIBILITY_CHANGE_TAG = "IconLabelVisibilityChange"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/IconLabelVisibilityLog.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/IconLabelVisibilityLog.kt
new file mode 100644
index 000000000000..c92234c3e535
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/IconLabelVisibilityLog.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.shared.model
+
+import javax.inject.Qualifier
+
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class IconLabelVisibilityLog()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
index f5ee720faff6..4aeaa7d23771 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
@@ -26,9 +26,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.qs.panels.domain.interactor.IconTilesInteractor
-import com.android.systemui.qs.panels.domain.interactor.InfiniteGridSizeInteractor
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.IconTilesViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.InfiniteGridSizeViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.res.R
@@ -38,8 +38,8 @@ import javax.inject.Inject
class InfiniteGridLayout
@Inject
constructor(
- private val iconTilesInteractor: IconTilesInteractor,
- private val gridSizeInteractor: InfiniteGridSizeInteractor
+ private val iconTilesViewModel: IconTilesViewModel,
+ private val gridSizeViewModel: InfiniteGridSizeViewModel,
) : GridLayout {
@Composable
@@ -52,8 +52,8 @@ constructor(
tiles.forEach { it.startListening(token) }
onDispose { tiles.forEach { it.stopListening(token) } }
}
- val iconTilesSpecs by iconTilesInteractor.iconTilesSpecs.collectAsStateWithLifecycle()
- val columns by gridSizeInteractor.columns.collectAsStateWithLifecycle()
+ val iconTilesSpecs by iconTilesViewModel.iconTilesSpecs.collectAsStateWithLifecycle()
+ val columns by gridSizeViewModel.columns.collectAsStateWithLifecycle()
TileLazyGrid(modifier = modifier, columns = GridCells.Fixed(columns)) {
items(
@@ -68,9 +68,9 @@ constructor(
}
) { index ->
Tile(
- tiles[index],
- iconTilesSpecs.contains(tiles[index].spec),
- Modifier.height(dimensionResource(id = R.dimen.qs_tile_height))
+ tile = tiles[index],
+ iconOnly = iconTilesSpecs.contains(tiles[index].spec),
+ modifier = Modifier.height(dimensionResource(id = R.dimen.qs_tile_height))
)
}
}
@@ -83,8 +83,8 @@ constructor(
onAddTile: (TileSpec, Int) -> Unit,
onRemoveTile: (TileSpec) -> Unit,
) {
- val iconOnlySpecs by iconTilesInteractor.iconTilesSpecs.collectAsStateWithLifecycle()
- val columns by gridSizeInteractor.columns.collectAsStateWithLifecycle()
+ val iconOnlySpecs by iconTilesViewModel.iconTilesSpecs.collectAsStateWithLifecycle()
+ val columns by gridSizeViewModel.columns.collectAsStateWithLifecycle()
DefaultEditTileGrid(
tiles = tiles,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PartitionedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PartitionedGridLayout.kt
index 8d0b386bd817..708ef0dd7ff6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PartitionedGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PartitionedGridLayout.kt
@@ -20,6 +20,7 @@ import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -32,6 +33,8 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Switch
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
@@ -39,14 +42,14 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.modifiers.background
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.qs.panels.domain.interactor.IconTilesInteractor
-import com.android.systemui.qs.panels.domain.interactor.InfiniteGridSizeInteractor
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.PartitionedGridViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
import com.android.systemui.qs.pipeline.shared.TileSpec
@@ -54,12 +57,8 @@ import com.android.systemui.res.R
import javax.inject.Inject
@SysUISingleton
-class PartitionedGridLayout
-@Inject
-constructor(
- private val iconTilesInteractor: IconTilesInteractor,
- private val gridSizeInteractor: InfiniteGridSizeInteractor,
-) : GridLayout {
+class PartitionedGridLayout @Inject constructor(private val viewModel: PartitionedGridViewModel) :
+ GridLayout {
@Composable
override fun TileGrid(tiles: List<TileViewModel>, modifier: Modifier) {
DisposableEffect(tiles) {
@@ -67,9 +66,11 @@ constructor(
tiles.forEach { it.startListening(token) }
onDispose { tiles.forEach { it.stopListening(token) } }
}
- val iconTilesSpecs by iconTilesInteractor.iconTilesSpecs.collectAsStateWithLifecycle()
- val columns by gridSizeInteractor.columns.collectAsStateWithLifecycle()
- val tileHeight = dimensionResource(id = R.dimen.qs_tile_height)
+ val iconTilesSpecs by viewModel.iconTilesSpecs.collectAsStateWithLifecycle()
+ val columns by viewModel.columns.collectAsStateWithLifecycle()
+ val showLabels by viewModel.showLabels.collectAsStateWithLifecycle()
+ val largeTileHeight = tileHeight()
+ val iconTileHeight = tileHeight(showLabels)
val (smallTiles, largeTiles) = tiles.partition { iconTilesSpecs.contains(it.spec) }
TileLazyGrid(modifier = modifier, columns = GridCells.Fixed(columns)) {
@@ -78,7 +79,7 @@ constructor(
Tile(
tile = largeTiles[index],
iconOnly = false,
- modifier = Modifier.height(tileHeight)
+ modifier = Modifier.height(largeTileHeight)
)
}
fillUpRow(nTiles = largeTiles.size, columns = columns / 2)
@@ -88,7 +89,8 @@ constructor(
Tile(
tile = smallTiles[index],
iconOnly = true,
- modifier = Modifier.height(tileHeight)
+ showLabels = showLabels,
+ modifier = Modifier.height(iconTileHeight)
)
}
}
@@ -101,8 +103,9 @@ constructor(
onAddTile: (TileSpec, Int) -> Unit,
onRemoveTile: (TileSpec) -> Unit
) {
- val iconOnlySpecs by iconTilesInteractor.iconTilesSpecs.collectAsStateWithLifecycle()
- val columns by gridSizeInteractor.columns.collectAsStateWithLifecycle()
+ val iconOnlySpecs by viewModel.iconTilesSpecs.collectAsStateWithLifecycle()
+ val columns by viewModel.columns.collectAsStateWithLifecycle()
+ val showLabels by viewModel.showLabels.collectAsStateWithLifecycle()
val (currentTiles, otherTiles) = tiles.partition { it.isCurrent }
val addTileToEnd: (TileSpec) -> Unit by rememberUpdatedState {
@@ -110,27 +113,56 @@ constructor(
}
val isIconOnly: (TileSpec) -> Boolean =
remember(iconOnlySpecs) { { tileSpec: TileSpec -> tileSpec in iconOnlySpecs } }
- val tileHeight = dimensionResource(id = R.dimen.qs_tile_height)
+ val largeTileHeight = tileHeight()
+ val iconTileHeight = tileHeight(showLabels)
val tilePadding = dimensionResource(R.dimen.qs_tile_margin_vertical)
Column(
verticalArrangement = Arrangement.spacedBy(tilePadding),
modifier = modifier.fillMaxSize().verticalScroll(rememberScrollState())
) {
+ Row(
+ modifier =
+ Modifier.background(
+ color = MaterialTheme.colorScheme.surfaceVariant,
+ alpha = { 1f },
+ shape = RoundedCornerShape(dimensionResource(R.dimen.qs_corner_radius))
+ )
+ .padding(tilePadding)
+ ) {
+ Column(Modifier.padding(start = tilePadding)) {
+ Text(
+ text = "Show text labels",
+ color = MaterialTheme.colorScheme.onBackground,
+ fontWeight = FontWeight.Bold
+ )
+ Text(
+ text = "Display names under each tile",
+ color = MaterialTheme.colorScheme.onBackground
+ )
+ }
+ Spacer(modifier = Modifier.weight(1f))
+ Switch(checked = showLabels, onCheckedChange = { viewModel.setShowLabels(it) })
+ }
+
CurrentTiles(
tiles = currentTiles,
- tileHeight = tileHeight,
+ largeTileHeight = largeTileHeight,
+ iconTileHeight = iconTileHeight,
tilePadding = tilePadding,
onRemoveTile = onRemoveTile,
isIconOnly = isIconOnly,
columns = columns,
+ showLabels = showLabels,
)
AvailableTiles(
tiles = otherTiles,
- tileHeight = tileHeight,
+ largeTileHeight = largeTileHeight,
+ iconTileHeight = iconTileHeight,
tilePadding = tilePadding,
addTileToEnd = addTileToEnd,
isIconOnly = isIconOnly,
+ showLabels = showLabels,
columns = columns,
)
}
@@ -139,23 +171,31 @@ constructor(
@Composable
private fun CurrentTiles(
tiles: List<EditTileViewModel>,
- tileHeight: Dp,
+ largeTileHeight: Dp,
+ iconTileHeight: Dp,
tilePadding: Dp,
onRemoveTile: (TileSpec) -> Unit,
isIconOnly: (TileSpec) -> Boolean,
+ showLabels: Boolean,
columns: Int,
) {
val (smallTiles, largeTiles) = tiles.partition { isIconOnly(it.tileSpec) }
- val largeGridHeight = gridHeight(largeTiles.size, tileHeight, columns / 2, tilePadding)
- val smallGridHeight = gridHeight(smallTiles.size, tileHeight, columns, tilePadding)
+ val largeGridHeight = gridHeight(largeTiles.size, largeTileHeight, columns / 2, tilePadding)
+ val smallGridHeight = gridHeight(smallTiles.size, iconTileHeight, columns, tilePadding)
CurrentTilesContainer {
TileLazyGrid(
columns = GridCells.Fixed(columns),
modifier = Modifier.height(largeGridHeight),
) {
- editTiles(largeTiles, ClickAction.REMOVE, onRemoveTile, { false }, true)
+ editTiles(
+ largeTiles,
+ ClickAction.REMOVE,
+ onRemoveTile,
+ { false },
+ indicatePosition = true
+ )
}
}
CurrentTilesContainer {
@@ -163,7 +203,14 @@ constructor(
columns = GridCells.Fixed(columns),
modifier = Modifier.height(smallGridHeight),
) {
- editTiles(smallTiles, ClickAction.REMOVE, onRemoveTile, { true }, true)
+ editTiles(
+ smallTiles,
+ ClickAction.REMOVE,
+ onRemoveTile,
+ { true },
+ showLabels = showLabels,
+ indicatePosition = true
+ )
}
}
}
@@ -171,19 +218,21 @@ constructor(
@Composable
private fun AvailableTiles(
tiles: List<EditTileViewModel>,
- tileHeight: Dp,
+ largeTileHeight: Dp,
+ iconTileHeight: Dp,
tilePadding: Dp,
addTileToEnd: (TileSpec) -> Unit,
isIconOnly: (TileSpec) -> Boolean,
+ showLabels: Boolean,
columns: Int,
) {
val (tilesStock, tilesCustom) = tiles.partition { it.appName == null }
val (smallTiles, largeTiles) = tilesStock.partition { isIconOnly(it.tileSpec) }
- val largeGridHeight = gridHeight(largeTiles.size, tileHeight, columns / 2, tilePadding)
- val smallGridHeight = gridHeight(smallTiles.size, tileHeight, columns, tilePadding)
+ val largeGridHeight = gridHeight(largeTiles.size, largeTileHeight, columns / 2, tilePadding)
+ val smallGridHeight = gridHeight(smallTiles.size, iconTileHeight, columns, tilePadding)
val largeGridHeightCustom =
- gridHeight(tilesCustom.size, tileHeight, columns / 2, tilePadding)
+ gridHeight(tilesCustom.size, largeTileHeight, columns / 2, tilePadding)
// Add up the height of all three grids and add padding in between
val gridHeight =
@@ -199,7 +248,13 @@ constructor(
fillUpRow(nTiles = largeTiles.size, columns = columns / 2)
// Small tiles
- editTiles(smallTiles, ClickAction.ADD, addTileToEnd, isIconOnly)
+ editTiles(
+ smallTiles,
+ ClickAction.ADD,
+ addTileToEnd,
+ isIconOnly,
+ showLabels = showLabels
+ )
fillUpRow(nTiles = smallTiles.size, columns = columns)
// Custom tiles, all large
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/StretchedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/StretchedGridLayout.kt
index ddd97c2e8944..70d629fa7c70 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/StretchedGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/StretchedGridLayout.kt
@@ -27,11 +27,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.qs.panels.domain.interactor.IconTilesInteractor
-import com.android.systemui.qs.panels.domain.interactor.InfiniteGridSizeInteractor
import com.android.systemui.qs.panels.shared.model.SizedTile
import com.android.systemui.qs.panels.shared.model.TileRow
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.IconTilesViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.InfiniteGridSizeViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.res.R
@@ -41,8 +41,8 @@ import javax.inject.Inject
class StretchedGridLayout
@Inject
constructor(
- private val iconTilesInteractor: IconTilesInteractor,
- private val gridSizeInteractor: InfiniteGridSizeInteractor,
+ private val iconTilesViewModel: IconTilesViewModel,
+ private val gridSizeViewModel: InfiniteGridSizeViewModel,
) : GridLayout {
@Composable
@@ -60,7 +60,7 @@ constructor(
// Icon [3 | 4]
// Large [6 | 8]
val columns = 12
- val iconTilesSpecs by iconTilesInteractor.iconTilesSpecs.collectAsStateWithLifecycle()
+ val iconTilesSpecs by iconTilesViewModel.iconTilesSpecs.collectAsStateWithLifecycle()
val stretchedTiles =
remember(tiles) {
val sizedTiles =
@@ -80,9 +80,9 @@ constructor(
TileLazyGrid(columns = GridCells.Fixed(columns), modifier = modifier) {
items(stretchedTiles.size, span = { GridItemSpan(stretchedTiles[it].width) }) { index ->
Tile(
- stretchedTiles[index].tile,
- iconTilesSpecs.contains(stretchedTiles[index].tile.spec),
- Modifier.height(dimensionResource(id = R.dimen.qs_tile_height))
+ tile = stretchedTiles[index].tile,
+ iconOnly = iconTilesSpecs.contains(stretchedTiles[index].tile.spec),
+ modifier = Modifier.height(dimensionResource(id = R.dimen.qs_tile_height))
)
}
}
@@ -95,8 +95,8 @@ constructor(
onAddTile: (TileSpec, Int) -> Unit,
onRemoveTile: (TileSpec) -> Unit
) {
- val iconOnlySpecs by iconTilesInteractor.iconTilesSpecs.collectAsStateWithLifecycle()
- val columns by gridSizeInteractor.columns.collectAsStateWithLifecycle()
+ val iconOnlySpecs by iconTilesViewModel.iconTilesSpecs.collectAsStateWithLifecycle()
+ val columns by gridSizeViewModel.columns.collectAsStateWithLifecycle()
DefaultEditTileGrid(
tiles = tiles,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
index e8c65a5ac78a..a6838c0c06a2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
@@ -69,6 +69,9 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.onClick
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.Expandable
@@ -98,6 +101,7 @@ object TileType
fun Tile(
tile: TileViewModel,
iconOnly: Boolean,
+ showLabels: Boolean = false,
modifier: Modifier,
) {
val state: TileUiState by
@@ -136,7 +140,8 @@ fun Tile(
secondaryLabel = state.secondaryLabel.toString(),
icon = icon,
colors = state.colors,
- iconOnly = iconOnly
+ iconOnly = iconOnly,
+ showLabels = showLabels,
)
}
}
@@ -213,6 +218,7 @@ fun LazyGridScope.editTiles(
clickAction: ClickAction,
onClick: (TileSpec) -> Unit,
isIconOnly: (TileSpec) -> Boolean,
+ showLabels: Boolean = false,
indicatePosition: Boolean = false,
) {
items(
@@ -250,10 +256,13 @@ fun LazyGridScope.editTiles(
this.stateDescription = stateDescription
}
) {
+ val iconOnly = isIconOnly(viewModel.tileSpec)
+ val tileHeight = tileHeight(iconOnly && showLabels)
EditTile(
tileViewModel = viewModel,
- isIconOnly(viewModel.tileSpec),
- modifier = Modifier.height(dimensionResource(id = R.dimen.qs_tile_height))
+ iconOnly = iconOnly,
+ showLabels = showLabels,
+ modifier = Modifier.height(tileHeight)
)
if (canClick) {
Badge(clickAction, Modifier.align(Alignment.TopEnd))
@@ -281,6 +290,7 @@ fun Badge(action: ClickAction, modifier: Modifier = Modifier) {
fun EditTile(
tileViewModel: EditTileViewModel,
iconOnly: Boolean,
+ showLabels: Boolean,
modifier: Modifier = Modifier,
) {
val label = tileViewModel.label.load() ?: tileViewModel.tileSpec.spec
@@ -297,6 +307,7 @@ fun EditTile(
colors = colors,
icon = tileViewModel.icon,
iconOnly = iconOnly,
+ showLabels = showLabels,
animateIconToEnd = true,
)
}
@@ -380,9 +391,26 @@ private fun TileContent(
icon: Icon,
colors: TileColorAttributes,
iconOnly: Boolean,
+ showLabels: Boolean = false,
animateIconToEnd: Boolean = false,
) {
- TileIcon(icon, colorAttr(colors.icon), animateIconToEnd)
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center,
+ modifier = Modifier.fillMaxHeight()
+ ) {
+ TileIcon(icon, colorAttr(colors.icon), animateIconToEnd)
+
+ if (iconOnly && showLabels) {
+ Text(
+ label,
+ maxLines = 2,
+ color = colorAttr(colors.label),
+ overflow = TextOverflow.Ellipsis,
+ textAlign = TextAlign.Center,
+ )
+ }
+ }
if (!iconOnly) {
Column(verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxHeight()) {
@@ -401,3 +429,16 @@ private fun TileContent(
}
}
}
+
+@Composable
+fun tileHeight(iconWithLabel: Boolean = false): Dp {
+ return if (iconWithLabel) {
+ TileDimensions.IconTileWithLabelHeight
+ } else {
+ dimensionResource(id = R.dimen.qs_tile_height)
+ }
+}
+
+private object TileDimensions {
+ val IconTileWithLabelHeight = 100.dp
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModel.kt
new file mode 100644
index 000000000000..5d4b8f1773f2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModel.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.domain.interactor.IconLabelVisibilityInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+interface IconLabelVisibilityViewModel {
+ val showLabels: StateFlow<Boolean>
+
+ fun setShowLabels(showLabels: Boolean)
+}
+
+@SysUISingleton
+class IconLabelVisibilityViewModelImpl
+@Inject
+constructor(private val interactor: IconLabelVisibilityInteractor) : IconLabelVisibilityViewModel {
+ override val showLabels: StateFlow<Boolean> = interactor.showLabels
+
+ override fun setShowLabels(showLabels: Boolean) {
+ interactor.setShowLabels(showLabels)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModel.kt
new file mode 100644
index 000000000000..9ad00c8d3cfa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModel.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.domain.interactor.IconTilesInteractor
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+interface IconTilesViewModel {
+ val iconTilesSpecs: StateFlow<Set<TileSpec>>
+}
+
+@SysUISingleton
+class IconTilesViewModelImpl @Inject constructor(interactor: IconTilesInteractor) :
+ IconTilesViewModel {
+ override val iconTilesSpecs = interactor.iconTilesSpecs
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModel.kt
new file mode 100644
index 000000000000..a4ee58f0963c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModel.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.domain.interactor.InfiniteGridSizeInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+interface InfiniteGridSizeViewModel {
+ val columns: StateFlow<Int>
+}
+
+@SysUISingleton
+class InfiniteGridSizeViewModelImpl @Inject constructor(interactor: InfiniteGridSizeInteractor) :
+ InfiniteGridSizeViewModel {
+ override val columns: StateFlow<Int> = interactor.columns
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModel.kt
new file mode 100644
index 000000000000..730cf635972d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModel.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+@SysUISingleton
+class PartitionedGridViewModel
+@Inject
+constructor(
+ iconTilesViewModel: IconTilesViewModel,
+ gridSizeViewModel: InfiniteGridSizeViewModel,
+ iconLabelVisibilityViewModel: IconLabelVisibilityViewModel,
+) :
+ IconTilesViewModel by iconTilesViewModel,
+ InfiniteGridSizeViewModel by gridSizeViewModel,
+ IconLabelVisibilityViewModel by iconLabelVisibilityViewModel
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepositoryKosmos.kt
new file mode 100644
index 000000000000..277dbb7016ad
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/IconLabelVisibilityRepositoryKosmos.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.iconLabelVisibilityRepository by Kosmos.Fixture { IconLabelVisibilityRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorKosmos.kt
new file mode 100644
index 000000000000..7b9e4a17e998
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.log.core.FakeLogBuffer
+import com.android.systemui.qs.panels.data.repository.iconLabelVisibilityRepository
+
+val Kosmos.iconLabelVisibilityInteractor by
+ Kosmos.Fixture {
+ IconLabelVisibilityInteractor(
+ iconLabelVisibilityRepository,
+ FakeLogBuffer.Factory.create(),
+ applicationCoroutineScope
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt
index 34b266a54f41..82cfaf50f823 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt
@@ -18,6 +18,8 @@ package com.android.systemui.qs.panels.domain.interactor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
+import com.android.systemui.qs.panels.ui.viewmodel.iconTilesViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.infiniteGridSizeViewModel
val Kosmos.infiniteGridLayout by
- Kosmos.Fixture { InfiniteGridLayout(iconTilesInteractor, infiniteGridSizeInteractor) }
+ Kosmos.Fixture { InfiniteGridLayout(iconTilesViewModel, infiniteGridSizeViewModel) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/PartitionedGridLayoutKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/PartitionedGridLayoutKosmos.kt
index 4febfe9160ab..37c9552ded44 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/PartitionedGridLayoutKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/PartitionedGridLayoutKosmos.kt
@@ -18,6 +18,7 @@ package com.android.systemui.qs.panels.domain.interactor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.qs.panels.ui.compose.PartitionedGridLayout
+import com.android.systemui.qs.panels.ui.viewmodel.partitionedGridViewModel
val Kosmos.partitionedGridLayout by
- Kosmos.Fixture { PartitionedGridLayout(iconTilesInteractor, infiniteGridSizeInteractor) }
+ Kosmos.Fixture { PartitionedGridLayout(partitionedGridViewModel) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModelKosmos.kt
new file mode 100644
index 000000000000..daf6087c2d6f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconLabelVisibilityViewModelKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.panels.domain.interactor.iconLabelVisibilityInteractor
+
+val Kosmos.iconLabelVisibilityViewModel by
+ Kosmos.Fixture { IconLabelVisibilityViewModelImpl(iconLabelVisibilityInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModelKosmos.kt
new file mode 100644
index 000000000000..89b42a69c326
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/IconTilesViewModelKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.panels.domain.interactor.iconTilesInteractor
+
+val Kosmos.iconTilesViewModel by Kosmos.Fixture { IconTilesViewModelImpl(iconTilesInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModelKosmos.kt
new file mode 100644
index 000000000000..f6dfb8bcd47b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/InfiniteGridSizeViewModelKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.panels.domain.interactor.infiniteGridSizeInteractor
+
+val Kosmos.infiniteGridSizeViewModel by
+ Kosmos.Fixture { InfiniteGridSizeViewModelImpl(infiniteGridSizeInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModelKosmos.kt
new file mode 100644
index 000000000000..b07cc7d8612d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PartitionedGridViewModelKosmos.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.partitionedGridViewModel by
+ Kosmos.Fixture {
+ PartitionedGridViewModel(
+ iconTilesViewModel,
+ infiniteGridSizeViewModel,
+ iconLabelVisibilityViewModel,
+ )
+ }