Skip to content

Commit fb3110f

Browse files
committed
Merge branch 'main' into next; resolve conflicts
2 parents 32c360e + f0604b0 commit fb3110f

27 files changed

+3041
-445
lines changed

android/src/main/java/com/swmansion/gesturehandler/RNGestureHandlerPackage.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.swmansion.gesturehandler
22

3-
import com.facebook.react.TurboReactPackage
3+
import com.facebook.react.BaseReactPackage
44
import com.facebook.react.ViewManagerOnDemandReactPackage
55
import com.facebook.react.bridge.ModuleSpec
66
import com.facebook.react.bridge.NativeModule
@@ -19,7 +19,7 @@ import com.swmansion.gesturehandler.react.RNGestureHandlerRootViewManager
1919
RNGestureHandlerModule::class
2020
]
2121
)
22-
class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPackage {
22+
class RNGestureHandlerPackage : BaseReactPackage(), ViewManagerOnDemandReactPackage {
2323
private val viewManagers: Map<String, ModuleSpec> by lazy {
2424
mapOf(
2525
RNGestureHandlerRootViewManager.REACT_CLASS to ModuleSpec.viewManagerSpec {
@@ -71,7 +71,6 @@ class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPac
7171
RNGestureHandlerModule::class.java.name,
7272
reactModule.canOverrideExistingModule,
7373
reactModule.needsEagerInit,
74-
true, // Has constants is hardcoded to return true, so replacing it with `true` changes nothing.
7574
reactModule.isCxxModule,
7675
true
7776
)

android/src/main/java/com/swmansion/gesturehandler/core/NativeViewGestureHandler.kt

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import android.widget.ScrollView
99
import com.facebook.react.views.scroll.ReactScrollView
1010
import com.facebook.react.views.swiperefresh.ReactSwipeRefreshLayout
1111
import com.facebook.react.views.textinput.ReactEditText
12+
import com.facebook.react.views.view.ReactViewGroup
1213
import com.swmansion.gesturehandler.react.RNGestureHandlerButtonViewManager
1314
import com.swmansion.gesturehandler.react.isScreenReaderOn
1415

@@ -79,6 +80,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
7980
is ReactEditText -> this.hook = EditTextHook(this, view)
8081
is ReactSwipeRefreshLayout -> this.hook = SwipeRefreshLayoutHook(this, view)
8182
is ReactScrollView -> this.hook = ScrollViewHook()
83+
is ReactViewGroup -> this.hook = ReactViewGroupHook()
8284
}
8385
}
8486

@@ -99,7 +101,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
99101
if (state == STATE_UNDETERMINED && !hook.canBegin(event)) {
100102
cancel()
101103
} else {
102-
view.onTouchEvent(event)
104+
hook.sendTouchEvent(view, event)
103105
if ((state == STATE_UNDETERMINED || state == STATE_BEGAN) && view.isPressed) {
104106
activate()
105107
}
@@ -116,12 +118,12 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
116118
when {
117119
shouldActivateOnStart -> {
118120
tryIntercept(view, event)
119-
view.onTouchEvent(event)
121+
hook.sendTouchEvent(view, event)
120122
activate()
121123
}
122124

123125
tryIntercept(view, event) -> {
124-
view.onTouchEvent(event)
126+
hook.sendTouchEvent(view, event)
125127
activate()
126128
}
127129

@@ -136,7 +138,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
136138
}
137139
}
138140
} else if (state == STATE_ACTIVE) {
139-
view.onTouchEvent(event)
141+
hook.sendTouchEvent(view, event)
140142
}
141143
}
142144

@@ -145,7 +147,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
145147
val event = MotionEvent.obtain(time, time, MotionEvent.ACTION_CANCEL, 0f, 0f, 0).apply {
146148
action = MotionEvent.ACTION_CANCEL
147149
}
148-
view!!.onTouchEvent(event)
150+
hook.sendTouchEvent(view, event)
149151
event.recycle()
150152
}
151153

@@ -199,6 +201,11 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
199201
* by this one.
200202
*/
201203
fun shouldCancelRootViewGestureHandlerIfNecessary() = false
204+
205+
/**
206+
* Passes the event down to the underlying view using the correct method.
207+
*/
208+
fun sendTouchEvent(view: View?, event: MotionEvent) = view?.onTouchEvent(event)
202209
}
203210

204211
private class EditTextHook(
@@ -278,4 +285,12 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
278285
private class ScrollViewHook : NativeViewGestureHandlerHook {
279286
override fun shouldCancelRootViewGestureHandlerIfNecessary() = true
280287
}
288+
289+
private class ReactViewGroupHook : NativeViewGestureHandlerHook {
290+
// There are cases where a native component is wrapped with a `ReactViewGroup` (the component is rendered
291+
// inside a `<View />` component in JS). In such cases, calling `onTouchEvent` wouldn't work as those are
292+
// ignored by the wrapper view. Instead `dispatchTouchEvent` can be used, which causes the view to dispatch
293+
// the event to its children.
294+
override fun sendTouchEvent(view: View?, event: MotionEvent) = view?.dispatchTouchEvent(event)
295+
}
281296
}

apple/RNGestureHandlerManager.mm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ @implementation RNGestureHandlerManager {
5151
RNGestureHandlerRegistry *_registry;
5252
NSHashTable<RNRootViewGestureRecognizer *> *_rootViewGestureRecognizers;
5353
NSMutableDictionary<NSNumber *, NSNumber *> *_attachRetryCounter;
54+
NSMutableSet *_droppedHandlers;
5455
#ifdef RCT_NEW_ARCH_ENABLED
5556
RCTModuleRegistry *_moduleRegistry;
5657
RCTViewRegistry *_viewRegistry;
@@ -90,6 +91,7 @@ - (void)initCommonProps
9091
_registry = [RNGestureHandlerRegistry new];
9192
_rootViewGestureRecognizers = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
9293
_attachRetryCounter = [[NSMutableDictionary alloc] init];
94+
_droppedHandlers = [NSMutableSet set];
9395
}
9496

9597
- (void)createGestureHandler:(NSString *)handlerName tag:(NSNumber *)handlerTag config:(NSDictionary *)config
@@ -168,7 +170,9 @@ - (void)attachGestureHandler:(nonnull NSNumber *)handlerTag
168170
[_attachRetryCounter setObject:counter forKey:viewTag];
169171

170172
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
171-
[self attachGestureHandler:handlerTag toViewWithTag:viewTag withActionType:actionType];
173+
if (![_droppedHandlers containsObject:handlerTag]) {
174+
[self attachGestureHandler:handlerTag toViewWithTag:viewTag withActionType:actionType];
175+
}
172176
});
173177
}
174178

@@ -205,6 +209,7 @@ - (void)updateGestureHandler:(NSNumber *)handlerTag config:(NSDictionary *)confi
205209
- (void)dropGestureHandler:(NSNumber *)handlerTag
206210
{
207211
[_registry dropHandlerWithTag:handlerTag];
212+
[_droppedHandlers addObject:handlerTag];
208213
}
209214

210215
- (void)dropAllGestureHandlers

docs/docs/guides/swipe-and-scroll.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
id: swipe-and-scroll
3+
title: Custom swipeable components inside ScrollView (web)
4+
---
5+
6+
While we recommend using our own [`ReanimatedSwipeable`](../components/reanimated_swipeable.md) component, creating your own version of swipeable gives you more control over its behavior. Common issue here is that after creating your own swipeable component, scroll does not work. In that case, try adding [`touchAction`](../gestures/gesture-detector.md#touchaction-web-only) set to `"pan-y"`, like this:
7+
8+
```jsx
9+
<GestureDetector gesture={...} ... touchAction="pan-y">
10+
...
11+
</GestureDetector>
12+
```

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"esbuild": "^0.20.2",
5757
"esbuild-register": "^3.5.0",
5858
"eslint-plugin-mdx": "^2.2.0",
59-
"prettier": "^2.8.4",
59+
"prettier": "^3.3.3",
6060
"typescript": "^4.7.4",
6161
"webpack-cli": "^5.0.1"
6262
},

docs/src/css/typography.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ code {
183183
border-bottom: 1px solid var(--ifm-font-color-base);
184184
}
185185

186+
.markdown h2 code {
187+
font-size: 22px;
188+
font-weight: 600;
189+
}
190+
186191
/* Sidebar */
187192
[class*='menu__list-item-collapsible'] a {
188193
font-family: var(--swm-title-font);

example/app.config.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
export default ({ config }) => ({
2+
...config,
3+
name: 'example',
4+
slug: 'example',
5+
version: '0.0.1',
6+
orientation: 'portrait',
7+
icon: './assets/icon.png',
8+
sdkVersion: '51.0.0',
9+
splash: {
10+
image: './assets/splash.png',
11+
resizeMode: 'cover',
12+
backgroundColor: '#F8F9FF',
13+
},
14+
ios: {
15+
bundleIdentifier: 'com.example',
16+
buildNumber: '1',
17+
supportsTablet: true,
18+
},
19+
android: {
20+
versionCode: 1,
21+
package: 'com.example',
22+
adaptiveIcon: {
23+
foregroundImage: './assets/adaptive-icon.png',
24+
backgroundColor: '#F8F9FF',
25+
},
26+
},
27+
web: {
28+
favicon: './assets/favicon.png',
29+
},
30+
plugins: [
31+
[
32+
'expo-camera',
33+
{
34+
cameraPermission: 'Allow RNGH example to access your camera',
35+
},
36+
],
37+
[
38+
'expo-font',
39+
{
40+
fonts: [
41+
'./node_modules/@swmansion/icons/fonts/broken/swm-icons-broken.ttf',
42+
'./node_modules/@swmansion/icons/fonts/outline/swm-icons-outline.ttf',
43+
'./node_modules/@swmansion/icons/fonts/curved/swm-icons-curved.ttf',
44+
],
45+
},
46+
],
47+
[
48+
'expo-build-properties',
49+
{
50+
ios: {
51+
newArchEnabled: Boolean(Number(process.env.FABRIC_ENABLED)),
52+
},
53+
android: {
54+
newArchEnabled: Boolean(Number(process.env.FABRIC_ENABLED)),
55+
},
56+
},
57+
],
58+
],
59+
});

example/app.json

Lines changed: 0 additions & 49 deletions
This file was deleted.

example/package.json

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,32 @@
1414
"postinstall": "patch-package && expo prebuild"
1515
},
1616
"dependencies": {
17-
"@expo/metro-config": "~0.18.1",
18-
"@expo/metro-runtime": "^3.2.1",
17+
"@expo/metro-config": "~0.18.11",
18+
"@expo/metro-runtime": "~3.2.3",
1919
"@react-native-async-storage/async-storage": "^1.23.1",
2020
"@react-native-community/slider": "^4.5.2",
2121
"@react-native-community/viewpager": "^5.0.11",
22-
"@react-native-masked-view/masked-view": "^0.2.8",
22+
"@react-native-masked-view/masked-view": "0.3.1",
2323
"@react-navigation/elements": "^1.3.7",
2424
"@react-navigation/native": "^6.1.17",
2525
"@react-navigation/stack": "^6.3.29",
2626
"@swmansion/icons": "^0.0.1",
27-
"expo": "^51.0.0",
28-
"expo-camera": "~15.0.9",
27+
"expo": "~51.0.38",
28+
"expo-build-properties": "^0.12.5",
29+
"expo-camera": "~15.0.16",
2930
"expo-font": "~12.0.10",
3031
"hoist-non-react-statics": "^3.3.2",
3132
"invariant": "^2.2.4",
3233
"patch-package": "^6.5.1",
3334
"postinstall-postinstall": "^2.1.0",
3435
"react": "18.2.0",
3536
"react-dom": "18.2.0",
36-
"react-native": "0.74.1",
37+
"react-native": "0.75.4",
3738
"react-native-gesture-handler": "link:..",
3839
"react-native-reanimated": "3.15.5",
39-
"react-native-safe-area-context": "4.10.1",
40-
"react-native-screens": "3.31.1",
41-
"react-native-svg": "^15.8.0",
40+
"react-native-safe-area-context": "4.10.5",
41+
"react-native-screens": "3.35.0",
42+
"react-native-svg": "15.8.0",
4243
"react-native-web": "~0.19.10"
4344
},
4445
"devDependencies": {
@@ -48,17 +49,18 @@
4849
"@tsconfig/react-native": "^3.0.5",
4950
"@types/jest": "^29.5.12",
5051
"@types/metro-config": "^0.76.3",
51-
"@types/react": "^18.3.1",
52+
"@types/react": "~18.2.79",
5253
"@types/react-native": "^0.73.0",
5354
"@types/react-test-renderer": "^18.3.0",
5455
"@typescript-eslint/parser": "^7.8.0",
5556
"babel-jest": "^29.7.0",
5657
"babel-plugin-module-resolver": "^5.0.2",
5758
"eslint": "^7.32.0",
59+
"eslint-plugin-prettier": "^5.2.1",
5860
"jest": "^29.7.0",
59-
"prettier": "2.7.1",
61+
"prettier": "3.3.3",
6062
"react-test-renderer": "18.3.1",
61-
"typescript": "^5.1.3"
63+
"typescript": "~5.3.3"
6264
},
6365
"resolutions": {
6466
"@typescript-eslint/eslint-plugin": "^5.17.0",

example/src/release_tests/gesturizedPressable/functionalStylesExample.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
import React from 'react';
2-
import {
3-
PressableStateCallbackType,
4-
StyleProp,
5-
StyleSheet,
6-
View,
7-
ViewStyle,
8-
} from 'react-native';
2+
import { PressableStateCallbackType, StyleSheet, View } from 'react-native';
93
import TestingBase from './testingBase';
104

115
export function FunctionalStyleExample() {
12-
const functionalStyle = (
13-
state: PressableStateCallbackType
14-
): StyleProp<ViewStyle> => {
6+
const functionalStyle = (state: PressableStateCallbackType) => {
157
if (state.pressed) {
168
return {
179
width: 100,

0 commit comments

Comments
 (0)