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

Commit d1488ece authored by Ale Nijamkin's avatar Ale Nijamkin Committed by Android (Google) Code Review
Browse files

Merge "[flexiglass] Unfold transition support in the lockscreen scene." into main

parents ee1dbf70 f03e716b
Loading
Loading
Loading
Loading
+33 −4
Original line number Diff line number Diff line
@@ -26,9 +26,11 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.unit.IntRect
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.padding
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
@@ -43,6 +45,7 @@ import dagger.Module
import dagger.multibindings.IntoSet
import java.util.Optional
import javax.inject.Inject
import kotlin.math.roundToInt

/**
 * Renders the lockscreen scene when showing with the default layout (e.g. vertical phone form
@@ -68,6 +71,7 @@ constructor(
        val isUdfpsVisible = viewModel.isUdfpsVisible
        val shouldUseSplitNotificationShade by
            viewModel.shouldUseSplitNotificationShade.collectAsState()
        val unfoldTranslations by viewModel.unfoldTranslations.collectAsState()

        LockscreenLongPress(
            viewModel = viewModel.longPress,
@@ -79,10 +83,25 @@ constructor(
                    Column(
                        modifier = Modifier.fillMaxSize(),
                    ) {
                        with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) }
                        with(statusBarSection) {
                            StatusBar(
                                modifier =
                                    Modifier.fillMaxWidth()
                                        .padding(
                                            horizontal = { unfoldTranslations.start.roundToInt() },
                                        )
                            )
                        }

                        Box {
                            with(topAreaSection) { DefaultClockLayout() }
                            with(topAreaSection) {
                                DefaultClockLayout(
                                    modifier =
                                        Modifier.graphicsLayer {
                                            translationX = unfoldTranslations.start
                                        }
                                )
                            }
                            if (shouldUseSplitNotificationShade) {
                                with(notificationSection) {
                                    Notifications(
@@ -127,8 +146,18 @@ constructor(

                    // Aligned to bottom and NOT constrained by the lock icon.
                    with(bottomAreaSection) {
                        Shortcut(isStart = true, applyPadding = true)
                        Shortcut(isStart = false, applyPadding = true)
                        Shortcut(
                            isStart = true,
                            applyPadding = true,
                            modifier =
                                Modifier.graphicsLayer { translationX = unfoldTranslations.start },
                        )
                        Shortcut(
                            isStart = false,
                            applyPadding = true,
                            modifier =
                                Modifier.graphicsLayer { translationX = unfoldTranslations.end },
                        )
                    }
                    with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) }
                },
+37 −4
Original line number Diff line number Diff line
@@ -26,9 +26,11 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.unit.IntRect
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.padding
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
@@ -43,6 +45,7 @@ import dagger.Module
import dagger.multibindings.IntoSet
import java.util.Optional
import javax.inject.Inject
import kotlin.math.roundToInt

/**
 * Renders the lockscreen scene when showing with the default layout (e.g. vertical phone form
@@ -68,6 +71,7 @@ constructor(
        val isUdfpsVisible = viewModel.isUdfpsVisible
        val shouldUseSplitNotificationShade by
            viewModel.shouldUseSplitNotificationShade.collectAsState()
        val unfoldTranslations by viewModel.unfoldTranslations.collectAsState()

        LockscreenLongPress(
            viewModel = viewModel.longPress,
@@ -79,10 +83,25 @@ constructor(
                    Column(
                        modifier = Modifier.fillMaxSize(),
                    ) {
                        with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) }
                        with(statusBarSection) {
                            StatusBar(
                                modifier =
                                    Modifier.fillMaxWidth()
                                        .padding(
                                            horizontal = { unfoldTranslations.start.roundToInt() },
                                        )
                            )
                        }

                        Box {
                            with(topAreaSection) { DefaultClockLayout() }
                            with(topAreaSection) {
                                DefaultClockLayout(
                                    modifier =
                                        Modifier.graphicsLayer {
                                            translationX = unfoldTranslations.start
                                        },
                                )
                            }
                            if (shouldUseSplitNotificationShade) {
                                with(notificationSection) {
                                    Notifications(
@@ -111,12 +130,26 @@ constructor(
                    }

                    // Constrained to the left of the lock icon (in left-to-right layouts).
                    with(bottomAreaSection) { Shortcut(isStart = true, applyPadding = false) }
                    with(bottomAreaSection) {
                        Shortcut(
                            isStart = true,
                            applyPadding = false,
                            modifier =
                                Modifier.graphicsLayer { translationX = unfoldTranslations.start },
                        )
                    }

                    with(lockSection) { LockIcon() }

                    // Constrained to the right of the lock icon (in left-to-right layouts).
                    with(bottomAreaSection) { Shortcut(isStart = false, applyPadding = false) }
                    with(bottomAreaSection) {
                        Shortcut(
                            isStart = false,
                            applyPadding = false,
                            modifier =
                                Modifier.graphicsLayer { translationX = unfoldTranslations.end },
                        )
                    }

                    // Aligned to bottom and constrained to below the lock icon.
                    Column(modifier = Modifier.fillMaxWidth()) {
+47 −0
Original line number Diff line number Diff line
@@ -21,17 +21,21 @@ import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardClockSwitch
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.authController
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import java.util.Locale
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -137,4 +141,47 @@ class LockscreenContentViewModelTest : SysuiTestCase() {
                    .isFalse()
            }
        }

    @Test
    fun unfoldTranslations() =
        with(kosmos) {
            testScope.runTest {
                val maxTranslation = prepareConfiguration()
                val translations by collectLastValue(underTest.unfoldTranslations)

                val unfoldProvider = fakeUnfoldTransitionProgressProvider
                unfoldProvider.onTransitionStarted()
                assertThat(translations?.start).isEqualTo(0f)
                assertThat(translations?.end).isEqualTo(-0f)

                repeat(10) { repetition ->
                    val transitionProgress = 0.1f * (repetition + 1)
                    unfoldProvider.onTransitionProgress(transitionProgress)
                    assertThat(translations?.start)
                        .isEqualTo((1 - transitionProgress) * maxTranslation)
                    assertThat(translations?.end)
                        .isEqualTo(-(1 - transitionProgress) * maxTranslation)
                }

                unfoldProvider.onTransitionFinishing()
                assertThat(translations?.start).isEqualTo(0f)
                assertThat(translations?.end).isEqualTo(-0f)

                unfoldProvider.onTransitionFinished()
                assertThat(translations?.start).isEqualTo(0f)
                assertThat(translations?.end).isEqualTo(-0f)
            }
        }

    private fun prepareConfiguration(): Int {
        val configuration = context.resources.configuration
        configuration.setLayoutDirection(Locale.US)
        kosmos.fakeConfigurationRepository.onConfigurationChange(configuration)
        val maxTranslation = 10
        kosmos.fakeConfigurationRepository.setDimensionPixelSize(
            R.dimen.notification_side_paddings,
            maxTranslation,
        )
        return maxTranslation
    }
}
+35 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
@@ -46,6 +47,7 @@ constructor(
    val longPress: KeyguardLongPressViewModel,
    val shadeInteractor: ShadeInteractor,
    @Application private val applicationScope: CoroutineScope,
    private val unfoldTransitionInteractor: UnfoldTransitionInteractor,
) {
    private val clockSize = clockInteractor.clockSize

@@ -75,6 +77,23 @@ constructor(
                initialValue = false,
            )

    /** Amount of horizontal translation that should be applied to elements in the scene. */
    val unfoldTranslations: StateFlow<UnfoldTranslations> =
        combine(
                unfoldTransitionInteractor.unfoldTranslationX(isOnStartSide = true),
                unfoldTransitionInteractor.unfoldTranslationX(isOnStartSide = false),
            ) { start, end ->
                UnfoldTranslations(
                    start = start,
                    end = end,
                )
            }
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = UnfoldTranslations(),
            )

    fun getSmartSpacePaddingTop(resources: Resources): Int {
        return if (isLargeClockVisible) {
            resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset) +
@@ -94,4 +113,20 @@ constructor(
                initialValue = interactor.getCurrentBlueprint().id,
            )
    }

    data class UnfoldTranslations(

        /**
         * Amount of horizontal translation to apply to elements that are aligned to the start side
         * (left in left-to-right layouts). Can also be used as horizontal padding for elements that
         * need horizontal padding on both side. In pixels.
         */
        val start: Float = 0f,

        /**
         * Amount of horizontal translation to apply to elements that are aligned to the end side
         * (right in left-to-right layouts). In pixels.
         */
        val end: Float = 0f,
    )
}
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor

val Kosmos.lockscreenContentViewModel by
    Kosmos.Fixture {
@@ -32,5 +33,6 @@ val Kosmos.lockscreenContentViewModel by
            longPress = keyguardLongPressViewModel,
            shadeInteractor = shadeInteractor,
            applicationScope = applicationCoroutineScope,
            unfoldTransitionInteractor = unfoldTransitionInteractor,
        )
    }