Move Edit mode to be top level in QS
That way, it doesn't need a GridAnchor. Even if we added a GridAnchor to
EditMode, the problem is that AnimatedContent ends up composing both at
the same time when swapping and STL crashes because there are two
elements with the same name.
Test: manual
Bug: 353254353
Flag: com.android.systemui.qs_ui_refactor_compose_fragment
Change-Id: I71735183f28221b69e4220991b6865b2ae8fbffb
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
index 8e6cb3f..54497f6 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
@@ -124,8 +124,9 @@
}
}
+/** Column containing Brightness and QS tiles. */
@Composable
-private fun SceneScope.QuickSettingsLayout(
+fun SceneScope.QuickSettingsLayout(
viewModel: QuickSettingsContainerViewModel,
modifier: Modifier = Modifier,
) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
index c174038..c807960 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
@@ -26,7 +26,12 @@
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
+import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -88,11 +93,12 @@
import com.android.systemui.qs.composefragment.viewmodel.QSFragmentComposeViewModel
import com.android.systemui.qs.flags.QSComposeFragment
import com.android.systemui.qs.footer.ui.compose.FooterActions
+import com.android.systemui.qs.panels.ui.compose.EditMode
import com.android.systemui.qs.panels.ui.compose.QuickQuickSettings
import com.android.systemui.qs.shared.ui.ElementKeys
+import com.android.systemui.qs.ui.composable.QuickSettingsLayout
import com.android.systemui.qs.ui.composable.QuickSettingsShade
import com.android.systemui.qs.ui.composable.QuickSettingsTheme
-import com.android.systemui.qs.ui.composable.ShadeBody
import com.android.systemui.res.R
import com.android.systemui.util.LifecycleFragment
import com.android.systemui.util.asIndenting
@@ -200,32 +206,36 @@
}
.graphicsLayer { elevation = 4.dp.toPx() },
) {
- val sceneState = remember {
- MutableSceneTransitionLayoutState(
- viewModel.expansionState.value.toIdleSceneKey(),
- transitions =
- transitions {
- from(QuickQuickSettings, QuickSettings) {
- quickQuickSettingsToQuickSettings()
- }
- },
- )
- }
-
- LaunchedEffect(Unit) {
- synchronizeQsState(
- sceneState,
- viewModel.expansionState.map { it.progress },
- )
- }
-
- SceneTransitionLayout(
- state = sceneState,
- modifier = Modifier.fillMaxSize(),
- ) {
- scene(QuickSettings) { QuickSettingsElement() }
-
- scene(QuickQuickSettings) { QuickQuickSettingsElement() }
+ val isEditing by
+ viewModel.containerViewModel.editModeViewModel.isEditing
+ .collectAsStateWithLifecycle()
+ val animationSpecEditMode = tween<Float>(EDIT_MODE_TIME_MILLIS)
+ AnimatedContent(
+ targetState = isEditing,
+ transitionSpec = {
+ fadeIn(animationSpecEditMode) togetherWith
+ fadeOut(animationSpecEditMode)
+ },
+ label = "EditModeAnimatedContent",
+ ) { editing ->
+ if (editing) {
+ val qqsPadding by
+ viewModel.qqsHeaderHeight.collectAsStateWithLifecycle()
+ EditMode(
+ viewModel = viewModel.containerViewModel.editModeViewModel,
+ modifier =
+ Modifier.fillMaxWidth()
+ .padding(top = { qqsPadding })
+ .padding(
+ horizontal = {
+ QuickSettingsShade.Dimensions.Padding
+ .roundToPx()
+ }
+ ),
+ )
+ } else {
+ CollapsableQuickSettingsSTL()
+ }
}
}
}
@@ -233,6 +243,36 @@
}
}
+ /**
+ * STL that contains both QQS (tiles) and QS (brightness, tiles, footer actions), but no Edit
+ * mode. It tracks [QSFragmentComposeViewModel.expansionState] to drive the transition between
+ * [SceneKeys.QuickQuickSettings] and [SceneKeys.QuickSettings].
+ */
+ @Composable
+ private fun CollapsableQuickSettingsSTL() {
+ val sceneState = remember {
+ MutableSceneTransitionLayoutState(
+ viewModel.expansionState.value.toIdleSceneKey(),
+ transitions =
+ transitions {
+ from(QuickQuickSettings, QuickSettings) {
+ quickQuickSettingsToQuickSettings()
+ }
+ },
+ )
+ }
+
+ LaunchedEffect(Unit) {
+ synchronizeQsState(sceneState, viewModel.expansionState.map { it.progress })
+ }
+
+ SceneTransitionLayout(state = sceneState, modifier = Modifier.fillMaxSize()) {
+ scene(QuickSettings) { QuickSettingsElement() }
+
+ scene(QuickQuickSettings) { QuickQuickSettingsElement() }
+ }
+ }
+
override fun setPanelView(notificationPanelView: QS.HeightListener?) {
heightListener.value = notificationPanelView
}
@@ -445,7 +485,7 @@
qsContainerController,
viewModel.containerViewModel.editModeViewModel.isEditing,
) {
- setCustomizerShowing(it)
+ setCustomizerShowing(it, EDIT_MODE_TIME_MILLIS.toLong())
}
}
}
@@ -519,7 +559,10 @@
Spacer(
modifier = Modifier.height { qqsPadding + qsExtraPadding.roundToPx() }
)
- ShadeBody(viewModel = viewModel.containerViewModel)
+ QuickSettingsLayout(
+ viewModel = viewModel.containerViewModel,
+ modifier = Modifier.sysuiResTag("quick_settings_panel"),
+ )
}
}
QuickSettingsTheme {
@@ -717,3 +760,5 @@
finishCompletable.complete(Unit)
}
}
+
+private const val EDIT_MODE_TIME_MILLIS = 500