Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c34465be authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[flexiglass] Consolidate drawBounds updates by HUN space into one place." into main

parents ba1c9398 7d1ee563
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import com.android.compose.animation.scene.ElementContentScope
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.notifications.ui.composable.ConstrainedNotificationStack
import com.android.systemui.notifications.ui.composable.SnoozeableHeadsUpNotificationSpace
import com.android.systemui.plugins.keyguard.ui.composable.elements.LockscreenElement
import com.android.systemui.plugins.keyguard.ui.composable.elements.LockscreenElementContext
import com.android.systemui.plugins.keyguard.ui.composable.elements.LockscreenElementFactory
@@ -98,12 +97,4 @@ constructor(
            modifier = modifier.fillMaxSize(),
        )
    }

    @Composable
    private fun ContentScope.HeadsUpNotifications(modifier: Modifier = Modifier) {
        SnoozeableHeadsUpNotificationSpace(
            stackScrollView = stackScrollView.get(),
            viewModel = rememberViewModel("HeadsUpNotifications") { viewModelFactory.create() },
        )
    }
}
+38 −4
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.toAndroidRectF
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -181,14 +182,18 @@ fun ContentScope.HeadsUpNotificationSpace(
/**
 * A version of [HeadsUpNotificationSpace] that can be swiped up off the top edge of the screen by
 * the user. When swiped up, the heads up notification is snoozed.
 *
 * @param useDrawBounds Whether to communicate drawBounds updated to the [stackScrollView]. This
 *   should be `true` when content rendering the regular stack is not setting draw bounds anymore,
 *   but HUNs can still appear.
 */
@Composable
fun ContentScope.SnoozeableHeadsUpNotificationSpace(
    useDrawBounds: () -> Boolean,
    stackScrollView: NotificationScrollView,
    viewModel: NotificationsPlaceholderViewModel,
    modifier: Modifier = Modifier,
) {

    val isSnoozable by viewModel.isHeadsUpOrAnimatingAway.collectAsStateWithLifecycle(false)

    var scrollOffset by remember { mutableFloatStateOf(0f) }
@@ -229,11 +234,38 @@ fun ContentScope.SnoozeableHeadsUpNotificationSpace(
        }
    }

    // Wait for being Idle on this content, otherwise LaunchedEffect would fire too soon, and
    // another transition could override the NSSL stack bounds.
    val updateDrawBounds = layoutState.transitionState.isIdle() && useDrawBounds()

    LaunchedEffect(updateDrawBounds) {
        if (updateDrawBounds) {
            // Reset the stack bounds to avoid caching these values from the previous Scenes, and
            // not to confuse the StackScrollAlgorithm when it displays a HUN over GONE.
            stackScrollView.apply {
                // use -headsUpInset to allow HUN translation outside bounds for snoozing
                setStackTop(-headsUpInset)
            }
        }
    }

    HeadsUpNotificationSpace(
        stackScrollView = stackScrollView,
        viewModel = viewModel,
        modifier =
            modifier
                .onGloballyPositioned {
                    if (updateDrawBounds) {
                        stackScrollView.updateDrawBounds(
                            it.boundsInWindow().toAndroidRectF().apply {
                                // extend bounds to the screen top to avoid cutting off HUN
                                // transitions
                                top = 0f
                                bottom += headsUpInset
                            }
                        )
                    }
                }
                .absoluteOffset {
                    IntOffset(
                        x = 0,
@@ -836,13 +868,15 @@ private suspend fun scrollNotificationStack(
private fun TransitionState.isOnLockscreen(): Boolean {
    return currentScene == Scenes.Lockscreen && currentOverlays.isEmpty()
}

private fun shouldUseLockscreenStackBounds(state: TransitionState): Boolean {
    return when (state) {
        is TransitionState.Idle -> state.isOnLockscreen()
        is TransitionState.Transition ->
            // Keep using the lockscreen stack bounds when there is no placeholder on the next content
            state.fromContent == Scenes.Lockscreen && state.toContent != Scenes.Shade
                || state.isTransitioningBetween(content = Scenes.Lockscreen, other = Overlays.Bouncer)
            // Keep using the lockscreen stack bounds when there is no placeholder on the next
            // content
            state.fromContent == Scenes.Lockscreen && state.toContent != Scenes.Shade ||
                state.isTransitioningBetween(content = Scenes.Lockscreen, other = Overlays.Bouncer)
    }
}

+8 −46
Original line number Diff line number Diff line
@@ -19,13 +19,8 @@ package com.android.systemui.occluded.ui.composable
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toAndroidRectF
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
@@ -34,7 +29,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.notifications.ui.composable.SnoozeableHeadsUpNotificationSpace
import com.android.systemui.notifications.ui.composable.headsUpTopInset
import com.android.systemui.qs.shared.ui.QuickSettings
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
@@ -46,7 +40,7 @@ import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow

/** The occluded scene shows when a non-dream activity is showing over keyguard */
/** The occluded scene shows when a non-dream activity is showing over the lock screen. */
@SysUISingleton
class OccludedScene
@Inject
@@ -69,49 +63,17 @@ constructor(

    @Composable
    override fun ContentScope.Content(modifier: Modifier) {

        val isIdleAndNotShadeExpanded =
            with(layoutState.transitionState) {
                isIdle(key) &&
                    !isIdle(Overlays.NotificationsShade) &&
                    !isIdle(Overlays.QuickSettingsShade)
            }

        val headsUpInset = with(LocalDensity.current) { headsUpTopInset().toPx() }

        LaunchedEffect(isIdleAndNotShadeExpanded) {
            // Wait for being Idle on this Scene, otherwise LaunchedEffect would fire too soon,
            // and another transition could override the NSSL stack bounds.
            if (isIdleAndNotShadeExpanded) {
                // Reset the stack bounds to avoid caching these values from the previous Scenes,
                // and not to confuse the StackScrollAlgorithm when it displays a HUN over OCCLUDED.
                notificationStackScrollView.get().apply {
                    // use -headsUpInset to allow HUN translation outside bounds for snoozing
                    setStackTop(-headsUpInset)
                }
            }
        }

        animateContentFloatAsState(
            value = QuickSettings.SharedValues.SquishinessValues.OccludedSceneStarting,
            key = QuickSettings.SharedValues.TilesSquishiness,
        )
        Spacer(modifier.fillMaxSize())
        SnoozeableHeadsUpNotificationSpace(
            modifier =
                Modifier.onGloballyPositioned {
                    // Once we are on the non-occluded Lockscreen, the regular stack is not setting
                    // draw bounds anymore, but HUNs can still appear.
                    if (isIdleAndNotShadeExpanded) {
                        notificationStackScrollView
                            .get()
                            .updateDrawBounds(
                                it.boundsInWindow().toAndroidRectF().apply {
                                    // extend bounds to the screen top to avoid cutting off HUN
                                    // transitions
                                    top = 0f
                                }
                            )
            useDrawBounds = {
                with(layoutState.transitionState) {
                    isIdle(key) &&
                        !isIdle(Overlays.NotificationsShade) &&
                        !isIdle(Overlays.QuickSettingsShade)
                }
            },
            stackScrollView = notificationStackScrollView.get(),
+8 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeOverlayActionsView
import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeOverlayContentViewModel
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Overlay
import com.android.systemui.shade.ui.composable.ChipHighlightModel
import com.android.systemui.shade.ui.composable.OverlayShade
@@ -218,6 +219,13 @@ constructor(
                )
            }
            SnoozeableHeadsUpNotificationSpace(
                useDrawBounds = {
                    with(layoutState.transitionState) {
                        // When overlaid on top of the lock screen, drawBounds updates are already
                        // being sent.
                        isIdle(key) && !isIdle(Scenes.Lockscreen)
                    }
                },
                stackScrollView = notificationStackScrollView.get(),
                viewModel = hunPlaceholderViewModel,
            )
+10 −50
Original line number Diff line number Diff line
@@ -19,13 +19,7 @@ package com.android.systemui.scene.ui.composable
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toAndroidRectF
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
@@ -34,7 +28,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.notifications.ui.composable.SnoozeableHeadsUpNotificationSpace
import com.android.systemui.notifications.ui.composable.headsUpTopInset
import com.android.systemui.qs.shared.ui.QuickSettings
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
@@ -47,13 +40,13 @@ import kotlinx.coroutines.flow.Flow

/**
 * "Gone" is not a real scene but rather the absence of scenes when we want to skip showing any
 * content from the scene framework.
 * scene from the scene framework. Overlays from the scene framework may still be shown.
 */
@SysUISingleton
class GoneScene
@Inject
constructor(
    private val notificationStackScrolLView: Lazy<NotificationScrollView>,
    private val notificationStackScrollView: Lazy<NotificationScrollView>,
    private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
    private val viewModelFactory: GoneUserActionsViewModel.Factory,
) : ExclusiveActivatable(), Scene {
@@ -71,53 +64,20 @@ constructor(

    @Composable
    override fun ContentScope.Content(modifier: Modifier) {

        val isIdleAndNotOccluded =
            with(layoutState.transitionState) {
                isIdle(key) &&
                    !isIdle(Overlays.NotificationsShade) &&
                    !isIdle(Overlays.QuickSettingsShade)
            }

        val headsUpInset = with(LocalDensity.current) { headsUpTopInset().toPx() }

        LaunchedEffect(isIdleAndNotOccluded) {
            // Wait for being Idle on this Scene, otherwise LaunchedEffect would fire too soon,
            // and another transition could override the NSSL stack bounds.
            if (isIdleAndNotOccluded) {
                // Reset the stack bounds to avoid caching these values from the previous Scenes,
                // and not to confuse the StackScrollAlgorithm when it displays a HUN over GONE.
                notificationStackScrolLView.get().apply {
                    // use -headsUpInset to allow HUN translation outside bounds for snoozing
                    setStackTop(-headsUpInset)
                }
            }
        }

        animateContentFloatAsState(
            value = QuickSettings.SharedValues.SquishinessValues.GoneSceneStarting,
            key = QuickSettings.SharedValues.TilesSquishiness,
        )
        Spacer(modifier.fillMaxSize())
        SnoozeableHeadsUpNotificationSpace(
            modifier =
                Modifier.onGloballyPositioned {
                    // Once we are on the non-occluded Lockscreen, the regular stack is not setting
                    // draw bounds anymore, but HUNs can still appear.
                    if (isIdleAndNotOccluded) {
                        notificationStackScrolLView
                            .get()
                            .updateDrawBounds(
                                it.boundsInWindow().toAndroidRectF().apply {
                                    // extend bounds to the screen top to avoid cutting off HUN
                                    // transitions
                                    top = 0f
                                    bottom += headsUpInset
                                }
                            )
            useDrawBounds = {
                with(layoutState.transitionState) {
                    isIdle(key) &&
                        !isIdle(Overlays.NotificationsShade) &&
                        !isIdle(Overlays.QuickSettingsShade)
                }
            },
            stackScrollView = notificationStackScrolLView.get(),
            stackScrollView = notificationStackScrollView.get(),
            viewModel =
                rememberViewModel("GoneScene") { notificationsPlaceholderViewModelFactory.create() },
        )