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

Commit e5e65f28 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Wait for overscroll to finish before finishing a transition" into main

parents 494594ea b8cd7a76
Loading
Loading
Loading
Loading
+19 −7
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.compose.nestedscroll.PriorityNestedScrollConnection
import com.android.compose.nestedscroll.ScrollController
import com.android.compose.ui.util.SpaceVectorConverter
import kotlin.math.absoluteValue
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -359,13 +360,24 @@ private class DragControllerImpl(
            return swipeAnimation.animateOffset(velocity, targetContent)
        }

        val overscrollCompletable = CompletableDeferred<Unit>()
        try {
            overscrollEffect.applyToFling(
                velocity = velocity.toVelocity(),
                performFling = {
                    val velocityLeft = it.toFloat()
                swipeAnimation.animateOffset(velocityLeft, targetContent).toVelocity()
                    swipeAnimation
                        .animateOffset(
                            velocityLeft,
                            targetContent,
                            overscrollCompletable = overscrollCompletable,
                        )
                        .toVelocity()
                },
            )
        } finally {
            overscrollCompletable.complete(Unit)
        }

        return velocity
    }
+13 −2
Original line number Diff line number Diff line
@@ -271,7 +271,7 @@ internal class SwipeAnimation<T : ContentKey>(

    /** The offset animation that animates the offset once the user lifts their finger. */
    private var offsetAnimation: Animatable<Float, AnimationVector1D>? by mutableStateOf(null)
    private val offsetAnimationRunnable = CompletableDeferred<(suspend () -> Unit)?>()
    private val offsetAnimationRunnable = CompletableDeferred<suspend () -> Unit>()

    val isUserInputOngoing: Boolean
        get() = offsetAnimation == null
@@ -333,6 +333,7 @@ internal class SwipeAnimation<T : ContentKey>(
        initialVelocity: Float,
        targetContent: T,
        spec: AnimationSpec<Float>? = null,
        overscrollCompletable: CompletableDeferred<Unit>? = null,
    ): Float {
        check(!isAnimatingOffset()) { "SwipeAnimation.animateOffset() can only be called once" }

@@ -391,7 +392,12 @@ internal class SwipeAnimation<T : ContentKey>(
        // detail).
        if (skipAnimation) {
            // Unblock the job.
            offsetAnimationRunnable.complete(null)
            offsetAnimationRunnable.complete {
                // Wait for overscroll to finish so that the transition is removed from the STLState
                // only after the overscroll is done, to avoid dropping frame right when the user
                // lifts their finger and overscroll is animated to 0.
                overscrollCompletable?.await()
            }
            return 0f
        }

@@ -450,6 +456,11 @@ internal class SwipeAnimation<T : ContentKey>(
                    // The animation consumed the whole available velocity
                    velocityConsumed.complete(initialVelocity)
                }

                // Wait for overscroll to finish so that the transition is removed from the STLState
                // only after the overscroll is done, to avoid dropping frame right when the user
                // lifts their finger and overscroll is animated to 0.
                overscrollCompletable?.await()
            }
        }