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

Commit 07615a94 authored by Danny Burakov's avatar Danny Burakov Committed by Android (Google) Code Review
Browse files

Merge "[Dual Shade] Add ShadeConfigRepository." into main

parents dc2b90cd 6fa4d288
Loading
Loading
Loading
Loading
+4 −13
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.focus.FocusRequester
@@ -83,7 +82,6 @@ constructor(
        actionsViewModel.activate()
    }

    @OptIn(ExperimentalComposeUiApi::class)
    @Composable
    override fun ContentScope.Content(modifier: Modifier) {
        val notificationStackPadding = dimensionResource(id = R.dimen.notification_side_paddings)
@@ -142,11 +140,7 @@ constructor(
                focusRequester.requestFocus()
            }

            Column(
                modifier = Modifier
                    .focusRequester(focusRequester)
                    .focusable()
            ) {
            Column(modifier = Modifier.focusRequester(focusRequester).focusable()) {
                if (viewModel.showMedia) {
                    Element(
                        key = Media.Elements.mediaCarousel,
@@ -179,14 +173,11 @@ constructor(
                    shouldFillMaxSize = false,
                    shouldShowScrim = false,
                    supportNestedScrolling = false,
                    modifier = Modifier
                        .fillMaxWidth()
                        .focusProperties {
                    modifier =
                        Modifier.fillMaxWidth().focusProperties {
                            // The `NotificationScrollingStack` is a compose placeholder. Therefore,
                            // focus on the view that actually shows notifications.
                            onEnter = {
                                stackScrollView.asView().requestFocus()
                            }
                            onEnter = { stackScrollView.asView().requestFocus() }
                        },
                )
            }
+19 −31
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.safeContent
import androidx.compose.foundation.layout.union
import androidx.compose.foundation.layout.width
@@ -44,23 +43,24 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.window.core.layout.WindowSizeClass
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.mechanics.TileRevealFlag
import com.android.compose.animation.scene.mechanics.rememberGestureContext
import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.mechanics.behavior.VerticalExpandContainerSpec
import com.android.mechanics.behavior.verticalExpandContainerBackground
import com.android.mechanics.compose.modifier.motionDriver
import com.android.systemui.res.R
import com.android.systemui.shade.ui.ShadeColors.shadePanel
import com.android.systemui.shade.ui.ShadeColors.shadePanelScrimBehind
import com.android.systemui.shade.ui.composable.OverlayShade.Colors
import com.android.systemui.shade.ui.composable.OverlayShade.Dimensions
import com.android.systemui.shade.ui.composable.OverlayShade.rememberShadeExpansionMotion
import kotlin.math.min

@@ -104,7 +104,7 @@ fun ContentScope.OverlayShade(
                    Modifier.overscroll(verticalOverscrollEffect)
                        .element(panelElement)
                        .thenIf(TileRevealFlag.isEnabled) { Modifier.motionDriver(gestureContext) }
                        .panelWidth(isFullWidth)
                        .width(Dimensions.PanelWidth)
                        // TODO(440566878): Investigate if this can be optimized by replacing with
                        // onLayoutRectChanged.
                        .onPlaced { coordinates ->
@@ -136,7 +136,7 @@ private fun ContentScope.Scrim(
    onClicked: () -> Unit,
    modifier: Modifier = Modifier,
) {
    val scrimBackgroundColor = OverlayShade.Colors.ScrimBackground
    val scrimBackgroundColor = Colors.ScrimBackground
    Spacer(
        modifier =
            modifier
@@ -159,10 +159,7 @@ private fun ContentScope.Panel(
        modifier =
            modifier
                .disableSwipesWhenScrolling()
                .verticalExpandContainerBackground(
                    backgroundColor = OverlayShade.Colors.panelBackground(enableTransparency),
                    spec = spec,
                )
                .verticalExpandContainerBackground(Colors.panelBackground(enableTransparency), spec)
    ) {
        Column {
            header?.invoke()
@@ -171,29 +168,14 @@ private fun ContentScope.Panel(
    }
}

@Composable
private fun Modifier.panelWidth(isFullWidthPanel: Boolean): Modifier {
    return if (isFullWidthPanel) {
        fillMaxWidth()
    } else {
        width(dimensionResource(R.dimen.shade_panel_width))
    }
}

@Composable
@ReadOnlyComposable
internal fun isFullWidthShade(): Boolean {
    return !LocalWindowSizeClass.current.isWidthAtLeastBreakpoint(
        WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND
    )
}
internal fun isFullWidthShade() = LocalResources.current.getBoolean(R.bool.config_isFullWidthShade)

@Composable
@ReadOnlyComposable
@SuppressLint("ConfigurationScreenWidthHeight")
private fun getHalfScreenWidth(): Dp {
    return LocalConfiguration.current.screenWidthDp.dp / 2
}
private fun getHalfScreenWidth() = LocalConfiguration.current.screenWidthDp.dp / 2

@Composable
private fun Modifier.panelContainerPadding(
@@ -205,13 +187,11 @@ private fun Modifier.panelContainerPadding(
    }
    // On wide screens, the shade panel width is limited to half the screen width.
    val halfScreenWidth = getHalfScreenWidth()
    val horizontalPaddingDp = dimensionResource(R.dimen.shade_panel_margin_horizontal)

    val (startPadding, endPadding) =
        when (alignment) {
            Alignment.Start -> horizontalPaddingDp to halfScreenWidth
            Alignment.End -> halfScreenWidth to horizontalPaddingDp
            else -> horizontalPaddingDp to horizontalPaddingDp
            Alignment.Start -> Dimensions.PanelPaddingHorizontal to halfScreenWidth
            Alignment.End -> halfScreenWidth to Dimensions.PanelPaddingHorizontal
            else -> Dimensions.PanelPaddingHorizontal to Dimensions.PanelPaddingHorizontal
        }
    val paddings = PaddingValues(start = startPadding, end = endPadding)
    val layoutDirection = LocalLayoutDirection.current
@@ -260,6 +240,14 @@ object OverlayShade {
            @Composable
            @ReadOnlyComposable
            get() = dimensionResource(R.dimen.overlay_shade_panel_shape_radius)

        val PanelPaddingHorizontal: Dp
            @Composable
            @ReadOnlyComposable
            get() = dimensionResource(R.dimen.shade_panel_margin_horizontal)

        val PanelWidth: Dp
            @Composable @ReadOnlyComposable get() = dimensionResource(R.dimen.shade_panel_width)
    }

    @Composable
+26 −32
Original line number Diff line number Diff line
@@ -38,19 +38,20 @@ import com.android.systemui.keyguard.ui.viewmodel.keyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.keyguardSmartspaceViewModel
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.advanceUntilIdle
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.keyguard.ui.clocks.ClockViewIds
import com.android.systemui.res.R
import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
import com.android.systemui.statusbar.policy.fakeConfigurationController
import com.android.systemui.statusbar.ui.fakeSystemBarUtilsProxy
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -59,7 +60,6 @@ import org.junit.runner.RunWith
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.mock

@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@SmallTest
@DisableSceneContainer
@@ -125,9 +125,9 @@ class ClockSectionTest : SysuiTestCase() {
    @DisableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_LargeClock_SplitShade() =
        kosmos.runTest {
            shadeRepository.setShadeLayoutWide(true)
            enableSplitShade()
            keyguardClockInteractor.setClockSize(ClockSize.LARGE)
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -140,9 +140,9 @@ class ClockSectionTest : SysuiTestCase() {
    @EnableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_LargeClock_SplitShade_ReactiveVariantsOn() =
        kosmos.runTest {
            shadeRepository.setShadeLayoutWide(true)
            enableSplitShade()
            keyguardClockInteractor.setClockSize(ClockSize.LARGE)
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -155,18 +155,17 @@ class ClockSectionTest : SysuiTestCase() {

    @Test
    @DisableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_LargeClock_NonSplitShade() =
    fun testApplyDefaultConstraints_LargeClock_SingleShade() =
        kosmos.runTest {
            val isWideScreen by collectLastValue(shadeRepository.isWideScreen)
            val legacyUseSplitShade by collectLastValue(shadeRepository.legacyUseSplitShade)
            val isLargeClockVisible by collectLastValue(keyguardClockViewModel.isLargeClockVisible)

            shadeRepository.setShadeLayoutWide(false)
            enableSingleShade()
            keyguardClockInteractor.setClockSize(ClockSize.LARGE)
            notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -177,18 +176,17 @@ class ClockSectionTest : SysuiTestCase() {

    @Test
    @EnableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_LargeClock_NonSplitShade_reactiveVariantsOn() =
    fun testApplyDefaultConstraints_LargeClock_SingleShade_reactiveVariantsOn() =
        kosmos.runTest {
            val isWideScreen by collectLastValue(shadeRepository.isWideScreen)
            val legacyUseSplitShade by collectLastValue(shadeRepository.legacyUseSplitShade)
            val isLargeClockVisible by collectLastValue(keyguardClockViewModel.isLargeClockVisible)

            shadeRepository.setShadeLayoutWide(false)
            enableSingleShade()
            keyguardClockInteractor.setClockSize(ClockSize.LARGE)
            notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -203,16 +201,15 @@ class ClockSectionTest : SysuiTestCase() {
    @DisableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_SmallClock_SplitShade() =
        kosmos.runTest {
            val isWideScreen by collectLastValue(shadeRepository.isWideScreen)
            val legacyUseSplitShade by collectLastValue(shadeRepository.legacyUseSplitShade)
            val isLargeClockVisible by collectLastValue(keyguardClockViewModel.isLargeClockVisible)

            shadeRepository.setShadeLayoutWide(true)
            enableSplitShade()
            keyguardClockInteractor.setClockSize(ClockSize.SMALL)
            notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -225,16 +222,15 @@ class ClockSectionTest : SysuiTestCase() {
    @EnableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_SmallClock_SplitShade_ReactiveVariantsOn() =
        kosmos.runTest {
            val isWideScreen by collectLastValue(shadeRepository.isWideScreen)
            val legacyUseSplitShade by collectLastValue(shadeRepository.legacyUseSplitShade)
            val isLargeClockVisible by collectLastValue(keyguardClockViewModel.isLargeClockVisible)

            shadeRepository.setShadeLayoutWide(true)
            enableSplitShade()
            keyguardClockInteractor.setClockSize(ClockSize.SMALL)
            notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -247,18 +243,17 @@ class ClockSectionTest : SysuiTestCase() {

    @Test
    @DisableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_SmallClock_NonSplitShade() =
    fun testApplyDefaultConstraints_SmallClock_SingleShade() =
        kosmos.runTest {
            val isWideScreen by collectLastValue(shadeRepository.isWideScreen)
            val legacyUseSplitShade by collectLastValue(shadeRepository.legacyUseSplitShade)
            val isLargeClockVisible by collectLastValue(keyguardClockViewModel.isLargeClockVisible)

            shadeRepository.setShadeLayoutWide(false)
            enableSingleShade()
            keyguardClockInteractor.setClockSize(ClockSize.SMALL)
            notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -269,18 +264,17 @@ class ClockSectionTest : SysuiTestCase() {

    @Test
    @EnableFlags(com.android.systemui.shared.Flags.FLAG_CLOCK_REACTIVE_SMARTSPACE_LAYOUT)
    fun testApplyDefaultConstraints_SmallClock_NonSplitShade_ReactiveVariantsOn() =
    fun testApplyDefaultConstraints_SmallClock_SingleShade_ReactiveVariantsOn() =
        kosmos.runTest {
            val isWideScreen by collectLastValue(shadeRepository.isWideScreen)
            val legacyUseSplitShade by collectLastValue(shadeRepository.legacyUseSplitShade)
            val isLargeClockVisible by collectLastValue(keyguardClockViewModel.isLargeClockVisible)

            shadeRepository.setShadeLayoutWide(false)
            enableSingleShade()
            keyguardClockInteractor.setClockSize(ClockSize.SMALL)
            notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -297,7 +291,7 @@ class ClockSectionTest : SysuiTestCase() {
            notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -313,7 +307,7 @@ class ClockSectionTest : SysuiTestCase() {
            notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
            keyguardSmartspaceInteractor.setBcSmartspaceVisibility(GONE)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
@@ -326,7 +320,7 @@ class ClockSectionTest : SysuiTestCase() {
        kosmos.runTest {
            notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
            fakeConfigurationController.notifyConfigurationChanged()
            testScope.advanceUntilIdle()
            advanceUntilIdle()

            val cs = ConstraintSet()
            underTest.applyDefaultConstraints(cs)
+3 −2
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.shadeConfigRepository
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
@@ -138,7 +139,7 @@ class LockscreenUpperRegionViewModelTest(flags: FlagsParameterization) : SysuiTe
        hasNotifications: Boolean = false,
        shadeLayoutWide: Boolean? = null,
    ) {
        val isWideScreen by collectLastValue(shadeRepository.isWideScreen)
        val isFullWidthShade by collectLastValue(shadeConfigRepository.isFullWidthShade)
        val legacyUseSplitShade by collectLastValue(shadeRepository.legacyUseSplitShade)
        val collectedClockSize by collectLastValue(keyguardClockInteractor.clockSize)
        val collectedShadeMode by collectLastValue(shadeModeInteractor.shadeMode)
@@ -166,7 +167,7 @@ class LockscreenUpperRegionViewModelTest(flags: FlagsParameterization) : SysuiTe
                .build()
        runCurrent()
        if (shadeLayoutWide != null) {
            assertThat(isWideScreen).isEqualTo(shadeLayoutWide)
            assertThat(isFullWidthShade).isEqualTo(!shadeLayoutWide)
            assertThat(legacyUseSplitShade).isEqualTo(shadeLayoutWide)
        }
        assertThat(collectedShadeMode).isEqualTo(shadeMode)
+0 −21
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.graphics.Rect
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -183,24 +182,4 @@ class ShadeRepositoryImplTest : SysuiTestCase() {
            underTest.setLegacyIsClosing(true)
            assertThat(underTest.legacyIsClosing.value).isTrue()
        }

    @Test
    fun updateLegacyUseSplitShade() =
        testScope.runTest {
            val legacyUseSplitShade by collectLastValue(underTest.legacyUseSplitShade)
            assertThat(legacyUseSplitShade).isFalse()

            underTest.setShadeLayoutWide(true)
            assertThat(legacyUseSplitShade).isTrue()
        }

    @Test
    fun updateIsWideScreen() =
        testScope.runTest {
            val isWideScreen by collectLastValue(underTest.isWideScreen)
            assertThat(isWideScreen).isFalse()

            underTest.setShadeLayoutWide(true)
            assertThat(isWideScreen).isTrue()
        }
}
Loading