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

Commit 8e40ecb1 authored by Jeff DeCew's avatar Jeff DeCew
Browse files

[flexiglass] Start adding the HeadsUpNotificationSpace to other Composables

Bug: 296118689
Test: atest SystemUITests
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT
Change-Id: I8850201248e083d72943de40fc53e9db613782b1
parent 8aef5589
Loading
Loading
Loading
Loading
+37 −29
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
@@ -60,7 +61,6 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.lerp
import com.android.compose.animation.scene.ElementKey
@@ -68,7 +68,6 @@ import com.android.compose.animation.scene.NestedScrollBehavior
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.height
import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius
import com.android.systemui.notifications.ui.composable.Notifications.Form
import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS
import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
import com.android.systemui.res.R
@@ -81,7 +80,8 @@ import kotlin.math.roundToInt
object Notifications {
    object Elements {
        val NotificationScrim = ElementKey("NotificationScrim")
        val NotificationPlaceholder = ElementKey("NotificationPlaceholder")
        val NotificationStackPlaceholder = ElementKey("NotificationStackPlaceholder")
        val HeadsUpNotificationPlaceholder = ElementKey("HeadsUpNotificationPlaceholder")
        val ShelfSpace = ElementKey("ShelfSpace")
    }

@@ -91,12 +91,6 @@ object Notifications {
        const val EXPANSION_FOR_MAX_CORNER_RADIUS = 0.1f
        const val EXPANSION_FOR_MAX_SCRIM_ALPHA = 0.3f
    }

    enum class Form {
        HunFromTop,
        Stack,
        HunFromBottom,
    }
}

/**
@@ -109,11 +103,27 @@ fun SceneScope.HeadsUpNotificationSpace(
    modifier: Modifier = Modifier,
    isPeekFromBottom: Boolean = false,
) {
    NotificationPlaceholder(
        viewModel = viewModel,
        form = if (isPeekFromBottom) Form.HunFromBottom else Form.HunFromTop,
        modifier = modifier,
    )
    val headsUpHeight = viewModel.headsUpHeight.collectAsState()

    Element(
        Notifications.Elements.HeadsUpNotificationPlaceholder,
        modifier =
            modifier
                .height { headsUpHeight.value.roundToInt() }
                .fillMaxWidth()
                .debugBackground(viewModel, DEBUG_HUN_COLOR)
                .onGloballyPositioned { coordinates: LayoutCoordinates ->
                    val boundsInWindow = coordinates.boundsInWindow()
                    debugLog(viewModel) {
                        "HUNS onGloballyPositioned:" +
                            " size=${coordinates.size}" +
                            " bounds=$boundsInWindow"
                    }
                    viewModel.onHeadsUpTopChanged(boundsInWindow.top)
                }
    ) {
        content {}
    }
}

/** Adds the space where notification stack should appear in the scene. */
@@ -128,9 +138,12 @@ fun SceneScope.ConstrainedNotificationStack(
    ) {
        NotificationPlaceholder(
            viewModel = viewModel,
            form = Form.Stack,
            modifier = Modifier.fillMaxSize(),
        )
        HeadsUpNotificationSpace(
            viewModel = viewModel,
            modifier = Modifier.align(Alignment.TopCenter),
        )
    }
}

@@ -273,11 +286,10 @@ fun SceneScope.NotificationScrollingStack(
                            } else 1f
                    }
                    .background(MaterialTheme.colorScheme.surface)
                    .debugBackground(viewModel, Color(0.5f, 0.5f, 0f, 0.2f))
                    .debugBackground(viewModel, DEBUG_BOX_COLOR)
        ) {
            NotificationPlaceholder(
                viewModel = viewModel,
                form = Form.Stack,
                modifier =
                    Modifier.verticalNestedScrollToScene(
                            topBehavior = NestedScrollBehavior.EdgeWithPreview,
@@ -303,6 +315,7 @@ fun SceneScope.NotificationScrollingStack(
                        .height { (stackHeight.value + navBarHeight).roundToInt() },
            )
        }
        HeadsUpNotificationSpace(viewModel = viewModel)
    }
}

