Skip to content

[Release] 2.32 Cherry-pick thread#4255

Merged
m-bert merged 17 commits into
v2-stablefrom
@mbert/cherry-picks-2.31
Jun 11, 2026
Merged

[Release] 2.32 Cherry-pick thread#4255
m-bert merged 17 commits into
v2-stablefrom
@mbert/cherry-picks-2.31

Conversation

javache and others added 13 commits June 10, 2026 18:14
- Remove the `getChildInDrawingOrderAtIndex` abstraction from
`ViewConfigurationHelper` and its implementation in
`RNViewConfigurationHelper`
- Inline `viewGroup.getChildAt(i)` at the two call sites
(`GestureHandlerOrchestrator` and `HoverGestureHandler`)
- `ReactViewGroup.getZIndexMappedChildIndex` is a legacy architecture
API that has been a no-op (returns its input unchanged) and has been
removed in react/react-native#56717

  ## Test plan
  - Android build via `cd apps/basic-example && yarn android`
React Native 0.86 removed `Libraries/Renderer/shims/ReactNative`,
breaking the `RNRenderer` import. This PR switch to `RendererProxy` and
fall back to the legacy shim for compatibility with RN < 0.86.
This PR fixes duplicated `testID` prop on iOS. Same `accessibilityLabel`
was assigned to both, wrapper and button, therefore frameworks like
`Detox` failed due to multiple elements with the same ID.

Fixes #3698

Tested on branch with e2e tests.
## Description

Discrete gestures on Android transition to `END` state before being
cancelled by other, higher priority gestures. Our current approach
missed case where gestures like `Tap` end in such transition (`5 -> 3`),
therefore `onFinalize` callback was never triggered.

## Test plan

<details>
<summary>Tested on the following code:</summary>

```tsx
import React from 'react';
import { StyleSheet, View } from 'react-native';
import {
  GestureDetector,
  useExclusiveGestures,
  useTapGesture,
} from 'react-native-gesture-handler';

export default function EmptyExample() {
  const t1 = useTapGesture({
    onBegin: () => {
      console.log('tap begin');
    },
    onActivate: () => {
      console.log('tap activate');
    },
    onDeactivate: () => {
      console.log('tap deactivate');
    },
    onFinalize: () => {
      console.log('tap finalize');
    },
  });

  const t2 = useTapGesture({
    numberOfTaps: 2,
    onBegin: () => {
      console.log('double tap begin');
    },
    onActivate: () => {
      console.log('double tap activate');
    },
    onDeactivate: () => {
      console.log('double tap deactivate');
    },
    onFinalize: () => {
      console.log('double tap finalize');
    },
  });

  const g = useExclusiveGestures(t2, t1);

  return (
    <View style={styles.container}>
      <GestureDetector gesture={g}>
        <View style={styles.box} />
      </GestureDetector>
    </View>
  );
}

const styles = StyleSheet.create({
  box: {
    width: 100,
    height: 100,
    backgroundColor: 'blue',
    borderRadius: 10,
  },
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});
```

</details>
Fixes
#3435

Android includes the pointer being lifted in the `ACTION_POINTER_UP`
event, so the event where the pointer is lifted is sent with
`numberOfPointers = 2`. This PR changes that so the `numberOfPointers`
is reported as `n - 1` for `ACTION_POINTER_UP` events.

Note: The same applies to `ACTION_UP` and `ACTION_CANCEL` but I didn't
include them to keep the behavior the same as on iOS.

