Fix drawer animation snapping on Reanimated 4
Reanimated 4 (New Architecture, #10980) rewrote spring termination: with `overshootClamping`, which drawer-layout always passes, an animation now ends as soon as the position leaves the corridor between its start and its target. Reanimated 3 only treated crossing the target as overshoot. So on Reanimated 4 any release whose velocity opposes the direction the drawer settles in ends the spring on its first frame, and the drawer teleports instead of animating. Two easy ways in: an aborted drag under `swipeMinDistance`/`swipeMinVelocity`, where `nextOpen` keeps its current value while the finger was moving the other way, and dragging the already-open drawer past its edge before releasing. Refresh the patch against upstream `main`, which fixes this by zeroing velocity that opposes the spring direction, and take the two other changes to the same function while we are here: an early return when the drawer is already at the target, and `useLayoutEffect` for the `open` prop so the follow-up `toggleDrawer` call does not depend on the spring still running to be deduped. Regenerated with `pnpm patch` / `pnpm patch-commit`. Also adds the patch doc this one was missing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011DRYvgEawpfehopEibJXQB
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
diff --git a/lib/module/views/Drawer.native.js b/lib/module/views/Drawer.native.js
|
||||
index 38470a658878a63919186257041098747ec55473..b9d25798c9be229efeb676166f89bfbc72615793 100644
|
||||
index 38470a658878a63919186257041098747ec55473..1836d661ca0f8fa3e886da06e72eb004cd8f585e 100644
|
||||
--- a/lib/module/views/Drawer.native.js
|
||||
+++ b/lib/module/views/Drawer.native.js
|
||||
@@ -124,15 +124,21 @@ export function Drawer({
|
||||
@@ -124,17 +124,33 @@ export function Drawer({
|
||||
}
|
||||
onTransitionEnd?.(!open);
|
||||
});
|
||||
@@ -10,21 +10,34 @@ index 38470a658878a63919186257041098747ec55473..b9d25798c9be229efeb676166f89bfbc
|
||||
const toggleDrawer = React.useCallback((open, velocity) => {
|
||||
'worklet';
|
||||
|
||||
const translateX = getDrawerTranslationX(open);
|
||||
+
|
||||
+ if (translationX.value === translateX) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (animatingTo.value === (open ? 'open' : 'close')) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
const translateX = getDrawerTranslationX(open);
|
||||
if (velocity === undefined) {
|
||||
runOnJS(onAnimationStart)(open);
|
||||
}
|
||||
touchStartX.value = 0;
|
||||
touchX.value = 0;
|
||||
+
|
||||
+ // Ignore velocity that opposes the spring direction.
|
||||
+ // Otherwise overshootClamping makes the spring snap instantly.
|
||||
+ const isSameDirection = velocity !== undefined && (translateX > translationX.value && velocity > 0 || translateX < translationX.value && velocity < 0);
|
||||
+ const effectiveVelocity = isSameDirection ? velocity : 0;
|
||||
+ animatingTo.value = open ? 'open' : 'close';
|
||||
translationX.value = withSpring(translateX, {
|
||||
velocity,
|
||||
- velocity,
|
||||
+ velocity: effectiveVelocity,
|
||||
stiffness: 1000,
|
||||
@@ -142,7 +148,10 @@ export function Drawer({
|
||||
damping: 500,
|
||||
mass: 3,
|
||||
@@ -142,14 +158,19 @@ export function Drawer({
|
||||
restDisplacementThreshold: 0.01,
|
||||
restSpeedThreshold: 0.01,
|
||||
reduceMotion: ReduceMotion.Never
|
||||
@@ -36,3 +49,13 @@ index 38470a658878a63919186257041098747ec55473..b9d25798c9be229efeb676166f89bfbc
|
||||
if (open) {
|
||||
runOnJS(onOpen)();
|
||||
} else {
|
||||
runOnJS(onClose)();
|
||||
}
|
||||
}, [getDrawerTranslationX, onAnimationEnd, onAnimationStart, onClose, onOpen, touchStartX, touchX, translationX]);
|
||||
- React.useEffect(() => toggleDrawer(open), [open, toggleDrawer]);
|
||||
+ React.useLayoutEffect(() => {
|
||||
+ toggleDrawer(open);
|
||||
+ }, [open, toggleDrawer]);
|
||||
const startX = useSharedValue(0);
|
||||
const pan = React.useMemo(() => {
|
||||
let panGesture = Gesture?.Pan().onBegin(event => {
|
||||
|
||||
Reference in New Issue
Block a user