@react-native-oh-tpl/react-native-gesture-handler 2.14.8-rc.1 → 2.14.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. package/DrawerLayout/index.ts +2 -2
  2. package/Swipeable/index.ts +2 -2
  3. package/harmony/gesture_handler/BuildProfile.ets +17 -0
  4. package/harmony/gesture_handler/build-profile.json5 +19 -0
  5. package/harmony/gesture_handler/hvigorfile.ts +2 -0
  6. package/harmony/gesture_handler/index.ets +2 -0
  7. package/harmony/gesture_handler/oh-package-lock.json5 +18 -0
  8. package/harmony/gesture_handler/oh-package.json5 +12 -0
  9. package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -0
  10. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +12 -0
  11. package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.cpp +123 -0
  12. package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.h +15 -0
  13. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerButtonComponentInstance.h +27 -0
  14. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +245 -0
  15. package/harmony/gesture_handler/src/main/ets/RNOHPackage.ets +17 -0
  16. package/harmony/gesture_handler/src/main/ets/core/CircularBuffer.ts +42 -0
  17. package/harmony/gesture_handler/src/main/ets/core/GestureHandler.ts +739 -0
  18. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerOrchestrator.ts +344 -0
  19. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +63 -0
  20. package/harmony/gesture_handler/src/main/ets/core/IncomingEvent.ts +78 -0
  21. package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +144 -0
  22. package/harmony/gesture_handler/src/main/ets/core/LeastSquareSolver.ts +182 -0
  23. package/harmony/gesture_handler/src/main/ets/core/Multiset.ts +26 -0
  24. package/harmony/gesture_handler/src/main/ets/core/OutgoingEvent.ts +34 -0
  25. package/harmony/gesture_handler/src/main/ets/core/OutgoingEventDispatcher.ts +12 -0
  26. package/harmony/gesture_handler/src/main/ets/core/PointerTracker.ts +239 -0
  27. package/harmony/gesture_handler/src/main/ets/core/RNGHError.ts +5 -0
  28. package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +16 -0
  29. package/harmony/gesture_handler/src/main/ets/core/State.ts +47 -0
  30. package/harmony/gesture_handler/src/main/ets/core/Vector2D.ts +80 -0
  31. package/harmony/gesture_handler/src/main/ets/core/VelocityTracker.ts +106 -0
  32. package/harmony/gesture_handler/src/main/ets/core/View.ts +21 -0
  33. package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +7 -0
  34. package/harmony/gesture_handler/src/main/ets/core/index.ts +15 -0
  35. package/harmony/gesture_handler/src/main/ets/detectors/ScaleGestureDetector.ts +169 -0
  36. package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +219 -0
  37. package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +67 -0
  38. package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +139 -0
  39. package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +50 -0
  40. package/harmony/gesture_handler/src/main/ets/gesture-handlers/NativeViewGestureHandler.ts +124 -0
  41. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PanGestureHandler.ts +361 -0
  42. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +174 -0
  43. package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +172 -0
  44. package/harmony/gesture_handler/src/main/ets/gesture-handlers/TapGestureHandler.ts +216 -0
  45. package/harmony/gesture_handler/src/main/ets/gesture-handlers/detectors/RotationGestureDetector.ts +167 -0
  46. package/harmony/gesture_handler/src/main/ets/gesture-handlers/index.ts +1 -0
  47. package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerPackage.ts +25 -0
  48. package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +107 -0
  49. package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +94 -0
  50. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootViewController.ts +182 -0
  51. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHView.ts +62 -0
  52. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHViewController.ts +262 -0
  53. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHViewRegistry.ts +19 -0
  54. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerModule.ts +267 -0
  55. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +15 -0
  56. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +25 -0
  57. package/harmony/gesture_handler/src/main/ets/rnoh/types.ts +25 -0
  58. package/harmony/gesture_handler/src/main/module.json5 +9 -0
  59. package/harmony/gesture_handler/src/main/resources/base/element/color.json +8 -0
  60. package/harmony/gesture_handler/src/main/resources/base/element/string.json +16 -0
  61. package/harmony/gesture_handler/src/main/resources/base/media/icon.png +0 -0
  62. package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -0
  63. package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +16 -0
  64. package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +16 -0
  65. package/harmony/gesture_handler/ts.ts +2 -0
  66. package/harmony/gesture_handler.har +0 -0
  67. package/lib/commonjs/RNGestureHandlerModule.js +3 -2
  68. package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
  69. package/lib/commonjs/components/GestureHandlerRootView.js +3 -3
  70. package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
  71. package/lib/commonjs/handlers/createHandler.js +18 -15
  72. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  73. package/lib/commonjs/index.js +36 -8
  74. package/lib/commonjs/index.js.map +1 -1
  75. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js +2 -1
  76. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  77. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js +3 -2
  78. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  79. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js +3 -2
  80. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  81. package/lib/module/RNGestureHandlerModule.js.map +1 -1
  82. package/lib/module/components/GestureHandlerRootView.js.map +1 -1
  83. package/lib/module/handlers/createHandler.js +15 -12
  84. package/lib/module/handlers/createHandler.js.map +1 -1
  85. package/lib/module/index.js +5 -7
  86. package/lib/module/index.js.map +1 -1
  87. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  88. package/lib/module/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  89. package/lib/module/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  90. package/lib/typescript/RNGestureHandlerModule.d.ts +2 -2
  91. package/lib/typescript/components/GestureHandlerRootView.d.ts +6 -6
  92. package/lib/typescript/handlers/createHandler.d.ts +11 -11
  93. package/lib/typescript/index.d.ts +47 -42
  94. package/lib/typescript/index.d.ts.map +1 -1
  95. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +14 -14
  96. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +14 -14
  97. package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts +6 -6
  98. package/package.json +78 -70
  99. package/src/RNGestureHandlerModule.ts +4 -4
  100. package/src/components/GestureHandlerRootView.tsx +23 -23
  101. package/src/handlers/createHandler.tsx +534 -534
  102. package/src/index.ts +172 -172
  103. package/src/specs/NativeRNGestureHandlerModule.ts +26 -26
  104. package/src/specs/RNGestureHandlerButtonNativeComponent.ts +18 -18
  105. package/src/specs/RNGestureHandlerRootViewNativeComponent.ts +6 -6
