diff options
4 files changed, 78 insertions, 9 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt index 4959ead3103d..a2426a6acff2 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt @@ -66,6 +66,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.util.lerp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.ElementKey +import com.android.compose.animation.scene.LowestZIndexScenePicker import com.android.compose.animation.scene.NestedScrollBehavior import com.android.compose.animation.scene.SceneScope import com.android.compose.modifiers.thenIf @@ -90,7 +91,8 @@ object Notifications { object Elements { val NotificationScrim = ElementKey("NotificationScrim") val NotificationStackPlaceholder = ElementKey("NotificationStackPlaceholder") - val HeadsUpNotificationPlaceholder = ElementKey("HeadsUpNotificationPlaceholder") + val HeadsUpNotificationPlaceholder = + ElementKey("HeadsUpNotificationPlaceholder", scenePicker = LowestZIndexScenePicker) val ShelfSpace = ElementKey("ShelfSpace") } @@ -113,10 +115,10 @@ fun SceneScope.HeadsUpNotificationSpace( modifier: Modifier = Modifier, isPeekFromBottom: Boolean = false, ) { - Element( - Notifications.Elements.HeadsUpNotificationPlaceholder, + Box( modifier = modifier + .element(Notifications.Elements.HeadsUpNotificationPlaceholder) .fillMaxWidth() .notificationHeadsUpHeight(stackScrollView) .debugBackground(viewModel, DEBUG_HUN_COLOR) @@ -130,9 +132,7 @@ fun SceneScope.HeadsUpNotificationSpace( // Note: boundsInWindow doesn't scroll off the screen stackScrollView.setHeadsUpTop(boundsInWindow.top) } - ) { - content {} - } + ) } /** Adds the space where notification stack should appear in the scene. */ @@ -177,6 +177,7 @@ fun SceneScope.NotificationScrollingStack( shouldPunchHoleBehindScrim: Boolean, shouldFillMaxSize: Boolean = true, shouldReserveSpaceForNavBar: Boolean = true, + shouldIncludeHeadsUpSpace: Boolean = true, shadeMode: ShadeMode, modifier: Modifier = Modifier, ) { @@ -366,7 +367,9 @@ fun SceneScope.NotificationScrollingStack( .onSizeChanged { size -> stackHeight.intValue = size.height }, ) } - HeadsUpNotificationSpace(stackScrollView = stackScrollView, viewModel = viewModel) + if (shouldIncludeHeadsUpSpace) { + HeadsUpNotificationSpace(stackScrollView = stackScrollView, viewModel = viewModel) + } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index 1b49b6702275..644040db7c8e 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -42,6 +42,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.rememberScrollState @@ -62,6 +63,7 @@ import androidx.compose.ui.layout.layoutId import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.colorResource +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.SceneScope @@ -82,6 +84,7 @@ import com.android.systemui.media.controls.ui.controller.MediaCarouselController import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.media.dagger.MediaModule import com.android.systemui.notifications.ui.composable.HeadsUpNotificationSpace +import com.android.systemui.notifications.ui.composable.NotificationScrollingStack import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.InQS @@ -90,6 +93,7 @@ import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene +import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.ui.composable.CollapsedShadeHeader import com.android.systemui.shade.ui.composable.ExpandedShadeHeader import com.android.systemui.shade.ui.composable.Shade @@ -102,6 +106,7 @@ import com.android.systemui.statusbar.phone.ui.TintedIconManager import dagger.Lazy import javax.inject.Inject import javax.inject.Named +import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn @@ -400,5 +405,16 @@ private fun SceneScope.QuickSettingsScene( modifier = Modifier.align(Alignment.BottomCenter), isPeekFromBottom = true, ) + NotificationScrollingStack( + shadeSession = shadeSession, + stackScrollView = notificationStackScrollView, + viewModel = notificationsPlaceholderViewModel, + maxScrimTop = { screenHeight }, + shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim, + shouldIncludeHeadsUpSpace = false, + shadeMode = ShadeMode.Single, + modifier = + Modifier.fillMaxWidth().offset { IntOffset(x = 0, y = screenHeight.roundToInt()) }, + ) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt index ca4434d233a6..cc3fdc592b45 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt @@ -32,6 +32,8 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape +import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_DELAYED_STACK_FADE_IN +import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationScrollViewModel import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel import com.android.systemui.testKosmos @@ -208,4 +210,50 @@ class NotificationStackAppearanceIntegrationTest : SysuiTestCase() { assertThat(expandFraction).isEqualTo(1f) assertThat(isScrollable).isFalse() } + + @Test + fun shadeExpansion_goneToQs() = + testScope.runTest { + val transitionState = + MutableStateFlow<ObservableTransitionState>( + ObservableTransitionState.Idle(currentScene = Scenes.Gone) + ) + sceneInteractor.setTransitionState(transitionState) + val expandFraction by collectLastValue(scrollViewModel.expandFraction) + assertThat(expandFraction).isEqualTo(0f) + + fakeSceneDataSource.changeScene(toScene = Scenes.Gone) + val isScrollable by collectLastValue(scrollViewModel.isScrollable) + assertThat(isScrollable).isFalse() + + fakeSceneDataSource.pause() + + sceneInteractor.changeScene(Scenes.QuickSettings, "reason") + val transitionProgress = MutableStateFlow(0f) + transitionState.value = + ObservableTransitionState.Transition( + fromScene = Scenes.Gone, + toScene = Scenes.QuickSettings, + currentScene = flowOf(Scenes.QuickSettings), + progress = transitionProgress, + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + ) + val steps = 10 + repeat(steps) { repetition -> + val progress = (1f / steps) * (repetition + 1) + transitionProgress.value = progress + runCurrent() + assertThat(expandFraction) + .isEqualTo( + (progress / EXPANSION_FOR_MAX_SCRIM_ALPHA - + EXPANSION_FOR_DELAYED_STACK_FADE_IN) + .coerceIn(0f, 1f) + ) + } + + fakeSceneDataSource.unpause(expectedScene = Scenes.QuickSettings) + assertThat(expandFraction).isEqualTo(1f) + assertThat(isScrollable).isFalse() + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt index a21db12db80b..ebb0d7dcee10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt @@ -90,8 +90,10 @@ constructor( 1f } else if ( shadeMode != ShadeMode.Split && - transitionState.fromScene in SceneFamilies.Home && - transitionState.toScene in quickSettingsScene + (transitionState.fromScene in SceneFamilies.Home && + transitionState.toScene == quickSettingsScene) || + (transitionState.fromScene == quickSettingsScene && + transitionState.toScene in SceneFamilies.Home) ) { // during QS expansion, increase fraction at same rate as scrim alpha, // but start when scrim alpha is at EXPANSION_FOR_DELAYED_STACK_FADE_IN. |