Loading packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationLockscreenScrim.kt +9 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember Loading Loading @@ -99,12 +98,18 @@ fun SceneScope.NotificationLockscreenScrim( } } val isBouncerToLockscreen = layoutState.currentTransition?.isTransitioning( from = Scenes.Bouncer, to = Scenes.Lockscreen, ) ?: false Box( modifier .fillMaxSize() .element(Notifications.Elements.NotificationScrim) .element(viewModel.element.key) .graphicsLayer { alpha = alphaAnimatable.value } .background(MaterialTheme.colorScheme.surface) .background(viewModel.element.color(isBouncerToLockscreen)) ) } Loading @@ -112,7 +117,7 @@ private fun shouldShowScrimFadeOut( currentTransition: TransitionState.Transition, shadeMode: ShadeMode, ): Boolean { return shadeMode == ShadeMode.Single && return shadeMode != ShadeMode.Dual && currentTransition.isInitiatedByUserInput && (currentTransition.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) || currentTransition.isTransitioning(from = Scenes.Bouncer, to = Scenes.Lockscreen)) Loading packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt +4 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ val SceneContainerTransitions = transitions { from(Scenes.Lockscreen, to = Scenes.Shade) { lockscreenToShadeTransition() } from(Scenes.Lockscreen, to = Scenes.Shade, key = ToSplitShade) { lockscreenToSplitShadeTransition() sharedElement(Shade.Elements.BackgroundScrim, enabled = false) } from(Scenes.Lockscreen, to = Scenes.Shade, key = SlightlyFasterShadeCollapse) { lockscreenToShadeTransition(durationScale = 0.9) Loading @@ -96,6 +97,9 @@ val SceneContainerTransitions = transitions { sharedElement(Notifications.Elements.NotificationStackPlaceholder, enabled = false) sharedElement(Notifications.Elements.HeadsUpNotificationPlaceholder, enabled = false) } from(Scenes.Shade, to = Scenes.Lockscreen, key = ToSplitShade) { reversed { lockscreenToSplitShadeTransition() } } from(Scenes.Communal, to = Scenes.Shade) { communalToShadeTransition() } from(Scenes.Communal, to = Scenes.Bouncer) { communalToBouncerTransition() } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationLockscreenScrimViewModel.kt +74 −2 Original line number Diff line number Diff line Loading @@ -16,14 +16,31 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.getValue import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import com.android.app.tracing.coroutines.coroutineScopeTraced import com.android.compose.animation.scene.ElementKey import com.android.systemui.dump.DumpManager import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.Hydrator import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.res.R import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.ui.composable.Shade import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor import com.android.systemui.util.kotlin.ActivatableFlowDumper import com.android.systemui.util.kotlin.ActivatableFlowDumperImpl import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch class NotificationLockscreenScrimViewModel @AssistedInject Loading @@ -35,7 +52,17 @@ constructor( ActivatableFlowDumper by ActivatableFlowDumperImpl(dumpManager, "NotificationScrollViewModel"), ExclusiveActivatable() { val shadeMode = shadeInteractor.shadeMode private val hydrator = Hydrator("NotificationLockscreenScrimViewModel.hydrator") val shadeMode: StateFlow<ShadeMode> = shadeInteractor.shadeMode /** The [ElementKey] to use for the scrim. */ val element: ElementViewModel by hydrator.hydratedStateOf( traceName = "elementKey", initialValue = element(shadeMode.value), source = shadeMode.map { element(it) }, ) /** Sets the alpha to apply to the NSSL for fade-in on lockscreen */ fun setAlphaForLockscreenFadeIn(alpha: Float) { Loading @@ -43,11 +70,56 @@ constructor( } override suspend fun onActivated(): Nothing { activateFlowDumper() coroutineScopeTraced("NotificationLockscreenScrimViewModel") { launch { activateFlowDumper() } launch { hydrator.activate() } awaitCancellation() } } private fun element(shadeMode: ShadeMode): ElementViewModel { return if (shadeMode == ShadeMode.Single) { ElementViewModel( key = Notifications.Elements.NotificationScrim, color = { SingleShadeBackground }, ) } else { ElementViewModel( key = Shade.Elements.BackgroundScrim, color = { isBouncerToLockscreen -> if (isBouncerToLockscreen) { SplitShadeBouncerToLockscreenBackground } else { SplitShadeDefaultBackground } }, ) } } /** Models the UI state of the scrim. */ data class ElementViewModel( /** The [ElementKey] to use with an `element` modifier. */ val key: ElementKey, /** A function that returns the color to use within a `background` modifier. */ val color: @Composable (isBouncerToLockscreen: Boolean) -> Color, ) @AssistedFactory interface Factory { fun create(): NotificationLockscreenScrimViewModel } companion object { private val SingleShadeBackground: Color @Composable @ReadOnlyComposable get() = MaterialTheme.colorScheme.surface private val SplitShadeBouncerToLockscreenBackground: Color @Composable @ReadOnlyComposable get() = MaterialTheme.colorScheme.surface private val SplitShadeDefaultBackground: Color @Composable @ReadOnlyComposable get() = colorResource(R.color.shade_scrim_background_dark) } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationLockscreenScrim.kt +9 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember Loading Loading @@ -99,12 +98,18 @@ fun SceneScope.NotificationLockscreenScrim( } } val isBouncerToLockscreen = layoutState.currentTransition?.isTransitioning( from = Scenes.Bouncer, to = Scenes.Lockscreen, ) ?: false Box( modifier .fillMaxSize() .element(Notifications.Elements.NotificationScrim) .element(viewModel.element.key) .graphicsLayer { alpha = alphaAnimatable.value } .background(MaterialTheme.colorScheme.surface) .background(viewModel.element.color(isBouncerToLockscreen)) ) } Loading @@ -112,7 +117,7 @@ private fun shouldShowScrimFadeOut( currentTransition: TransitionState.Transition, shadeMode: ShadeMode, ): Boolean { return shadeMode == ShadeMode.Single && return shadeMode != ShadeMode.Dual && currentTransition.isInitiatedByUserInput && (currentTransition.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) || currentTransition.isTransitioning(from = Scenes.Bouncer, to = Scenes.Lockscreen)) Loading
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt +4 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ val SceneContainerTransitions = transitions { from(Scenes.Lockscreen, to = Scenes.Shade) { lockscreenToShadeTransition() } from(Scenes.Lockscreen, to = Scenes.Shade, key = ToSplitShade) { lockscreenToSplitShadeTransition() sharedElement(Shade.Elements.BackgroundScrim, enabled = false) } from(Scenes.Lockscreen, to = Scenes.Shade, key = SlightlyFasterShadeCollapse) { lockscreenToShadeTransition(durationScale = 0.9) Loading @@ -96,6 +97,9 @@ val SceneContainerTransitions = transitions { sharedElement(Notifications.Elements.NotificationStackPlaceholder, enabled = false) sharedElement(Notifications.Elements.HeadsUpNotificationPlaceholder, enabled = false) } from(Scenes.Shade, to = Scenes.Lockscreen, key = ToSplitShade) { reversed { lockscreenToSplitShadeTransition() } } from(Scenes.Communal, to = Scenes.Shade) { communalToShadeTransition() } from(Scenes.Communal, to = Scenes.Bouncer) { communalToBouncerTransition() } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationLockscreenScrimViewModel.kt +74 −2 Original line number Diff line number Diff line Loading @@ -16,14 +16,31 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.getValue import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import com.android.app.tracing.coroutines.coroutineScopeTraced import com.android.compose.animation.scene.ElementKey import com.android.systemui.dump.DumpManager import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.Hydrator import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.res.R import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.ui.composable.Shade import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor import com.android.systemui.util.kotlin.ActivatableFlowDumper import com.android.systemui.util.kotlin.ActivatableFlowDumperImpl import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch class NotificationLockscreenScrimViewModel @AssistedInject Loading @@ -35,7 +52,17 @@ constructor( ActivatableFlowDumper by ActivatableFlowDumperImpl(dumpManager, "NotificationScrollViewModel"), ExclusiveActivatable() { val shadeMode = shadeInteractor.shadeMode private val hydrator = Hydrator("NotificationLockscreenScrimViewModel.hydrator") val shadeMode: StateFlow<ShadeMode> = shadeInteractor.shadeMode /** The [ElementKey] to use for the scrim. */ val element: ElementViewModel by hydrator.hydratedStateOf( traceName = "elementKey", initialValue = element(shadeMode.value), source = shadeMode.map { element(it) }, ) /** Sets the alpha to apply to the NSSL for fade-in on lockscreen */ fun setAlphaForLockscreenFadeIn(alpha: Float) { Loading @@ -43,11 +70,56 @@ constructor( } override suspend fun onActivated(): Nothing { activateFlowDumper() coroutineScopeTraced("NotificationLockscreenScrimViewModel") { launch { activateFlowDumper() } launch { hydrator.activate() } awaitCancellation() } } private fun element(shadeMode: ShadeMode): ElementViewModel { return if (shadeMode == ShadeMode.Single) { ElementViewModel( key = Notifications.Elements.NotificationScrim, color = { SingleShadeBackground }, ) } else { ElementViewModel( key = Shade.Elements.BackgroundScrim, color = { isBouncerToLockscreen -> if (isBouncerToLockscreen) { SplitShadeBouncerToLockscreenBackground } else { SplitShadeDefaultBackground } }, ) } } /** Models the UI state of the scrim. */ data class ElementViewModel( /** The [ElementKey] to use with an `element` modifier. */ val key: ElementKey, /** A function that returns the color to use within a `background` modifier. */ val color: @Composable (isBouncerToLockscreen: Boolean) -> Color, ) @AssistedFactory interface Factory { fun create(): NotificationLockscreenScrimViewModel } companion object { private val SingleShadeBackground: Color @Composable @ReadOnlyComposable get() = MaterialTheme.colorScheme.surface private val SplitShadeBouncerToLockscreenBackground: Color @Composable @ReadOnlyComposable get() = MaterialTheme.colorScheme.surface private val SplitShadeDefaultBackground: Color @Composable @ReadOnlyComposable get() = colorResource(R.color.shade_scrim_background_dark) } }