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

Commit 64868085 authored by 0's avatar 0
Browse files

[flexiglass] Add logic to dispatch touches from NSSL to Flexiglass

When NSSL determines a touch will drag the scroller, the MotionEvent is dispatched directly to the root Composable of Flexiglass.
Also positions NSSL and its scrim correctly under the rest of the content in the shade, and fades them in during shade expansion.

Note: touch does not get correctly intercepted by NSSL when touching a notification that has just been received. This case will be covered in the follow-up nested scrolling CL, as the fix depends on the scroll state of the scrim.

Bug: 296118689
Test: added unit tests
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT
Change-Id: I5b405d5edbe31c47feca08f40a91e7e858af04de
parent 5b4e13aa
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -16,23 +16,55 @@

package com.android.systemui.keyguard.ui.composable.section

import android.content.Context
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.SceneScope
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.notifications.ui.composable.NotificationStack
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.notification.stack.shared.flexiNotifsEnabled
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackAppearanceViewBinder
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import javax.inject.Inject

class NotificationSection
@Inject
constructor(
    @Application context: Context,
    private val viewModel: NotificationsPlaceholderViewModel,
    controller: NotificationStackScrollLayoutController,
    sceneContainerFlags: SceneContainerFlags,
    sharedNotificationContainer: SharedNotificationContainer,
    stackScrollLayout: NotificationStackScrollLayout,
    notificationStackAppearanceViewModel: NotificationStackAppearanceViewModel,
    ambientState: AmbientState,
) {
    init {
        if (sceneContainerFlags.flexiNotifsEnabled()) {
            (stackScrollLayout.parent as? ViewGroup)?.removeView(stackScrollLayout)
            sharedNotificationContainer.addNotificationStackScrollLayout(stackScrollLayout)

            NotificationStackAppearanceViewBinder.bind(
                context,
                sharedNotificationContainer,
                notificationStackAppearanceViewModel,
                ambientState,
                controller,
            )
        }
    }

    @Composable
    fun SceneScope.Notifications(modifier: Modifier = Modifier) {
        NotificationStack(
            viewModel = viewModel,
            isScrimVisible = false,
            modifier = modifier,
        )
    }
+40 −16
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
@@ -43,8 +44,10 @@ import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.height
import com.android.systemui.notifications.ui.composable.Notifications.Form
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import kotlin.math.roundToInt

object Notifications {
    object Elements {
@@ -77,32 +80,52 @@ fun SceneScope.HeadsUpNotificationSpace(
    )
}

/** Adds the space where notification stack will appear in the scene. */
/** Adds the space where notification stack should appear in the scene. */
@Composable
fun SceneScope.NotificationStack(
    viewModel: NotificationsPlaceholderViewModel,
    isScrimVisible: Boolean,
    modifier: Modifier = Modifier,
) {
    NotificationPlaceholder(
        viewModel = viewModel,
        form = Form.Stack,
        modifier = modifier,
    )
}

/**
 * Adds the space where notification stack should appear in the scene, with a scrim and nested
 * scrolling.
 */
@Composable
fun SceneScope.NotificationScrollingStack(
    viewModel: NotificationsPlaceholderViewModel,
    modifier: Modifier = Modifier,
) {
    val cornerRadius by viewModel.cornerRadiusDp.collectAsState()

    Box(modifier = modifier) {
        if (isScrimVisible) {
    val contentHeight by viewModel.intrinsicContentHeight.collectAsState()

    val expansionFraction by viewModel.expandFraction.collectAsState(0f)

    Box(
        modifier =
                    Modifier.element(Notifications.Elements.NotificationScrim)
                        .fillMaxSize()
            modifier
                .verticalNestedScrollToScene()
                .fillMaxWidth()
                .element(Notifications.Elements.NotificationScrim)
                .graphicsLayer {
                    shape = RoundedCornerShape(cornerRadius.dp)
                    clip = true
                    alpha = expansionFraction
                }
                .background(MaterialTheme.colorScheme.surface)
            )
        }
                .debugBackground(viewModel, Color(0.5f, 0.5f, 0f, 0.2f))
    ) {
        NotificationPlaceholder(
            viewModel = viewModel,
            form = Form.Stack,
            modifier = Modifier.fillMaxSize(),
            modifier = Modifier.fillMaxWidth().height { contentHeight.roundToInt() }
        )
    }
}
@@ -159,6 +182,7 @@ private fun SceneScope.NotificationPlaceholder(
                    debugLog(viewModel) { "STACK onSizeChanged: size=$size" }
                }
                .onPlaced { coordinates: LayoutCoordinates ->
                    viewModel.onContentTopChanged(coordinates.positionInWindow().y)
                    debugLog(viewModel) {
                        "STACK onPlaced:" +
                            " size=${coordinates.size}" +
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.SceneScope
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.notifications.ui.composable.HeadsUpNotificationSpace
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.scene.shared.model.Direction
import com.android.systemui.scene.shared.model.Edge
import com.android.systemui.scene.shared.model.SceneKey
@@ -66,6 +67,7 @@ constructor(
        modifier: Modifier,
    ) {
        Box(modifier = modifier) {
            Box(modifier = Modifier.fillMaxSize().element(Notifications.Elements.NotificationScrim))
            HeadsUpNotificationSpace(
                viewModel = notificationsViewModel,
                modifier = Modifier.padding(16.dp).fillMaxSize(),
+4 −4
Original line number Diff line number Diff line
@@ -3,12 +3,12 @@ package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.tween
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.scene.ui.composable.Shade
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.shade.ui.composable.ShadeHeader

fun TransitionBuilder.goneToShadeTransition() {
    spec = tween(durationMillis = 500)

    translate(Shade.rootElementKey, Edge.Top, true)
    fade(Notifications.Elements.NotificationScrim)
    fractionRange(start = .58f) { fade(ShadeHeader.Elements.CollapsedContent) }
    translate(QuickSettings.Elements.Content, Edge.Top, true)
}
+13 −24
Original line number Diff line number Diff line
@@ -22,11 +22,9 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
@@ -47,7 +45,7 @@ import com.android.systemui.media.controls.ui.MediaCarouselController
import com.android.systemui.media.controls.ui.MediaHost
import com.android.systemui.media.controls.ui.composable.MediaCarousel
import com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL
import com.android.systemui.notifications.ui.composable.NotificationStack
import com.android.systemui.notifications.ui.composable.NotificationScrollingStack
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Direction
@@ -148,35 +146,27 @@ private fun SceneScope.ShadeScene(
    mediaHost: MediaHost,
    modifier: Modifier = Modifier,
) {
    val localDensity = LocalDensity.current
    val layoutWidth = remember { mutableStateOf(0) }

    Box(modifier.element(Shade.Elements.Scrim)) {
        Spacer(
    Box(
        modifier =
                Modifier.element(Shade.Elements.ScrimBackground)
                    .fillMaxSize()
                    .background(MaterialTheme.colorScheme.scrim, shape = Shade.Shapes.Scrim)
            modifier.element(Shade.Elements.Scrim).background(MaterialTheme.colorScheme.scrim),
    )
    Box {
        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier =
                Modifier.fillMaxSize()
                    .clickable(onClick = { viewModel.onContentClicked() })
                    .padding(
                        start = Shade.Dimensions.HorizontalPadding,
                        end = Shade.Dimensions.HorizontalPadding,
                        bottom = 48.dp
                    )
            modifier = Modifier.fillMaxWidth().clickable(onClick = { viewModel.onContentClicked() })
        ) {
            CollapsedShadeHeader(
                viewModel = viewModel.shadeHeaderViewModel,
                createTintedIconManager = createTintedIconManager,
                createBatteryMeterViewController = createBatteryMeterViewController,
                statusBarIconController = statusBarIconController,
                modifier = Modifier.padding(horizontal = Shade.Dimensions.HorizontalPadding)
            )
            Spacer(modifier = Modifier.height(16.dp))
            QuickSettings(
                modifier = Modifier.wrapContentHeight(),
                modifier = Modifier.height(130.dp),
                viewModel.qsSceneAdapter,
            )

@@ -202,16 +192,15 @@ private fun SceneScope.ShadeScene(
                        },
                    mediaHost = mediaHost,
                    layoutWidth = layoutWidth.value,
                    layoutHeight = with(LocalDensity.current) { mediaHeight.toPx() }.toInt(),
                    layoutHeight = with(localDensity) { mediaHeight.toPx() }.toInt(),
                    carouselController = mediaCarouselController,
                )
            }

            Spacer(modifier = Modifier.height(16.dp))
            NotificationStack(
            NotificationScrollingStack(
                viewModel = viewModel.notifications,
                isScrimVisible = true,
                modifier = Modifier.weight(1f),
                modifier = Modifier.fillMaxWidth().weight(1f),
            )
        }
    }
Loading