Skip to content

refactor: Upgrade to React Native Gesture Handler v3#499

Merged
cyanChill merged 9 commits into
devfrom
refactor/rngh-3
May 29, 2026
Merged

refactor: Upgrade to React Native Gesture Handler v3#499
cyanChill merged 9 commits into
devfrom
refactor/rngh-3

Conversation

@cyanChill

@cyanChill cyanChill commented May 29, 2026

Copy link
Copy Markdown
Member

Why

The migration to the hook-based API was mostly smooth, with some hiccups. Some notable changes include:

  • Switching the Gesture API to be hook-based, which improves compatibility with the React Compiler.
  • Some callbacks were renamed: onStart -> onActivate & onEnd -> onDeactivate.
  • We can use Reanimated's SharedValue directly in the Gesture configs.
  • This does result in the installed app size to increase by ~0.35 MB.

One thing that did break during this migration were the swipe gestures on our miniplayer, which was handled by our Swipeable component. Due to switching to the hook-based API, if we update the value of a ref inside one of the callbacks and later accessed it in the same callback, we would see that the ref doesn't contain the latest value. This might be due to the cloning that happens under the hood in the hook.

Besides that, we get a lot more worklet warnings.

Other Changes / Notes

  • We re-add some styling defaults to the DragList component.
    • These are layout-related (vertical padding & adjustments to our "fake gaps").
  • We don't want to change the onCleanup function in the DragList component to a worklet function due to the timing changes resulting in a worse "jumping" effect after dropping the item.

References:

Checklist

  • Documentation is up to date to reflect these changes.
  • Ensure dependency licenses are up-to-date by running pnpm sync:licenses.
  • This diff will work correctly for pnpm android:prod.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed TypeScript type compatibility warnings in form input components
  • Chores

    • Updated react-native-gesture-handler library to version 3.0.0
    • Improved gesture handling implementation across dragging, swiping, and touch-based interactions

Review Change Stack

cyanChill added 9 commits May 28, 2026 21:16
- v3 was released as stable today, but we won't install it immediately due to our PNPM rules of waiting a day after a package has been released before installing it.
- Gestures are now created with hooks.
- `onStart` & `onEnd` were renamed.
- We can pass SharedValue to the config properties.
- Since to apply our "fake gaps", we add a "mb-2" style basically to every rendered item, this would result in a bigger gap at the bottom of the list. To counter this, we had a `-mb-2` style on the draglist.
- We get have worklet warnings.
- One of the annoying ones is "Tried to modify key `current` of an object which has been already passed to a worklet".
  - From this, we found our that our `Swipeable` component broke, which was due to the value we assigned to `ref.current` not being available in the current callback.
@cyanChill cyanChill added the enhancement New feature or request label May 29, 2026
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 84b7a31b-e0ba-463b-8817-d57c73981289

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
mobile/src/components/Swipeable.tsx (1)

147-151: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Missing .start() call on reset animation.

The Animated.timing() is created but never started. The comment above indicates this animation should reset dragX to prevent recycled items from staying swiped, but without calling .start(), it has no effect.

🐛 Proposed fix
         // Reset to prevent the recycled item being stuck in the swiped state.
         //  - Use `Animated.timing()` instead of `setValue()` due to the animation
         //  resolving before the UI removes the item on the New Architecture.
         Animated.timing(dragX, {
           duration: 0,
           toValue: 0,
           useNativeDriver: true,
-        });
+        }).start();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mobile/src/components/Swipeable.tsx` around lines 147 - 151, The reset
animation for dragX in the Swipeable component is created but never started;
update the code that constructs Animated.timing(dragX, { duration: 0, toValue:
0, useNativeDriver: true }) so it is invoked (e.g., call .start() on the
returned animation) to actually reset dragX when recycling items, ensuring the
timing animation runs and clears any residual swipe state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mobile/src/components/NScrollbar.tsx`:
- Around line 157-164: The onFinalize callback currently calls onEnd
unconditionally which can fire when a pan never became ACTIVE; modify the
NScrollbar gesture handlers to track whether a real drag occurred (e.g.,
introduce a didDrag boolean set to true inside onActivate or onUpdate on first
movement and reset in onDeactivate/dismissScrollbar), and change onFinalize to
only call onEnd when didDrag is true; ensure you still reset didDrag alongside
nextScrollPosition.set(-1) and prevY.set(-1) in onDeactivate so subsequent
gestures are clean.

---

Outside diff comments:
In `@mobile/src/components/Swipeable.tsx`:
- Around line 147-151: The reset animation for dragX in the Swipeable component
is created but never started; update the code that constructs
Animated.timing(dragX, { duration: 0, toValue: 0, useNativeDriver: true }) so it
is invoked (e.g., call .start() on the returned animation) to actually reset
dragX when recycling items, ensuring the timing animation runs and clears any
residual swipe state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 516402e0-0937-49ee-9134-2076f4c24dd1

📥 Commits

Reviewing files that changed from the base of the PR and between dfbcc21 and 3189db3.

⛔ Files ignored due to path filters (1)
  • mobile/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • mobile/modules/toast/src/components/Toast.tsx
  • mobile/package.json
  • mobile/src/components/DragList.tsx
  • mobile/src/components/Form/Input.tsx
  • mobile/src/components/Form/Slider.tsx
  • mobile/src/components/NScrollbar.tsx
  • mobile/src/components/Swipeable.tsx
  • mobile/src/modules/customization/theme/components/ColorPicker.tsx
  • mobile/src/navigation/components/MiniPlayer.tsx
  • mobile/src/navigation/screens/now-playing/helpers/useVinylSeekbar.ts
  • mobile/src/navigation/screens/settings/sheets/TabOrderSheet.tsx
  • mobile/src/resources/licenses.json
💤 Files with no reviewable changes (1)
  • mobile/src/components/Form/Input.tsx

Comment thread mobile/src/components/NScrollbar.tsx
@cyanChill cyanChill marked this pull request as ready for review May 29, 2026 21:03
@cyanChill cyanChill merged commit a37b095 into dev May 29, 2026
1 check passed
@cyanChill cyanChill deleted the refactor/rngh-3 branch May 29, 2026 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant