1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.qs.panels.ui.viewmodel 18 19 import androidx.compose.runtime.derivedStateOf 20 import androidx.compose.runtime.getValue 21 import com.android.systemui.haptics.msdl.qs.TileHapticsViewModelFactoryProvider 22 import com.android.systemui.lifecycle.ExclusiveActivatable 23 import com.android.systemui.lifecycle.Hydrator 24 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QQS 25 import com.android.systemui.qs.panels.domain.interactor.QuickQuickSettingsRowInteractor 26 import com.android.systemui.qs.panels.shared.model.SizedTileImpl 27 import com.android.systemui.qs.panels.shared.model.splitInRowsSequence 28 import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor 29 import com.android.systemui.qs.pipeline.shared.TileSpec 30 import dagger.assisted.AssistedFactory 31 import dagger.assisted.AssistedInject 32 import kotlinx.coroutines.awaitCancellation 33 import kotlinx.coroutines.coroutineScope 34 import kotlinx.coroutines.launch 35 36 class QuickQuickSettingsViewModel 37 @AssistedInject 38 constructor( 39 tilesInteractor: CurrentTilesInteractor, 40 qsColumnsViewModelFactory: QSColumnsViewModel.Factory, 41 quickQuickSettingsRowInteractor: QuickQuickSettingsRowInteractor, 42 mediaInRowInLandscapeViewModelFactory: MediaInRowInLandscapeViewModel.Factory, 43 val squishinessViewModel: TileSquishinessViewModel, 44 iconTilesViewModel: IconTilesViewModel, 45 val tileHapticsViewModelFactoryProvider: TileHapticsViewModelFactoryProvider, 46 ) : ExclusiveActivatable() { 47 48 private val hydrator = Hydrator("QuickQuickSettingsViewModel") 49 private val qsColumnsViewModel = qsColumnsViewModelFactory.create(LOCATION_QQS) 50 private val mediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QQS) 51 52 val columns: Int 53 get() = qsColumnsViewModel.columns 54 55 private val largeTiles by 56 hydrator.hydratedStateOf(traceName = "largeTiles", source = iconTilesViewModel.largeTiles) 57 58 private val rows: Int 59 get() = 60 if (mediaInRowViewModel.shouldMediaShowInRow) { 61 rowsWithoutMedia * 2 62 } else { 63 rowsWithoutMedia 64 } 65 66 private val rowsWithoutMedia by 67 hydrator.hydratedStateOf( 68 traceName = "rowsWithoutMedia", 69 initialValue = quickQuickSettingsRowInteractor.defaultRows, 70 source = quickQuickSettingsRowInteractor.rows, 71 ) 72 73 private val largeTilesSpan by 74 hydrator.hydratedStateOf( 75 traceName = "largeTilesSpan", 76 source = iconTilesViewModel.largeTilesSpan, 77 ) 78 79 private val currentTiles by 80 hydrator.hydratedStateOf(traceName = "currentTiles", source = tilesInteractor.currentTiles) 81 <lambda>null82 val tileViewModels by derivedStateOf { 83 currentTiles 84 .map { SizedTileImpl(TileViewModel(it.tile, it.spec), it.spec.width()) } 85 .let { splitInRowsSequence(it, columns).take(rows).toList().flatten() } 86 } 87 onActivatednull88 override suspend fun onActivated(): Nothing { 89 coroutineScope { 90 launch { hydrator.activate() } 91 launch { qsColumnsViewModel.activate() } 92 launch { mediaInRowViewModel.activate() } 93 awaitCancellation() 94 } 95 } 96 97 @AssistedFactory 98 interface Factory { createnull99 fun create(): QuickQuickSettingsViewModel 100 } 101 102 private fun TileSpec.width(): Int = if (largeTiles.contains(this)) largeTilesSpan else 1 103 } 104