Skip to content

Commit

Permalink
Do not continue animation if it's cancelled with higher priority
Browse files Browse the repository at this point in the history
  • Loading branch information
MatkovIvan committed Feb 12, 2024
1 parent fbdc4cd commit 5bbe23d
Showing 1 changed file with 29 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope

private val AnimationThreshold = 4.dp
private val AnimationSpeed = 1.dp // dp / ms
Expand Down Expand Up @@ -169,7 +170,7 @@ private class AnimatedMouseWheelScrollPhysics(
private fun ScrollingLogic.dispatchWheelScroll(delta: Float) {
val offset = delta.reverseIfNeeded().toOffset()
coroutineScope.launch {
scrollableState.scroll(MutatePriority.UserInput) {
scrollableState.userScroll {
dispatchScroll(offset, NestedScrollSource.Wheel)
}

Expand All @@ -191,6 +192,13 @@ private class AnimatedMouseWheelScrollPhysics(
consumed.reverseIfNeeded().toFloat()
}

private suspend fun ScrollableState.userScroll(
block: suspend ScrollScope.() -> Unit
) = supervisorScope {
// Run it in supervisorScope to ignore cancellations from scrolls with higher MutatePriority
scroll(MutatePriority.UserInput, block)
}

override fun PointerInputScope.onMouseWheel(pointerEvent: PointerEvent): Boolean {
val scrollDelta = with(mouseWheelScrollConfig) {
calculateMouseWheelScroll(pointerEvent, size)
Expand Down Expand Up @@ -256,34 +264,30 @@ private class AnimatedMouseWheelScrollPhysics(
val durationMillis = (abs(target - anim.value) / speed)
.roundToInt()
.coerceAtMost(MaxAnimationDuration)
try {
scrollableState.scroll(MutatePriority.UserInput) {
anim.animateTo(
target,
animationSpec = tween(
durationMillis = durationMillis,
easing = LinearEasing
),
sequentialAnimation = true
) {
val delta = value - lastValue
if (!delta.isLowScrollingDelta()) {
val consumedDelta = dispatchWheelScroll(delta)
if (!(delta - consumedDelta).isLowScrollingDelta()) {
cancelAnimation()
return@animateTo
}
lastValue += delta
}
tryReceiveNext()?.let {
target += it
requiredAnimation = !(target - lastValue).isLowScrollingDelta()
scrollableState.userScroll {
anim.animateTo(
target,
animationSpec = tween(
durationMillis = durationMillis,
easing = LinearEasing
),
sequentialAnimation = true
) {
val delta = value - lastValue
if (!delta.isLowScrollingDelta()) {
val consumedDelta = dispatchWheelScroll(delta)
if (!(delta - consumedDelta).isLowScrollingDelta()) {
cancelAnimation()
return@animateTo
}
lastValue += delta
}
tryReceiveNext()?.let {
target += it
requiredAnimation = !(target - lastValue).isLowScrollingDelta()
cancelAnimation()
}
}
} catch (ignore: CancellationException) {
requiredAnimation = true
}
}
}
Expand Down

0 comments on commit 5bbe23d

Please sign in to comment.