@@ -0,0 +1,344 @@
1
+ import { GestureHandler } from "./GestureHandler"
2
+ import { State, getStateName } from "./State"
3
+ import { PointerType } from "./IncomingEvent"
4
+ import { RNGHLogger } from "./RNGHLogger"
5
+
6
+ export class GestureHandlerOrchestrator {
7
+ private awaitingHandlers: Set<GestureHandler> = new Set()
8
+ private gestureHandlers: GestureHandler[] = []
9
+ private handlersToCancel: GestureHandler[] = []
10
+ private activationIndex: number = 0
11
+
12
+ private logger: RNGHLogger
13
+
14
+ constructor(logger: RNGHLogger) {
15
+ this.logger = logger.cloneAndJoinPrefix("GestureHandlerOrchestrator")
16
+ }
17
+
18
+ public onHandlerStateChange(handler: GestureHandler, newState: State, oldState: State, sendIfDisabled?: boolean) {
19
+ const logger =
20
+ this.logger.cloneAndJoinPrefix(`onHandlerStateChange(handler=${handler.getTag()}, newState=${getStateName(newState)}, oldState=${getStateName(oldState)})`)
21
+ logger.debug("start")
22
+
23
+ if (!handler.isEnabled() && !sendIfDisabled) {
24
+ return;
25
+ }
26
+
27
+ // this.handlingChangeSemaphore += 1;
28
+
29
+ if (this.isFinishedState(newState)) {
30
+ this.awaitingHandlers.forEach((otherHandler) => {
31
+ if (otherHandler.shouldWaitFor(handler)) {
32
+ if (newState === State.END) {
33
+ otherHandler?.cancel();
34
+ if (otherHandler.getState() === State.END) {
35
+ // Handle edge case, where discrete gestures end immediately after activation thus
36
+ // their state is set to END and when the gesture they are waiting for activates they
37
+ // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
38
+ // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
39
+ otherHandler.sendEvent({ newState: State.CANCELLED, oldState: State.BEGAN });
40
+ }
41
+ otherHandler?.setAwaiting(false);
42
+ } else {
43
+ this.tryActivate(otherHandler);
44
+ }
45
+ }
46
+ });
47
+ }
48
+
49
+ if (newState === State.ACTIVE) {
50
+ this.tryActivate(handler);
51
+ } else if (oldState === State.ACTIVE || oldState === State.END) {
52
+ if (handler.isActive()) {
53
+ handler.sendEvent({ newState, oldState });
54
+ } else if (
55
+ oldState === State.ACTIVE &&
56
+ (newState === State.CANCELLED || newState === State.FAILED)
57
+ ) {
58
+ handler.sendEvent({ newState, oldState: State.BEGAN });
59
+ }
60
+ } else if (
61
+ oldState !== State.UNDETERMINED ||
62
+ newState !== State.CANCELLED
63
+ ) {
64
+ handler.sendEvent({ newState, oldState });
65
+ }
66
+
67
+ // this.handlingChangeSemaphore -= 1;
68
+
69
+ this.cleanUpFinishedHandlers();
70
+ if (!this.awaitingHandlers.has(handler)) {
71
+ this.cleanupAwaitingHandlers(handler);
72
+ }
73
+ }
74
+
75
+ private isFinishedState(state: State) {
76
+ return [State.END, State.FAILED, State.CANCELLED].includes(state)
77
+ }
78
+
79
+ private tryActivate(handler: GestureHandler): void {
80
+ const logger = this.logger.cloneAndJoinPrefix(`tryActivate(${handler.getTag()})`)
81
+ logger.debug({
82
+ gestureHandlers: this.gestureHandlers.map(gh => gh.getTag()),
83
+ awaitingHandlers: Array.from(this.awaitingHandlers).map(gh => gh.getTag()),
84
+ handlersToCancel: this.handlersToCancel.map(gh => gh.getTag())
85
+ })
86
+ if (this.shouldBeCancelledByFinishedHandler(handler)) {
87
+ logger.debug("failed to activate - cancelling")
88
+ handler.cancel();
89
+ return;
90
+ }
91
+ if (this.hasOtherHandlerToWaitFor(handler)) {
92
+ this.addAwaitingHandler(handler);
93
+ logger.debug("request ignored - has other handler waiting")
94
+ return;
95
+ }
96
+ const handlerState = handler.getState();
97
+ if (handlerState === State.CANCELLED || handlerState === State.FAILED) {
98
+ logger.debug("request ignored - handler is in cancelled or failed state")
99
+ return;
100
+ }
101
+ if (this.shouldActivate(handler)) {
102
+ logger.debug("activating")
103
+ this.makeActive(handler);
104
+ return;
105
+ }
106
+ if (handlerState === State.ACTIVE) {
107
+ logger.debug("failed to activate - handler is already active, marking as fail")
108
+ handler.fail();
109
+ return;
110
+ }
111
+ if (handlerState === State.BEGAN) {
112
+ logger.debug("handler is in BEGAN state but shouldActivate returned false - cancelling")
113
+ handler.cancel();
114
+ }
115
+ }
116
+
117
+ private shouldBeCancelledByFinishedHandler(
118
+ handler: GestureHandler
119
+ ): boolean {
120
+ const shouldBeCancelled = (otherHandler: GestureHandler) => {
121
+ return (
122
+ handler.shouldWaitFor(otherHandler) &&
123
+ otherHandler.getState() === State.END
124
+ );
125
+ };
126
+ return this.gestureHandlers.some(shouldBeCancelled);
127
+ }
128
+
129
+ private hasOtherHandlerToWaitFor(handler: GestureHandler): boolean {
130
+ const logger = this.logger.cloneAndJoinPrefix(`hasOtherHandlerToWaitFor(handler=${handler.getTag()})`)
131
+ for (const otherHandler of this.gestureHandlers) {
132
+ if (otherHandler === handler) {
133
+ return false
134
+ }
135
+ if (!this.isFinishedState(otherHandler.getState()) && handler.shouldWaitFor(otherHandler)) {
136
+ logger.debug("true")
137
+ return true
138
+ }
139
+ }
140
+ logger.debug("false")
141
+ return false;
142
+ }
143
+
144
+ private addAwaitingHandler(handler: GestureHandler) {
145
+ const logger = this.logger.cloneAndJoinPrefix(`addAwaitingHandler(handlerTag=${handler.getTag()})`)
146
+ logger.debug({ awaitingHandlers: this.awaitingHandlers })
147
+ if (!this.awaitingHandlers.has(handler)) {
148
+ this.awaitingHandlers.add(handler)
149
+ handler.setAwaiting(true)
150
+ handler.setActivationIndex(this.activationIndex++)
151
+ }
152
+ }
153
+
154
+ private shouldActivate(handler: GestureHandler) {
155
+ for (const otherHandler of this.gestureHandlers) {
156
+ if (this.shouldHandlerBeCancelledByOtherHandler({ handler, otherHandler })) {
157
+ return false
158
+ }
159
+ }
160
+ return true
161
+ }
162
+
163
+ private shouldHandlerBeCancelledByOtherHandler({ handler, otherHandler }: {
164
+ handler: GestureHandler,
165
+ otherHandler: GestureHandler
166
+ }): boolean {
167
+ const logger =
168
+ this.logger.cloneAndJoinPrefix(`shouldHandlerBeCancelledByOtherHandler(${handler.getTag()}, ${otherHandler.getTag()})`)
169
+ if (this.canRunSimultaneously(handler, otherHandler)) {
170
+ logger.debug("false")
171
+ return false;
172
+ }
173
+ if (handler !== otherHandler && (handler.isAwaiting() || handler.getState() === State.ACTIVE)) {
174
+ const result = handler.shouldBeCancelledByOther(otherHandler)
175
+ logger.debug(`${result} (1)`)
176
+ return result
177
+ }
178
+ const result = this.checkOverlap(handler, otherHandler)
179
+ logger.debug(`${result} (2)`)
180
+ return result;
181
+ }
182
+
183
+ private canRunSimultaneously(handlerA: GestureHandler, handlerB: GestureHandler) {
184
+ const logger = this.logger.cloneAndJoinPrefix("canRunSimultaneously")
185
+ const result = handlerA === handlerB
186
+ || handlerA.shouldRecognizeSimultaneously(handlerB)
187
+ || handlerB.shouldRecognizeSimultaneously(handlerA)
188
+
189
+ logger.debug({ result, handlerA: handlerA.getTag(), handlerB: handlerB.getTag() })
190
+ return result
191
+ }
192
+
193
+ private checkOverlap(
194
+ handler: GestureHandler,
195
+ otherHandler: GestureHandler
196
+ ): boolean {
197
+ // If handlers don't have common pointers, default return value is false.
198
+ // However, if at least on pointer overlaps with both handlers, we return true
199
+ // This solves issue in overlapping parents example
200
+
201
+ // TODO: Find better way to handle that issue, for example by activation order and handler cancelling
202
+
203
+ const handlerPointers: number[] = handler.getTrackedPointersID();
204
+ const otherPointers: number[] = otherHandler.getTrackedPointersID();
205
+ let overlap = false;
206
+ handlerPointers.forEach((pointer: number) => {
207
+ const handlerX: number = handler.getTracker().getLastX(pointer);
208
+ const handlerY: number = handler.getTracker().getLastY(pointer);
209
+ if (
210
+ handler.getView().isPositionInBounds({ x: handlerX, y: handlerY }) &&
211
+ otherHandler.getView().isPositionInBounds({ x: handlerX, y: handlerY })
212
+ ) {
213
+ overlap = true;
214
+ }
215
+ });
216
+ otherPointers.forEach((pointer: number) => {
217
+ const otherX: number = otherHandler.getTracker().getLastX(pointer);
218
+ const otherY: number = otherHandler.getTracker().getLastY(pointer);
219
+ if (
220
+ handler.getView().isPositionInBounds({ x: otherX, y: otherY }) &&
221
+ otherHandler.getView().isPositionInBounds({ x: otherX, y: otherY })
222
+ ) {
223
+ overlap = true;
224
+ }
225
+ });
226
+ return overlap;
227
+ }
228
+
229
+ private makeActive(handler: GestureHandler): void {
230
+ handler.setActive(true)
231
+ handler.setShouldResetProgress(true)
232
+ handler.setActivationIndex(this.activationIndex++)
233
+ for (const otherHandler of this.gestureHandlers) {
234
+ if (this.shouldHandlerBeCancelledByOtherHandler({ handler: otherHandler, otherHandler: handler })) {
235
+ this.handlersToCancel.push(otherHandler)
236
+ }
237
+ }
238
+ for (let i = this.handlersToCancel.length - 1; i >= 0; --i) {
239
+ this.handlersToCancel[i]?.cancel();
240
+ }
241
+ this.handlersToCancel = []
242
+ for (const awaitingHandler of this.awaitingHandlers) {
243
+ if (this.shouldHandlerBeCancelledByOtherHandler({ handler: awaitingHandler, otherHandler: handler })) {
244
+ awaitingHandler.cancel();
245
+ awaitingHandler.setAwaiting(true);
246
+ }
247
+ }
248
+ const currentState = handler.getState()
249
+ handler.sendEvent({ newState: State.ACTIVE, oldState: State.BEGAN })
250
+ if (currentState !== State.ACTIVE) {
251
+ handler.sendEvent({ newState: State.END, oldState: State.ACTIVE })
252
+ if (currentState !== State.END) {
253
+ handler.sendEvent({ newState: State.UNDETERMINED, oldState: State.END })
254
+ }
255
+ }
256
+ if (handler.isAwaiting()) {
257
+ handler.setAwaiting(false)
258
+ this.awaitingHandlers.delete(handler)
259
+ }
260
+ }
261
+
262
+ private cleanUpHandlers(handler: GestureHandler) {
263
+ this.cleanUpFinishedHandlers()
264
+ if (this.awaitingHandlers.has(handler)) {
265
+ this.cleanupAwaitingHandlers(handler);
266
+ }
267
+ }
268
+
269
+ private cleanUpFinishedHandlers(): void {
270
+ for (let i = this.gestureHandlers.length - 1; i >= 0; --i) {
271
+ const handler = this.gestureHandlers[i];
272
+ if (!handler) {
273
+ continue;
274
+ }
275
+ if (this.isFinishedState(handler.getState()) && !handler.isAwaiting()) {
276
+ this.gestureHandlers.splice(i, 1);
277
+ this.cleanUpHandler(handler);
278
+ }
279
+ }
280
+ }
281
+
282
+ private cleanupAwaitingHandlers(handler: GestureHandler): void {
283
+ const logger = this.logger.cloneAndJoinPrefix(`cleanupAwaitingHandlers(handler=${handler.getTag()})`)
284
+ logger.debug({ awaitingHandlers: this.awaitingHandlers })
285
+ for (const awaitingHandler of this.awaitingHandlers) {
286
+ if (
287
+ awaitingHandler.isAwaiting() &&
288
+ awaitingHandler.shouldWaitFor(handler)
289
+ ) {
290
+ this.cleanUpHandler(awaitingHandler);
291
+ this.awaitingHandlers.delete(awaitingHandler)
292
+ }
293
+ }
294
+ }
295
+
296
+ private cleanUpHandler(handler: GestureHandler) {
297
+ handler.reset();
298
+ handler.setActive(false);
299
+ handler.setAwaiting(false);
300
+ handler.setActivationIndex(Number.MAX_VALUE);
301
+ }
302
+
303
+ public registerHandlerIfNotPresent(handler: GestureHandler) {
304
+ this.logger.info(`registerHandlerIfNotPresent(${handler.getTag()})`)
305
+ if (this.gestureHandlers.includes(handler)) {
306
+ return;
307
+ }
308
+ this.gestureHandlers.push(handler);
309
+ handler.setActive(false);
310
+ handler.setAwaiting(false);
311
+ handler.setActivationIndex(Number.MAX_SAFE_INTEGER);
312
+ }
313
+
314
+ /**
315
+ This function is called when handler receives touchdown event
316
+ If handler is using mouse or pen as a pointer and any handler receives touch event,
317
+ mouse/pen event disappears - it doesn't send onPointerCancel nor onPointerUp (and others)
318
+ This became a problem because handler was left at active state without any signal to end or fail
319
+ To handle this, when new touch event is received, we loop through active handlers and check which type of
320
+ pointer they're using. If there are any handler with mouse/pen as a pointer, we cancel them
321
+ */
322
+ public cancelMouseAndPenGestures(currentHandler: GestureHandler): void {
323
+ this.logger.info("cancelMouseAndPenGestures")
324
+ this.gestureHandlers.forEach((handler: GestureHandler) => {
325
+ if (handler.getPointerType() !== PointerType.MOUSE && handler.getPointerType() !== PointerType.PEN) {
326
+ return;
327
+ }
328
+
329
+ if (handler !== currentHandler) {
330
+ handler.cancel();
331
+ } else {
332
+ // Handler that received touch event should have its pointer tracker reset
333
+ // This allows handler to smoothly change from mouse/pen to touch
334
+ // The drawback is, that when we try to use mouse/pen one more time, it doesn't send onPointerDown at the first time
335
+ // so it is required to click two times to get handler to work
336
+ //
337
+ // However, handler will receive manually created onPointerEnter that is triggered in EventManager in onPointerMove method.
338
+ // There may be possibility to use that fact to make handler respond properly to first mouse click
339
+ handler.getTracker().resetTracker();
340
+ }
341
+ });
342
+ }
343
+ }
344
+
@@ -0,0 +1,63 @@
1
+ import { GestureHandler } from "./GestureHandler"
2
+ import { View } from "./View"
3
+ import { RNGHLogger } from "./RNGHLogger"
4
+ import { ViewRegistry } from "./ViewRegistry"
5
+
6
+ export class GestureHandlerRegistry {
7
+ private gestureHandlerByHandlerTag: Map<number, GestureHandler> = new Map()
8
+ private gestureHandlersByViewTag: Map<number, Set<GestureHandler>> = new Map()
9
+ private viewRegistry: ViewRegistry | undefined
10
+ private logger: RNGHLogger
11
+
12
+ constructor(viewRegistry: ViewRegistry | undefined, logger: RNGHLogger) {
13
+ this.logger = logger.cloneAndJoinPrefix("GestureHandlerRegistry")
14
+ this.viewRegistry = viewRegistry
15
+ }
16
+
17
+ public addGestureHandler(gestureHandler: GestureHandler) {
18
+ this.gestureHandlerByHandlerTag.set(gestureHandler.getTag(), gestureHandler)
19
+ }
20
+
21
+ public bindGestureHandlerWithView(gestureHandlerTag: number, view: View) {
22
+ this.logger.cloneAndJoinPrefix("bindGestureHandlerWithView").debug({gestureHandlerTag, viewTag: view.getTag()})
23
+ const viewTag = view.getTag()
24
+ if (!this.gestureHandlersByViewTag.has(viewTag))
25
+ this.gestureHandlersByViewTag.set(viewTag, new Set())
26
+ const gestureHandler = this.gestureHandlerByHandlerTag.get(gestureHandlerTag)
27
+ this.gestureHandlersByViewTag.get(viewTag).add(gestureHandler)
28
+ gestureHandler.onViewAttached(view)
29
+ }
30
+
31
+ public getGestureHandlersByViewTag(viewTag: number): GestureHandler[] {
32
+ return Array.from(this.gestureHandlersByViewTag.get(viewTag) ?? [])
33
+ }
34
+
35
+ public removeGestureHandlerByHandlerTag(handlerTag: number) {
36
+ const gestureHandler = this.gestureHandlerByHandlerTag.get(handlerTag)
37
+ if (!gestureHandler) {
38
+ return;
39
+ }
40
+ const viewTag = gestureHandler.getView()?.getTag();
41
+ if (viewTag) {
42
+ const gestureHandlers = this.gestureHandlersByViewTag.get(viewTag)
43
+ if (gestureHandlers) {
44
+ gestureHandlers.delete(gestureHandler)
45
+ if (gestureHandlers.size === 0) {
46
+ this.gestureHandlersByViewTag.delete(viewTag)
47
+ this.viewRegistry?.deleteByTag(viewTag)
48
+ }
49
+ }
50
+ }
51
+ if (gestureHandler.getView()) {
52
+ // Handler is in "prepared" state which means it is registered in the orchestrator and can
53
+ // receive touch events. This means that before we remove it from the registry we need to
54
+ // "cancel" it so that orchestrator does no longer keep a reference to it.
55
+ gestureHandler.cancel()
56
+ }
57
+ this.gestureHandlerByHandlerTag.delete(handlerTag)
58
+ }
59
+
60
+ public getGestureHandlerByHandlerTag(handlerTag: number): GestureHandler {
61
+ return this.gestureHandlerByHandlerTag.get(handlerTag)
62
+ }
63
+ }
@@ -0,0 +1,78 @@
1
+ export interface HitSlop {
2
+ left?: number;
3
+ right?: number;
4
+ top?: number;
5
+ bottom?: number;
6
+ horizontal?: number;
7
+ vertical?: number;
8
+ width?: number;
9
+ height?: number;
10
+ }
11
+
12
+ const RIGHT = 1;
13
+ const LEFT = 2;
14
+ const UP = 4;
15
+ const DOWN = 8;
16
+
17
+ export const Directions = {
18
+ RIGHT: RIGHT,
19
+ LEFT: LEFT,
20
+ UP: UP,
21
+ DOWN: DOWN,
22
+ } as const;
23
+
24
+ export type Directions = typeof Directions[keyof typeof Directions];
25
+
26
+ export const DiagonalDirections = {
27
+ UP_RIGHT: UP | RIGHT,
28
+ DOWN_RIGHT: DOWN | RIGHT,
29
+ UP_LEFT: UP | LEFT,
30
+ DOWN_LEFT: DOWN | LEFT,
31
+ } as const;
32
+
33
+ export type DiagonalDirections =
34
+ typeof DiagonalDirections[keyof typeof DiagonalDirections];
35
+
36
+ export enum PointerType {
37
+ NONE = 'none',
38
+ MOUSE = 'mouse',
39
+ TOUCH = 'touch',
40
+ PEN = 'pen',
41
+ }
42
+
43
+ export enum EventType {
44
+ DOWN = "DOWN",
45
+ ADDITIONAL_POINTER_DOWN = "ADDITIONAL_POINTER_DOWN",
46
+ UP = "UP",
47
+ ADDITIONAL_POINTER_UP = "ADDITIONAL_POINTER_UP",
48
+ MOVE = "MOVE",
49
+ ENTER = "ENTER",
50
+ OUT = "OUT",
51
+ CANCEL = "CANCEL",
52
+ }
53
+
54
+ export type Touch = {id: number, x: number, y: number, absoluteX: number, absoluteY: number}
55
+
56
+ export enum TouchEventType {
57
+ UNDETERMINED = 0,
58
+ DOWN = 1,
59
+ MOVE = 2,
60
+ UP = 3,
61
+ CANCELLED = 4,
62
+ }
63
+
64
+ export interface IncomingEvent {
65
+ x: number;
66
+ y: number;
67
+ offsetX: number;
68
+ offsetY: number;
69
+ pointerId: number;
70
+ eventType: EventType;
71
+ pointerType: PointerType;
72
+ buttons: number;
73
+ time: number;
74
+ allTouches?: Touch[];
75
+ changedTouches?: Touch[];
76
+ touchEventType?: TouchEventType;
77
+ }
78
+
@@ -0,0 +1,144 @@
1
+ import { GestureHandler, Handler, GestureConfig as Config, GHTag } from "./GestureHandler"
2
+ import { RNGHLogger } from "./RNGHLogger"
3
+
4
+ export class InteractionManager {
5
+ private readonly waitForRelations: Map<GHTag, Set<GHTag>> = new Map()
6
+ private readonly simultaneousRelations: Map<GHTag, GHTag[]> = new Map()
7
+ private readonly blocksHandlersRelations: Map<GHTag, GHTag[]> = new Map();
8
+
9
+ private logger: RNGHLogger
10
+
11
+ constructor(logger: RNGHLogger) {
12
+ this.logger = logger.cloneAndJoinPrefix("InteractionManager")
13
+ }
14
+
15
+ public configureInteractions(handler: GestureHandler, config: Config) {
16
+ this.dropRelationsForHandlerWithTag(handler.getTag());
17
+
18
+ if (config.waitFor) {
19
+ const waitFor = new Set<GHTag>();
20
+ config.waitFor.forEach((otherHandler: Handler): void => {
21
+ // New API reference
22
+ if (typeof otherHandler === 'number') {
23
+ waitFor.add(otherHandler);
24
+ } else {
25
+ // Old API reference
26
+ waitFor.add(otherHandler.handlerTag);
27
+ }
28
+ });
29
+
30
+ this.waitForRelations.set(handler.getTag(), waitFor);
31
+ }
32
+
33
+ if (config.simultaneousHandlers) {
34
+ const simultaneousHandlers: number[] = [];
35
+ config.simultaneousHandlers.forEach((otherHandler: Handler): void => {
36
+ if (typeof otherHandler === 'number') {
37
+ simultaneousHandlers.push(otherHandler);
38
+ } else {
39
+ simultaneousHandlers.push(otherHandler.handlerTag);
40
+ }
41
+ });
42
+
43
+ this.simultaneousRelations.set(handler.getTag(), simultaneousHandlers);
44
+ }
45
+
46
+ if (config.blocksHandlers) {
47
+ const blocksHandlers: number[] = [];
48
+ config.blocksHandlers.forEach((otherHandler: Handler): void => {
49
+ if (typeof otherHandler === 'number') {
50
+ blocksHandlers.push(otherHandler);
51
+ } else {
52
+ blocksHandlers.push(otherHandler.handlerTag);
53
+ }
54
+ });
55
+ this.blocksHandlersRelations.set(handler.getTag(), blocksHandlers);
56
+ }
57
+ }
58
+
59
+ public shouldWaitForHandlerFailure(
60
+ handler: GestureHandler,
61
+ otherHandler: GestureHandler
62
+ ): boolean {
63
+ const logger = this.logger.cloneAndJoinPrefix(`shouldWaitForHandlerFailure(${handler.getTag()}, ${otherHandler.getTag()})`)
64
+ const waitFor = this.waitForRelations.get(
65
+ handler.getTag()
66
+ );
67
+ logger.debug({waitFor: Array.from(waitFor ?? [])})
68
+ if (!waitFor) {
69
+ logger.debug("false")
70
+ return false;
71
+ }
72
+
73
+ let shouldWait = false;
74
+ waitFor.forEach((tag: number): void => {
75
+ if (tag === otherHandler.getTag()) {
76
+ shouldWait = true;
77
+ return; //Returns from callback
78
+ }
79
+ });
80
+ logger.debug(shouldWait)
81
+ return shouldWait;
82
+ }
83
+
84
+ public shouldRecognizeSimultaneously(
85
+ handler: GestureHandler,
86
+ otherHandler: GestureHandler
87
+ ): boolean {
88
+ const logger = this.logger.cloneAndJoinPrefix(`shouldRecognizeSimultaneously(${handler.getTag()}, ${otherHandler.getTag()})`)
89
+ const simultaneousHandlers: number[] | undefined =
90
+ this.simultaneousRelations.get(handler.getTag());
91
+ if (!simultaneousHandlers) {
92
+ logger.debug(`false - Handler ${handler.getTag()} doesn't have simultaneousRelations specified`)
93
+ return false;
94
+ }
95
+ let shouldRecognizeSimultaneously = false;
96
+ simultaneousHandlers.forEach((tag: number): void => {
97
+ if (tag === otherHandler.getTag()) {
98
+ shouldRecognizeSimultaneously = true;
99
+ return;
100
+ }
101
+ });
102
+ logger.debug(`${shouldRecognizeSimultaneously} ${JSON.stringify({ simultaneousHandlers })}`)
103
+ return shouldRecognizeSimultaneously;
104
+ }
105
+
106
+ public shouldRequireHandlerToWaitForFailure(
107
+ handler: GestureHandler,
108
+ otherHandler: GestureHandler
109
+ ): boolean {
110
+ const waitFor: number[] | undefined = this.blocksHandlersRelations.get(
111
+ handler.getTag()
112
+ );
113
+
114
+ return (
115
+ waitFor?.find((tag: number) => {
116
+ return tag === otherHandler.getTag();
117
+ }) !== undefined
118
+ );
119
+ }
120
+
121
+ public shouldHandlerBeCancelledBy(
122
+ handler: GestureHandler,
123
+ otherHandler: GestureHandler
124
+ ): boolean {
125
+ const logger = this.logger.cloneAndJoinPrefix(`shouldHandlerBeCancelledBy(handler=${handler.getTag()}, otherHandler=${otherHandler.getTag()})`)
126
+ // We check constructor name instead of using `instanceof` in order do avoid circular dependencies
127
+ // const isNativeHandler =
128
+ // otherHandler.constructor.name === 'NativeViewGestureHandler';
129
+ // const isActive = otherHandler.getState() === State.ACTIVE;
130
+ // const isButton = otherHandler.isButton?.() === true;
131
+ // return isNativeHandler && isActive && !isButton;
132
+ return false
133
+ }
134
+
135
+ public dropRelationsForHandlerWithTag(handlerTag: number): void {
136
+ this.waitForRelations.delete(handlerTag);
137
+ this.simultaneousRelations.delete(handlerTag);
138
+ }
139
+
140
+ public reset() {
141
+ this.waitForRelations.clear();
142
+ this.simultaneousRelations.clear();
143
+ }
144
+ }