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

Commit 8790c082 authored by Aaron Liu's avatar Aaron Liu Committed by Android (Google) Code Review
Browse files

Merge "Add splitshade blueprint in compose." into main

parents 1ca908dc 10a22e2a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -173,7 +173,8 @@ constructor(
                val belowLockIconPlaceable =
                    belowLockIconMeasurable.measure(
                        noMinConstraints.copy(
                            maxHeight = constraints.maxHeight - lockIconBounds.bottom
                            maxHeight =
                                (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0)
                        )
                    )
                val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints)
+186 −11
Original line number Diff line number Diff line
@@ -16,19 +16,42 @@

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

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntRect
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.padding
import com.android.systemui.Flags
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.ui.composable.LockscreenLongPress
import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection
import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection
import com.android.systemui.keyguard.ui.composable.section.ClockSection
import com.android.systemui.keyguard.ui.composable.section.LockSection
import com.android.systemui.keyguard.ui.composable.section.NotificationSection
import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection
import com.android.systemui.keyguard.ui.composable.section.SmartSpaceSection
import com.android.systemui.keyguard.ui.composable.section.StatusBarSection
import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
import com.android.systemui.res.R
import com.android.systemui.shade.LargeScreenHeaderHelper
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoSet
import java.util.Optional
import javax.inject.Inject

/**
@@ -39,22 +62,174 @@ class SplitShadeBlueprint
@Inject
constructor(
    private val viewModel: LockscreenContentViewModel,
    private val statusBarSection: StatusBarSection,
    private val clockSection: ClockSection,
    private val smartSpaceSection: SmartSpaceSection,
    private val notificationSection: NotificationSection,
    private val lockSection: LockSection,
    private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>,
    private val bottomAreaSection: BottomAreaSection,
    private val settingsMenuSection: SettingsMenuSection,
    private val clockInteractor: KeyguardClockInteractor,
    private val largeScreenHeaderHelper: LargeScreenHeaderHelper,
) : LockscreenSceneBlueprint {

    override val id: String = "split-shade"

    @Composable
    override fun SceneScope.Content(modifier: Modifier) {
        val isUdfpsVisible = viewModel.isUdfpsVisible
        val burnIn = rememberBurnIn(clockInteractor)
        val resources = LocalContext.current.resources

        LockscreenLongPress(
            viewModel = viewModel.longPress,
            modifier = modifier,
        ) { _ ->
            Box(modifier.background(Color.Black)) {
                Text(
                    text = "TODO(b/316211368): split shade blueprint",
                    color = Color.White,
                    modifier = Modifier.align(Alignment.Center),
        ) { onSettingsMenuPlaced ->
            Layout(
                content = {
                    // Constrained to above the lock icon.
                    Column(
                        modifier = Modifier.fillMaxSize(),
                    ) {
                        with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) }
                        Row(
                            modifier = Modifier.fillMaxSize(),
                        ) {
                            Column(
                                modifier = Modifier.fillMaxHeight().weight(weight = 1f),
                                horizontalAlignment = Alignment.CenterHorizontally,
                            ) {
                                with(smartSpaceSection) {
                                    SmartSpace(
                                        burnInParams = burnIn.parameters,
                                        onTopChanged = burnIn.onSmartspaceTopChanged,
                                        modifier =
                                            Modifier.fillMaxWidth()
                                                .padding(
                                                    top = {
                                                        viewModel.getSmartSpacePaddingTop(resources)
                                                    }
                                                ),
                                    )
                                }

                                Spacer(modifier = Modifier.weight(weight = 1f))
                                with(clockSection) { LargeClock() }
                                Spacer(modifier = Modifier.weight(weight = 1f))
                            }
                            with(notificationSection) {
                                val splitShadeTopMargin: Dp =
                                    if (Flags.centralizedStatusBarDimensRefactor()) {
                                        largeScreenHeaderHelper.getLargeScreenHeaderHeight().dp
                                    } else {
                                        dimensionResource(
                                            id = R.dimen.large_screen_shade_header_height
                                        )
                                    }
                                Notifications(
                                    modifier =
                                        Modifier.fillMaxHeight()
                                            .weight(weight = 1f)
                                            .padding(top = splitShadeTopMargin)
                                )
                            }
                        }

                        if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
                            with(ambientIndicationSectionOptional.get()) {
                                AmbientIndication(modifier = Modifier.fillMaxWidth())
                            }
                        }
                    }

                    with(lockSection) { LockIcon() }

                    // Aligned to bottom and constrained to below the lock icon.
                    Column(modifier = Modifier.fillMaxWidth()) {
                        if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
                            with(ambientIndicationSectionOptional.get()) {
                                AmbientIndication(modifier = Modifier.fillMaxWidth())
                            }
                        }

                        with(bottomAreaSection) {
                            IndicationArea(modifier = Modifier.fillMaxWidth())
                        }
                    }

                    // Aligned to bottom and NOT constrained by the lock icon.
                    with(bottomAreaSection) {
                        Shortcut(isStart = true, applyPadding = true)
                        Shortcut(isStart = false, applyPadding = true)
                    }
                    with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) }
                },
                modifier = Modifier.fillMaxSize(),
            ) { measurables, constraints ->
                check(measurables.size == 6)
                val aboveLockIconMeasurable = measurables[0]
                val lockIconMeasurable = measurables[1]
                val belowLockIconMeasurable = measurables[2]
                val startShortcutMeasurable = measurables[3]
                val endShortcutMeasurable = measurables[4]
                val settingsMenuMeasurable = measurables[5]

                val noMinConstraints =
                    constraints.copy(
                        minWidth = 0,
                        minHeight = 0,
                    )
                val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints)
                val lockIconBounds =
                    IntRect(
                        left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left],
                        top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top],
                        right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right],
                        bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom],
                    )

                val aboveLockIconPlaceable =
                    aboveLockIconMeasurable.measure(
                        noMinConstraints.copy(maxHeight = lockIconBounds.top)
                    )
                val belowLockIconPlaceable =
                    belowLockIconMeasurable.measure(
                        noMinConstraints.copy(
                            maxHeight =
                                (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0)
                        )
                    )
                val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints)
                val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints)
                val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints)

                layout(constraints.maxWidth, constraints.maxHeight) {
                    aboveLockIconPlaceable.place(
                        x = 0,
                        y = 0,
                    )
                    lockIconPlaceable.place(
                        x = lockIconBounds.left,
                        y = lockIconBounds.top,
                    )
                    belowLockIconPlaceable.place(
                        x = 0,
                        y = constraints.maxHeight - belowLockIconPlaceable.height,
                    )
                    startShortcutPleaceable.place(
                        x = 0,
                        y = constraints.maxHeight - startShortcutPleaceable.height,
                    )
                    endShortcutPleaceable.place(
                        x = constraints.maxWidth - endShortcutPleaceable.width,
                        y = constraints.maxHeight - endShortcutPleaceable.height,
                    )
                    settingsMenuPlaceable.place(
                        x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2,
                        y = constraints.maxHeight - settingsMenuPlaceable.height,
                    )
                }
            }
        }
    }
+28 −4
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@

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

import androidx.compose.foundation.layout.fillMaxWidth
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@@ -75,7 +76,13 @@ constructor(
        ) {
            content {
                AndroidView(
                    factory = { checkNotNull(currentClock).smallClock.view },
                    factory = { context ->
                        FrameLayout(context).apply {
                            val newClockView = checkNotNull(currentClock).smallClock.view
                            (newClockView.parent as? ViewGroup)?.removeView(newClockView)
                            addView(newClockView)
                        }
                    },
                    modifier =
                        Modifier.padding(
                                horizontal =
@@ -83,6 +90,12 @@ constructor(
                            )
                            .padding(top = { viewModel.getSmallClockTopMargin(view.context) })
                            .onTopPlacementChanged(onTopChanged),
                    update = {
                        val newClockView = checkNotNull(currentClock).smallClock.view
                        it.removeAllViews()
                        (newClockView.parent as? ViewGroup)?.removeView(newClockView)
                        it.addView(newClockView)
                    },
                )
            }
        }
@@ -116,8 +129,19 @@ constructor(
        ) {
            content {
                AndroidView(
                    factory = { checkNotNull(currentClock).largeClock.view },
                    modifier = Modifier.fillMaxWidth()
                    factory = { context ->
                        FrameLayout(context).apply {
                            val newClockView = checkNotNull(currentClock).largeClock.view
                            (newClockView.parent as? ViewGroup)?.removeView(newClockView)
                            addView(newClockView)
                        }
                    },
                    update = {
                        val newClockView = checkNotNull(currentClock).largeClock.view
                        it.removeAllViews()
                        (newClockView.parent as? ViewGroup)?.removeView(newClockView)
                        it.addView(newClockView)
                    },
                )
            }
        }