react-native-gesture-handler 2.3.2 → 2.4.2
Sign up to get free protection for your applications and to get access to all the features.
- package/RNGestureHandler.podspec +2 -1
- package/android/build.gradle +38 -6
- package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandler.kt +14 -2
- package/android/noreanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +10 -0
- package/android/reanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +17 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEnabledRootView.kt +3 -41
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEvent.kt +6 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +10 -54
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +2 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerStateChangeEvent.kt +6 -0
- package/ios/RNGHTouchEventType.h +9 -0
- package/ios/RNGestureHandler.h +2 -2
- package/ios/RNGestureHandler.m +21 -8
- package/ios/RNGestureHandlerButton.h +1 -0
- package/ios/RNGestureHandlerButton.m +9 -1
- package/ios/RNGestureHandlerButtonComponentView.mm +14 -1
- package/ios/RNGestureHandlerButtonManager.m +4 -1
- package/ios/RNGestureHandlerEvents.h +2 -2
- package/ios/RNGestureHandlerEvents.m +2 -2
- package/ios/RNGestureHandlerManager.h +2 -0
- package/ios/RNGestureHandlerManager.mm +30 -20
- package/ios/RNGestureHandlerModule.mm +18 -0
- package/ios/RNGestureHandlerPointerTracker.h +2 -2
- package/ios/RNGestureHandlerPointerTracker.m +9 -6
- package/ios/RNGestureHandlerRegistry.h +1 -0
- package/ios/RNGestureHandlerRegistry.m +10 -0
- package/lib/commonjs/GestureHandlerRootView.android.js +7 -1
- package/lib/commonjs/GestureHandlerRootView.android.js.map +1 -1
- package/lib/commonjs/GestureHandlerRootView.js +6 -0
- package/lib/commonjs/GestureHandlerRootView.js.map +1 -1
- package/lib/commonjs/GestureHandlerRootView.web.js +19 -0
- package/lib/commonjs/GestureHandlerRootView.web.js.map +1 -0
- package/lib/commonjs/RNGestureHandlerModule.js +5 -0
- package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
- package/lib/commonjs/RNGestureHandlerModule.web.js +4 -1
- package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/commonjs/{EventType.js → TouchEventType.js} +4 -4
- package/lib/commonjs/TouchEventType.js.map +1 -0
- package/lib/commonjs/components/DrawerLayout.js +38 -11
- package/lib/commonjs/components/DrawerLayout.js.map +1 -1
- package/lib/commonjs/components/GestureButtons.js.map +1 -1
- package/lib/commonjs/components/GestureHandlerButton.js +1 -1
- package/lib/commonjs/components/GestureHandlerButton.js.map +1 -1
- package/lib/commonjs/components/touchables/GenericTouchable.js +2 -0
- package/lib/commonjs/components/touchables/GenericTouchable.js.map +1 -1
- package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js +4 -6
- package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js +4 -6
- package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/commonjs/getShadowNodeFromRef.js +12 -9
- package/lib/commonjs/getShadowNodeFromRef.js.map +1 -1
- package/lib/commonjs/handlers/ForceTouchGestureHandler.js +2 -1
- package/lib/commonjs/handlers/ForceTouchGestureHandler.js.map +1 -1
- package/lib/commonjs/handlers/createHandler.js +25 -20
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestureHandlerCommon.js +18 -1
- package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector.js +120 -80
- package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/commonjs/handlers/gestures/eventReceiver.js +6 -5
- package/lib/commonjs/handlers/gestures/eventReceiver.js.map +1 -1
- package/lib/commonjs/handlers/gestures/gesture.js +24 -4
- package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
- package/lib/commonjs/init.js +10 -1
- package/lib/commonjs/init.js.map +1 -1
- package/lib/commonjs/mocks.js +2 -0
- package/lib/commonjs/mocks.js.map +1 -1
- package/lib/commonjs/utils.js +23 -1
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/commonjs/web/GestureHandler.js +4 -1
- package/lib/commonjs/web/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/utils.js.map +1 -1
- package/lib/module/GestureHandlerRootView.android.js +7 -2
- package/lib/module/GestureHandlerRootView.android.js.map +1 -1
- package/lib/module/GestureHandlerRootView.js +5 -0
- package/lib/module/GestureHandlerRootView.js.map +1 -1
- package/lib/module/GestureHandlerRootView.web.js +6 -0
- package/lib/module/GestureHandlerRootView.web.js.map +1 -0
- package/lib/module/RNGestureHandlerModule.js +5 -0
- package/lib/module/RNGestureHandlerModule.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.web.js +4 -1
- package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/module/{EventType.js → TouchEventType.js} +2 -2
- package/lib/module/TouchEventType.js.map +1 -0
- package/lib/module/components/DrawerLayout.js +38 -11
- package/lib/module/components/DrawerLayout.js.map +1 -1
- package/lib/module/components/GestureButtons.js.map +1 -1
- package/lib/module/components/GestureHandlerButton.js +2 -2
- package/lib/module/components/GestureHandlerButton.js.map +1 -1
- package/lib/module/components/touchables/GenericTouchable.js +2 -0
- package/lib/module/components/touchables/GenericTouchable.js.map +1 -1
- package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js +5 -7
- package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js +5 -8
- package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/module/getShadowNodeFromRef.js +11 -8
- package/lib/module/getShadowNodeFromRef.js.map +1 -1
- package/lib/module/handlers/ForceTouchGestureHandler.js +1 -1
- package/lib/module/handlers/ForceTouchGestureHandler.js.map +1 -1
- package/lib/module/handlers/createHandler.js +25 -22
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/handlers/gestureHandlerCommon.js +11 -1
- package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector.js +120 -81
- package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/module/handlers/gestures/eventReceiver.js +6 -7
- package/lib/module/handlers/gestures/eventReceiver.js.map +1 -1
- package/lib/module/handlers/gestures/gesture.js +23 -4
- package/lib/module/handlers/gestures/gesture.js.map +1 -1
- package/lib/module/init.js +6 -1
- package/lib/module/init.js.map +1 -1
- package/lib/module/mocks.js +2 -0
- package/lib/module/mocks.js.map +1 -1
- package/lib/module/utils.js +17 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/module/web/GestureHandler.js +4 -1
- package/lib/module/web/GestureHandler.js.map +1 -1
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/GestureHandlerRootView.web.d.ts +5 -0
- package/lib/typescript/RNGestureHandlerModule.d.ts +1 -0
- package/lib/typescript/RNGestureHandlerModule.web.d.ts +1 -0
- package/lib/typescript/{EventType.d.ts → TouchEventType.d.ts} +2 -2
- package/lib/typescript/components/DrawerLayout.d.ts +3 -0
- package/lib/typescript/components/GestureButtons.d.ts +18 -6
- package/lib/typescript/fabric/RNGestureHandlerButtonNativeComponent.d.ts +13 -0
- package/lib/typescript/fabric/RNGestureHandlerRootViewNativeComponent.d.ts +5 -0
- package/lib/typescript/handlers/ForceTouchGestureHandler.d.ts +2 -2
- package/lib/typescript/handlers/NativeViewGestureHandler.d.ts +1 -1
- package/lib/typescript/handlers/gestureHandlerCommon.d.ts +6 -3
- package/lib/typescript/handlers/gestures/GestureDetector.d.ts +2 -4
- package/lib/typescript/handlers/gestures/eventReceiver.d.ts +2 -0
- package/lib/typescript/handlers/gestures/gesture.d.ts +5 -0
- package/lib/typescript/init.d.ts +1 -0
- package/lib/typescript/mocks.d.ts +1 -0
- package/lib/typescript/utils.d.ts +2 -0
- package/lib/typescript/web/GestureHandler.d.ts +1 -1
- package/package.json +4 -2
- package/src/GestureHandlerRootView.android.tsx +8 -2
- package/src/GestureHandlerRootView.tsx +6 -0
- package/src/GestureHandlerRootView.web.tsx +12 -0
- package/src/RNGestureHandlerModule.ts +7 -0
- package/src/RNGestureHandlerModule.web.ts +2 -0
- package/src/{EventType.ts → TouchEventType.ts} +2 -2
- package/src/components/DrawerLayout.tsx +34 -10
- package/src/components/GestureButtons.tsx +21 -7
- package/src/components/GestureHandlerButton.tsx +2 -2
- package/src/components/touchables/GenericTouchable.tsx +2 -0
- package/src/fabric/RNGestureHandlerButtonNativeComponent.ts +27 -0
- package/src/fabric/RNGestureHandlerRootViewNativeComponent.ts +12 -0
- package/src/getShadowNodeFromRef.ts +12 -9
- package/src/handlers/ForceTouchGestureHandler.ts +3 -2
- package/src/handlers/createHandler.ts +30 -26
- package/src/handlers/gestureHandlerCommon.ts +21 -2
- package/src/handlers/gestures/GestureDetector.tsx +164 -105
- package/src/handlers/gestures/eventReceiver.ts +6 -6
- package/src/handlers/gestures/gesture.ts +29 -2
- package/src/init.ts +8 -1
- package/src/mocks.ts +2 -0
- package/src/utils.ts +20 -0
- package/src/web/GestureHandler.ts +7 -1
- package/src/web/utils.ts +1 -1
- package/ios/RNTouchEventType.h +0 -9
- package/lib/commonjs/EventType.js.map +0 -1
- package/lib/module/EventType.js.map +0 -1
- package/src/fabric/RNGestureHandlerButtonNativeComponent.js +0 -27
- package/src/fabric/RNGestureHandlerRootViewNativeComponent.js +0 -19
@@ -6,16 +6,18 @@ import * as React from 'react';
|
|
6
6
|
import { Platform, findNodeHandle as findNodeHandleRN } from 'react-native';
|
7
7
|
|
8
8
|
import { State } from '../State';
|
9
|
-
import {
|
9
|
+
import { TouchEventType } from '../TouchEventType';
|
10
10
|
import { ValueOf } from '../typeUtils';
|
11
11
|
import { handlerIDToTag } from './handlersRegistry';
|
12
12
|
import { toArray } from '../utils';
|
13
|
+
import RNGestureHandlerModule from '../RNGestureHandlerModule';
|
13
14
|
|
14
15
|
const commonProps = [
|
15
16
|
'id',
|
16
17
|
'enabled',
|
17
18
|
'shouldCancelWhenOutside',
|
18
19
|
'hitSlop',
|
20
|
+
'cancelsTouchesInView',
|
19
21
|
] as const;
|
20
22
|
|
21
23
|
const componentInteractionProps = ['waitFor', 'simultaneousHandlers'] as const;
|
@@ -83,7 +85,7 @@ export type GestureTouchEvent = {
|
|
83
85
|
handlerTag: number;
|
84
86
|
numberOfTouches: number;
|
85
87
|
state: ValueOf<typeof State>;
|
86
|
-
eventType:
|
88
|
+
eventType: TouchEventType;
|
87
89
|
allTouches: TouchData[];
|
88
90
|
changedTouches: TouchData[];
|
89
91
|
};
|
@@ -111,6 +113,7 @@ export type BaseGestureHandlerProps<
|
|
111
113
|
waitFor?: React.Ref<unknown> | React.Ref<unknown>[];
|
112
114
|
simultaneousHandlers?: React.Ref<unknown> | React.Ref<unknown>[];
|
113
115
|
testID?: string;
|
116
|
+
cancelsTouchesInView?: boolean;
|
114
117
|
// TODO(TS) - fix event types
|
115
118
|
onBegan?: (event: HandlerStateChangeEvent) => void;
|
116
119
|
onFailed?: (event: HandlerStateChangeEvent) => void;
|
@@ -123,6 +126,8 @@ export type BaseGestureHandlerProps<
|
|
123
126
|
onHandlerStateChange?: (
|
124
127
|
event: HandlerStateChangeEvent<ExtraEventPayloadT>
|
125
128
|
) => void;
|
129
|
+
// implicit `children` prop has been removed in @types/react^18.0.0
|
130
|
+
children?: React.ReactNode;
|
126
131
|
};
|
127
132
|
|
128
133
|
function isConfigParam(param: unknown, name: string) {
|
@@ -180,3 +185,17 @@ export function findNodeHandle(
|
|
180
185
|
if (Platform.OS === 'web') return node;
|
181
186
|
return findNodeHandleRN(node);
|
182
187
|
}
|
188
|
+
|
189
|
+
let scheduledFlushOperationsId: ReturnType<
|
190
|
+
typeof requestAnimationFrame
|
191
|
+
> | null = null;
|
192
|
+
|
193
|
+
export function scheduleFlushOperations() {
|
194
|
+
if (scheduledFlushOperationsId === null) {
|
195
|
+
scheduledFlushOperationsId = requestAnimationFrame(() => {
|
196
|
+
RNGestureHandlerModule.flushOperations();
|
197
|
+
|
198
|
+
scheduledFlushOperationsId = null;
|
199
|
+
});
|
200
|
+
}
|
201
|
+
}
|
@@ -16,6 +16,8 @@ import {
|
|
16
16
|
GestureTouchEvent,
|
17
17
|
GestureUpdateEvent,
|
18
18
|
GestureStateChangeEvent,
|
19
|
+
HandlerStateChangeEvent,
|
20
|
+
scheduleFlushOperations,
|
19
21
|
} from '../gestureHandlerCommon';
|
20
22
|
import {
|
21
23
|
GestureStateManager,
|
@@ -30,15 +32,18 @@ import {
|
|
30
32
|
} from '../PanGestureHandler';
|
31
33
|
import { tapGestureHandlerProps } from '../TapGestureHandler';
|
32
34
|
import { State } from '../../State';
|
33
|
-
import {
|
35
|
+
import { TouchEventType } from '../../TouchEventType';
|
34
36
|
import { ComposedGesture } from './gestureComposition';
|
35
37
|
import { ActionType } from '../../ActionType';
|
36
38
|
import { isFabric, tagMessage } from '../../utils';
|
37
39
|
import { getShadowNodeFromRef } from '../../getShadowNodeFromRef';
|
40
|
+
import { Platform } from 'react-native';
|
41
|
+
import type RNGestureHandlerModuleWeb from '../../RNGestureHandlerModule.web';
|
42
|
+
import { onGestureHandlerEvent } from './eventReceiver';
|
38
43
|
|
39
|
-
declare global {
|
40
|
-
|
41
|
-
}
|
44
|
+
declare const global: {
|
45
|
+
isFormsStackingContext: (node: unknown) => boolean | null; // JSI function
|
46
|
+
};
|
42
47
|
|
43
48
|
const ALLOWED_PROPS = [
|
44
49
|
...baseGestureHandlerWithMonitorProps,
|
@@ -84,6 +89,8 @@ function dropHandlers(preparedGesture: GestureConfigReference) {
|
|
84
89
|
|
85
90
|
unregisterHandler(handler.handlerTag, handler.config.testId);
|
86
91
|
}
|
92
|
+
|
93
|
+
scheduleFlushOperations();
|
87
94
|
}
|
88
95
|
|
89
96
|
function checkGestureCallbacksForWorklets(gesture: GestureType) {
|
@@ -107,11 +114,16 @@ function checkGestureCallbacksForWorklets(gesture: GestureType) {
|
|
107
114
|
}
|
108
115
|
}
|
109
116
|
|
117
|
+
interface WebEventHandler {
|
118
|
+
onGestureHandlerEvent: (event: HandlerStateChangeEvent<unknown>) => void;
|
119
|
+
}
|
120
|
+
|
110
121
|
interface AttachHandlersConfig {
|
111
122
|
preparedGesture: GestureConfigReference;
|
112
123
|
gestureConfig: ComposedGesture | GestureType | undefined;
|
113
124
|
gesture: GestureType[];
|
114
125
|
viewTag: number;
|
126
|
+
webEventHandlersRef: React.RefObject<WebEventHandler>;
|
115
127
|
}
|
116
128
|
|
117
129
|
function attachHandlers({
|
@@ -119,6 +131,7 @@ function attachHandlers({
|
|
119
131
|
gestureConfig,
|
120
132
|
gesture,
|
121
133
|
viewTag,
|
134
|
+
webEventHandlersRef,
|
122
135
|
}: AttachHandlersConfig) {
|
123
136
|
if (!preparedGesture.firstExecution) {
|
124
137
|
gestureConfig?.initialize();
|
@@ -142,10 +155,12 @@ function attachHandlers({
|
|
142
155
|
);
|
143
156
|
|
144
157
|
registerHandler(handler.handlerTag, handler, handler.config.testId);
|
158
|
+
}
|
145
159
|
|
146
|
-
|
147
|
-
|
148
|
-
|
160
|
+
// use setImmediate to extract handlerTags, because all refs should be initialized
|
161
|
+
// when it's ran
|
162
|
+
setImmediate(() => {
|
163
|
+
for (const handler of gesture) {
|
149
164
|
let requireToFail: number[] = [];
|
150
165
|
if (handler.config.requireToFail) {
|
151
166
|
requireToFail = extractValidHandlerTags(handler.config.requireToFail);
|
@@ -165,8 +180,11 @@ function attachHandlers({
|
|
165
180
|
waitFor: requireToFail,
|
166
181
|
})
|
167
182
|
);
|
168
|
-
}
|
169
|
-
|
183
|
+
}
|
184
|
+
|
185
|
+
scheduleFlushOperations();
|
186
|
+
});
|
187
|
+
|
170
188
|
preparedGesture.config = gesture;
|
171
189
|
|
172
190
|
for (const gesture of preparedGesture.config) {
|
@@ -174,11 +192,20 @@ function attachHandlers({
|
|
174
192
|
? ActionType.REANIMATED_WORKLET
|
175
193
|
: ActionType.JS_FUNCTION_NEW_API;
|
176
194
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
195
|
+
if (Platform.OS === 'web') {
|
196
|
+
(RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler)(
|
197
|
+
gesture.handlerTag,
|
198
|
+
viewTag,
|
199
|
+
ActionType.JS_FUNCTION_OLD_API, // ignored on web
|
200
|
+
webEventHandlersRef
|
201
|
+
);
|
202
|
+
} else {
|
203
|
+
RNGestureHandlerModule.attachGestureHandler(
|
204
|
+
gesture.handlerTag,
|
205
|
+
viewTag,
|
206
|
+
actionType
|
207
|
+
);
|
208
|
+
}
|
182
209
|
}
|
183
210
|
|
184
211
|
if (preparedGesture.animatedHandlers) {
|
@@ -241,12 +268,37 @@ function updateHandlers(
|
|
241
268
|
}
|
242
269
|
|
243
270
|
if (preparedGesture.animatedHandlers) {
|
244
|
-
|
271
|
+
const previousHandlersValue =
|
272
|
+
preparedGesture.animatedHandlers.value ?? [];
|
273
|
+
const newHandlersValue = (preparedGesture.config
|
245
274
|
.filter((g) => g.shouldUseReanimated) // ignore gestures that shouldn't run on UI
|
246
275
|
.map((g) => g.handlers) as unknown) as HandlerCallbacks<
|
247
276
|
Record<string, unknown>
|
248
277
|
>[];
|
278
|
+
|
279
|
+
// if amount of gesture configs changes, we need to update the callbacks in shared value
|
280
|
+
let shouldUpdateSharedValue =
|
281
|
+
previousHandlersValue.length !== newHandlersValue.length;
|
282
|
+
|
283
|
+
if (!shouldUpdateSharedValue) {
|
284
|
+
// if the amount is the same, we need to check if any of the configs inside has changed
|
285
|
+
for (let i = 0; i < newHandlersValue.length; i++) {
|
286
|
+
if (
|
287
|
+
// we can use the `gestureId` prop as it's unique for every config instance
|
288
|
+
newHandlersValue[i].gestureId !== previousHandlersValue[i].gestureId
|
289
|
+
) {
|
290
|
+
shouldUpdateSharedValue = true;
|
291
|
+
break;
|
292
|
+
}
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
if (shouldUpdateSharedValue) {
|
297
|
+
preparedGesture.animatedHandlers.value = newHandlersValue;
|
298
|
+
}
|
249
299
|
}
|
300
|
+
|
301
|
+
scheduleFlushOperations();
|
250
302
|
});
|
251
303
|
}
|
252
304
|
|
@@ -270,88 +322,90 @@ function needsToReattach(
|
|
270
322
|
return false;
|
271
323
|
}
|
272
324
|
|
273
|
-
function
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
325
|
+
function isStateChangeEvent(
|
326
|
+
event: GestureUpdateEvent | GestureStateChangeEvent | GestureTouchEvent
|
327
|
+
): event is GestureStateChangeEvent {
|
328
|
+
'worklet';
|
329
|
+
// @ts-ignore Yes, the oldState prop is missing on GestureTouchEvent, that's the point
|
330
|
+
return event.oldState != null;
|
331
|
+
}
|
280
332
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
}
|
333
|
+
function isTouchEvent(
|
334
|
+
event: GestureUpdateEvent | GestureStateChangeEvent | GestureTouchEvent
|
335
|
+
): event is GestureTouchEvent {
|
336
|
+
'worklet';
|
337
|
+
return event.eventType != null;
|
338
|
+
}
|
288
339
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
340
|
+
function getHandler(
|
341
|
+
type: CALLBACK_TYPE,
|
342
|
+
gesture: HandlerCallbacks<Record<string, unknown>>
|
343
|
+
) {
|
344
|
+
'worklet';
|
345
|
+
switch (type) {
|
346
|
+
case CALLBACK_TYPE.BEGAN:
|
347
|
+
return gesture.onBegin;
|
348
|
+
case CALLBACK_TYPE.START:
|
349
|
+
return gesture.onStart;
|
350
|
+
case CALLBACK_TYPE.UPDATE:
|
351
|
+
return gesture.onUpdate;
|
352
|
+
case CALLBACK_TYPE.CHANGE:
|
353
|
+
return gesture.onChange;
|
354
|
+
case CALLBACK_TYPE.END:
|
355
|
+
return gesture.onEnd;
|
356
|
+
case CALLBACK_TYPE.FINALIZE:
|
357
|
+
return gesture.onFinalize;
|
358
|
+
case CALLBACK_TYPE.TOUCHES_DOWN:
|
359
|
+
return gesture.onTouchesDown;
|
360
|
+
case CALLBACK_TYPE.TOUCHES_MOVE:
|
361
|
+
return gesture.onTouchesMove;
|
362
|
+
case CALLBACK_TYPE.TOUCHES_UP:
|
363
|
+
return gesture.onTouchesUp;
|
364
|
+
case CALLBACK_TYPE.TOUCHES_CANCELLED:
|
365
|
+
return gesture.onTouchesCancelled;
|
294
366
|
}
|
367
|
+
}
|
295
368
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
return gesture.onChange;
|
310
|
-
case CALLBACK_TYPE.END:
|
311
|
-
return gesture.onEnd;
|
312
|
-
case CALLBACK_TYPE.FINALIZE:
|
313
|
-
return gesture.onFinalize;
|
314
|
-
case CALLBACK_TYPE.TOUCHES_DOWN:
|
315
|
-
return gesture.onTouchesDown;
|
316
|
-
case CALLBACK_TYPE.TOUCHES_MOVE:
|
317
|
-
return gesture.onTouchesMove;
|
318
|
-
case CALLBACK_TYPE.TOUCHES_UP:
|
319
|
-
return gesture.onTouchesUp;
|
320
|
-
case CALLBACK_TYPE.TOUCHES_CANCELLED:
|
321
|
-
return gesture.onTouchesCancelled;
|
322
|
-
}
|
369
|
+
function touchEventTypeToCallbackType(
|
370
|
+
eventType: TouchEventType
|
371
|
+
): CALLBACK_TYPE {
|
372
|
+
'worklet';
|
373
|
+
switch (eventType) {
|
374
|
+
case TouchEventType.TOUCHES_DOWN:
|
375
|
+
return CALLBACK_TYPE.TOUCHES_DOWN;
|
376
|
+
case TouchEventType.TOUCHES_MOVE:
|
377
|
+
return CALLBACK_TYPE.TOUCHES_MOVE;
|
378
|
+
case TouchEventType.TOUCHES_UP:
|
379
|
+
return CALLBACK_TYPE.TOUCHES_UP;
|
380
|
+
case TouchEventType.TOUCHES_CANCELLED:
|
381
|
+
return CALLBACK_TYPE.TOUCHES_CANCELLED;
|
323
382
|
}
|
383
|
+
return CALLBACK_TYPE.UNDEFINED;
|
384
|
+
}
|
324
385
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
386
|
+
function runWorklet(
|
387
|
+
type: CALLBACK_TYPE,
|
388
|
+
gesture: HandlerCallbacks<Record<string, unknown>>,
|
389
|
+
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
390
|
+
...args: any[]
|
391
|
+
) {
|
392
|
+
'worklet';
|
393
|
+
const handler = getHandler(type, gesture);
|
394
|
+
if (gesture.isWorklet[type]) {
|
395
|
+
// @ts-ignore Logic below makes sure the correct event is send to the
|
396
|
+
// correct handler.
|
397
|
+
handler?.(event, ...args);
|
398
|
+
} else if (handler) {
|
399
|
+
console.warn(tagMessage('Animated gesture callback must be a worklet'));
|
338
400
|
}
|
401
|
+
}
|
339
402
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
'worklet';
|
347
|
-
const handler = getHandler(type, gesture);
|
348
|
-
if (gesture.isWorklet[type]) {
|
349
|
-
// @ts-ignore Logic below makes sure the correct event is send to the
|
350
|
-
// correct handler.
|
351
|
-
handler?.(event, ...args);
|
352
|
-
} else if (handler) {
|
353
|
-
console.warn(tagMessage('Animated gesture callback must be a worklet'));
|
354
|
-
}
|
403
|
+
function useAnimatedGesture(
|
404
|
+
preparedGesture: GestureConfigReference,
|
405
|
+
needsRebuild: boolean
|
406
|
+
) {
|
407
|
+
if (!Reanimated) {
|
408
|
+
return;
|
355
409
|
}
|
356
410
|
|
357
411
|
// Hooks are called conditionally, but the condition is whether the
|
@@ -418,7 +472,7 @@ function useAnimatedGesture(
|
|
418
472
|
stateControllers[i] = GestureStateManager.create(event.handlerTag);
|
419
473
|
}
|
420
474
|
|
421
|
-
if (event.eventType !==
|
475
|
+
if (event.eventType !== TouchEventType.UNDETERMINED) {
|
422
476
|
runWorklet(
|
423
477
|
touchEventTypeToCallbackType(event.eventType),
|
424
478
|
gesture,
|
@@ -459,15 +513,19 @@ function useAnimatedGesture(
|
|
459
513
|
|
460
514
|
interface GestureDetectorProps {
|
461
515
|
gesture?: ComposedGesture | GestureType;
|
516
|
+
children?: React.ReactNode;
|
462
517
|
}
|
463
|
-
export const GestureDetector:
|
464
|
-
props
|
465
|
-
) => {
|
518
|
+
export const GestureDetector = (props: GestureDetectorProps) => {
|
466
519
|
const gestureConfig = props.gesture;
|
467
520
|
const gesture = gestureConfig?.toGestureArray?.() ?? [];
|
468
521
|
const useReanimatedHook = gesture.some((g) => g.shouldUseReanimated);
|
469
522
|
const viewRef = useRef(null);
|
470
523
|
const firstRenderRef = useRef(true);
|
524
|
+
const webEventHandlersRef = useRef<WebEventHandler>({
|
525
|
+
onGestureHandlerEvent: (e: HandlerStateChangeEvent<unknown>) => {
|
526
|
+
onGestureHandlerEvent(e.nativeEvent);
|
527
|
+
},
|
528
|
+
});
|
471
529
|
|
472
530
|
const preparedGesture = React.useRef<GestureConfigReference>({
|
473
531
|
config: gesture,
|
@@ -508,6 +566,7 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
508
566
|
gestureConfig,
|
509
567
|
gesture,
|
510
568
|
viewTag,
|
569
|
+
webEventHandlersRef,
|
511
570
|
});
|
512
571
|
|
513
572
|
return () => {
|
@@ -526,6 +585,7 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
526
585
|
gestureConfig,
|
527
586
|
gesture,
|
528
587
|
viewTag,
|
588
|
+
webEventHandlersRef,
|
529
589
|
});
|
530
590
|
} else {
|
531
591
|
updateHandlers(preparedGesture, gestureConfig, gesture);
|
@@ -543,17 +603,12 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
543
603
|
if (isFabric()) {
|
544
604
|
const node = getShadowNodeFromRef(ref);
|
545
605
|
if (global.isFormsStackingContext(node) === false) {
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
'GestureDetector has received a child that may get view-flattened. ' +
|
553
|
-
'\nTo prevent it from misbehaving you need to wrap the child with a `<View collapsable={false}>`.'
|
554
|
-
)
|
555
|
-
);
|
556
|
-
});
|
606
|
+
console.error(
|
607
|
+
tagMessage(
|
608
|
+
'GestureDetector has received a child that may get view-flattened. ' +
|
609
|
+
'\nTo prevent it from misbehaving you need to wrap the child with a `<View collapsable={false}>`.'
|
610
|
+
)
|
611
|
+
);
|
557
612
|
}
|
558
613
|
}
|
559
614
|
}
|
@@ -572,7 +627,11 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
572
627
|
}
|
573
628
|
};
|
574
629
|
|
575
|
-
class Wrap extends React.Component<{
|
630
|
+
class Wrap extends React.Component<{
|
631
|
+
onGestureHandlerEvent?: unknown;
|
632
|
+
// implicit `children` prop has been removed in @types/react^18.0.0
|
633
|
+
children?: React.ReactNode;
|
634
|
+
}> {
|
576
635
|
render() {
|
577
636
|
// I don't think that fighting with types over such a simple function is worth it
|
578
637
|
// The only thing it does is add 'collapsable: false' to the child component
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { DeviceEventEmitter, EmitterSubscription } from 'react-native';
|
2
2
|
import { State } from '../../State';
|
3
|
-
import {
|
3
|
+
import { TouchEventType } from '../../TouchEventType';
|
4
4
|
import {
|
5
5
|
GestureTouchEvent,
|
6
6
|
GestureUpdateEvent,
|
@@ -48,7 +48,7 @@ function isTouchEvent(
|
|
48
48
|
return event.eventType != null;
|
49
49
|
}
|
50
50
|
|
51
|
-
function onGestureHandlerEvent(
|
51
|
+
export function onGestureHandlerEvent(
|
52
52
|
event: GestureUpdateEvent | GestureStateChangeEvent | GestureTouchEvent
|
53
53
|
) {
|
54
54
|
const handler = findHandler(event.handlerTag) as BaseGesture<
|
@@ -87,16 +87,16 @@ function onGestureHandlerEvent(
|
|
87
87
|
}
|
88
88
|
} else if (isTouchEvent(event)) {
|
89
89
|
switch (event.eventType) {
|
90
|
-
case
|
90
|
+
case TouchEventType.TOUCHES_DOWN:
|
91
91
|
handler.handlers?.onTouchesDown?.(event, dummyStateManager);
|
92
92
|
break;
|
93
|
-
case
|
93
|
+
case TouchEventType.TOUCHES_MOVE:
|
94
94
|
handler.handlers?.onTouchesMove?.(event, dummyStateManager);
|
95
95
|
break;
|
96
|
-
case
|
96
|
+
case TouchEventType.TOUCHES_UP:
|
97
97
|
handler.handlers?.onTouchesUp?.(event, dummyStateManager);
|
98
98
|
break;
|
99
|
-
case
|
99
|
+
case TouchEventType.TOUCHES_CANCELLED:
|
100
100
|
handler.handlers?.onTouchesCancelled?.(event, dummyStateManager);
|
101
101
|
break;
|
102
102
|
}
|
@@ -15,6 +15,7 @@ import { PinchGestureHandlerEventPayload } from '../PinchGestureHandler';
|
|
15
15
|
import { RotationGestureHandlerEventPayload } from '../RotationGestureHandler';
|
16
16
|
import { TapGestureHandlerEventPayload } from '../TapGestureHandler';
|
17
17
|
import { NativeViewGestureHandlerPayload } from '../NativeViewGestureHandler';
|
18
|
+
import { isRemoteDebuggingEnabled } from '../../utils';
|
18
19
|
|
19
20
|
export type GestureType =
|
20
21
|
| BaseGesture<Record<string, unknown>>
|
@@ -43,6 +44,7 @@ export interface BaseGestureConfig
|
|
43
44
|
manualActivation?: boolean;
|
44
45
|
runOnJS?: boolean;
|
45
46
|
testId?: string;
|
47
|
+
cancelsTouchesInView?: boolean;
|
46
48
|
}
|
47
49
|
|
48
50
|
type TouchEventHandlerType = (
|
@@ -51,6 +53,7 @@ type TouchEventHandlerType = (
|
|
51
53
|
) => void;
|
52
54
|
|
53
55
|
export type HandlerCallbacks<EventPayloadT extends Record<string, unknown>> = {
|
56
|
+
gestureId: number;
|
54
57
|
handlerTag: number;
|
55
58
|
onBegin?: (event: GestureStateChangeEvent<EventPayloadT>) => void;
|
56
59
|
onStart?: (event: GestureStateChangeEvent<EventPayloadT>) => void;
|
@@ -113,17 +116,32 @@ export abstract class Gesture {
|
|
113
116
|
abstract prepare(): void;
|
114
117
|
}
|
115
118
|
|
119
|
+
let nextGestureId = 0;
|
116
120
|
export abstract class BaseGesture<
|
117
121
|
EventPayloadT extends Record<string, unknown>
|
118
122
|
> extends Gesture {
|
123
|
+
private gestureId = -1;
|
119
124
|
public handlerTag = -1;
|
120
125
|
public handlerName = '';
|
121
126
|
public config: BaseGestureConfig = {};
|
122
127
|
public handlers: HandlerCallbacks<EventPayloadT> = {
|
128
|
+
gestureId: -1,
|
123
129
|
handlerTag: -1,
|
124
130
|
isWorklet: [],
|
125
131
|
};
|
126
132
|
|
133
|
+
constructor() {
|
134
|
+
super();
|
135
|
+
|
136
|
+
// Used to check whether the gesture config has been updated when wrapping it
|
137
|
+
// with `useMemo`. Since every config will have a unique id, when the dependencies
|
138
|
+
// don't change, the config won't be recreated and the id will stay the same.
|
139
|
+
// If the id is different, it means that the config has changed and the gesture
|
140
|
+
// needs to be updated.
|
141
|
+
this.gestureId = nextGestureId++;
|
142
|
+
this.handlers.gestureId = this.gestureId;
|
143
|
+
}
|
144
|
+
|
127
145
|
private addDependency(
|
128
146
|
key: 'simultaneousWith' | 'requireToFail',
|
129
147
|
gesture: Exclude<GestureRef, number>
|
@@ -260,6 +278,11 @@ export abstract class BaseGesture<
|
|
260
278
|
return this;
|
261
279
|
}
|
262
280
|
|
281
|
+
cancelsTouchesInView(value: boolean) {
|
282
|
+
this.config.cancelsTouchesInView = value;
|
283
|
+
return this;
|
284
|
+
}
|
285
|
+
|
263
286
|
initialize() {
|
264
287
|
this.handlerTag = getNextHandlerTag();
|
265
288
|
|
@@ -278,9 +301,13 @@ export abstract class BaseGesture<
|
|
278
301
|
prepare() {}
|
279
302
|
|
280
303
|
get shouldUseReanimated(): boolean {
|
281
|
-
// use Reanimated when runOnJS isn't set explicitly
|
304
|
+
// use Reanimated when runOnJS isn't set explicitly,
|
305
|
+
// and all defined callbacks are worklets,
|
306
|
+
// and remote debugging is disabled
|
282
307
|
return (
|
283
|
-
this.config.runOnJS !== true &&
|
308
|
+
this.config.runOnJS !== true &&
|
309
|
+
!this.handlers.isWorklet.includes(false) &&
|
310
|
+
!isRemoteDebuggingEnabled()
|
284
311
|
);
|
285
312
|
}
|
286
313
|
}
|
package/src/init.ts
CHANGED
@@ -2,10 +2,17 @@ import { startListening } from './handlers/gestures/eventReceiver';
|
|
2
2
|
import RNGestureHandlerModule from './RNGestureHandlerModule';
|
3
3
|
import { isFabric } from './utils';
|
4
4
|
|
5
|
+
let fabricInitialized = false;
|
6
|
+
|
5
7
|
export function initialize() {
|
6
8
|
startListening();
|
9
|
+
}
|
7
10
|
|
8
|
-
|
11
|
+
// since isFabric() may give wrong results before the first render, we call this
|
12
|
+
// method during render of GestureHandlerRootView
|
13
|
+
export function maybeInitializeFabric() {
|
14
|
+
if (isFabric() && !fabricInitialized) {
|
9
15
|
RNGestureHandlerModule.install();
|
16
|
+
fabricInitialized = true;
|
10
17
|
}
|
11
18
|
}
|
package/src/mocks.ts
CHANGED
@@ -21,6 +21,7 @@ const attachGestureHandler = NOOP;
|
|
21
21
|
const createGestureHandler = NOOP;
|
22
22
|
const dropGestureHandler = NOOP;
|
23
23
|
const updateGestureHandler = NOOP;
|
24
|
+
const flushOperations = NOOP;
|
24
25
|
const NativeViewGestureHandler = View;
|
25
26
|
const TapGestureHandler = View;
|
26
27
|
const ForceTouchGestureHandler = View;
|
@@ -59,6 +60,7 @@ export default {
|
|
59
60
|
createGestureHandler,
|
60
61
|
dropGestureHandler,
|
61
62
|
updateGestureHandler,
|
63
|
+
flushOperations,
|
62
64
|
// probably can be removed
|
63
65
|
Directions,
|
64
66
|
State,
|
package/src/utils.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import { version as rnVersion } from 'react-native/package.json';
|
2
|
+
|
1
3
|
export function toArray<T>(object: T | T[]): T[] {
|
2
4
|
if (!Array.isArray(object)) {
|
3
5
|
return [object];
|
@@ -32,6 +34,7 @@ export function hasProperty(object: object, key: string) {
|
|
32
34
|
}
|
33
35
|
|
34
36
|
export function isJestEnv(): boolean {
|
37
|
+
// @ts-ignore Do not use `@types/node` because it will prioritise Node types over RN types which breaks the types (ex. setTimeout) in React Native projects.
|
35
38
|
return hasProperty(global, 'process') && !!process.env.JEST_WORKER_ID;
|
36
39
|
}
|
37
40
|
|
@@ -39,7 +42,24 @@ export function tagMessage(msg: string) {
|
|
39
42
|
return `[react-native-gesture-handler] ${msg}`;
|
40
43
|
}
|
41
44
|
|
45
|
+
// helper method to check whether Fabric is enabled, however global.nativeFabricUIManager
|
46
|
+
// may not be initialized before the first render
|
42
47
|
export function isFabric(): boolean {
|
43
48
|
// @ts-expect-error nativeFabricUIManager is not yet included in the RN types
|
44
49
|
return !!global?.nativeFabricUIManager;
|
45
50
|
}
|
51
|
+
|
52
|
+
export function shouldUseCodegenNativeComponent(): boolean {
|
53
|
+
const [majorStr, minorStr] = rnVersion.split('.');
|
54
|
+
const major = Number.parseInt(majorStr);
|
55
|
+
const minor = Number.parseInt(minorStr);
|
56
|
+
|
57
|
+
// use codegenNativeComponent starting with RN 0.68
|
58
|
+
return minor >= 68 || major > 0;
|
59
|
+
}
|
60
|
+
|
61
|
+
export function isRemoteDebuggingEnabled(): boolean {
|
62
|
+
// react-native-reanimated checks if in remote debugging in the same way
|
63
|
+
// @ts-ignore global is available but node types are not included
|
64
|
+
return !(global as any).nativeCallSyncHook || (global as any).__REMOTEDEV__;
|
65
|
+
}
|
@@ -182,7 +182,13 @@ abstract class GestureHandler {
|
|
182
182
|
// onHandlerStateChange only
|
183
183
|
handlerTag: this.handlerTag,
|
184
184
|
target: this.ref,
|
185
|
-
oldState
|
185
|
+
// send oldState only when the state was changed, or is different than ACTIVE
|
186
|
+
// GestureDetector relies on the presence of `oldState` to differentiate between
|
187
|
+
// update events and state change events
|
188
|
+
oldState:
|
189
|
+
state !== this.previousState || state != 4
|
190
|
+
? this.oldState
|
191
|
+
: undefined,
|
186
192
|
},
|
187
193
|
timeStamp: Date.now(),
|
188
194
|
};
|