@react-native-oh-tpl/react-native-gesture-handler 2.14.1-2.14.8 → 2.14.1-2.14.9

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