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

Commit b6030848 authored by cocod's avatar cocod
Browse files

Motion for hub <-> edit mode transition

Fix lockscreen flashing when starting the edit mode activity and
transitioning from alternate_bouncer to gone state.
Add custom keys and animations for entering and exiting the edit
mode in sceneTransitions.
Add animations for the grid and toolbar in CommunalHub for edit mode.

Bug: b/325108777
Flag: com.android.systemui.communal_hub
Test: atest CommunalInteractorTest
Test: atest CommunalSceneInteractorTest
Test: atest CommunalEditModeViewModelTest
Test: atest FromAlternateBouncerTransitionInteractorTest
Test: manually enter or exit the edit mode
Change-Id: Idfe1297679085c46c18af9ad09d1dd4f6e2391b1
parent 0c1aab59
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import com.android.systemui.Flags.glanceableHubFullscreenSwipe
import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalTransitionKeys
import com.android.systemui.communal.ui.compose.Dimensions.SlideOffsetY
import com.android.systemui.communal.ui.compose.extensions.allowGestures
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.util.CommunalColors
@@ -75,6 +76,15 @@ object AllElements : ElementMatcher {
    override fun matches(key: ElementKey, scene: SceneKey) = true
}

private object TransitionDuration {
    const val BETWEEN_HUB_AND_EDIT_MODE_MS = 1000
    const val EDIT_MODE_TO_HUB_CONTENT_MS = 167
    const val EDIT_MODE_TO_HUB_GRID_DELAY_MS = 167
    const val EDIT_MODE_TO_HUB_GRID_END_MS =
        EDIT_MODE_TO_HUB_GRID_DELAY_MS + EDIT_MODE_TO_HUB_CONTENT_MS
    const val HUB_TO_EDIT_MODE_CONTENT_MS = 250
}

val sceneTransitions = transitions {
    to(CommunalScenes.Communal, key = CommunalTransitionKeys.SimpleFade) {
        spec = tween(durationMillis = 250)
@@ -95,6 +105,30 @@ val sceneTransitions = transitions {
        }
        timestampRange(startMillis = 167, endMillis = 334) { fade(Communal.Elements.Scrim) }
    }
    to(CommunalScenes.Blank, key = CommunalTransitionKeys.ToEditMode) {
        spec = tween(durationMillis = TransitionDuration.BETWEEN_HUB_AND_EDIT_MODE_MS)
        timestampRange(endMillis = TransitionDuration.HUB_TO_EDIT_MODE_CONTENT_MS) {
            fade(Communal.Elements.Grid)
            fade(Communal.Elements.IndicationArea)
            fade(Communal.Elements.LockIcon)
        }
        fade(Communal.Elements.Scrim)
    }
    to(CommunalScenes.Communal, key = CommunalTransitionKeys.FromEditMode) {
        spec = tween(durationMillis = TransitionDuration.BETWEEN_HUB_AND_EDIT_MODE_MS)
        translate(Communal.Elements.Grid, y = SlideOffsetY)
        timestampRange(endMillis = TransitionDuration.EDIT_MODE_TO_HUB_CONTENT_MS) {
            fade(Communal.Elements.IndicationArea)
            fade(Communal.Elements.LockIcon)
            fade(Communal.Elements.Scrim)
        }
        timestampRange(
            startMillis = TransitionDuration.EDIT_MODE_TO_HUB_GRID_DELAY_MS,
            endMillis = TransitionDuration.EDIT_MODE_TO_HUB_GRID_END_MS
        ) {
            fade(Communal.Elements.Grid)
        }
    }
}

