From cb67ac2c2482d5ade1d5a8add8171fcb493dfbe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Fri, 17 Nov 2023 09:40:54 +0100 Subject: [PATCH 01/35] Remove context menu --- src/web/tools/GestureHandlerWebDelegate.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index 39d2052a1b..8171c8ec4b 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -31,6 +31,8 @@ export class GestureHandlerWebDelegate this.gestureHandler = handler; this.view = findNodeHandle(viewRef) as unknown as HTMLElement; + this.view.oncontextmenu = () => false; + this.view.style['touchAction'] = 'none'; //@ts-ignore This one disables default events on Safari this.view.style['WebkitTouchCallout'] = 'none'; From bd3b6a9210debb942858310bd2075d99feef339e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Fri, 17 Nov 2023 09:43:06 +0100 Subject: [PATCH 02/35] Add prop --- src/handlers/gestureHandlerCommon.ts | 2 ++ src/handlers/gestures/gesture.ts | 5 +++++ src/web/interfaces.ts | 11 +++-------- src/web/tools/TouchEventManager.ts | 3 +-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/handlers/gestureHandlerCommon.ts b/src/handlers/gestureHandlerCommon.ts index 9e795e1439..c1b4ed9236 100644 --- a/src/handlers/gestureHandlerCommon.ts +++ b/src/handlers/gestureHandlerCommon.ts @@ -21,6 +21,7 @@ const commonProps = [ 'cancelsTouchesInView', 'userSelect', 'activeCursor', + 'mouseButton', ] as const; const componentInteractionProps = ['waitFor', 'simultaneousHandlers'] as const; @@ -145,6 +146,7 @@ export type CommonGestureConfig = { hitSlop?: HitSlop; userSelect?: UserSelect; activeCursor?: ActiveCursor; + mouseButton?: number; }; // Events payloads are types instead of interfaces due to TS limitation. diff --git a/src/handlers/gestures/gesture.ts b/src/handlers/gestures/gesture.ts index 93d8dd8560..f5b59e8a0b 100644 --- a/src/handlers/gestures/gesture.ts +++ b/src/handlers/gestures/gesture.ts @@ -256,6 +256,11 @@ export abstract class BaseGesture< return this; } + mouseButton(mouseButton: number) { + this.config.mouseButton = mouseButton; + return this; + } + runOnJS(runOnJS: boolean) { this.config.runOnJS = runOnJS; return this; diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index fb435c3881..c679c0ff16 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -121,22 +121,17 @@ export interface AdaptedEvent { pointerId: number; eventType: EventTypes; pointerType: PointerType; - buttons: number; + buttons: number | null; time: number; allTouches?: TouchList; changedTouches?: TouchList; touchEventType?: TouchEventType; } -export enum MouseButtons { - NONE, +export enum MouseButton { LEFT, RIGHT, - LEFT_RIGHT, - SCROLL, - SCROLL_LEFT, - SCROLL_RIGHT, - SCROLL_LEFT_RIGHT, + MIDDLE, } export enum EventTypes { diff --git a/src/web/tools/TouchEventManager.ts b/src/web/tools/TouchEventManager.ts index aabdd0bf62..9c2013bcb7 100644 --- a/src/web/tools/TouchEventManager.ts +++ b/src/web/tools/TouchEventManager.ts @@ -1,7 +1,6 @@ import { AdaptedEvent, EventTypes, - MouseButtons, PointerType, TouchEventType, } from '../interfaces'; @@ -157,7 +156,7 @@ export default class TouchEventManager extends EventManager { pointerId: event.changedTouches[index].identifier, eventType: eventType, pointerType: PointerType.TOUCH, - buttons: MouseButtons.NONE, + buttons: null, time: event.timeStamp, allTouches: event.touches, changedTouches: event.changedTouches, From 441c02c63fd21e49c66e625665c4d689ba48d2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Fri, 17 Nov 2023 10:02:29 +0100 Subject: [PATCH 03/35] Change enum order to match web --- src/web/interfaces.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index c679c0ff16..ee6e19ddfc 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -130,8 +130,8 @@ export interface AdaptedEvent { export enum MouseButton { LEFT, - RIGHT, MIDDLE, + RIGHT, } export enum EventTypes { From f82e08a3db7e822ec5f696f77bbc3e5b148d8dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Fri, 17 Nov 2023 12:37:05 +0100 Subject: [PATCH 04/35] Change enum --- src/index.ts | 1 + src/web/interfaces.ts | 11 +++++++---- src/web/tools/PointerEventManager.ts | 20 ++++++++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index 343998ca14..49fd999c64 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import { initialize } from './init'; export { Directions } from './Directions'; export { State } from './State'; +export { MouseButton } from './web/interfaces'; export { default as gestureHandlerRootHOC } from './components/gestureHandlerRootHOC'; export { default as GestureHandlerRootView } from './components/GestureHandlerRootView'; export type { diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index ee6e19ddfc..055a4a534a 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -36,6 +36,7 @@ export interface Config extends Record { shouldCancelWhenOutside?: boolean; userSelect?: UserSelect; activeCursor?: ActiveCursor; + mouseButton?: MouseButton; activateAfterLongPress?: number; failOffsetXStart?: number; @@ -121,7 +122,7 @@ export interface AdaptedEvent { pointerId: number; eventType: EventTypes; pointerType: PointerType; - buttons: number | null; + button: MouseButton | null; time: number; allTouches?: TouchList; changedTouches?: TouchList; @@ -129,9 +130,11 @@ export interface AdaptedEvent { } export enum MouseButton { - LEFT, - MIDDLE, - RIGHT, + LEFT = 1, + MIDDLE = 2, + RIGHT = 4, + BTN4 = 8, + BTN5 = 16, } export enum EventTypes { diff --git a/src/web/tools/PointerEventManager.ts b/src/web/tools/PointerEventManager.ts index 734848ef22..0c9fd9b6c5 100644 --- a/src/web/tools/PointerEventManager.ts +++ b/src/web/tools/PointerEventManager.ts @@ -1,9 +1,25 @@ -import { AdaptedEvent, EventTypes, PointerType } from '../interfaces'; +import { + AdaptedEvent, + EventTypes, + MouseButton, + PointerType, +} from '../interfaces'; import EventManager from './EventManager'; import { isPointerInBounds } from '../utils'; export default class PointerEventManager extends EventManager { private trackedPointers = new Set(); + private readonly mouseButtonsMapper = new Map(); + + constructor(view: HTMLElement) { + super(view); + + this.mouseButtonsMapper.set(0, MouseButton.LEFT); + this.mouseButtonsMapper.set(1, MouseButton.MIDDLE); + this.mouseButtonsMapper.set(2, MouseButton.RIGHT); + this.mouseButtonsMapper.set(3, MouseButton.BTN4); + this.mouseButtonsMapper.set(4, MouseButton.BTN5); + } public setListeners(): void { this.view.addEventListener('pointerdown', (event: PointerEvent): void => { @@ -181,7 +197,7 @@ export default class PointerEventManager extends EventManager { pointerId: event.pointerId, eventType: eventType, pointerType: event.pointerType as PointerType, - buttons: event.buttons, + button: this.mouseButtonsMapper.get(event.button)!, time: event.timeStamp, }; } From 6e1c651539866cf9e27ca71c59ea25ac77ffb357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Fri, 17 Nov 2023 12:37:30 +0100 Subject: [PATCH 05/35] Fix field in TouchEventManager --- src/web/tools/TouchEventManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/tools/TouchEventManager.ts b/src/web/tools/TouchEventManager.ts index 9c2013bcb7..3b2a5ad1be 100644 --- a/src/web/tools/TouchEventManager.ts +++ b/src/web/tools/TouchEventManager.ts @@ -156,7 +156,7 @@ export default class TouchEventManager extends EventManager { pointerId: event.changedTouches[index].identifier, eventType: eventType, pointerType: PointerType.TOUCH, - buttons: null, + button: null, time: event.timeStamp, allTouches: event.touches, changedTouches: event.changedTouches, From 97317770d78d040ad701f6cb91fa6bdca0ac80a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Fri, 17 Nov 2023 12:38:22 +0100 Subject: [PATCH 06/35] Implement logic on tap --- src/web/handlers/GestureHandler.ts | 9 +++++++++ src/web/handlers/TapGestureHandler.ts | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index ac6a0e1813..ab8e0c37f7 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -10,6 +10,7 @@ import { PointerType, TouchEventType, EventTypes, + MouseButton, } from '../interfaces'; import EventManager from '../tools/EventManager'; import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator'; @@ -736,6 +737,14 @@ export default abstract class GestureHandler { return false; } + protected wasPressedButtonCorrect(mouseButton: MouseButton | null) { + return ( + typeof mouseButton !== 'number' || + (!this.config.mouseButton && mouseButton === MouseButton.LEFT) || + (this.config.mouseButton && mouseButton & this.config.mouseButton) + ); + } + protected resetConfig(): void {} // diff --git a/src/web/handlers/TapGestureHandler.ts b/src/web/handlers/TapGestureHandler.ts index 92920e0d33..5ded4bb987 100644 --- a/src/web/handlers/TapGestureHandler.ts +++ b/src/web/handlers/TapGestureHandler.ts @@ -105,6 +105,10 @@ export default class TapGestureHandler extends GestureHandler { //Handling Events protected onPointerDown(event: AdaptedEvent): void { + if (!this.wasPressedButtonCorrect(event.button)) { + return; + } + this.tracker.addToTracker(event); super.onPointerDown(event); From edd5c2cb20ad69d4377682f1520ee88864a5701b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Fri, 17 Nov 2023 12:40:21 +0100 Subject: [PATCH 07/35] Add example --- example/src/App.tsx | 2 + .../src/release_tests/mouseButtons/index.tsx | 87 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 example/src/release_tests/mouseButtons/index.tsx diff --git a/example/src/App.tsx b/example/src/App.tsx index 67a0c3a718..63be255707 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -16,6 +16,7 @@ import { ComboWithGHScroll } from './release_tests/combo'; import { TouchablesIndex, TouchableExample } from './release_tests/touchables'; import Rows from './release_tests/rows'; import Fling from './release_tests/fling'; +import Buttons from './release_tests/mouseButtons'; import NestedTouchables from './release_tests/nestedTouchables'; import NestedButtons from './release_tests/nestedButtons'; import NestedGestureHandlerRootViewWithModal from './release_tests/nestedGHRootViewWithModal'; @@ -115,6 +116,7 @@ const EXAMPLES: ExamplesSection[] = [ { name: 'Fling', component: Fling }, { name: 'Combo', component: ComboWithGHScroll }, { name: 'Touchables', component: TouchablesIndex as React.ComponentType }, + { name: 'MouseButtons', component: Buttons }, ], }, { diff --git a/example/src/release_tests/mouseButtons/index.tsx b/example/src/release_tests/mouseButtons/index.tsx new file mode 100644 index 0000000000..e358eabfca --- /dev/null +++ b/example/src/release_tests/mouseButtons/index.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { + Gesture, + GestureDetector, + MouseButton, +} from 'react-native-gesture-handler'; +import { StyleSheet, View } from 'react-native'; + +export default function Buttons() { + const leftTap = Gesture.Tap() + .mouseButton(MouseButton.LEFT) + .onEnd(() => console.log('LEFT')); + + const rightTap = Gesture.Tap() + .mouseButton(MouseButton.RIGHT) + .onEnd(() => console.log('RIGHT')); + + const middleTap = Gesture.Tap() + .mouseButton(MouseButton.MIDDLE) + .onEnd(() => console.log('MIDDLE')); + + const leftRightTap = Gesture.Tap() + .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) + .onEnd(() => console.log('LEFT | RIGHT')); + + const allTap = Gesture.Tap() + .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) + .onEnd(() => console.log('LEFT | MIDDLE | RIGHT')); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +const styles = StyleSheet.create({ + center: { + alignItems: 'center', + justifyContent: 'space-around', + }, + boxLeft: { + width: 100, + height: 100, + backgroundColor: 'darkmagenta', + }, + boxRight: { + width: 100, + height: 100, + backgroundColor: 'darkblue', + }, + boxMiddle: { + width: 100, + height: 100, + backgroundColor: 'darkgreen', + }, + boxLeftRight: { + width: 100, + height: 100, + backgroundColor: 'crimson', + }, + boxAll: { + width: 100, + height: 100, + backgroundColor: 'plum', + }, +}); From eeb5adadcdd17cc6e2b4814ea72d93abc006e0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 20 Nov 2023 08:41:41 +0100 Subject: [PATCH 08/35] Change type --- src/handlers/gestureHandlerCommon.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/handlers/gestureHandlerCommon.ts b/src/handlers/gestureHandlerCommon.ts index c1b4ed9236..b9a34309e2 100644 --- a/src/handlers/gestureHandlerCommon.ts +++ b/src/handlers/gestureHandlerCommon.ts @@ -12,6 +12,7 @@ import { handlerIDToTag } from './handlersRegistry'; import { toArray } from '../utils'; import RNGestureHandlerModule from '../RNGestureHandlerModule'; import { ghQueueMicrotask } from '../ghQueueMicrotask'; +import { MouseButton } from '../web/interfaces'; const commonProps = [ 'id', @@ -146,7 +147,7 @@ export type CommonGestureConfig = { hitSlop?: HitSlop; userSelect?: UserSelect; activeCursor?: ActiveCursor; - mouseButton?: number; + mouseButton?: MouseButton; }; // Events payloads are types instead of interfaces due to TS limitation. From f4147605f1cd1fe99a99e1f68d5cd15d5568e698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 20 Nov 2023 08:43:24 +0100 Subject: [PATCH 09/35] Another type change --- src/handlers/gestures/gesture.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/handlers/gestures/gesture.ts b/src/handlers/gestures/gesture.ts index f5b59e8a0b..17c3b88c68 100644 --- a/src/handlers/gestures/gesture.ts +++ b/src/handlers/gestures/gesture.ts @@ -17,6 +17,7 @@ import { RotationGestureHandlerEventPayload } from '../RotationGestureHandler'; import { TapGestureHandlerEventPayload } from '../TapGestureHandler'; import { NativeViewGestureHandlerPayload } from '../NativeViewGestureHandler'; import { isRemoteDebuggingEnabled } from '../../utils'; +import { MouseButton } from '../../web/interfaces'; export type GestureType = | BaseGesture> @@ -256,7 +257,7 @@ export abstract class BaseGesture< return this; } - mouseButton(mouseButton: number) { + mouseButton(mouseButton: MouseButton) { this.config.mouseButton = mouseButton; return this; } From fd7e0bb80d16c1a2e3e5deef7907d736cc914113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 20 Nov 2023 08:50:04 +0100 Subject: [PATCH 10/35] Yet another type change --- src/web/handlers/GestureHandler.ts | 2 +- src/web/interfaces.ts | 2 +- src/web/tools/PointerEventManager.ts | 2 +- src/web/tools/TouchEventManager.ts | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index ab8e0c37f7..6d049d637c 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -737,7 +737,7 @@ export default abstract class GestureHandler { return false; } - protected wasPressedButtonCorrect(mouseButton: MouseButton | null) { + protected wasPressedButtonCorrect(mouseButton: MouseButton | undefined) { return ( typeof mouseButton !== 'number' || (!this.config.mouseButton && mouseButton === MouseButton.LEFT) || diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index 055a4a534a..9920a6fbad 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -122,8 +122,8 @@ export interface AdaptedEvent { pointerId: number; eventType: EventTypes; pointerType: PointerType; - button: MouseButton | null; time: number; + button?: MouseButton; allTouches?: TouchList; changedTouches?: TouchList; touchEventType?: TouchEventType; diff --git a/src/web/tools/PointerEventManager.ts b/src/web/tools/PointerEventManager.ts index ef47fb1c27..769ab55d83 100644 --- a/src/web/tools/PointerEventManager.ts +++ b/src/web/tools/PointerEventManager.ts @@ -206,7 +206,7 @@ export default class PointerEventManager extends EventManager { pointerId: event.pointerId, eventType: eventType, pointerType: event.pointerType as PointerType, - button: this.mouseButtonsMapper.get(event.button)!, + button: this.mouseButtonsMapper.get(event.button), time: event.timeStamp, }; } diff --git a/src/web/tools/TouchEventManager.ts b/src/web/tools/TouchEventManager.ts index 3b2a5ad1be..d73c11dc3c 100644 --- a/src/web/tools/TouchEventManager.ts +++ b/src/web/tools/TouchEventManager.ts @@ -156,7 +156,6 @@ export default class TouchEventManager extends EventManager { pointerId: event.changedTouches[index].identifier, eventType: eventType, pointerType: PointerType.TOUCH, - button: null, time: event.timeStamp, allTouches: event.touches, changedTouches: event.changedTouches, From 5373c13c07f93169419166ab35d06d624ee76123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 20 Nov 2023 08:52:13 +0100 Subject: [PATCH 11/35] change condition --- src/web/handlers/GestureHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index 6d049d637c..c7b5bfd4a5 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -739,7 +739,7 @@ export default abstract class GestureHandler { protected wasPressedButtonCorrect(mouseButton: MouseButton | undefined) { return ( - typeof mouseButton !== 'number' || + !mouseButton || (!this.config.mouseButton && mouseButton === MouseButton.LEFT) || (this.config.mouseButton && mouseButton & this.config.mouseButton) ); From 0e2aaf830caa462fc4d1ef41cdfcabb94440493e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 20 Nov 2023 08:58:55 +0100 Subject: [PATCH 12/35] Add check to other gestures --- src/web/handlers/FlingGestureHandler.ts | 4 ++++ src/web/handlers/LongPressGestureHandler.ts | 9 ++++----- src/web/handlers/PanGestureHandler.ts | 4 ++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/web/handlers/FlingGestureHandler.ts b/src/web/handlers/FlingGestureHandler.ts index 0c2a117b2d..24114c0a57 100644 --- a/src/web/handlers/FlingGestureHandler.ts +++ b/src/web/handlers/FlingGestureHandler.ts @@ -83,6 +83,10 @@ export default class FlingGestureHandler extends GestureHandler { } protected onPointerDown(event: AdaptedEvent): void { + if (!this.wasPressedButtonCorrect(event.button)) { + return; + } + this.tracker.addToTracker(event); this.keyPointer = event.pointerId; diff --git a/src/web/handlers/LongPressGestureHandler.ts b/src/web/handlers/LongPressGestureHandler.ts index d21815f314..bad9d2b82b 100644 --- a/src/web/handlers/LongPressGestureHandler.ts +++ b/src/web/handlers/LongPressGestureHandler.ts @@ -1,4 +1,3 @@ -import { Platform } from 'react-native'; import { State } from '../../State'; import { AdaptedEvent, Config } from '../interfaces'; @@ -23,10 +22,6 @@ export default class LongPressGestureHandler extends GestureHandler { public init(ref: number, propsRef: React.RefObject) { super.init(ref, propsRef); - - if (Platform.OS === 'web') { - (this.delegate.getView() as HTMLElement).oncontextmenu = () => false; - } } protected transformNativeEvent() { @@ -59,6 +54,10 @@ export default class LongPressGestureHandler extends GestureHandler { } protected onPointerDown(event: AdaptedEvent): void { + if (!this.wasPressedButtonCorrect(event.button)) { + return; + } + this.tracker.addToTracker(event); super.onPointerDown(event); this.tryBegin(event); diff --git a/src/web/handlers/PanGestureHandler.ts b/src/web/handlers/PanGestureHandler.ts index a6a180490e..3afdd89b1d 100644 --- a/src/web/handlers/PanGestureHandler.ts +++ b/src/web/handlers/PanGestureHandler.ts @@ -211,6 +211,10 @@ export default class PanGestureHandler extends GestureHandler { //EventsHandling protected onPointerDown(event: AdaptedEvent): void { + if (!this.wasPressedButtonCorrect(event.button)) { + return; + } + this.tracker.addToTracker(event); super.onPointerDown(event); From ecfcee205d20ad24debcedae221dc454fcb5d3df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 20 Nov 2023 09:59:58 +0100 Subject: [PATCH 13/35] Update example --- .../src/release_tests/mouseButtons/index.tsx | 176 +++++++++++++++--- src/web/handlers/FlingGestureHandler.ts | 4 +- 2 files changed, 150 insertions(+), 30 deletions(-) diff --git a/example/src/release_tests/mouseButtons/index.tsx b/example/src/release_tests/mouseButtons/index.tsx index e358eabfca..e74a3dd3d1 100644 --- a/example/src/release_tests/mouseButtons/index.tsx +++ b/example/src/release_tests/mouseButtons/index.tsx @@ -2,54 +2,172 @@ import React from 'react'; import { Gesture, GestureDetector, + GestureType, MouseButton, + Directions, } from 'react-native-gesture-handler'; -import { StyleSheet, View } from 'react-native'; +import { StyleSheet, View, Text } from 'react-native'; -export default function Buttons() { +type TestProps = { + name: string; + gestureHandlers: GestureType[]; +}; + +function Test({ name, gestureHandlers }: TestProps) { + return ( + + {name} + + + + + + + + + + + + + + + + + + + + + ); +} + +function TapTests() { const leftTap = Gesture.Tap() .mouseButton(MouseButton.LEFT) - .onEnd(() => console.log('LEFT')); + .onEnd(() => console.log('Tap with left')); const rightTap = Gesture.Tap() .mouseButton(MouseButton.RIGHT) - .onEnd(() => console.log('RIGHT')); + .onEnd(() => console.log('Tap with right')); const middleTap = Gesture.Tap() .mouseButton(MouseButton.MIDDLE) - .onEnd(() => console.log('MIDDLE')); + .onEnd(() => console.log('Tap with middle')); const leftRightTap = Gesture.Tap() .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) - .onEnd(() => console.log('LEFT | RIGHT')); + .onEnd(() => console.log('Tap with left | right')); const allTap = Gesture.Tap() .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) - .onEnd(() => console.log('LEFT | MIDDLE | RIGHT')); + .onEnd(() => console.log('Tap with left | middle | right')); + + const gestureHandlers = [leftTap, middleTap, rightTap, leftRightTap, allTap]; + + return ; +} + +function PanTests() { + const leftPan = Gesture.Pan() + .mouseButton(MouseButton.LEFT) + .onChange(() => console.log('Panning with left')); + + const rightPan = Gesture.Pan() + .mouseButton(MouseButton.RIGHT) + .onChange(() => console.log('Panning with right')); + + const middlePan = Gesture.Pan() + .mouseButton(MouseButton.MIDDLE) + .onChange(() => console.log('Panning with middle')); + + const leftRightPan = Gesture.Pan() + .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) + .onChange(() => console.log('Panning with left | right')); + + const allPan = Gesture.Pan() + .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) + .onChange(() => console.log('Panning with left | middle | right')); + + const gestureHandlers = [leftPan, middlePan, rightPan, leftRightPan, allPan]; + + return ; +} + +function LongPressTests() { + const leftLongPress = Gesture.LongPress() + .mouseButton(MouseButton.LEFT) + .onStart(() => console.log('LongPress with left')); + const rightLongPress = Gesture.LongPress() + .mouseButton(MouseButton.RIGHT) + .onStart(() => console.log('LongPress with right')); + + const middleLongPress = Gesture.LongPress() + .mouseButton(MouseButton.MIDDLE) + .onStart(() => console.log('LongPress with middle')); + + const leftRightLongPress = Gesture.LongPress() + .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) + .onStart(() => console.log('LongPress with left | right')); + + const allLongPress = Gesture.LongPress() + .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) + .onStart(() => console.log('LongPress with left | middle | right')); + + const gestureHandlers = [ + leftLongPress, + middleLongPress, + rightLongPress, + leftRightLongPress, + allLongPress, + ]; + + return ; +} + +function FlingTests() { + const leftFling = Gesture.Fling() + .direction(Directions.LEFT | Directions.RIGHT) + .mouseButton(MouseButton.LEFT) + .onStart(() => console.log('Fling with left')); + + const rightFling = Gesture.Fling() + .direction(Directions.LEFT | Directions.RIGHT) + .mouseButton(MouseButton.RIGHT) + .onStart(() => console.log('Fling with right')); + + const middleFling = Gesture.Fling() + .direction(Directions.LEFT | Directions.RIGHT) + .mouseButton(MouseButton.MIDDLE) + .onStart(() => console.log('Fling with middle')); + + const leftRightFling = Gesture.Fling() + .direction(Directions.LEFT | Directions.RIGHT) + .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) + .onStart(() => console.log('Fling with left | right')); + + const allFling = Gesture.Fling() + .direction(Directions.LEFT | Directions.RIGHT) + .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) + .onStart(() => console.log('Fling with left | middle | right')); + + const gestureHandlers = [ + leftFling, + middleFling, + rightFling, + leftRightFling, + allFling, + ]; + + return ; +} + +export default function Buttons() { return ( - - - - - - - - - - - - - - - - - - - - - - + + + + + ); } diff --git a/src/web/handlers/FlingGestureHandler.ts b/src/web/handlers/FlingGestureHandler.ts index 24114c0a57..f8aab9892a 100644 --- a/src/web/handlers/FlingGestureHandler.ts +++ b/src/web/handlers/FlingGestureHandler.ts @@ -5,7 +5,7 @@ import { AdaptedEvent, Config } from '../interfaces'; import GestureHandler from './GestureHandler'; const DEFAULT_MAX_DURATION_MS = 800; -const DEFAULT_MIN_ACCEPTABLE_DELTA = 160; +const DEFAULT_MIN_ACCEPTABLE_DELTA = 35; const DEFAULT_DIRECTION = Direction.RIGHT; const DEFAULT_NUMBER_OF_TOUCHES_REQUIRED = 1; @@ -51,6 +51,8 @@ export default class FlingGestureHandler extends GestureHandler { } private tryEndFling(): boolean { + console.log(this.tracker.getLastAvgX(), this.startX); + if ( this.maxNumberOfPointersSimultaneously === this.numberOfPointersRequired && From 6284ab33641165ffaa47617aa514b3341499cd5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 20 Nov 2023 16:27:45 +0100 Subject: [PATCH 14/35] Change View to ScrollView --- example/src/release_tests/mouseButtons/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/example/src/release_tests/mouseButtons/index.tsx b/example/src/release_tests/mouseButtons/index.tsx index e74a3dd3d1..f1578e6fe6 100644 --- a/example/src/release_tests/mouseButtons/index.tsx +++ b/example/src/release_tests/mouseButtons/index.tsx @@ -5,6 +5,7 @@ import { GestureType, MouseButton, Directions, + ScrollView, } from 'react-native-gesture-handler'; import { StyleSheet, View, Text } from 'react-native'; @@ -163,12 +164,12 @@ function FlingTests() { export default function Buttons() { return ( - + - + ); } From 64ff5d4c385a0a2987bd8ce931fbf340803c32ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 21 Nov 2023 08:22:02 +0100 Subject: [PATCH 15/35] remove console.log --- src/web/handlers/FlingGestureHandler.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/web/handlers/FlingGestureHandler.ts b/src/web/handlers/FlingGestureHandler.ts index f8aab9892a..da09747457 100644 --- a/src/web/handlers/FlingGestureHandler.ts +++ b/src/web/handlers/FlingGestureHandler.ts @@ -51,8 +51,6 @@ export default class FlingGestureHandler extends GestureHandler { } private tryEndFling(): boolean { - console.log(this.tracker.getLastAvgX(), this.startX); - if ( this.maxNumberOfPointersSimultaneously === this.numberOfPointersRequired && From 193e24009e37266cd1a9ec800c3525a91627c889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 21 Nov 2023 08:48:30 +0100 Subject: [PATCH 16/35] Change button names --- src/web/interfaces.ts | 4 ++-- src/web/tools/PointerEventManager.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index 9920a6fbad..05012264e0 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -133,8 +133,8 @@ export enum MouseButton { LEFT = 1, MIDDLE = 2, RIGHT = 4, - BTN4 = 8, - BTN5 = 16, + BUTTON_4 = 8, + BUTTON_5 = 16, } export enum EventTypes { diff --git a/src/web/tools/PointerEventManager.ts b/src/web/tools/PointerEventManager.ts index 769ab55d83..fafb6a47d0 100644 --- a/src/web/tools/PointerEventManager.ts +++ b/src/web/tools/PointerEventManager.ts @@ -17,8 +17,8 @@ export default class PointerEventManager extends EventManager { this.mouseButtonsMapper.set(0, MouseButton.LEFT); this.mouseButtonsMapper.set(1, MouseButton.MIDDLE); this.mouseButtonsMapper.set(2, MouseButton.RIGHT); - this.mouseButtonsMapper.set(3, MouseButton.BTN4); - this.mouseButtonsMapper.set(4, MouseButton.BTN5); + this.mouseButtonsMapper.set(3, MouseButton.BUTTON_4); + this.mouseButtonsMapper.set(4, MouseButton.BUTTON_5); } public setListeners(): void { From 0cbaebd85a445c9469aa45a6f9994c2d30d06578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 21 Nov 2023 08:57:22 +0100 Subject: [PATCH 17/35] Change MouseButtons name in App --- example/src/App.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/src/App.tsx b/example/src/App.tsx index 63be255707..30b0715c88 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -16,7 +16,7 @@ import { ComboWithGHScroll } from './release_tests/combo'; import { TouchablesIndex, TouchableExample } from './release_tests/touchables'; import Rows from './release_tests/rows'; import Fling from './release_tests/fling'; -import Buttons from './release_tests/mouseButtons'; +import MouseButtons from './release_tests/mouseButtons'; import NestedTouchables from './release_tests/nestedTouchables'; import NestedButtons from './release_tests/nestedButtons'; import NestedGestureHandlerRootViewWithModal from './release_tests/nestedGHRootViewWithModal'; @@ -116,7 +116,7 @@ const EXAMPLES: ExamplesSection[] = [ { name: 'Fling', component: Fling }, { name: 'Combo', component: ComboWithGHScroll }, { name: 'Touchables', component: TouchablesIndex as React.ComponentType }, - { name: 'MouseButtons', component: Buttons }, + { name: 'MouseButtons', component: MouseButtons }, ], }, { From f77f4532e41fc25ac9f03b7bf98f8ddbba33bbda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 21 Nov 2023 09:04:37 +0100 Subject: [PATCH 18/35] Add MouseButton.ALL --- example/src/release_tests/mouseButtons/index.tsx | 16 ++++++++-------- src/web/interfaces.ts | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/example/src/release_tests/mouseButtons/index.tsx b/example/src/release_tests/mouseButtons/index.tsx index f1578e6fe6..6a90543611 100644 --- a/example/src/release_tests/mouseButtons/index.tsx +++ b/example/src/release_tests/mouseButtons/index.tsx @@ -59,8 +59,8 @@ function TapTests() { .onEnd(() => console.log('Tap with left | right')); const allTap = Gesture.Tap() - .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) - .onEnd(() => console.log('Tap with left | middle | right')); + .mouseButton(MouseButton.ALL) + .onEnd(() => console.log('Tap with any button')); const gestureHandlers = [leftTap, middleTap, rightTap, leftRightTap, allTap]; @@ -85,8 +85,8 @@ function PanTests() { .onChange(() => console.log('Panning with left | right')); const allPan = Gesture.Pan() - .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) - .onChange(() => console.log('Panning with left | middle | right')); + .mouseButton(MouseButton.ALL) + .onChange(() => console.log('Panning with any button')); const gestureHandlers = [leftPan, middlePan, rightPan, leftRightPan, allPan]; @@ -111,8 +111,8 @@ function LongPressTests() { .onStart(() => console.log('LongPress with left | right')); const allLongPress = Gesture.LongPress() - .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) - .onStart(() => console.log('LongPress with left | middle | right')); + .mouseButton(MouseButton.ALL) + .onStart(() => console.log('LongPress with any button')); const gestureHandlers = [ leftLongPress, @@ -148,8 +148,8 @@ function FlingTests() { const allFling = Gesture.Fling() .direction(Directions.LEFT | Directions.RIGHT) - .mouseButton(MouseButton.LEFT | MouseButton.MIDDLE | MouseButton.RIGHT) - .onStart(() => console.log('Fling with left | middle | right')); + .mouseButton(MouseButton.ALL) + .onStart(() => console.log('Fling with any button')); const gestureHandlers = [ leftFling, diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index 05012264e0..eceac2f51b 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -135,6 +135,7 @@ export enum MouseButton { RIGHT = 4, BUTTON_4 = 8, BUTTON_5 = 16, + ALL = 31, } export enum EventTypes { From 09e11fdf9a0e9ea06446a026ed4a5bf68058b745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 21 Nov 2023 09:58:10 +0100 Subject: [PATCH 19/35] Rename function --- src/web/handlers/FlingGestureHandler.ts | 2 +- src/web/handlers/GestureHandler.ts | 2 +- src/web/handlers/LongPressGestureHandler.ts | 2 +- src/web/handlers/PanGestureHandler.ts | 2 +- src/web/handlers/TapGestureHandler.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/web/handlers/FlingGestureHandler.ts b/src/web/handlers/FlingGestureHandler.ts index da09747457..2776c18496 100644 --- a/src/web/handlers/FlingGestureHandler.ts +++ b/src/web/handlers/FlingGestureHandler.ts @@ -83,7 +83,7 @@ export default class FlingGestureHandler extends GestureHandler { } protected onPointerDown(event: AdaptedEvent): void { - if (!this.wasPressedButtonCorrect(event.button)) { + if (!this.isButtonInConfig(event.button)) { return; } diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index c7b5bfd4a5..726e0427f4 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -737,7 +737,7 @@ export default abstract class GestureHandler { return false; } - protected wasPressedButtonCorrect(mouseButton: MouseButton | undefined) { + protected isButtonInConfig(mouseButton: MouseButton | undefined) { return ( !mouseButton || (!this.config.mouseButton && mouseButton === MouseButton.LEFT) || diff --git a/src/web/handlers/LongPressGestureHandler.ts b/src/web/handlers/LongPressGestureHandler.ts index bad9d2b82b..86a74d8614 100644 --- a/src/web/handlers/LongPressGestureHandler.ts +++ b/src/web/handlers/LongPressGestureHandler.ts @@ -54,7 +54,7 @@ export default class LongPressGestureHandler extends GestureHandler { } protected onPointerDown(event: AdaptedEvent): void { - if (!this.wasPressedButtonCorrect(event.button)) { + if (!this.isButtonInConfig(event.button)) { return; } diff --git a/src/web/handlers/PanGestureHandler.ts b/src/web/handlers/PanGestureHandler.ts index 3afdd89b1d..43347401ec 100644 --- a/src/web/handlers/PanGestureHandler.ts +++ b/src/web/handlers/PanGestureHandler.ts @@ -211,7 +211,7 @@ export default class PanGestureHandler extends GestureHandler { //EventsHandling protected onPointerDown(event: AdaptedEvent): void { - if (!this.wasPressedButtonCorrect(event.button)) { + if (!this.isButtonInConfig(event.button)) { return; } diff --git a/src/web/handlers/TapGestureHandler.ts b/src/web/handlers/TapGestureHandler.ts index 5ded4bb987..7aa52c3ba2 100644 --- a/src/web/handlers/TapGestureHandler.ts +++ b/src/web/handlers/TapGestureHandler.ts @@ -105,7 +105,7 @@ export default class TapGestureHandler extends GestureHandler { //Handling Events protected onPointerDown(event: AdaptedEvent): void { - if (!this.wasPressedButtonCorrect(event.button)) { + if (!this.isButtonInConfig(event.button)) { return; } From fbe82e283271c60475bec51fa5421331b8ecf9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 18 Dec 2023 16:19:33 +0100 Subject: [PATCH 20/35] Add enableContextMenu to builder --- .../src/release_tests/mouseButtons/index.tsx | 34 +++++++++---------- src/handlers/FlingGestureHandler.ts | 8 ++++- src/handlers/LongPressGestureHandler.ts | 8 ++++- src/handlers/PanGestureHandler.ts | 6 ++++ src/handlers/TapGestureHandler.ts | 8 ++++- src/handlers/gestures/flingGesture.ts | 5 +++ src/handlers/gestures/longPressGesture.ts | 5 +++ src/handlers/gestures/panGesture.ts | 5 +++ src/handlers/gestures/tapGesture.ts | 5 +++ src/web/handlers/GestureHandler.ts | 2 +- src/web/interfaces.ts | 1 + src/web/tools/GestureHandlerWebDelegate.ts | 12 +++++-- 12 files changed, 76 insertions(+), 23 deletions(-) diff --git a/example/src/release_tests/mouseButtons/index.tsx b/example/src/release_tests/mouseButtons/index.tsx index 6a90543611..65487224cf 100644 --- a/example/src/release_tests/mouseButtons/index.tsx +++ b/example/src/release_tests/mouseButtons/index.tsx @@ -46,14 +46,14 @@ function TapTests() { .mouseButton(MouseButton.LEFT) .onEnd(() => console.log('Tap with left')); - const rightTap = Gesture.Tap() - .mouseButton(MouseButton.RIGHT) - .onEnd(() => console.log('Tap with right')); - const middleTap = Gesture.Tap() .mouseButton(MouseButton.MIDDLE) .onEnd(() => console.log('Tap with middle')); + const rightTap = Gesture.Tap() + .mouseButton(MouseButton.RIGHT) + .onEnd(() => console.log('Tap with right')); + const leftRightTap = Gesture.Tap() .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) .onEnd(() => console.log('Tap with left | right')); @@ -72,14 +72,14 @@ function PanTests() { .mouseButton(MouseButton.LEFT) .onChange(() => console.log('Panning with left')); - const rightPan = Gesture.Pan() - .mouseButton(MouseButton.RIGHT) - .onChange(() => console.log('Panning with right')); - const middlePan = Gesture.Pan() .mouseButton(MouseButton.MIDDLE) .onChange(() => console.log('Panning with middle')); + const rightPan = Gesture.Pan() + .mouseButton(MouseButton.RIGHT) + .onChange(() => console.log('Panning with right')); + const leftRightPan = Gesture.Pan() .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) .onChange(() => console.log('Panning with left | right')); @@ -98,14 +98,14 @@ function LongPressTests() { .mouseButton(MouseButton.LEFT) .onStart(() => console.log('LongPress with left')); - const rightLongPress = Gesture.LongPress() - .mouseButton(MouseButton.RIGHT) - .onStart(() => console.log('LongPress with right')); - const middleLongPress = Gesture.LongPress() .mouseButton(MouseButton.MIDDLE) .onStart(() => console.log('LongPress with middle')); + const rightLongPress = Gesture.LongPress() + .mouseButton(MouseButton.RIGHT) + .onStart(() => console.log('LongPress with right')); + const leftRightLongPress = Gesture.LongPress() .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) .onStart(() => console.log('LongPress with left | right')); @@ -131,16 +131,16 @@ function FlingTests() { .mouseButton(MouseButton.LEFT) .onStart(() => console.log('Fling with left')); - const rightFling = Gesture.Fling() - .direction(Directions.LEFT | Directions.RIGHT) - .mouseButton(MouseButton.RIGHT) - .onStart(() => console.log('Fling with right')); - const middleFling = Gesture.Fling() .direction(Directions.LEFT | Directions.RIGHT) .mouseButton(MouseButton.MIDDLE) .onStart(() => console.log('Fling with middle')); + const rightFling = Gesture.Fling() + .direction(Directions.LEFT | Directions.RIGHT) + .mouseButton(MouseButton.RIGHT) + .onStart(() => console.log('Fling with right')); + const leftRightFling = Gesture.Fling() .direction(Directions.LEFT | Directions.RIGHT) .mouseButton(MouseButton.LEFT | MouseButton.RIGHT) diff --git a/src/handlers/FlingGestureHandler.ts b/src/handlers/FlingGestureHandler.ts index 88e0d5521b..8fb9c20c06 100644 --- a/src/handlers/FlingGestureHandler.ts +++ b/src/handlers/FlingGestureHandler.ts @@ -7,6 +7,7 @@ import { export const flingGestureHandlerProps = [ 'numberOfPointers', 'direction', + 'enableContextMenu', ] as const; export type FlingGestureHandlerEventPayload = { @@ -40,7 +41,12 @@ export interface FlingGestureConfig { export interface FlingGestureHandlerProps extends BaseGestureHandlerProps, - FlingGestureConfig {} + FlingGestureConfig { + /** + * Specifies whether context menu should be enabled when you click on handler with right mouse button. + */ + enableContextMenu?: boolean; +} export const flingHandlerName = 'FlingGestureHandler'; diff --git a/src/handlers/LongPressGestureHandler.ts b/src/handlers/LongPressGestureHandler.ts index 1cfaa7f874..0b007bdeea 100644 --- a/src/handlers/LongPressGestureHandler.ts +++ b/src/handlers/LongPressGestureHandler.ts @@ -7,6 +7,7 @@ import { export const longPressGestureHandlerProps = [ 'minDurationMs', 'maxDist', + 'enableContextMenu', ] as const; export type LongPressGestureHandlerEventPayload = { @@ -67,7 +68,12 @@ export interface LongPressGestureConfig { export interface LongPressGestureHandlerProps extends BaseGestureHandlerProps, - LongPressGestureConfig {} + LongPressGestureConfig { + /** + * Specifies whether context menu should be enabled when you click on handler with right mouse button. + */ + enableContextMenu?: boolean; +} export const longPressHandlerName = 'LongPressGestureHandler'; diff --git a/src/handlers/PanGestureHandler.ts b/src/handlers/PanGestureHandler.ts index c596535f0e..49e0498234 100644 --- a/src/handlers/PanGestureHandler.ts +++ b/src/handlers/PanGestureHandler.ts @@ -18,6 +18,7 @@ export const panGestureHandlerProps = [ 'avgTouches', 'enableTrackpadTwoFingerGesture', 'activateAfterLongPress', + 'enableContextMenu', ] as const; export const panGestureHandlerCustomNativeProps = [ @@ -181,6 +182,11 @@ export interface PanGestureHandlerProps * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. */ failOffsetX?: number | number[]; + + /** + * Specifies whether context menu should be enabled when you click on handler with right mouse button. + */ + enableContextMenu?: boolean; } export const panHandlerName = 'PanGestureHandler'; diff --git a/src/handlers/TapGestureHandler.ts b/src/handlers/TapGestureHandler.ts index 9ea3a98b9a..bc3234904c 100644 --- a/src/handlers/TapGestureHandler.ts +++ b/src/handlers/TapGestureHandler.ts @@ -12,6 +12,7 @@ export const tapGestureHandlerProps = [ 'maxDeltaY', 'maxDist', 'minPointers', + 'enableContextMenu', ] as const; export type TapGestureHandlerEventPayload = { @@ -73,7 +74,12 @@ export interface TapGestureConfig { export interface TapGestureHandlerProps extends BaseGestureHandlerProps, - TapGestureConfig {} + TapGestureConfig { + /** + * Specifies whether context menu should be enabled when you click on handler with right mouse button. + */ + enableContextMenu?: boolean; +} export const tapHandlerName = 'TapGestureHandler'; diff --git a/src/handlers/gestures/flingGesture.ts b/src/handlers/gestures/flingGesture.ts index 579e62b605..76297b1d1b 100644 --- a/src/handlers/gestures/flingGesture.ts +++ b/src/handlers/gestures/flingGesture.ts @@ -22,6 +22,11 @@ export class FlingGesture extends BaseGesture { this.config.direction = direction; return this; } + + enableContextMenu(value: boolean) { + this.config.enableContextMenu = value; + return this; + } } export type FlingGestureType = InstanceType; diff --git a/src/handlers/gestures/longPressGesture.ts b/src/handlers/gestures/longPressGesture.ts index 9ad2a94dda..9d126bc766 100644 --- a/src/handlers/gestures/longPressGesture.ts +++ b/src/handlers/gestures/longPressGesture.ts @@ -23,6 +23,11 @@ export class LongPressGesture extends BaseGesture; diff --git a/src/handlers/gestures/panGesture.ts b/src/handlers/gestures/panGesture.ts index 7b782943e8..5cabfdc2d7 100644 --- a/src/handlers/gestures/panGesture.ts +++ b/src/handlers/gestures/panGesture.ts @@ -136,6 +136,11 @@ export class PanGesture extends ContinousBaseGesture< return this; } + enableContextMenu(value: boolean) { + this.config.enableContextMenu = value; + return this; + } + onChange( callback: ( event: GestureUpdateEvent< diff --git a/src/handlers/gestures/tapGesture.ts b/src/handlers/gestures/tapGesture.ts index e09ab3f33b..9da4b683e6 100644 --- a/src/handlers/gestures/tapGesture.ts +++ b/src/handlers/gestures/tapGesture.ts @@ -48,6 +48,11 @@ export class TapGesture extends BaseGesture { this.config.maxDeltaY = delta; return this; } + + enableContextMenu(value: boolean) { + this.config.enableContextMenu = value; + return this; + } } export type TapGestureType = InstanceType; diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index 3367148fc5..ca56e91517 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -737,7 +737,7 @@ export default abstract class GestureHandler { return false; } - protected isButtonInConfig(mouseButton: MouseButton | undefined) { + public isButtonInConfig(mouseButton: MouseButton | undefined) { return ( !mouseButton || (!this.config.mouseButton && mouseButton === MouseButton.LEFT) || diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index 108fc762f7..155ee59a43 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -38,6 +38,7 @@ export interface Config extends Record { userSelect?: UserSelect; activeCursor?: ActiveCursor; mouseButton?: MouseButton; + enableContextMenu?: boolean; activateAfterLongPress?: number; failOffsetXStart?: number; diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index 8171c8ec4b..3317829583 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -9,6 +9,7 @@ import TouchEventManager from './TouchEventManager'; import { State } from '../../State'; import { isPointerInBounds } from '../utils'; import EventManager from './EventManager'; +import { MouseButton } from '../interfaces'; export class GestureHandlerWebDelegate implements GestureHandlerDelegate @@ -31,14 +32,21 @@ export class GestureHandlerWebDelegate this.gestureHandler = handler; this.view = findNodeHandle(viewRef) as unknown as HTMLElement; - this.view.oncontextmenu = () => false; - this.view.style['touchAction'] = 'none'; //@ts-ignore This one disables default events on Safari this.view.style['WebkitTouchCallout'] = 'none'; const config = handler.getConfig(); + if ( + !config.enableContextMenu && + handler.isButtonInConfig(MouseButton.RIGHT) + ) { + this.view.addEventListener('contextmenu', (e) => e.preventDefault()); + } else if (config.enableContextMenu) { + this.view.addEventListener('contextmenu', (e) => e.stopPropagation()); + } + if (!config.userSelect) { this.view.style['webkitUserSelect'] = 'none'; this.view.style['userSelect'] = 'none'; From 0a1a18d5083839a9b561f9ed72dd4fd4ab59f938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 19 Dec 2023 10:59:35 +0100 Subject: [PATCH 21/35] False now turns off context menu --- src/web/tools/GestureHandlerWebDelegate.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index 3317829583..bff5c04807 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -39,8 +39,9 @@ export class GestureHandlerWebDelegate const config = handler.getConfig(); if ( - !config.enableContextMenu && - handler.isButtonInConfig(MouseButton.RIGHT) + (config.enableContextMenu === undefined && + handler.isButtonInConfig(MouseButton.RIGHT)) || + config.enableContextMenu === false ) { this.view.addEventListener('contextmenu', (e) => e.preventDefault()); } else if (config.enableContextMenu) { From 1107e3853918db4eada102c69b4c6cf7bf6bf8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 19 Dec 2023 11:28:26 +0100 Subject: [PATCH 22/35] Move enableContextMenu to GestureDetector --- src/components/DrawerLayout.tsx | 16 ++++++++++++++++ src/handlers/FlingGestureHandler.ts | 8 +------- src/handlers/LongPressGestureHandler.ts | 8 +------- src/handlers/PanGestureHandler.ts | 6 ------ src/handlers/TapGestureHandler.ts | 8 +------- src/handlers/gestureHandlerCommon.ts | 4 ++++ src/handlers/gestures/GestureDetector.tsx | 17 ++++++++++++++++- src/handlers/gestures/flingGesture.ts | 5 ----- src/handlers/gestures/longPressGesture.ts | 5 ----- src/handlers/gestures/panGesture.ts | 5 ----- src/handlers/gestures/tapGesture.ts | 5 ----- 11 files changed, 39 insertions(+), 48 deletions(-) diff --git a/src/components/DrawerLayout.tsx b/src/components/DrawerLayout.tsx index 479b3618bb..2c35488a80 100644 --- a/src/components/DrawerLayout.tsx +++ b/src/components/DrawerLayout.tsx @@ -28,6 +28,7 @@ import { HandlerStateChangeEvent, UserSelect, ActiveCursor, + EnableContextMenu, } from '../handlers/gestureHandlerCommon'; import { PanGestureHandler, @@ -38,6 +39,7 @@ import { TapGestureHandlerEventPayload, } from '../handlers/TapGestureHandler'; import { State } from '../State'; +import { MouseButton } from '../web/interfaces'; const DRAG_TOSS = 0.05; @@ -173,6 +175,18 @@ export interface DrawerLayoutProps { * Values: see CSS cursor values */ activeCursor?: ActiveCursor; + + /** + * @default 'MouseButton.LEFT' + * Allows to choose which mouse button should underlying pan handler react to. + */ + mouseButton?: MouseButton; + + /** + * @default 'false if MouseButton.RIGHT is specified' + * Allows to enable/disable context menu. + */ + enableContextMenu?: EnableContextMenu; } export type DrawerLayoutState = { @@ -700,6 +714,8 @@ export default class DrawerLayout extends Component< // @ts-ignore could be fixed in handler types userSelect={this.props.userSelect} activeCursor={this.props.activeCursor} + mouseButton={this.props.mouseButton} + enableContextMenu={this.props.enableContextMenu} ref={this.setPanGestureRef} hitSlop={hitSlop} activeOffsetX={gestureOrientation * minSwipeDistance!} diff --git a/src/handlers/FlingGestureHandler.ts b/src/handlers/FlingGestureHandler.ts index 8fb9c20c06..88e0d5521b 100644 --- a/src/handlers/FlingGestureHandler.ts +++ b/src/handlers/FlingGestureHandler.ts @@ -7,7 +7,6 @@ import { export const flingGestureHandlerProps = [ 'numberOfPointers', 'direction', - 'enableContextMenu', ] as const; export type FlingGestureHandlerEventPayload = { @@ -41,12 +40,7 @@ export interface FlingGestureConfig { export interface FlingGestureHandlerProps extends BaseGestureHandlerProps, - FlingGestureConfig { - /** - * Specifies whether context menu should be enabled when you click on handler with right mouse button. - */ - enableContextMenu?: boolean; -} + FlingGestureConfig {} export const flingHandlerName = 'FlingGestureHandler'; diff --git a/src/handlers/LongPressGestureHandler.ts b/src/handlers/LongPressGestureHandler.ts index 0b007bdeea..1cfaa7f874 100644 --- a/src/handlers/LongPressGestureHandler.ts +++ b/src/handlers/LongPressGestureHandler.ts @@ -7,7 +7,6 @@ import { export const longPressGestureHandlerProps = [ 'minDurationMs', 'maxDist', - 'enableContextMenu', ] as const; export type LongPressGestureHandlerEventPayload = { @@ -68,12 +67,7 @@ export interface LongPressGestureConfig { export interface LongPressGestureHandlerProps extends BaseGestureHandlerProps, - LongPressGestureConfig { - /** - * Specifies whether context menu should be enabled when you click on handler with right mouse button. - */ - enableContextMenu?: boolean; -} + LongPressGestureConfig {} export const longPressHandlerName = 'LongPressGestureHandler'; diff --git a/src/handlers/PanGestureHandler.ts b/src/handlers/PanGestureHandler.ts index 49e0498234..c596535f0e 100644 --- a/src/handlers/PanGestureHandler.ts +++ b/src/handlers/PanGestureHandler.ts @@ -18,7 +18,6 @@ export const panGestureHandlerProps = [ 'avgTouches', 'enableTrackpadTwoFingerGesture', 'activateAfterLongPress', - 'enableContextMenu', ] as const; export const panGestureHandlerCustomNativeProps = [ @@ -182,11 +181,6 @@ export interface PanGestureHandlerProps * if `p` is higher or equal to 0 and `(-p, inf)` otherwise. */ failOffsetX?: number | number[]; - - /** - * Specifies whether context menu should be enabled when you click on handler with right mouse button. - */ - enableContextMenu?: boolean; } export const panHandlerName = 'PanGestureHandler'; diff --git a/src/handlers/TapGestureHandler.ts b/src/handlers/TapGestureHandler.ts index bc3234904c..9ea3a98b9a 100644 --- a/src/handlers/TapGestureHandler.ts +++ b/src/handlers/TapGestureHandler.ts @@ -12,7 +12,6 @@ export const tapGestureHandlerProps = [ 'maxDeltaY', 'maxDist', 'minPointers', - 'enableContextMenu', ] as const; export type TapGestureHandlerEventPayload = { @@ -74,12 +73,7 @@ export interface TapGestureConfig { export interface TapGestureHandlerProps extends BaseGestureHandlerProps, - TapGestureConfig { - /** - * Specifies whether context menu should be enabled when you click on handler with right mouse button. - */ - enableContextMenu?: boolean; -} + TapGestureConfig {} export const tapHandlerName = 'TapGestureHandler'; diff --git a/src/handlers/gestureHandlerCommon.ts b/src/handlers/gestureHandlerCommon.ts index 759b52a457..11bcf41599 100644 --- a/src/handlers/gestureHandlerCommon.ts +++ b/src/handlers/gestureHandlerCommon.ts @@ -23,6 +23,7 @@ const commonProps = [ 'userSelect', 'activeCursor', 'mouseButton', + 'enableContextMenu', ] as const; const componentInteractionProps = [ @@ -110,6 +111,8 @@ export type ActiveCursor = | 'zoom-in' | 'zoom-out'; +export type EnableContextMenu = boolean; + //TODO(TS) events in handlers export interface GestureEvent> { @@ -152,6 +155,7 @@ export type CommonGestureConfig = { userSelect?: UserSelect; activeCursor?: ActiveCursor; mouseButton?: MouseButton; + enableContextMenu?: EnableContextMenu; }; // Events payloads are types instead of interfaces due to TS limitation. diff --git a/src/handlers/gestures/GestureDetector.tsx b/src/handlers/gestures/GestureDetector.tsx index 71a21dece9..3cb0ba3962 100644 --- a/src/handlers/gestures/GestureDetector.tsx +++ b/src/handlers/gestures/GestureDetector.tsx @@ -19,6 +19,7 @@ import { HandlerStateChangeEvent, scheduleFlushOperations, UserSelect, + EnableContextMenu, } from '../gestureHandlerCommon'; import { GestureStateManager, @@ -605,10 +606,20 @@ const applyUserSelectProp = ( } }; +const applyEnableContextMenuProp = ( + enableContextMenu: EnableContextMenu, + gesture: ComposedGesture | GestureType +): void => { + for (const g of gesture.toGestureArray()) { + g.config.enableContextMenu = enableContextMenu; + } +}; + interface GestureDetectorProps { gesture: ComposedGesture | GestureType; - userSelect?: UserSelect; children?: React.ReactNode; + userSelect?: UserSelect; + enableContextMenu?: EnableContextMenu; } interface GestureDetectorState { firstRender: boolean; @@ -630,6 +641,10 @@ export const GestureDetector = (props: GestureDetectorProps) => { applyUserSelectProp(props.userSelect, gestureConfig); } + if (props.enableContextMenu !== undefined) { + applyEnableContextMenuProp(props.enableContextMenu, gestureConfig); + } + const gesture = gestureConfig.toGestureArray(); const useReanimatedHook = gesture.some((g) => g.shouldUseReanimated); diff --git a/src/handlers/gestures/flingGesture.ts b/src/handlers/gestures/flingGesture.ts index 76297b1d1b..579e62b605 100644 --- a/src/handlers/gestures/flingGesture.ts +++ b/src/handlers/gestures/flingGesture.ts @@ -22,11 +22,6 @@ export class FlingGesture extends BaseGesture { this.config.direction = direction; return this; } - - enableContextMenu(value: boolean) { - this.config.enableContextMenu = value; - return this; - } } export type FlingGestureType = InstanceType; diff --git a/src/handlers/gestures/longPressGesture.ts b/src/handlers/gestures/longPressGesture.ts index 9d126bc766..9ad2a94dda 100644 --- a/src/handlers/gestures/longPressGesture.ts +++ b/src/handlers/gestures/longPressGesture.ts @@ -23,11 +23,6 @@ export class LongPressGesture extends BaseGesture; diff --git a/src/handlers/gestures/panGesture.ts b/src/handlers/gestures/panGesture.ts index 5cabfdc2d7..7b782943e8 100644 --- a/src/handlers/gestures/panGesture.ts +++ b/src/handlers/gestures/panGesture.ts @@ -136,11 +136,6 @@ export class PanGesture extends ContinousBaseGesture< return this; } - enableContextMenu(value: boolean) { - this.config.enableContextMenu = value; - return this; - } - onChange( callback: ( event: GestureUpdateEvent< diff --git a/src/handlers/gestures/tapGesture.ts b/src/handlers/gestures/tapGesture.ts index 9da4b683e6..e09ab3f33b 100644 --- a/src/handlers/gestures/tapGesture.ts +++ b/src/handlers/gestures/tapGesture.ts @@ -48,11 +48,6 @@ export class TapGesture extends BaseGesture { this.config.maxDeltaY = delta; return this; } - - enableContextMenu(value: boolean) { - this.config.enableContextMenu = value; - return this; - } } export type TapGestureType = InstanceType; From 6bd1c79498ce836e688fce1a074dd5e3cb58d908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Wed, 20 Dec 2023 15:34:09 +0100 Subject: [PATCH 23/35] Add context menu example --- example/src/App.tsx | 2 + .../src/release_tests/contextMenu/index.tsx | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 example/src/release_tests/contextMenu/index.tsx diff --git a/example/src/App.tsx b/example/src/App.tsx index 30b0715c88..4dc7ea4fe9 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -17,6 +17,7 @@ import { TouchablesIndex, TouchableExample } from './release_tests/touchables'; import Rows from './release_tests/rows'; import Fling from './release_tests/fling'; import MouseButtons from './release_tests/mouseButtons'; +import ContextMenu from './release_tests/contextMenu'; import NestedTouchables from './release_tests/nestedTouchables'; import NestedButtons from './release_tests/nestedButtons'; import NestedGestureHandlerRootViewWithModal from './release_tests/nestedGHRootViewWithModal'; @@ -117,6 +118,7 @@ const EXAMPLES: ExamplesSection[] = [ { name: 'Combo', component: ComboWithGHScroll }, { name: 'Touchables', component: TouchablesIndex as React.ComponentType }, { name: 'MouseButtons', component: MouseButtons }, + { name: 'ContextMenu (web only)', component: ContextMenu }, ], }, { diff --git a/example/src/release_tests/contextMenu/index.tsx b/example/src/release_tests/contextMenu/index.tsx new file mode 100644 index 0000000000..67f9e89348 --- /dev/null +++ b/example/src/release_tests/contextMenu/index.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import { Gesture, GestureDetector } from 'react-native-gesture-handler'; + +export default function ContextMenuExample() { + const p1 = Gesture.Pan(); + const p2 = Gesture.Pan(); + const p3 = Gesture.Pan(); + + return ( + + + + + + + + + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'space-around', + alignItems: 'center', + }, + + grandParent: { + width: 300, + height: 300, + backgroundColor: 'lightblue', + }, + + parent: { + width: 200, + height: 200, + backgroundColor: 'lightgreen', + }, + + child: { + width: 100, + height: 100, + backgroundColor: 'crimson', + }, + + box: { + display: 'flex', + justifyContent: 'space-around', + alignItems: 'center', + }, +}); From 19aa15b3dfa1d52343da56a86e3fa19f254bdc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Wed, 20 Dec 2023 16:23:10 +0100 Subject: [PATCH 24/35] Remove listeners on handler drop --- src/web/handlers/GestureHandler.ts | 7 +++ src/web/tools/GestureHandlerWebDelegate.ts | 54 ++++++++++++++++++---- src/web/tools/NodeManager.ts | 2 + 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index ca56e91517..624a38d071 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -17,6 +17,7 @@ import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator'; import InteractionManager from '../tools/InteractionManager'; import PointerTracker, { TrackerElement } from '../tools/PointerTracker'; import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate'; +import type { GestureHandlerWebDelegate } from '../tools/GestureHandlerWebDelegate'; export default abstract class GestureHandler { private lastSentState: State | null = null; @@ -747,6 +748,12 @@ export default abstract class GestureHandler { protected resetConfig(): void {} + public finalize(): void { + (this.delegate as GestureHandlerWebDelegate).removeContextMenuListeners( + this.config + ); + } + // // Getters and setters // diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index bff5c04807..733308fec0 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -9,7 +9,7 @@ import TouchEventManager from './TouchEventManager'; import { State } from '../../State'; import { isPointerInBounds } from '../utils'; import EventManager from './EventManager'; -import { MouseButton } from '../interfaces'; +import { Config, MouseButton } from '../interfaces'; export class GestureHandlerWebDelegate implements GestureHandlerDelegate @@ -17,6 +17,13 @@ export class GestureHandlerWebDelegate private view!: HTMLElement; private gestureHandler!: GestureHandler; private eventManagers: EventManager[] = []; + private boundDisableContextMenu: (e: MouseEvent) => void; + private boundEnableContextMenu: (e: MouseEvent) => void; + + constructor() { + this.boundDisableContextMenu = this.disableContextMenu.bind(this); + this.boundEnableContextMenu = this.enableContextMenu.bind(this); + } getView(): HTMLElement { return this.view; @@ -38,15 +45,7 @@ export class GestureHandlerWebDelegate const config = handler.getConfig(); - if ( - (config.enableContextMenu === undefined && - handler.isButtonInConfig(MouseButton.RIGHT)) || - config.enableContextMenu === false - ) { - this.view.addEventListener('contextmenu', (e) => e.preventDefault()); - } else if (config.enableContextMenu) { - this.view.addEventListener('contextmenu', (e) => e.stopPropagation()); - } + this.addContextMenuListeners(config); if (!config.userSelect) { this.view.style['webkitUserSelect'] = 'none'; @@ -97,6 +96,41 @@ export class GestureHandlerWebDelegate } } + private shouldDisableContextMenu(config: Config) { + return ( + (config.enableContextMenu === undefined && + this.gestureHandler.isButtonInConfig(MouseButton.RIGHT)) || + config.enableContextMenu === false + ); + } + + addContextMenuListeners(config: Config): void { + if (this.shouldDisableContextMenu(config)) { + this.view.addEventListener('contextmenu', this.boundDisableContextMenu); + } else if (config.enableContextMenu) { + this.view.addEventListener('contextmenu', this.boundEnableContextMenu); + } + } + + public removeContextMenuListeners(config: Config): void { + if (this.shouldDisableContextMenu(config)) { + this.view.removeEventListener( + 'contextmenu', + this.boundDisableContextMenu + ); + } else if (config.enableContextMenu) { + this.view.removeEventListener('contextmenu', this.boundEnableContextMenu); + } + } + + private disableContextMenu(e: MouseEvent): void { + e.preventDefault(); + } + + private enableContextMenu(e: MouseEvent): void { + e.stopPropagation(); + } + onBegin(): void { // no-op for now } diff --git a/src/web/tools/NodeManager.ts b/src/web/tools/NodeManager.ts index fd4a9c630c..ff98926cef 100644 --- a/src/web/tools/NodeManager.ts +++ b/src/web/tools/NodeManager.ts @@ -35,6 +35,8 @@ export default abstract class NodeManager { return; } + this.gestures[handlerTag].finalize(); + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete this.gestures[handlerTag]; } From 063889ebc6cc1240d70ffc27c0a9584ac81df5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Wed, 20 Dec 2023 16:24:36 +0100 Subject: [PATCH 25/35] Update example --- example/src/release_tests/contextMenu/index.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/example/src/release_tests/contextMenu/index.tsx b/example/src/release_tests/contextMenu/index.tsx index 67f9e89348..d89ed1a007 100644 --- a/example/src/release_tests/contextMenu/index.tsx +++ b/example/src/release_tests/contextMenu/index.tsx @@ -1,19 +1,23 @@ import React from 'react'; import { StyleSheet, View } from 'react-native'; -import { Gesture, GestureDetector } from 'react-native-gesture-handler'; +import { + Gesture, + GestureDetector, + MouseButton, +} from 'react-native-gesture-handler'; export default function ContextMenuExample() { - const p1 = Gesture.Pan(); + const p1 = Gesture.Pan().mouseButton(MouseButton.RIGHT); const p2 = Gesture.Pan(); const p3 = Gesture.Pan(); return ( - + - + From 60b84877d793bdc44406903c2a6f13def8d1b8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 12:47:34 +0100 Subject: [PATCH 26/35] Change example --- .../src/release_tests/mouseButtons/index.tsx | 63 ++++++------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/example/src/release_tests/mouseButtons/index.tsx b/example/src/release_tests/mouseButtons/index.tsx index 65487224cf..8eafb46954 100644 --- a/example/src/release_tests/mouseButtons/index.tsx +++ b/example/src/release_tests/mouseButtons/index.tsx @@ -9,6 +9,8 @@ import { } from 'react-native-gesture-handler'; import { StyleSheet, View, Text } from 'react-native'; +const COLORS = ['darkmagenta', 'darkgreen', 'darkblue', 'crimson', 'pink']; + type TestProps = { name: string; gestureHandlers: GestureType[]; @@ -16,26 +18,20 @@ type TestProps = { function Test({ name, gestureHandlers }: TestProps) { return ( - - {name} - - - - - - - - - - - - - - - - - - + + {name} + + {gestureHandlers.map((handler, index) => { + return ( + + + + ); + })} ); @@ -178,29 +174,8 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'space-around', }, - boxLeft: { - width: 100, - height: 100, - backgroundColor: 'darkmagenta', - }, - boxRight: { - width: 100, - height: 100, - backgroundColor: 'darkblue', - }, - boxMiddle: { - width: 100, - height: 100, - backgroundColor: 'darkgreen', - }, - boxLeftRight: { - width: 100, - height: 100, - backgroundColor: 'crimson', - }, - boxAll: { - width: 100, - height: 100, - backgroundColor: 'plum', + box: { + width: 75, + height: 75, }, }); From 9ece9f962995bba79e05eaba569c5008b53b1616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 12:51:26 +0100 Subject: [PATCH 27/35] Remove EnableContextMenu alias --- src/components/DrawerLayout.tsx | 3 +-- src/handlers/gestureHandlerCommon.ts | 4 +--- src/handlers/gestures/GestureDetector.tsx | 5 ++--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/DrawerLayout.tsx b/src/components/DrawerLayout.tsx index 2c35488a80..3d6148d851 100644 --- a/src/components/DrawerLayout.tsx +++ b/src/components/DrawerLayout.tsx @@ -28,7 +28,6 @@ import { HandlerStateChangeEvent, UserSelect, ActiveCursor, - EnableContextMenu, } from '../handlers/gestureHandlerCommon'; import { PanGestureHandler, @@ -186,7 +185,7 @@ export interface DrawerLayoutProps { * @default 'false if MouseButton.RIGHT is specified' * Allows to enable/disable context menu. */ - enableContextMenu?: EnableContextMenu; + enableContextMenu?: boolean; } export type DrawerLayoutState = { diff --git a/src/handlers/gestureHandlerCommon.ts b/src/handlers/gestureHandlerCommon.ts index 11bcf41599..5fb4889b91 100644 --- a/src/handlers/gestureHandlerCommon.ts +++ b/src/handlers/gestureHandlerCommon.ts @@ -111,8 +111,6 @@ export type ActiveCursor = | 'zoom-in' | 'zoom-out'; -export type EnableContextMenu = boolean; - //TODO(TS) events in handlers export interface GestureEvent> { @@ -155,7 +153,7 @@ export type CommonGestureConfig = { userSelect?: UserSelect; activeCursor?: ActiveCursor; mouseButton?: MouseButton; - enableContextMenu?: EnableContextMenu; + enableContextMenu?: boolean; }; // Events payloads are types instead of interfaces due to TS limitation. diff --git a/src/handlers/gestures/GestureDetector.tsx b/src/handlers/gestures/GestureDetector.tsx index bdda345ccb..5f55b5eeab 100644 --- a/src/handlers/gestures/GestureDetector.tsx +++ b/src/handlers/gestures/GestureDetector.tsx @@ -19,7 +19,6 @@ import { HandlerStateChangeEvent, scheduleFlushOperations, UserSelect, - EnableContextMenu, } from '../gestureHandlerCommon'; import { GestureStateManager, @@ -607,7 +606,7 @@ const applyUserSelectProp = ( }; const applyEnableContextMenuProp = ( - enableContextMenu: EnableContextMenu, + enableContextMenu: boolean, gesture: ComposedGesture | GestureType ): void => { for (const g of gesture.toGestureArray()) { @@ -619,7 +618,7 @@ interface GestureDetectorProps { gesture: ComposedGesture | GestureType; children?: React.ReactNode; userSelect?: UserSelect; - enableContextMenu?: EnableContextMenu; + enableContextMenu?: boolean; } interface GestureDetectorState { firstRender: boolean; From 2327174097999adef49e7b4833fc13aa471757eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 13:21:01 +0100 Subject: [PATCH 28/35] Remove bounded listeners --- src/web/tools/GestureHandlerWebDelegate.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index 733308fec0..015d4f6016 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -17,13 +17,6 @@ export class GestureHandlerWebDelegate private view!: HTMLElement; private gestureHandler!: GestureHandler; private eventManagers: EventManager[] = []; - private boundDisableContextMenu: (e: MouseEvent) => void; - private boundEnableContextMenu: (e: MouseEvent) => void; - - constructor() { - this.boundDisableContextMenu = this.disableContextMenu.bind(this); - this.boundEnableContextMenu = this.enableContextMenu.bind(this); - } getView(): HTMLElement { return this.view; @@ -106,20 +99,17 @@ export class GestureHandlerWebDelegate addContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { - this.view.addEventListener('contextmenu', this.boundDisableContextMenu); + this.view.addEventListener('contextmenu', this.disableContextMenu); } else if (config.enableContextMenu) { - this.view.addEventListener('contextmenu', this.boundEnableContextMenu); + this.view.addEventListener('contextmenu', this.enableContextMenu); } } public removeContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { - this.view.removeEventListener( - 'contextmenu', - this.boundDisableContextMenu - ); + this.view.removeEventListener('contextmenu', this.disableContextMenu); } else if (config.enableContextMenu) { - this.view.removeEventListener('contextmenu', this.boundEnableContextMenu); + this.view.removeEventListener('contextmenu', this.enableContextMenu); } } From 1da7bfbb71e81a90ab41800260a5ba91eb5b550e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 13:23:03 +0100 Subject: [PATCH 29/35] Remove finalize to onDestroy --- src/web/handlers/GestureHandler.ts | 2 +- src/web/tools/NodeManager.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index 624a38d071..629081a84e 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -748,7 +748,7 @@ export default abstract class GestureHandler { protected resetConfig(): void {} - public finalize(): void { + public onDestroy(): void { (this.delegate as GestureHandlerWebDelegate).removeContextMenuListeners( this.config ); diff --git a/src/web/tools/NodeManager.ts b/src/web/tools/NodeManager.ts index ff98926cef..ca452324e6 100644 --- a/src/web/tools/NodeManager.ts +++ b/src/web/tools/NodeManager.ts @@ -35,7 +35,7 @@ export default abstract class NodeManager { return; } - this.gestures[handlerTag].finalize(); + this.gestures[handlerTag].onDestroy(); // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete this.gestures[handlerTag]; From 26c4b3c55fe4924274c971ad6bc786058c923179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 13:53:06 +0100 Subject: [PATCH 30/35] Restore default context menu blockade in LongPress --- src/web/handlers/LongPressGestureHandler.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/web/handlers/LongPressGestureHandler.ts b/src/web/handlers/LongPressGestureHandler.ts index 86a74d8614..7707b90aba 100644 --- a/src/web/handlers/LongPressGestureHandler.ts +++ b/src/web/handlers/LongPressGestureHandler.ts @@ -21,6 +21,10 @@ export default class LongPressGestureHandler extends GestureHandler { private activationTimeout: number | undefined; public init(ref: number, propsRef: React.RefObject) { + if (this.config.enableContextMenu === undefined) { + this.config.enableContextMenu = false; + } + super.init(ref, propsRef); } From 8279c908fdd36fc9031b6ca8953f74c165e8614e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 13:58:39 +0100 Subject: [PATCH 31/35] Add destroy to WebDelegate --- src/web/handlers/GestureHandler.ts | 4 +--- src/web/tools/GestureHandlerWebDelegate.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index 629081a84e..dbdbb00145 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -749,9 +749,7 @@ export default abstract class GestureHandler { protected resetConfig(): void {} public onDestroy(): void { - (this.delegate as GestureHandlerWebDelegate).removeContextMenuListeners( - this.config - ); + (this.delegate as GestureHandlerWebDelegate).destroy(this.config); } // diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index 015d4f6016..c2cd8a25c4 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -97,7 +97,7 @@ export class GestureHandlerWebDelegate ); } - addContextMenuListeners(config: Config): void { + private addContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { this.view.addEventListener('contextmenu', this.disableContextMenu); } else if (config.enableContextMenu) { @@ -105,7 +105,7 @@ export class GestureHandlerWebDelegate } } - public removeContextMenuListeners(config: Config): void { + private removeContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { this.view.removeEventListener('contextmenu', this.disableContextMenu); } else if (config.enableContextMenu) { @@ -147,4 +147,8 @@ export class GestureHandlerWebDelegate onFail(): void { this.tryResetCursor(); } + + public destroy(config: Config): void { + this.removeContextMenuListeners(config); + } } From 471002ea3f42597ddbc8c84b61e9aebe466725e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 14:04:26 +0100 Subject: [PATCH 32/35] Restore bounded listeners --- src/web/tools/GestureHandlerWebDelegate.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index c2cd8a25c4..863c7da631 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -18,6 +18,14 @@ export class GestureHandlerWebDelegate private gestureHandler!: GestureHandler; private eventManagers: EventManager[] = []; + private boundDisableContextMenu: (e: MouseEvent) => void; + private boundEnableContextMenu: (e: MouseEvent) => void; + + constructor() { + this.boundDisableContextMenu = this.disableContextMenu.bind(this); + this.boundEnableContextMenu = this.enableContextMenu.bind(this); + } + getView(): HTMLElement { return this.view; } @@ -99,17 +107,20 @@ export class GestureHandlerWebDelegate private addContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { - this.view.addEventListener('contextmenu', this.disableContextMenu); + this.view.addEventListener('contextmenu', this.boundDisableContextMenu); } else if (config.enableContextMenu) { - this.view.addEventListener('contextmenu', this.enableContextMenu); + this.view.addEventListener('contextmenu', this.boundEnableContextMenu); } } private removeContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { - this.view.removeEventListener('contextmenu', this.disableContextMenu); + this.view.removeEventListener( + 'contextmenu', + this.boundDisableContextMenu + ); } else if (config.enableContextMenu) { - this.view.removeEventListener('contextmenu', this.enableContextMenu); + this.view.removeEventListener('contextmenu', this.boundEnableContextMenu); } } From 7432cddc99c8ce4abb34d65cc00031a8cfc371a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 14:08:12 +0100 Subject: [PATCH 33/35] Revert "Restore bounded listeners" This reverts commit 471002ea3f42597ddbc8c84b61e9aebe466725e8. --- src/web/tools/GestureHandlerWebDelegate.ts | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index 863c7da631..c2cd8a25c4 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -18,14 +18,6 @@ export class GestureHandlerWebDelegate private gestureHandler!: GestureHandler; private eventManagers: EventManager[] = []; - private boundDisableContextMenu: (e: MouseEvent) => void; - private boundEnableContextMenu: (e: MouseEvent) => void; - - constructor() { - this.boundDisableContextMenu = this.disableContextMenu.bind(this); - this.boundEnableContextMenu = this.enableContextMenu.bind(this); - } - getView(): HTMLElement { return this.view; } @@ -107,20 +99,17 @@ export class GestureHandlerWebDelegate private addContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { - this.view.addEventListener('contextmenu', this.boundDisableContextMenu); + this.view.addEventListener('contextmenu', this.disableContextMenu); } else if (config.enableContextMenu) { - this.view.addEventListener('contextmenu', this.boundEnableContextMenu); + this.view.addEventListener('contextmenu', this.enableContextMenu); } } private removeContextMenuListeners(config: Config): void { if (this.shouldDisableContextMenu(config)) { - this.view.removeEventListener( - 'contextmenu', - this.boundDisableContextMenu - ); + this.view.removeEventListener('contextmenu', this.disableContextMenu); } else if (config.enableContextMenu) { - this.view.removeEventListener('contextmenu', this.boundEnableContextMenu); + this.view.removeEventListener('contextmenu', this.enableContextMenu); } } From c75fdb766e6993f48b6a6511cb250e977928b6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Mon, 15 Jan 2024 14:11:34 +0100 Subject: [PATCH 34/35] Change binding to this:void --- src/web/tools/GestureHandlerWebDelegate.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index c2cd8a25c4..fad27df38c 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -113,11 +113,11 @@ export class GestureHandlerWebDelegate } } - private disableContextMenu(e: MouseEvent): void { + private disableContextMenu(this: void, e: MouseEvent): void { e.preventDefault(); } - private enableContextMenu(e: MouseEvent): void { + private enableContextMenu(this: void, e: MouseEvent): void { e.stopPropagation(); } From f3574116aeaab2570e27679cc55e8d12a5d3b2a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= Date: Tue, 16 Jan 2024 11:09:03 +0100 Subject: [PATCH 35/35] Add destroy to delegate interface --- src/web/handlers/GestureHandler.ts | 3 +-- src/web/tools/GestureHandlerDelegate.ts | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/web/handlers/GestureHandler.ts b/src/web/handlers/GestureHandler.ts index dbdbb00145..3a15283060 100644 --- a/src/web/handlers/GestureHandler.ts +++ b/src/web/handlers/GestureHandler.ts @@ -17,7 +17,6 @@ import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator'; import InteractionManager from '../tools/InteractionManager'; import PointerTracker, { TrackerElement } from '../tools/PointerTracker'; import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate'; -import type { GestureHandlerWebDelegate } from '../tools/GestureHandlerWebDelegate'; export default abstract class GestureHandler { private lastSentState: State | null = null; @@ -749,7 +748,7 @@ export default abstract class GestureHandler { protected resetConfig(): void {} public onDestroy(): void { - (this.delegate as GestureHandlerWebDelegate).destroy(this.config); + this.delegate.destroy(this.config); } // diff --git a/src/web/tools/GestureHandlerDelegate.ts b/src/web/tools/GestureHandlerDelegate.ts index ac68196f98..259b1c52c9 100644 --- a/src/web/tools/GestureHandlerDelegate.ts +++ b/src/web/tools/GestureHandlerDelegate.ts @@ -1,4 +1,5 @@ import type GestureHandler from '../handlers/GestureHandler'; +import { Config } from '../interfaces'; export interface MeasureResult { pageX: number; @@ -20,4 +21,6 @@ export interface GestureHandlerDelegate { onEnd(): void; onCancel(): void; onFail(): void; + + destroy(config: Config): void; }