@@ -323,9 +336,6 @@ fun SceneScope.NotificationShelfSpace(
        modifier
            .element(key = Notifications.Elements.ShelfSpace)
            .fillMaxWidth()
            .onSizeChanged { size: IntSize ->
                debugLog(viewModel) { "SHELF onSizeChanged: size=$size" }
            }
            .onPlaced { coordinates: LayoutCoordinates ->
                debugLog(viewModel) {
                    ("SHELF onPlaced:" +
@@ -344,18 +354,14 @@ fun SceneScope.NotificationShelfSpace(
@Composable
private fun SceneScope.NotificationPlaceholder(
    viewModel: NotificationsPlaceholderViewModel,
    form: Form,
    modifier: Modifier = Modifier,
) {
    val elementKey = Notifications.Elements.NotificationPlaceholder
    Element(
        elementKey,
        Notifications.Elements.NotificationStackPlaceholder,
        modifier =
            modifier
                .debugBackground(viewModel)
                .onSizeChanged { size: IntSize ->
                    debugLog(viewModel) { "STACK onSizeChanged: size=$size" }
                }
                .debugBackground(viewModel, DEBUG_STACK_COLOR)
                .onSizeChanged { size -> debugLog(viewModel) { "STACK onSizeChanged: size=$size" } }
                .onGloballyPositioned { coordinates: LayoutCoordinates ->
                    val positionInWindow = coordinates.positionInWindow()
                    debugLog(viewModel) {
@@ -404,7 +410,7 @@ private inline fun debugLog(

private fun Modifier.debugBackground(
    viewModel: NotificationsPlaceholderViewModel,
    color: Color = DEBUG_COLOR,
    color: Color,
): Modifier =
    if (viewModel.isVisualDebuggingEnabled) {
        background(color)
@@ -424,4 +430,6 @@ fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape {
}

private const val TAG = "FlexiNotifs"
private val DEBUG_COLOR = Color(1f, 0f, 0f, 0.2f)
private val DEBUG_STACK_COLOR = Color(1f, 0f, 0f, 0.2f)
private val DEBUG_HUN_COLOR = Color(0f, 0f, 1f, 0.2f)
private val DEBUG_BOX_COLOR = Color(0f, 1f, 0f, 0.2f)
+11 −4
Original line number Diff line number Diff line
@@ -72,6 +72,9 @@ constructor(
     */
    val stackHeight: StateFlow<Float> = viewHeightRepository.stackHeight.asStateFlow()

    /** The height in px of the contents of the HUN. */
    val headsUpHeight: StateFlow<Float> = viewHeightRepository.headsUpHeight.asStateFlow()

    /** The y-coordinate in px of top of the contents of the notification stack. */
    val stackTop: StateFlow<Float> = placeholderRepository.stackTop.asStateFlow()

@@ -115,13 +118,13 @@ constructor(
    }

    /** Sets the y-coord in px of the top of the contents of the notification stack. */
    fun setStackTop(startY: Float) {
        placeholderRepository.stackTop.value = startY
    fun setStackTop(stackTop: Float) {
        placeholderRepository.stackTop.value = stackTop
    }

    /** Sets the y-coord in px of the bottom of the contents of the notification stack. */
    fun setStackBottom(endY: Float) {
        placeholderRepository.stackBottom.value = endY
    fun setStackBottom(stackBottom: Float) {
        placeholderRepository.stackBottom.value = stackBottom
    }

    /** Sets whether the notification stack is scrolled to the top. */
@@ -137,4 +140,8 @@ constructor(
    fun setConstrainedAvailableSpace(height: Int) {
        placeholderRepository.constrainedAvailableSpace.value = height
    }

    fun setHeadsUpTop(headsUpTop: Float) {
        placeholderRepository.headsUpTop.value = headsUpTop
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrim
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow

/**
 * ViewModel used by the Notification placeholders inside the scene container to update the
@@ -78,6 +79,10 @@ constructor(
        interactor.setConstrainedAvailableSpace(height)
    }

    fun onHeadsUpTopChanged(headsUpTop: Float) {
        interactor.setHeadsUpTop(headsUpTop)
    }

    /** Corner rounding of the stack */
    val shadeScrimRounding: Flow<ShadeScrimRounding> = interactor.shadeScrimRounding

@@ -86,7 +91,10 @@ constructor(
     * notifications, this can exceed the space available on screen to show notifications, at which
     * point the notification stack should become scrollable.
     */
    val stackHeight = interactor.stackHeight
    val stackHeight: StateFlow<Float> = interactor.stackHeight

    /** The height in px of the contents of the HUN. */
    val headsUpHeight: StateFlow<Float> = interactor.headsUpHeight

    /**
     * The amount [0-1] that the shade has been opened. At 0, the shade is closed; at 1, the shade