/**
+85 −36
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
@@ -128,6 +130,7 @@ import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Popup
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.layout.WindowMetricsCalculator
import com.android.compose.animation.Easings.Emphasized
import com.android.compose.modifiers.thenIf
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
@@ -176,6 +179,10 @@ fun CommunalHub(
        derivedStateOf { selectedKey.value != null || reorderingWidgets }
    }
    val isEmptyState by viewModel.isEmptyState.collectAsStateWithLifecycle(initialValue = false)
    val isCommunalContentVisible by
        viewModel.isCommunalContentVisible.collectAsStateWithLifecycle(
            initialValue = !viewModel.isEditMode
        )

    val contentPadding = gridContentPadding(viewModel.isEditMode, toolbarSize)
    val contentOffset = beforeContentPadding(contentPadding).toOffset()
@@ -248,6 +255,30 @@ fun CommunalHub(
                    viewModel = viewModel,
                )
            } else {
                val slideOffsetInPx =
                    with(LocalDensity.current) { Dimensions.SlideOffsetY.toPx().toInt() }
                AnimatedVisibility(
                    visible = isCommunalContentVisible,
                    enter =
                        fadeIn(
                            animationSpec =
                                tween(durationMillis = 83, delayMillis = 83, easing = LinearEasing)
                        ) +
                            slideInVertically(
                                animationSpec = tween(durationMillis = 1000, easing = Emphasized),
                                initialOffsetY = { -slideOffsetInPx }
                            ),
                    exit =
                        fadeOut(
                            animationSpec = tween(durationMillis = 167, easing = LinearEasing)
                        ) +
                            slideOutVertically(
                                animationSpec = tween(durationMillis = 1000, easing = Emphasized),
                                targetOffsetY = { -slideOffsetInPx }
                            ),
                    modifier = Modifier.fillMaxSize(),
                ) {
                    Box {
                        CommunalHubLazyGrid(
                            communalContent = communalContent,
                            viewModel = viewModel,
@@ -257,7 +288,8 @@ fun CommunalHub(
                            updateDragPositionForRemove = { offset ->
                                isPointerWithinEnabledRemoveButton(
                                    removeEnabled = removeButtonEnabled,
                            offset = gridCoordinates?.let { it.positionInWindow() + offset },
                                    offset =
                                        gridCoordinates?.let { it.positionInWindow() + offset },
                                    containerToCheck = removeButtonCoordinates
                                )
                            },
@@ -269,8 +301,23 @@ fun CommunalHub(
                        )
                    }
                }
            }
        }

        if (viewModel.isEditMode && onOpenWidgetPicker != null && onEditDone != null) {
        if (onOpenWidgetPicker != null && onEditDone != null) {
            AnimatedVisibility(
                visible = viewModel.isEditMode && isCommunalContentVisible,
                enter =
                    fadeIn(animationSpec = tween(durationMillis = 250, easing = LinearEasing)) +
                        slideInVertically(
                            animationSpec = tween(durationMillis = 1000, easing = Emphasized),
                        ),
                exit =
                    fadeOut(animationSpec = tween(durationMillis = 167, easing = LinearEasing)) +
                        slideOutVertically(
                            animationSpec = tween(durationMillis = 1000, easing = Emphasized)
                        ),
            ) {
                Toolbar(
                    setToolbarSize = { toolbarSize = it },
                    setRemoveButtonCoordinates = { removeButtonCoordinates = it },
@@ -290,6 +337,7 @@ fun CommunalHub(
                    removeEnabled = removeButtonEnabled
                )
            }
        }
        if (currentPopup == PopupType.CtaTile) {
            PopupOnDismissCtaTile(viewModel::onHidePopup)
        }
@@ -1277,6 +1325,7 @@ object Dimensions {
            horizontal = ToolbarButtonPaddingHorizontal,
        )
    val IconSize = 40.dp
    val SlideOffsetY = 30.dp
}

private object Colors {
+19 −0
Original line number Diff line number Diff line
@@ -111,6 +111,25 @@ class CommunalSceneStartableTest : SysuiTestCase() {
            }
        }

    @Test
    fun keyguardGoesAway_whenInEditMode_doesNotChangeScene() =
        with(kosmos) {
            testScope.runTest {
                val scene by collectLastValue(communalSceneInteractor.currentScene)
                communalSceneInteractor.changeScene(CommunalScenes.Communal)
                assertThat(scene).isEqualTo(CommunalScenes.Communal)

                communalInteractor.setEditModeOpen(true)
                fakeKeyguardTransitionRepository.sendTransitionSteps(
                    from = KeyguardState.ALTERNATE_BOUNCER,
                    to = KeyguardState.GONE,
                    testScope = this
                )
                // Scene change will be handled in EditWidgetsActivity not here
                assertThat(scene).isEqualTo(CommunalScenes.Communal)
            }
        }

    @Ignore("Ignored until custom animations are implemented in b/322787129")
    @Test
    fun deviceDocked_forceCommunalScene() =
+7 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import com.android.systemui.communal.domain.model.CommunalTransitionProgressMode
import com.android.systemui.communal.shared.model.CommunalContentSize
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
import com.android.systemui.communal.shared.model.EditModeState
import com.android.systemui.communal.widgets.EditWidgetsActivityStarter
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
@@ -121,6 +122,7 @@ class CommunalInteractorTest : SysuiTestCase() {
    private lateinit var communalPrefsRepository: FakeCommunalPrefsRepository
    private lateinit var editWidgetsActivityStarter: EditWidgetsActivityStarter
    private lateinit var sceneInteractor: SceneInteractor
    private lateinit var communalSceneInteractor: CommunalSceneInteractor
    private lateinit var userTracker: FakeUserTracker
    private lateinit var activityStarter: ActivityStarter
    private lateinit var userManager: UserManager
@@ -141,6 +143,7 @@ class CommunalInteractorTest : SysuiTestCase() {
        editWidgetsActivityStarter = kosmos.editWidgetsActivityStarter
        communalPrefsRepository = kosmos.fakeCommunalPrefsRepository
        sceneInteractor = kosmos.sceneInteractor
        communalSceneInteractor = kosmos.communalSceneInteractor
        userTracker = kosmos.fakeUserTracker
        activityStarter = kosmos.activityStarter
        userManager = kosmos.userManager
@@ -815,7 +818,11 @@ class CommunalInteractorTest : SysuiTestCase() {
    @Test
    fun testShowWidgetEditorStartsActivity() =
        testScope.runTest {
            val editModeState by collectLastValue(communalSceneInteractor.editModeState)

            underTest.showWidgetEditor()

            assertThat(editModeState).isEqualTo(EditModeState.STARTING)
            verify(editWidgetsActivityStarter).startActivity()
        }

+22 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import com.android.systemui.animation.ActivityTransitionAnimator
import com.android.systemui.communal.data.repository.communalSceneRepository
import com.android.systemui.communal.domain.model.CommunalTransitionProgressModel
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.EditModeState
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
@@ -81,6 +82,27 @@ class CommunalSceneInteractorTest : SysuiTestCase() {
            assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
        }

    @Test
    fun snapToSceneForActivity() =
        testScope.runTest {
            val currentScene by collectLastValue(underTest.currentScene)
            assertThat(currentScene).isEqualTo(CommunalScenes.Blank)

            underTest.snapToSceneForActivityStart(CommunalScenes.Communal)
            assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
        }

    @Test
    fun snapToSceneForActivity_willNotChangeScene_forEditModeActivity() =
        testScope.runTest {
            val currentScene by collectLastValue(underTest.currentScene)
            assertThat(currentScene).isEqualTo(CommunalScenes.Blank)

            underTest.setEditModeState(EditModeState.STARTING)
            underTest.snapToSceneForActivityStart(CommunalScenes.Communal)
            assertThat(currentScene).isEqualTo(CommunalScenes.Blank)
        }

    @Test
    fun transitionProgress_fullProgress() =
        testScope.runTest {
Loading