diff options
5 files changed, 154 insertions, 8 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt index 28e92aad914a..e499c6908b86 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt @@ -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) } }, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt index b8f00dce53df..9d31955122eb 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt @@ -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()) { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt index e9a825721f5f..3497183c2c69 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt @@ -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 + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt index 36896f916e7d..ecad1483ba61 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt @@ -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, + ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt index 1e25f7fd470e..30a4f21b67f5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt @@ -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, ) } |