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

Commit 7167a27a authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Extract SwipeAnimation out of SwipeTransition

This CL is very similar to ag/28575909: it extracts a SwipeAnimation
class that contain most of the logic needed for swipe transitions. This
will be used to implement swipe transition that can animate overlays in
& out.

This is a pure refactoring that does not add any feature.

Bug: 353679003
Test: atest DraggableHandlerTest
Flag: com.android.systemui.scene_container
Change-Id: I65511c8354ff14b431fd34abae30b666ea99d514
parent e2729293
Loading
Loading
Loading
Loading
+316 −266

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -269,13 +269,13 @@ internal class MultiPointerDraggableNode(
                                                    velocityTracker.calculateVelocity(maxVelocity)
                                                }
                                                .toFloat(),
                                        onFling = { controller.onStop(it, canChangeScene = true) }
                                        onFling = { controller.onStop(it, canChangeContent = true) }
                                    )
                                },
                                onDragCancel = { controller ->
                                    startFlingGesture(
                                        initialVelocity = 0f,
                                        onFling = { controller.onStop(it, canChangeScene = true) }
                                        onFling = { controller.onStop(it, canChangeContent = true) }
                                    )
                                },
                                swipeDetector = swipeDetector,
+34 −7
Original line number Diff line number Diff line
@@ -479,20 +479,47 @@ interface SwipeSourceDetector {
}

/** The result of performing a [UserAction]. */
data class UserActionResult(
    /** The scene we should be transitioning to during the [UserAction]. */
    val toScene: SceneKey,

sealed class UserActionResult(
    /** The key of the transition that should be used. */
    val transitionKey: TransitionKey? = null,
    open val transitionKey: TransitionKey? = null,

    /**
     * If `true`, the swipe will be committed and we will settle to [toScene] if only if the user
     * swiped at least the swipe distance, i.e. the transition progress was already equal to or
     * bigger than 100% when the user released their finger. `
     */
    val requiresFullDistanceSwipe: Boolean = false,
)
    open val requiresFullDistanceSwipe: Boolean,
) {
    internal abstract fun toContent(currentScene: SceneKey): ContentKey

    data class ChangeScene
    internal constructor(
        /** The scene we should be transitioning to during the [UserAction]. */
        val toScene: SceneKey,
        override val transitionKey: TransitionKey? = null,
        override val requiresFullDistanceSwipe: Boolean = false,
    ) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
        override fun toContent(currentScene: SceneKey): ContentKey = toScene
    }

    companion object {
        /** A [UserActionResult] that changes the current scene to [toScene]. */
        operator fun invoke(
            /** The scene we should be transitioning to during the [UserAction]. */
            toScene: SceneKey,

            /** The key of the transition that should be used. */
            transitionKey: TransitionKey? = null,

            /**
             * If `true`, the swipe will be committed if only if the user swiped at least the swipe
             * distance, i.e. the transition progress was already equal to or bigger than 100% when
             * the user released their finger.
             */
            requiresFullDistanceSwipe: Boolean = false,
        ): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe)
    }
}

fun interface UserActionDistance {
    /**
+16 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import androidx.compose.ui.layout.ApproachMeasureScope
import androidx.compose.ui.layout.LookaheadScope
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.node.LayoutAwareModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Density
@@ -132,6 +133,8 @@ internal class SceneTransitionLayoutImpl(
    internal lateinit var lookaheadScope: LookaheadScope
        private set

    internal var lastSize: IntSize = IntSize.Zero

    init {
        updateContents(builder, layoutDirection)

@@ -286,8 +289,13 @@ internal class SceneTransitionLayoutImpl(

    @Composable
    private fun BackHandler() {
        val result = scene(state.transitionState.currentScene).userActions[Back.Resolved]
        val targetSceneForBack =
            scene(state.transitionState.currentScene).userActions[Back.Resolved]?.toScene
            when (result) {
                null -> null
                is UserActionResult.ChangeScene -> result.toScene
            }

        PredictiveBackHandler(state, coroutineScope, targetSceneForBack)
    }

@@ -379,7 +387,8 @@ internal class SceneTransitionLayoutImpl(
            .sortedBy { it.zIndex }
    }

    internal fun setScenesTargetSizeForTest(size: IntSize) {
    internal fun setScenesAndLayoutTargetSizeForTest(size: IntSize) {
        lastSize = size
        scenes.values.forEach { it.targetSize = size }
    }

@@ -396,7 +405,11 @@ private data class LayoutElement(private val layoutImpl: SceneTransitionLayoutIm
}

private class LayoutNode(var layoutImpl: SceneTransitionLayoutImpl) :
    Modifier.Node(), ApproachLayoutModifierNode {
    Modifier.Node(), ApproachLayoutModifierNode, LayoutAwareModifierNode {
    override fun onRemeasured(size: IntSize) {
        layoutImpl.lastSize = size
    }

    override fun isMeasurementApproachInProgress(lookaheadSize: IntSize): Boolean {
        return layoutImpl.state.isTransitioning()
    }
+9 −5
Original line number Diff line number Diff line
@@ -78,13 +78,17 @@ internal sealed class Content(
        userActions: Map<UserAction.Resolved, UserActionResult>
    ): Map<UserAction.Resolved, UserActionResult> {
        userActions.forEach { (action, result) ->
            when (result) {
                is UserActionResult.ChangeScene -> {
                    if (key == result.toScene) {
                        error(
                    "Transition to the same content (scene/overlay) is not supported. Content " +
                        "$key, action $action, result $result"
                            "Transition to the same content (scene/overlay) is not supported. " +
                                "Content $key, action $action, result $result"
                        )
                    }
                }
            }
        }
        return userActions
    }

Loading