Merge "[QSDetailedView] Move Composable Rendering out from TileDetailsViewModel" into main
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/DetailsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/DetailsViewModelTest.kt
index 98770c7..c5d679f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/DetailsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/DetailsViewModelTest.kt
@@ -62,8 +62,8 @@
val tiles = currentTilesInteractor.currentTiles.value
assertThat(currentTilesInteractor.currentTilesSpecs.size).isEqualTo(2)
- assertThat(tiles!![1].spec).isEqualTo(specNoDetails)
- (tiles!![1].tile as FakeQSTile).hasDetailsViewModel = false
+ assertThat(tiles[1].spec).isEqualTo(specNoDetails)
+ (tiles[1].tile as FakeQSTile).hasDetailsViewModel = false
assertThat(underTest.activeTileDetails).isNull()
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/TileDetailsViewModel.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/TileDetailsViewModel.kt
index eab7d79..be0362f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/TileDetailsViewModel.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/TileDetailsViewModel.kt
@@ -16,17 +16,10 @@
package com.android.systemui.plugins.qs
-import androidx.compose.runtime.Composable
-
/**
* The base view model class for rendering the Tile's TileDetailsView.
*/
abstract class TileDetailsViewModel {
-
- // The view content of this tile details view.
- @Composable
- abstract fun GetContentView()
-
// The callback when the settings button is clicked. Currently this is the same as the on tile
// long press callback
abstract fun clickOnSettingsButton()
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContent.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContent.kt
new file mode 100644
index 0000000..8bc9299
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContent.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.qsdialog
+
+import android.view.LayoutInflater
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.viewinterop.AndroidView
+import com.android.systemui.res.R
+
+@Composable
+fun BluetoothDetailsContent() {
+ AndroidView(
+ modifier = Modifier.fillMaxSize(),
+ factory = { context ->
+ // Inflate with the existing dialog xml layout
+ LayoutInflater.from(context).inflate(R.layout.bluetooth_tile_dialog, null)
+ // TODO: b/378513956 - Implement the bluetooth details view
+ },
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsViewModel.kt
index 9dd3b6d..ac4d82a 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsViewModel.kt
@@ -16,30 +16,11 @@
package com.android.systemui.bluetooth.qsdialog
-import android.view.LayoutInflater
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.viewinterop.AndroidView
import com.android.systemui.plugins.qs.TileDetailsViewModel
-import com.android.systemui.res.R
class BluetoothDetailsViewModel(onLongClick: () -> Unit) : TileDetailsViewModel() {
private val _onLongClick = onLongClick
- @Composable
- override fun GetContentView() {
- AndroidView(
- modifier = Modifier.fillMaxWidth().fillMaxHeight(),
- factory = { context ->
- // Inflate with the existing dialog xml layout
- LayoutInflater.from(context).inflate(R.layout.bluetooth_tile_dialog, null)
- // TODO: b/378513956 - Implement the bluetooth details view
- },
- )
- }
-
override fun clickOnSettingsButton() {
_onLongClick()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileDetails.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileDetails.kt
index 30fb50d..1233a2f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileDetails.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileDetails.kt
@@ -38,8 +38,17 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
+import com.android.systemui.bluetooth.qsdialog.BluetoothDetailsContent
+import com.android.systemui.bluetooth.qsdialog.BluetoothDetailsViewModel
+import com.android.systemui.plugins.qs.TileDetailsViewModel
import com.android.systemui.qs.flags.QsDetailedView
import com.android.systemui.qs.panels.ui.viewmodel.DetailsViewModel
+import com.android.systemui.qs.tiles.dialog.InternetDetailsContent
+import com.android.systemui.qs.tiles.dialog.InternetDetailsViewModel
+import com.android.systemui.qs.tiles.dialog.ModesDetailsContent
+import com.android.systemui.qs.tiles.dialog.ModesDetailsViewModel
+import com.android.systemui.qs.tiles.dialog.ScreenRecordDetailsContent
+import com.android.systemui.qs.tiles.dialog.ScreenRecordDetailsViewModel
@Composable
fun TileDetails(modifier: Modifier = Modifier, detailsViewModel: DetailsViewModel) {
@@ -107,7 +116,17 @@
style = MaterialTheme.typography.titleSmall,
)
}
- tileDetailedViewModel.GetContentView()
+ MapTileDetailsContent(tileDetailedViewModel)
+ }
+}
+
+@Composable
+private fun MapTileDetailsContent(tileDetailsViewModel: TileDetailsViewModel) {
+ when (tileDetailsViewModel) {
+ is InternetDetailsViewModel -> InternetDetailsContent(tileDetailsViewModel)
+ is ScreenRecordDetailsViewModel -> ScreenRecordDetailsContent(tileDetailsViewModel)
+ is BluetoothDetailsViewModel -> BluetoothDetailsContent()
+ is ModesDetailsViewModel -> ModesDetailsContent(tileDetailsViewModel)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContent.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContent.kt
new file mode 100644
index 0000000..7d396c5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContent.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2025 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.tiles.dialog
+
+import android.view.LayoutInflater
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.viewinterop.AndroidView
+import com.android.systemui.res.R
+
+@Composable
+fun InternetDetailsContent(viewModel: InternetDetailsViewModel) {
+ val coroutineScope = rememberCoroutineScope()
+ val context = LocalContext.current
+
+ val internetDetailsContentManager = remember {
+ viewModel.contentManagerFactory.create(
+ canConfigMobileData = viewModel.getCanConfigMobileData(),
+ canConfigWifi = viewModel.getCanConfigWifi(),
+ coroutineScope = coroutineScope,
+ context = context,
+ )
+ }
+
+ AndroidView(
+ modifier = Modifier.fillMaxSize(),
+ factory = { context ->
+ // Inflate with the existing dialog xml layout and bind it with the manager
+ val view =
+ LayoutInflater.from(context).inflate(R.layout.internet_connectivity_dialog, null)
+ internetDetailsContentManager.bind(view)
+
+ view
+ // TODO: b/377388104 - Polish the internet details view UI
+ },
+ onRelease = { internetDetailsContentManager.unBind() },
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
index df4dddb..0ed56f6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
@@ -16,18 +16,7 @@
package com.android.systemui.qs.tiles.dialog
-import android.util.Log
-import android.view.LayoutInflater
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.viewinterop.AndroidView
import com.android.systemui.plugins.qs.TileDetailsViewModel
-import com.android.systemui.res.R
import com.android.systemui.statusbar.connectivity.AccessPointController
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@@ -37,45 +26,9 @@
@AssistedInject
constructor(
private val accessPointController: AccessPointController,
- private val contentManagerFactory: InternetDetailsContentManager.Factory,
+ val contentManagerFactory: InternetDetailsContentManager.Factory,
@Assisted private val onLongClick: () -> Unit,
) : TileDetailsViewModel() {
- private lateinit var internetDetailsContentManager: InternetDetailsContentManager
-
- @Composable
- override fun GetContentView() {
- val coroutineScope = rememberCoroutineScope()
- val context = LocalContext.current
-
- internetDetailsContentManager = remember {
- contentManagerFactory.create(
- canConfigMobileData = accessPointController.canConfigMobileData(),
- canConfigWifi = accessPointController.canConfigWifi(),
- coroutineScope = coroutineScope,
- context = context,
- )
- }
- AndroidView(
- modifier = Modifier.fillMaxWidth().fillMaxHeight(),
- factory = { context ->
- // Inflate with the existing dialog xml layout and bind it with the manager
- val view =
- LayoutInflater.from(context)
- .inflate(R.layout.internet_connectivity_dialog, null)
- internetDetailsContentManager.bind(view)
-
- view
- // TODO: b/377388104 - Polish the internet details view UI
- },
- onRelease = {
- internetDetailsContentManager.unBind()
- if (DEBUG) {
- Log.d(TAG, "onRelease")
- }
- },
- )
- }
-
override fun clickOnSettingsButton() {
onLongClick()
}
@@ -96,13 +49,16 @@
return "Tab a network to connect"
}
+ fun getCanConfigMobileData(): Boolean {
+ return accessPointController.canConfigMobileData()
+ }
+
+ fun getCanConfigWifi(): Boolean {
+ return accessPointController.canConfigWifi()
+ }
+
@AssistedFactory
interface Factory {
fun create(onLongClick: () -> Unit): InternetDetailsViewModel
}
-
- companion object {
- private const val TAG = "InternetDetailsVModel"
- private val DEBUG: Boolean = Log.isLoggable(TAG, Log.DEBUG)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsContent.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsContent.kt
new file mode 100644
index 0000000..c5ecaff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsContent.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2025 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.tiles.dialog
+
+import androidx.compose.runtime.Composable
+import com.android.systemui.statusbar.policy.ui.dialog.composable.ModeTileGrid
+
+@Composable
+fun ModesDetailsContent(viewModel: ModesDetailsViewModel) {
+ // TODO(b/378513940): Finish implementing this function.
+ ModeTileGrid(viewModel = viewModel.viewModel)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.kt
index 511597d..9a39c3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.kt
@@ -16,22 +16,14 @@
package com.android.systemui.qs.tiles.dialog
-import androidx.compose.runtime.Composable
import com.android.systemui.plugins.qs.TileDetailsViewModel
-import com.android.systemui.statusbar.policy.ui.dialog.composable.ModeTileGrid
import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel
/** The view model used for the modes details view in the Quick Settings */
class ModesDetailsViewModel(
private val onSettingsClick: () -> Unit,
- private val viewModel: ModesDialogViewModel,
+ val viewModel: ModesDialogViewModel,
) : TileDetailsViewModel() {
- @Composable
- override fun GetContentView() {
- // TODO(b/378513940): Finish implementing this function.
- ModeTileGrid(viewModel = viewModel)
- }
-
override fun clickOnSettingsButton() {
onSettingsClick()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsContent.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsContent.kt
new file mode 100644
index 0000000..bf1a51d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsContent.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2025 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.tiles.dialog
+
+import android.view.LayoutInflater
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.viewinterop.AndroidView
+import com.android.systemui.res.R
+import com.android.systemui.screenrecord.ScreenRecordPermissionViewBinder
+
+@Composable
+fun ScreenRecordDetailsContent(viewModel: ScreenRecordDetailsViewModel) {
+ // TODO(b/378514312): Finish implementing this function.
+
+ if (viewModel.recordingController.isScreenCaptureDisabled) {
+ // TODO(b/388345506): Show disabled page here.
+ return
+ }
+
+ val viewBinder: ScreenRecordPermissionViewBinder = remember {
+ viewModel.recordingController.createScreenRecordPermissionViewBinder(
+ viewModel.onStartRecordingClicked
+ )
+ }
+
+ AndroidView(
+ modifier = Modifier.fillMaxWidth().fillMaxHeight(),
+ factory = { context ->
+ // Inflate with the existing dialog xml layout
+ val view = LayoutInflater.from(context).inflate(R.layout.screen_share_dialog, null)
+ viewBinder.bind(view)
+
+ view
+ // TODO(b/378514473): Revamp the details view according to the spec.
+ },
+ onRelease = { viewBinder.unbind() },
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt
index 54e4a52..c84ddb6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt
@@ -16,49 +16,15 @@
package com.android.systemui.qs.tiles.dialog
-import android.view.LayoutInflater
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.viewinterop.AndroidView
import com.android.systemui.plugins.qs.TileDetailsViewModel
-import com.android.systemui.res.R
import com.android.systemui.screenrecord.RecordingController
-import com.android.systemui.screenrecord.ScreenRecordPermissionViewBinder
/** The view model used for the screen record details view in the Quick Settings */
class ScreenRecordDetailsViewModel(
- private val recordingController: RecordingController,
- private val onStartRecordingClicked: Runnable,
+ val recordingController: RecordingController,
+ val onStartRecordingClicked: Runnable,
) : TileDetailsViewModel() {
- private var viewBinder: ScreenRecordPermissionViewBinder =
- recordingController.createScreenRecordPermissionViewBinder(onStartRecordingClicked)
-
- @Composable
- override fun GetContentView() {
- // TODO(b/378514312): Finish implementing this function.
-
- if (recordingController.isScreenCaptureDisabled) {
- // TODO(b/388345506): Show disabled page here.
- return
- }
-
- AndroidView(
- modifier = Modifier.fillMaxWidth().fillMaxHeight(),
- factory = { context ->
- // Inflate with the existing dialog xml layout
- val view = LayoutInflater.from(context).inflate(R.layout.screen_share_dialog, null)
- viewBinder.bind(view)
-
- view
- // TODO(b/378514473): Revamp the details view according to the spec.
- },
- onRelease = { viewBinder.unbind() },
- )
- }
-
override fun clickOnSettingsButton() {
// No settings button in this tile.
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeTileDetailsContent.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeTileDetailsContent.kt
new file mode 100644
index 0000000..84a7364
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeTileDetailsContent.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2025 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
+
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+
+@Composable
+fun FakeTileDetailsContent() {
+ Text(
+ text = "Fake details content",
+ textAlign = TextAlign.Center,
+ fontWeight = FontWeight.ExtraBold,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeTileDetailsViewModel.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeTileDetailsViewModel.kt
index 555f019..4f8d5a1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeTileDetailsViewModel.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeTileDetailsViewModel.kt
@@ -16,24 +16,11 @@
package com.android.systemui.qs
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.style.TextAlign
import com.android.systemui.plugins.qs.TileDetailsViewModel
class FakeTileDetailsViewModel(var tileSpec: String?) : TileDetailsViewModel() {
private var _clickOnSettingsButton = 0
- @Composable
- override fun GetContentView() {
- Text(
- text = "Fake details content",
- textAlign = TextAlign.Center,
- fontWeight = FontWeight.ExtraBold,
- )
- }
-
override fun clickOnSettingsButton() {
_clickOnSettingsButton++
}