Reproducer from
#3435
…aliases (#4232)

## Description

Related:
software-mansion/react-native-reanimated#9592
(same fix for `react-native-reanimated` and `react-native-worklets`)

The pod script attempts to resolve `react-native/package.json` to get to
the `version` and perform a version check. It however performs a
redundant `react-native/../react-native` resolution i.e. it essentially
performs `path.dirname(require.resolve('react-native/package.json'))`
(correct), but then joins this with `${dir}/..`, then re-joins this with
`react-native`.

Re-entering the `react-native` directory can be invalid in case of
symlinks in the `node_modules` structure. The easiest way to reproduce
an issue is to use react-native-tvos's pattern of aliasing
`"react-native": "npm:react-native-tvos@x.x.x"`. With isolated
dependencies this will point a symlink at a directory that's named
`react-native-tvos` and not `react-native`. The also applies to local
`link:` dependency specifiers. Essentially, the directory name
`react-native` is unnecessarily enforced.

This would lead to a cryptic `file: no implicit conversion of nil into
String.` error

## Test plan

- Existing `pod install` in working projects should continue passing
unchanged
-
https://github.com/kitten/douglowder--with-monorepo-tv-test/tree/init-pnpm
- `pnpm i` then in `apps/tv` run `pnpm prebuild` (which runs `pod
install`)

---------

Co-authored-by: Michał Bert <63123542+m-bert@users.noreply.github.com>
## Description

In ruby, functions and variables are global by design. In #4232 we dealt
with it by changing name of exported function. However, the correct
approach would be to keep our utils in separate module. This has also
been introduced in
[Reanimated](software-mansion/react-native-reanimated#9617).

## Test plan

`pod install`
Fixes three issues:
1. `findGestureHandlerByRecognizer` was relying on `reactTag` to
determine whether a view is managed by React Native. This is no longer
set on the new architecture (we do it
[here](https://github.com/software-mansion/react-native-gesture-handler/blob/e362f3a1ea2c04b78d3923c377dc2c62b23ca2d0/packages/react-native-gesture-handler/apple/RNGestureHandlerManager.mm#L206),
this needs to be investigated). Instead, I changed it to check whether
the view is a subclass of `RCTViewComponentView` which is a base for
Fabric components.
2. `shouldHandleTouch` in the button component was converting the point
to the wrong coordinate space when calling `wantsToHandleEventsAtPoint`.
3. `wantsToHandleEventsAtPoint` for api v3 was always trying to get the
child of the view the gesture is attached to. Correct when gesture is
attached to the detector, not when directly to view (virtual
detector/`wantsToAttachDirectlyToView: YES`).

Enable "Legacy examples" in the expo app and try to scroll, starting on
one of the disabled buttons.

|Before|After|
|-|-|
|<video
src="https://github.com/user-attachments/assets/28cd0b95-85df-46e8-8ca4-28c042d725b0"
/>|<video
src="https://github.com/user-attachments/assets/7116d3aa-557f-4828-9b4e-c0177ed89202"
/>|

There's no pointer captured, but in the "before" video, I'm trying to
scroll starting on `Nested buttons (sound & ripple)`.
## Description

The updated loop in
#4199
didn't accurately represent the semantics from the old arch. It didn't
stop on the views managed by React Native, instead iterating to the root
of the hierarchy.

## Test plan

Checked that it doesn't regress
#4199
For now it doesn't work with hook-based API 😞

<details>
<summary>Tested on the following code:</summary>

```tsx
import { useState } from 'react';
import { Pressable, StyleSheet, View } from 'react-native';
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
  RectButton,
  useTapGesture,
} from 'react-native-gesture-handler';

const randomColor = () => {
  const r = Math.floor(Math.random() * 256);
  const g = Math.floor(Math.random() * 256);
  const b = Math.floor(Math.random() * 256);

  return `rgb(${r},${g},${b})`;
};

export default function App() {
  const [bgColor, setBgColor] = useState('black');

  const tap = useTapGesture({
    onDeactivate: () => {
      setBgColor(randomColor());
    },
    disableReanimated: true,
  });

  const oldTap = Gesture.Tap()
    .onEnd(() => {
      setBgColor(randomColor());
    })
    .runOnJS(true);

  return (
    <GestureHandlerRootView style={styles.container}>
      <View
        style={{
          width: 100,
          height: 100,
          borderRadius: 50,
          backgroundColor: bgColor,
        }}
      />
      <View
        style={[
          styles.container,
          {
            width: '100%',
            flexDirection: 'row',
          },
        ]}>
        <GestureDetector gesture={tap}>
          <View style={styles.button} />
        </GestureDetector>

        <GestureDetector gesture={oldTap}>
          <View style={styles.button} />
        </GestureDetector>

        <Pressable
          style={styles.button}
          onPress={() => {
            setBgColor(randomColor());
          }}
        />

        <RectButton
          style={styles.button}
          onPress={() => {
            setBgColor(randomColor());
          }}
        />
      </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'space-evenly',
    alignItems: 'center',
  },
  button: {
    width: 100,
    height: 50,
    backgroundColor: 'crimson',
    borderRadius: 10,
  },
});
```

</details>
This PR bumps Reanimated version, along with worklets. Since in
`common-app` we still had Reanimated 3.18, I've also introduced
necessary changes to types.

Also, it turned out that our current setup cannot correctly resolve
dependencies - I've updated `metro.config.js` to also block
`common-app`, since this "app" only contains sources for examples and
their `node_modules` shouldn't be used.

Build and run example apps.
This PR bumps `expo` version in `expo-example` to 56. It also adds `yarn
constraints` in order to keep Reanimated and Worklets in sync. Now
running `yarn constraints --fix` will automatically set desired versions
of packages in all `package.json` files across workspaces.

Test example apps.

> [!NOTE]
> macOS is left far behind with React Native 0.81, so I guess it just
waits for better time 😶
This PR brings support for React Native 0.86

-
#4160
- Module has not been registered as callable
([6c29e4e](6c29e4e))

- ## 0.86.0 ✅
- 0.86.0-rc.3 ✅
- 0.86.0-rc.2 ✅
- 0.86.0-rc.1 ✅
- 0.86.0-rc.0 ✅

Tested that `basic-example` builds and works correctly.
@m-bert m-bert changed the title [Android] Remove getChildInDrawingOrderAtIndex (#4156) [Release 2.32] Cherry-pick thread Jun 11, 2026
@m-bert m-bert marked this pull request as ready for review June 11, 2026 11:06
Copilot AI review requested due to automatic review settings June 11, 2026 11:06
@m-bert m-bert requested a review from j-piasecki June 11, 2026 11:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Release-branch cherry-pick aggregation for react-native-gesture-handler 2.32, combining Android/iOS fixes and ecosystem upgrades (React Native 0.86, Expo 56, Reanimated/Worklets), plus example app and CI adjustments.

Changes:

  • Update dependencies across workspaces (RN 0.86, Expo 56, Reanimated/Worklets) and add Yarn constraints config.
  • iOS: adjust event dispatching behavior for RN 0.86/Fabric, fix duplicated testID, and update recognizer/handler resolution logic.
  • Android: fix discrete gesture finalize edge case, pointer count reporting, and remove legacy child drawing-order helper.

Reviewed changes

Copilot reviewed 44 out of 49 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
yarn.config.cjs Adds Yarn constraints to keep versions aligned across workspaces.
packages/react-native-gesture-handler/src/RNRenderer.web.ts Removes web RNRenderer shim.
packages/react-native-gesture-handler/src/RNRenderer.ts Removes RNRenderer shim import for RN < 0.86.
packages/react-native-gesture-handler/src/handlers/gestures/GestureDetector/utils.ts Removes detector child validation logic and RNRenderer usage; import ordering tweak.
packages/react-native-gesture-handler/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts Stops calling removed detector-children validator.
packages/react-native-gesture-handler/scripts/gesture_handler_utils.rb Moves pod utils into a module and adjusts RN version detection.
packages/react-native-gesture-handler/RNGestureHandler.podspec Uses the new Ruby module helper to compute RN minor version.
packages/react-native-gesture-handler/package.json Bumps dev deps to RN 0.86 and adds Reanimated/Worklets dev deps.
packages/react-native-gesture-handler/jestSetup.js Updates mocks formatting; adds GestureComponents + worklets mocks.
packages/react-native-gesture-handler/apple/RNGestureHandlerManager.mm Updates NativeAnimated delivery path for RN 0.86+; removes direct-event helper.
packages/react-native-gesture-handler/apple/RNGestureHandlerButtonComponentView.mm Clears wrapper accessibilityIdentifier to avoid duplicated testID matches (Detox).
packages/react-native-gesture-handler/apple/RNGestureHandlerButton.mm Whitespace-only formatting changes.
packages/react-native-gesture-handler/apple/RNGestureHandler.mm Updates dummy-handler lookup logic / coordinate-space-related behavior.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNViewConfigurationHelper.kt Removes legacy drawing-order child helper method.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/ViewConfigurationHelper.kt Removes drawing-order child helper API from interface.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt Inlines getChildAt and removes static helper usage.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt Updates state-change edge case comment; inlines getChildAt usage.
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt Fixes pointer count reported for ACTION_POINTER_UP.
package.json Adds @yarnpkg/types dependency (for constraints typing/tooling).
apps/macos-example/tsconfig.json Adds TS types reference and excludes Pods.
apps/macos-example/package.json Bumps macOS example dependencies (RN macOS, Reanimated/Worklets, etc.) and Node engine.
apps/macos-example/metro.config.js Updates exclusionList import path and blacklists both monorepo + common-app node_modules.
apps/macos-example/macos/Podfile Enables new arch/Fabric and bumps macOS deployment target.
apps/macos-example/macos/MacOSExample.xcodeproj/project.pbxproj Updates project settings, embeds frameworks phase, adjusts runpaths, enables Hermes.
apps/macos-example/macos/MacOSExample-macOS/Info.plist Adds RCTNewArchEnabled key and formatting tweaks.
apps/macos-example/macos/MacOSExample-macOS/AppDelegate.mm Sets RCTAppDependencyProvider for RN 0.86+ style app setup.
apps/macos-example/Gemfile.lock Updates lockfile deps (Ruby stdlib gem extractions).
apps/macos-example/Gemfile Adds gems needed for Ruby 3.4 stdlib removals.
apps/expo-example/package.json Bumps Expo SDK and related deps; adds pager-view/worklets.
apps/expo-example/metro.config.js Mirrors common-app node_modules blacklisting approach.
apps/common-app/src/release_tests/gesturizedPressable/delayedPressExample.tsx Updates Reanimated spring config usage.
apps/common-app/src/release_tests/combo/index.tsx Removes slider/native wrapper usage and related styles.
apps/common-app/src/new_api/manualGestures/index.tsx Updates Reanimated SharedValue typings.
apps/common-app/src/new_api/drag_n_drop/Draggable.tsx Updates Reanimated SharedValue typings.
apps/common-app/src/new_api/chat_heads/index.tsx Updates Reanimated SharedValue typings.
apps/common-app/src/new_api/camera/AnimatedCameraView.tsx Updates Reanimated typings and ref typing for animated camera component.
apps/common-app/src/new_api/calculator/index.tsx Updates SharedValue typings in props.
apps/common-app/src/new_api/betterHorizontalDrawer/index.tsx Updates SharedValue typings in helper function signature.
apps/common-app/src/new_api/betterHorizontalDrawer/BetterHorizonatalDrawer.tsx Updates SharedValue typings in public props and internal props.
apps/common-app/src/ListWithHeader/ListWithHeader.tsx Updates AnimatedRef typing and uses destructured props in reactions/gestures.
apps/common-app/src/basic/pagerAndDrawer/index.android.tsx Migrates from deprecated viewpager package to react-native-pager-view.
apps/common-app/package.json Bumps deps; adds pager-view/svg/worklets and aligns versions.
apps/basic-example/package.json Bumps RN to 0.86 and adds Reanimated/Worklets dependencies.
apps/basic-example/metro.config.js Removes Reanimated blacklist now that it’s installed in the app.
apps/basic-example/ios/Podfile.lock Updates pods for RN 0.86 and adds Reanimated/Worklets pods.
apps/basic-example/ios/BasicExample.xcodeproj/project.pbxproj Sets PODFILE_DIR build setting.
.github/workflows/ios-build.yml Updates iOS CI runner/Xcode selection.
Comments suppressed due to low confidence (1)

packages/react-native-gesture-handler/apple/RNGestureHandlerManager.mm:452

  • sendEventForDirectEvent: is still called in the old-arch paths (e.g. here) but the method implementation was removed below, which will break compilation for non-Fabric builds. Re-introduce sendEventForDirectEvent: (old-arch only) or inline [_eventDispatcher sendEvent:event] at the call sites.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/react-native-gesture-handler/apple/RNGestureHandler.mm
Comment thread apps/macos-example/tsconfig.json Outdated
Comment thread packages/react-native-gesture-handler/jestSetup.js Outdated
prashanFOMO and others added 3 commits June 11, 2026 13:17
…t in LongPressGestureHandler (#4253)

## Description

Fixes #4252

On Android, the `numberOfPointers` config of the LongPress gesture has
been silently ignored since 2.26.0: a gesture configured with
`Gesture.LongPress().numberOfPointers(3)` activates after a
**single-pointer** long press, and can never activate with the
configured pointer count (the second pointer trips `currentPointers >
numberOfPointersRequired` and fails the handler). iOS is unaffected,
since the prop maps to
`UILongPressGestureRecognizer.numberOfTouchesRequired`.

The cause is a one-line mix-up introduced by the factory refactor in
2.26.0. The factory's `updateConfig` assigns the config value to
`handler.numberOfPointers`, which resolves to the inherited
`GestureHandler.numberOfPointers` — the live pointer-count used for
event payloads, overwritten with `event.pointerCount` on every motion
event. The field that actually gates activation,
`numberOfPointersRequired`, stays at its default of `1` and is never
written from config. Before 2.26.0, the module factory called
`handler.setNumberOfPointers(...)`, which set `numberOfPointersRequired`
correctly.

This PR routes the config value to `numberOfPointersRequired`, restoring
the pre-2.26 behavior. The private-field access from the nested
`Factory` matches the existing `maxDist` assignment directly above.

## Test plan

- Applied this same one-liner to 2.28.0 via patch-package in an RN
0.81.5 (Expo 54, new architecture, Hermes) app that uses
`Gesture.LongPress().numberOfPointers(3)` as a global gesture, and
verified on an Android device:
- three-pointer long press now activates the gesture (previously never
fired)
- single-pointer long press no longer activates it (previously fired
after ~500 ms)
- gestures with the default single pointer (no `numberOfPointers` set)
are unaffected
- Verified iOS behavior is unchanged (the fix doesn't touch the iOS
path)
- Repro snippet:
https://gist.github.com/prashanFOMO/ad838ce8a3c77c59759b8583fe8d3393
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 45 out of 50 changed files in this pull request and generated 2 comments.

Comment thread packages/react-native-gesture-handler/jestSetup.js Outdated
@m-bert m-bert merged commit 4afdcbd into v2-stable Jun 11, 2026
13 of 17 checks passed
@m-bert m-bert deleted the @mbert/cherry-picks-2.31 branch June 11, 2026 12:00
@m-bert m-bert changed the title [Release 2.32] Cherry-pick thread [Release] 2.32 Cherry-pick thread Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants