Fix stuck lightbox (#6166)

* Add early exit guards once the gesture is over

* Work around the Reanimated bug

* Move derived reaction upwards to avoid duplicating it
This commit is contained in:
dan
2024-11-08 17:48:01 +00:00
committed by GitHub
parent 7c45f7dcc7
commit ce8d62f8c9
+28 -16
View File
@@ -160,6 +160,23 @@ function ImageView({
} }
}, []) }, [])
useAnimatedReaction(
() => {
const screenSize = measure(safeAreaRef)
return (
!screenSize ||
Math.abs(dismissSwipeTranslateY.value) > screenSize.height
)
},
(isOut, wasOut) => {
if (isOut && !wasOut) {
// Stop the animation from blocking the screen forever.
cancelAnimation(dismissSwipeTranslateY)
runOnJS(onRequestClose)()
}
},
)
return ( return (
<Animated.View style={[styles.container, containerStyle]}> <Animated.View style={[styles.container, containerStyle]}>
<Animated.View <Animated.View
@@ -256,12 +273,23 @@ function LightboxImage({
.maxPointers(1) .maxPointers(1)
.onUpdate(e => { .onUpdate(e => {
'worklet' 'worklet'
if (isFlyingAway.value) {
return
}
dismissSwipeTranslateY.value = e.translationY dismissSwipeTranslateY.value = e.translationY
}) })
.onEnd(e => { .onEnd(e => {
'worklet' 'worklet'
if (isFlyingAway.value) {
return
}
if (Math.abs(e.velocityY) > 1000) { if (Math.abs(e.velocityY) > 1000) {
isFlyingAway.value = true isFlyingAway.value = true
if (dismissSwipeTranslateY.value === 0) {
// HACK: If the initial value is 0, withDecay() animation doesn't start.
// This is a bug in Reanimated, but for now we'll work around it like this.
dismissSwipeTranslateY.value = 1
}
dismissSwipeTranslateY.value = withDecay({ dismissSwipeTranslateY.value = withDecay({
velocity: e.velocityY, velocity: e.velocityY,
velocityFactor: Math.max(3000 / Math.abs(e.velocityY), 1), // Speed up if it's too slow. velocityFactor: Math.max(3000 / Math.abs(e.velocityY), 1), // Speed up if it's too slow.
@@ -274,22 +302,6 @@ function LightboxImage({
}) })
} }
}) })
useAnimatedReaction(
() => {
const screenSize = measure(safeAreaRef)
return (
!screenSize ||
Math.abs(dismissSwipeTranslateY.value) > screenSize.height
)
},
(isOut, wasOut) => {
if (isOut && !wasOut) {
// Stop the animation from blocking the screen forever.
cancelAnimation(dismissSwipeTranslateY)
runOnJS(onRequestClose)()
}
},
)
const imageStyle = useAnimatedStyle(() => { const imageStyle = useAnimatedStyle(() => {
return { return {