Skip to content

Commit 8b0f128

Browse files
authored
[Web] v3 typing and using handler data (#3651)
## Description Changing web implementation to use v3 types with a proper `handlerData` field. ## Test plan check whether `handledData` is a proper field of `nativeEvent` when using `NativeDetector`. ```ts const gesture = useGesture('PanGestureHandler', { onBegin: (e: any) => { console.log('onGestureHandlerEvent', e.nativeEvent.handlerData); }, }); ```
1 parent cd27bfd commit 8b0f128

File tree

8 files changed

+138
-86
lines changed

8 files changed

+138
-86
lines changed

packages/react-native-gesture-handler/src/handlers/GestureHandlerEventPayload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StylusData } from '../web/interfaces';
1+
import { StylusData } from './gestureHandlerCommon';
22

33
export type FlingGestureHandlerEventPayload = {
44
x: number;

packages/react-native-gesture-handler/src/handlers/gestureHandlerCommon.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ export type GestureTouchEvent = {
165165
pointerType: PointerType;
166166
};
167167

168+
export interface StylusData {
169+
tiltX: number;
170+
tiltY: number;
171+
azimuthAngle: number;
172+
altitudeAngle: number;
173+
pressure: number;
174+
}
175+
168176
export type GestureUpdateEvent<GestureEventPayloadT = Record<string, unknown>> =
169177
GestureEventPayload & GestureEventPayloadT;
170178

packages/react-native-gesture-handler/src/handlers/gestures/GestureDetector/utils.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@ import {
1313
import { tapGestureHandlerProps } from '../../TapGestureHandler';
1414
import { hoverGestureHandlerProps } from '../hoverGesture';
1515
import { nativeViewGestureHandlerProps } from '../../NativeViewGestureHandler';
16-
import {
17-
HandlerStateChangeEvent,
18-
baseGestureHandlerWithDetectorProps,
19-
} from '../../gestureHandlerCommon';
16+
import { baseGestureHandlerWithDetectorProps } from '../../gestureHandlerCommon';
2017
import { RNRenderer } from '../../../RNRenderer';
2118
import { useCallback, useRef, useState } from 'react';
2219
import { Reanimated } from '../reanimatedWrapper';
2320
import { onGestureHandlerEvent } from '../eventReceiver';
24-
import { PropsRef } from '../../../web/interfaces';
21+
import {
22+
GestureHandlerNativeEvent,
23+
PropsRef,
24+
ResultEvent,
25+
} from '../../../web/interfaces';
2526

2627
export const ALLOWED_PROPS = [
2728
...baseGestureHandlerWithDetectorProps,
@@ -168,11 +169,11 @@ export function useForceRender() {
168169

169170
export function useWebEventHandlers() {
170171
return useRef<PropsRef>({
171-
onGestureHandlerEvent: (e: HandlerStateChangeEvent<unknown>) => {
172-
onGestureHandlerEvent(e.nativeEvent);
172+
onGestureHandlerEvent: (e: ResultEvent) => {
173+
onGestureHandlerEvent(e.nativeEvent as GestureHandlerNativeEvent);
173174
},
174-
onGestureHandlerStateChange: (e: HandlerStateChangeEvent<unknown>) => {
175-
onGestureHandlerEvent(e.nativeEvent);
175+
onGestureHandlerStateChange: (e: ResultEvent) => {
176+
onGestureHandlerEvent(e.nativeEvent as GestureHandlerNativeEvent);
176177
},
177178
});
178179
}

packages/react-native-gesture-handler/src/web/handlers/GestureHandler.ts

Lines changed: 91 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,27 @@ import {
66
PropsRef,
77
ResultEvent,
88
PointerData,
9-
ResultTouchEvent,
10-
TouchEventType,
119
EventTypes,
10+
GestureHandlerNativeEvent,
1211
} from '../interfaces';
1312
import EventManager from '../tools/EventManager';
1413
import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator';
1514
import InteractionManager from '../tools/InteractionManager';
1615
import PointerTracker, { TrackerElement } from '../tools/PointerTracker';
1716
import IGestureHandler from './IGestureHandler';
18-
import { MouseButton } from '../../handlers/gestureHandlerCommon';
17+
import {
18+
GestureTouchEvent,
19+
MouseButton,
20+
} from '../../handlers/gestureHandlerCommon';
1921
import { PointerType } from '../../PointerType';
2022
import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
2123
import { ActionType } from '../../ActionType';
2224
import { tagMessage } from '../../utils';
25+
import {
26+
GestureStateChangeEventWithData,
27+
GestureUpdateEventWithData,
28+
} from '../../v3/types';
29+
import { TouchEventType } from '../../TouchEventType';
2330

2431
export default abstract class GestureHandler implements IGestureHandler {
2532
private lastSentState: State | null = null;
@@ -369,7 +376,7 @@ export default abstract class GestureHandler implements IGestureHandler {
369376
const { onGestureHandlerEvent, onGestureHandlerTouchEvent }: PropsRef =
370377
this.propsRef!.current;
371378

372-
const touchEvent: ResultTouchEvent | undefined =
379+
const touchEvent: ResultEvent<GestureTouchEvent> | undefined =
373380
this.transformTouchEvent(event);
374381

375382
if (touchEvent) {
@@ -389,18 +396,19 @@ export default abstract class GestureHandler implements IGestureHandler {
389396
//
390397

391398
public sendEvent = (newState: State, oldState: State): void => {
392-
this.ensurePropsRef();
393399
const {
394400
onGestureHandlerEvent,
395401
onGestureHandlerStateChange,
396402
onGestureHandlerAnimatedEvent,
397403
}: PropsRef = this.propsRef!.current;
398-
const resultEvent: ResultEvent = this.transformEventData(
399-
newState,
400-
oldState
401-
);
402-
403-
// In the new API oldState field has to be undefined, unless we send event state changed
404+
const resultEvent: ResultEvent =
405+
this.actionType !== ActionType.NATIVE_DETECTOR
406+
? this.transformEventData(newState, oldState)
407+
: this.lastSentState !== newState
408+
? this.transformStateChangeEvent(newState, oldState)
409+
: this.transformUpdateEvent(newState);
410+
411+
// In the v2 API oldState field has to be undefined, unless we send event state changed
404412
// Here the order is flipped to avoid workarounds such as making backup of the state and setting it to undefined first, then changing it back
405413
// Flipping order with setting oldState to undefined solves issue, when events were being sent twice instead of once
406414
// However, this may cause trouble in the future (but for now we don't know that)
@@ -410,18 +418,22 @@ export default abstract class GestureHandler implements IGestureHandler {
410418
invokeNullableMethod(onGestureHandlerStateChange, resultEvent);
411419
}
412420
if (this.state === State.ACTIVE) {
413-
resultEvent.nativeEvent.oldState = undefined;
421+
if (this.actionType !== ActionType.NATIVE_DETECTOR) {
422+
(resultEvent.nativeEvent as GestureHandlerNativeEvent).oldState =
423+
undefined;
424+
}
414425
if (onGestureHandlerAnimatedEvent && this.forAnimated) {
415426
invokeNullableMethod(onGestureHandlerAnimatedEvent, resultEvent);
416427
}
417428
invokeNullableMethod(onGestureHandlerEvent, resultEvent);
418429
}
419430
};
420431

421-
private transformEventData(newState: State, oldState: State): ResultEvent {
422-
if (!this.viewRef) {
423-
throw new Error(tagMessage('Cannot handle event when target is null'));
424-
}
432+
private transformEventData(
433+
newState: State,
434+
oldState: State
435+
): ResultEvent<GestureHandlerNativeEvent> {
436+
this.ensureViewRef(this.viewRef);
425437
return {
426438
nativeEvent: {
427439
numberOfPointers: this.tracker.trackedPointersCount,
@@ -439,9 +451,55 @@ export default abstract class GestureHandler implements IGestureHandler {
439451
};
440452
}
441453

454+
private transformStateChangeEvent(
455+
newState: State,
456+
oldState: State
457+
): ResultEvent<GestureStateChangeEventWithData<unknown>> {
458+
this.ensureViewRef(this.viewRef);
459+
return {
460+
nativeEvent: {
461+
state: newState,
462+
handlerTag: this.handlerTag,
463+
pointerType: this.pointerType,
464+
oldState: oldState,
465+
numberOfPointers: this.tracker.trackedPointersCount,
466+
handlerData: {
467+
pointerInside: this.delegate.isPointerInBounds(
468+
this.tracker.getAbsoluteCoordsAverage()
469+
),
470+
...this.transformNativeEvent(),
471+
target: this.viewRef,
472+
},
473+
},
474+
timeStamp: Date.now(),
475+
};
476+
}
477+
478+
private transformUpdateEvent(
479+
newState: State
480+
): ResultEvent<GestureUpdateEventWithData<unknown>> {
481+
this.ensureViewRef(this.viewRef);
482+
return {
483+
nativeEvent: {
484+
state: newState,
485+
handlerTag: this.handlerTag,
486+
pointerType: this.pointerType,
487+
numberOfPointers: this.tracker.trackedPointersCount,
488+
handlerData: {
489+
pointerInside: this.delegate.isPointerInBounds(
490+
this.tracker.getAbsoluteCoordsAverage()
491+
),
492+
...this.transformNativeEvent(),
493+
target: this.viewRef,
494+
},
495+
},
496+
timeStamp: Date.now(),
497+
};
498+
}
499+
442500
private transformTouchEvent(
443501
event: AdaptedEvent
444-
): ResultTouchEvent | undefined {
502+
): ResultEvent<GestureTouchEvent> | undefined {
445503
const rect = this.delegate.measureView();
446504

447505
const all: PointerData[] = [];
@@ -498,17 +556,17 @@ export default abstract class GestureHandler implements IGestureHandler {
498556
switch (event.eventType) {
499557
case EventTypes.DOWN:
500558
case EventTypes.ADDITIONAL_POINTER_DOWN:
501-
eventType = TouchEventType.DOWN;
559+
eventType = TouchEventType.TOUCHES_DOWN;
502560
break;
503561
case EventTypes.UP:
504562
case EventTypes.ADDITIONAL_POINTER_UP:
505-
eventType = TouchEventType.UP;
563+
eventType = TouchEventType.TOUCHES_UP;
506564
break;
507565
case EventTypes.MOVE:
508-
eventType = TouchEventType.MOVE;
566+
eventType = TouchEventType.TOUCHES_MOVE;
509567
break;
510568
case EventTypes.CANCEL:
511-
eventType = TouchEventType.CANCELLED;
569+
eventType = TouchEventType.TOUCHES_CANCELLED;
512570
break;
513571
}
514572

@@ -571,11 +629,11 @@ export default abstract class GestureHandler implements IGestureHandler {
571629
});
572630
});
573631

574-
const cancelEvent: ResultTouchEvent = {
632+
const cancelEvent: ResultEvent<GestureTouchEvent> = {
575633
nativeEvent: {
576634
handlerTag: this.handlerTag,
577635
state: this.state,
578-
eventType: TouchEventType.CANCELLED,
636+
eventType: TouchEventType.TOUCHES_CANCELLED,
579637
changedTouches: changed,
580638
allTouches: all,
581639
numberOfTouches: all.length,
@@ -597,6 +655,12 @@ export default abstract class GestureHandler implements IGestureHandler {
597655
}
598656
}
599657

658+
private ensureViewRef(viewRef: any): asserts viewRef is number {
659+
if (!viewRef) {
660+
throw new Error(tagMessage('Cannot handle event when target is null'));
661+
}
662+
}
663+
600664
protected transformNativeEvent(): Record<string, unknown> {
601665
// Those properties are shared by most handlers and if not this method will be overriden
602666
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
@@ -888,10 +952,10 @@ export default abstract class GestureHandler implements IGestureHandler {
888952

889953
function invokeNullableMethod(
890954
method:
891-
| ((event: ResultEvent | ResultTouchEvent) => void)
892-
| { __getHandler: () => (event: ResultEvent | ResultTouchEvent) => void }
955+
| ((event: ResultEvent) => void)
956+
| { __getHandler: () => (event: ResultEvent) => void }
893957
| { __nodeConfig: { argMapping: unknown[] } },
894-
event: ResultEvent | ResultTouchEvent
958+
event: ResultEvent
895959
): void {
896960
if (!method) {
897961
return;
@@ -923,7 +987,7 @@ function invokeNullableMethod(
923987
}
924988

925989
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
926-
const nativeValue = event.nativeEvent[key];
990+
const nativeValue = (event.nativeEvent as any)[key];
927991

928992
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
929993
if (value?.setValue) {

packages/react-native-gesture-handler/src/web/handlers/HoverGestureHandler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { State } from '../../State';
2-
import { AdaptedEvent, StylusData } from '../interfaces';
2+
import { AdaptedEvent } from '../interfaces';
33
import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator';
44
import GestureHandler from './GestureHandler';
5+
import { StylusData } from '../../handlers/gestureHandlerCommon';
56

67
export default class HoverGestureHandler extends GestureHandler {
78
private stylusData: StylusData | undefined;

packages/react-native-gesture-handler/src/web/handlers/PanGestureHandler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { State } from '../../State';
22
import { DEFAULT_TOUCH_SLOP } from '../constants';
3-
import { AdaptedEvent, Config, StylusData, WheelDevice } from '../interfaces';
3+
import { AdaptedEvent, Config, WheelDevice } from '../interfaces';
4+
import { StylusData } from '../../handlers/gestureHandlerCommon';
45

56
import GestureHandler from './GestureHandler';
67

0 commit comments

Comments
 (0)