@react-native-oh-tpl/react-native-gesture-handler 2.12.6-1 → 2.12.6-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/harmony/gesture_handler/LICENSE +21 -0
  2. package/harmony/gesture_handler/OAT.xml +44 -0
  3. package/harmony/gesture_handler/README.OpenSource +11 -0
  4. package/harmony/gesture_handler/README.md +1 -0
  5. package/harmony/gesture_handler/build-profile.json5 +7 -7
  6. package/harmony/gesture_handler/hvigorfile.ts +2 -2
  7. package/harmony/gesture_handler/index.ets +2 -2
  8. package/harmony/gesture_handler/oh-package.json5 +13 -11
  9. package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -8
  10. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +33 -33
  11. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +14 -14
  12. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonComponentDescriptor.h +60 -60
  13. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.cpp +17 -17
  14. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.h +11 -11
  15. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentDescriptor.h +60 -60
  16. package/harmony/gesture_handler/src/main/ets/CircularBuffer.ts +42 -42
  17. package/harmony/gesture_handler/src/main/ets/Event.ts +67 -67
  18. package/harmony/gesture_handler/src/main/ets/EventDispatcher.ts +37 -37
  19. package/harmony/gesture_handler/src/main/ets/GestureHandler.ts +663 -663
  20. package/harmony/gesture_handler/src/main/ets/GestureHandlerArkUIAdapter.ets +201 -201
  21. package/harmony/gesture_handler/src/main/ets/GestureHandlerFactory.ts +44 -44
  22. package/harmony/gesture_handler/src/main/ets/GestureHandlerOrchestrator.ts +280 -280
  23. package/harmony/gesture_handler/src/main/ets/GestureHandlerPackage.ts +22 -22
  24. package/harmony/gesture_handler/src/main/ets/GestureHandlerRegistry.ts +27 -27
  25. package/harmony/gesture_handler/src/main/ets/InteractionManager.ts +108 -108
  26. package/harmony/gesture_handler/src/main/ets/LeastSquareSolver.ts +182 -182
  27. package/harmony/gesture_handler/src/main/ets/NativeViewGestureHandler.ts +114 -114
  28. package/harmony/gesture_handler/src/main/ets/OutgoingEvent.ts +33 -33
  29. package/harmony/gesture_handler/src/main/ets/PanGestureHandler.ts +327 -327
  30. package/harmony/gesture_handler/src/main/ets/PointerTracker.ts +239 -239
  31. package/harmony/gesture_handler/src/main/ets/RNGHError.ts +4 -4
  32. package/harmony/gesture_handler/src/main/ets/RNGHLogger.ts +28 -28
  33. package/harmony/gesture_handler/src/main/ets/RNGHRootTouchHandler.ets +57 -57
  34. package/harmony/gesture_handler/src/main/ets/RNGestureHandlerButton.ets +36 -36
  35. package/harmony/gesture_handler/src/main/ets/RNGestureHandlerModule.ts +125 -125
  36. package/harmony/gesture_handler/src/main/ets/RNGestureHandlerRootView.ets +56 -55
  37. package/harmony/gesture_handler/src/main/ets/RNOHScrollLocker.ts +10 -10
  38. package/harmony/gesture_handler/src/main/ets/State.ts +46 -46
  39. package/harmony/gesture_handler/src/main/ets/TapGestureHandler.ts +205 -205
  40. package/harmony/gesture_handler/src/main/ets/Vector2D.ts +36 -36
  41. package/harmony/gesture_handler/src/main/ets/VelocityTracker.ts +98 -98
  42. package/harmony/gesture_handler/src/main/ets/View.ts +70 -70
  43. package/harmony/gesture_handler/src/main/ets/ViewRegistry.ts +42 -42
  44. package/harmony/gesture_handler/src/main/ets/pages/Index.ets +16 -16
  45. package/harmony/gesture_handler/src/main/ets/webviewability/WebviewAbility.ts +41 -41
  46. package/harmony/gesture_handler/src/main/module.json5 +6 -6
  47. package/harmony/gesture_handler/src/main/resources/base/element/color.json +7 -7
  48. package/harmony/gesture_handler/src/main/resources/base/element/string.json +15 -15
  49. package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -5
  50. package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +15 -15
  51. package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +15 -15
  52. package/harmony/gesture_handler.har +0 -0
  53. package/lib/commonjs/components/touchables/GenericTouchable.js +9 -9
  54. package/lib/commonjs/components/touchables/TouchableOpacity.js +2 -2
  55. package/lib/commonjs/handlers/createNativeWrapper.js +6 -6
  56. package/lib/commonjs/handlers/gestures/GestureDetector.js +3 -3
  57. package/lib/module/components/touchables/GenericTouchable.js +9 -9
  58. package/lib/module/components/touchables/TouchableOpacity.js +2 -2
  59. package/lib/module/handlers/createNativeWrapper.js +6 -6
  60. package/lib/module/handlers/gestures/GestureDetector.js +3 -3
  61. package/package.json +70 -70
  62. package/src/RNGestureHandlerModule.ts +6 -6
  63. package/src/components/GestureButtons.tsx +334 -334
  64. package/src/components/GestureHandlerButton.tsx +5 -5
  65. package/src/components/GestureHandlerRootView.tsx +34 -34
  66. package/src/components/RNGestureHandlerButton.tsx +23 -23
  67. package/src/components/touchables/GenericTouchable.tsx +301 -301
  68. package/src/components/touchables/TouchableOpacity.tsx +76 -76
  69. package/src/components/touchables/TouchableWithoutFeedback.tsx +14 -14
  70. package/src/components/touchables/index.ts +7 -7
  71. package/src/handlers/NativeViewGestureHandler.ts +55 -55
  72. package/src/handlers/PanGestureHandler.ts +327 -327
  73. package/src/handlers/TapGestureHandler.ts +95 -95
  74. package/src/handlers/createHandler.tsx +535 -535
  75. package/src/handlers/createNativeWrapper.tsx +81 -81
  76. package/src/handlers/gestureHandlerCommon.ts +15 -15
  77. package/src/handlers/gestures/GestureDetector.tsx +823 -823
  78. package/src/index.ts +172 -172
  79. package/src/init.ts +18 -18
@@ -1,280 +1,280 @@
1
- import { GestureHandler } from "./GestureHandler"
2
- import { State } from "./State"
3
- import { PointerType } from "./Event"
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
- this.logger.info("onHandlerStateChange")
17
- if (this.shouldCancelStateChange(handler, sendIfDisabled)) return;
18
- if (this.isFinishedState(newState)) {
19
- this.handleChangingToFinishedState(handler, newState)
20
- }
21
- if (newState === State.ACTIVE) {
22
- this.tryActivate(handler)
23
- } else if (oldState === State.ACTIVE || oldState === State.END) {
24
- if (handler.isActive()) {
25
- handler.sendEvent({ newState, oldState })
26
- } else if (oldState === State.ACTIVE && (newState === State.CANCELLED || newState === State.FAILED)) {
27
- // Handle edge case where handler awaiting for another one tries to activate but finishes
28
- // before the other would not send state change event upon ending. Note that we only want
29
- // to do this if the newState is either CANCELLED or FAILED, if it is END we still want to
30
- // wait for the other handler to finish as in that case synthetic events will be sent by the
31
- // makeActive method.
32
- handler.sendEvent({ newState, oldState: State.BEGAN })
33
- }
34
- } else if (newState !== State.CANCELLED || oldState !== State.UNDETERMINED) {
35
- // If handler is changing state from UNDETERMINED to CANCELLED, the state change event shouldn't
36
- // be sent. Handler hasn't yet began so it may not be initialized which results in crashes.
37
- // If it doesn't crash, there may be some weird behavior on JS side, as `onFinalize` will be
38
- // called without calling `onBegin` first.
39
- handler.sendEvent({ newState, oldState })
40
- }
41
- this.cleanUpHandlers(handler)
42
- }
43
-
44
- private isFinishedState(state: State) {
45
- return [State.END, State.FAILED, State.CANCELLED].includes(state)
46
- }
47
-
48
- private shouldCancelStateChange(handler: GestureHandler, sendIfDisabled?: boolean) {
49
- const isHandlerDisabled = !handler.isEnabled()
50
- return!sendIfDisabled && isHandlerDisabled
51
- }
52
-
53
- private handleChangingToFinishedState(handler: GestureHandler, newState: State) {
54
- this.awaitingHandlers.forEach(awaitingHandler => {
55
- if (handler.shouldWaitFor(awaitingHandler)) {
56
- if (newState === State.END) {
57
- awaitingHandler.cancel()
58
- if (awaitingHandler.getState() === State.END) {
59
- // Handle edge case, where discrete gestures end immediately after activation thus
60
- // their state is set to END and when the gesture they are waiting for activates they
61
- // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
62
- // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
63
- awaitingHandler.sendEvent({ newState: State.CANCELLED, oldState: State.BEGAN })
64
- }
65
- awaitingHandler.setAwaiting(false)
66
- } else {
67
- this.tryActivate(awaitingHandler)
68
- }
69
- }
70
- })
71
- }
72
-
73
- private tryActivate(handler: GestureHandler): void {
74
- if (this.hasOtherHandlerToWaitFor(handler)) {
75
- this.addAwaitingHandler(handler)
76
- } else if (handler.getState() !== State.CANCELLED && handler.getState() !== State.FAILED) {
77
- if (this.shouldActivate(handler)) {
78
- this.makeActive(handler);
79
- } else {
80
- switch (handler.getState()) {
81
- case State.ACTIVE:
82
- handler.fail();
83
- break;
84
- case State.BEGAN:
85
- handler.cancel();
86
- break;
87
- }
88
- }
89
- }
90
- }
91
-
92
- private hasOtherHandlerToWaitFor(handler: GestureHandler): boolean {
93
- for (const otherHandler of this.gestureHandlers) {
94
- if (!this.isFinishedState(otherHandler.getState()) && otherHandler.shouldWaitFor(handler)) {
95
- return true
96
- }
97
- }
98
- return false;
99
- }
100
-
101
- private addAwaitingHandler(handler: GestureHandler) {
102
- if (!this.awaitingHandlers.has(handler)) {
103
- this.awaitingHandlers.add(handler)
104
- handler.setAwaiting(true)
105
- handler.setActivationIndex(this.activationIndex++)
106
- }
107
- }
108
-
109
- private shouldActivate(handler: GestureHandler) {
110
- for (const otherHandler of this.gestureHandlers) {
111
- if (this.shouldHandlerBeCancelledByOtherHandler({ handler, otherHandler })) {
112
- return false
113
- }
114
- }
115
- return true
116
- }
117
-
118
- private shouldHandlerBeCancelledByOtherHandler({handler, otherHandler}: {
119
- handler: GestureHandler,
120
- otherHandler: GestureHandler
121
- }): boolean {
122
- if (this.canRunSimultaneously(handler, otherHandler))
123
- return false;
124
- if (handler !== otherHandler && (handler.isAwaiting() || handler.getState() === State.ACTIVE))
125
- return handler.shouldBeCancelledByOther(otherHandler)
126
- return this.checkOverlap(handler, otherHandler)
127
- }
128
-
129
- private canRunSimultaneously(handlerA: GestureHandler, handlerB: GestureHandler) {
130
- return handlerA === handlerB
131
- || handlerA.shouldRecognizeSimultaneously(handlerB)
132
- || handlerB.shouldRecognizeSimultaneously(handlerA)
133
- }
134
-
135
- private checkOverlap(
136
- handler: GestureHandler,
137
- otherHandler: GestureHandler
138
- ): boolean {
139
- // If handlers don't have common pointers, default return value is false.
140
- // However, if at least on pointer overlaps with both handlers, we return true
141
- // This solves issue in overlapping parents example
142
-
143
- // TODO: Find better way to handle that issue, for example by activation order and handler cancelling
144
-
145
- const handlerPointers: number[] = handler.getTrackedPointersID();
146
- const otherPointers: number[] = otherHandler.getTrackedPointersID();
147
- let overlap = false;
148
- handlerPointers.forEach((pointer: number) => {
149
- const handlerX: number = handler.getTracker().getLastX(pointer);
150
- const handlerY: number = handler.getTracker().getLastY(pointer);
151
- if (
152
- handler.getView().isPositionInBounds({ x: handlerX, y: handlerY }) &&
153
- otherHandler.getView().isPositionInBounds({ x: handlerX, y: handlerY })
154
- ) {
155
- overlap = true;
156
- }
157
- });
158
- otherPointers.forEach((pointer: number) => {
159
- const otherX: number = otherHandler.getTracker().getLastX(pointer);
160
- const otherY: number = otherHandler.getTracker().getLastY(pointer);
161
- if (
162
- handler.getView().isPositionInBounds({ x: otherX, y: otherY }) &&
163
- otherHandler.getView().isPositionInBounds({ x: otherX, y: otherY })
164
- ) {
165
- overlap = true;
166
- }
167
- });
168
- return overlap;
169
- }
170
-
171
- private makeActive(handler: GestureHandler): void {
172
- handler.setActive(true)
173
- handler.setShouldResetProgress(true)
174
- handler.setActivationIndex(this.activationIndex++)
175
- for (const otherHandler of this.gestureHandlers) {
176
- if (this.shouldHandlerBeCancelledByOtherHandler({ handler: otherHandler, otherHandler: handler })) {
177
- this.handlersToCancel.push(otherHandler)
178
- }
179
- }
180
- for (let i = this.handlersToCancel.length - 1; i >= 0; --i) {
181
- this.handlersToCancel[i]?.cancel();
182
- }
183
- this.handlersToCancel = []
184
- for (const awaitingHandler of this.awaitingHandlers) {
185
- if (this.shouldHandlerBeCancelledByOtherHandler({ handler: awaitingHandler, otherHandler: handler })) {
186
- awaitingHandler.cancel();
187
- awaitingHandler.setAwaiting(true);
188
- }
189
- }
190
- const currentState = handler.getState()
191
- handler.sendEvent({ newState: State.ACTIVE, oldState: State.BEGAN })
192
- if (currentState !== State.ACTIVE) {
193
- handler.sendEvent({ newState: State.END, oldState: State.ACTIVE })
194
- if (currentState !== State.END) {
195
- handler.sendEvent({ newState: State.UNDETERMINED, oldState: State.END })
196
- }
197
- }
198
- if (handler.isAwaiting()) {
199
- handler.setAwaiting(false)
200
- this.awaitingHandlers.delete(handler)
201
- }
202
- }
203
-
204
- private cleanUpHandlers(handler: GestureHandler) {
205
- this.cleanUpFinishedHandlers()
206
- if (this.awaitingHandlers.has(handler)) {
207
- this.cleanupAwaitingHandlers(handler);
208
- }
209
- }
210
-
211
- private cleanUpFinishedHandlers(): void {
212
- for (let i = this.gestureHandlers.length - 1; i >= 0; --i) {
213
- const handler = this.gestureHandlers[i];
214
- if (!handler) {
215
- continue;
216
- }
217
- if (this.isFinishedState(handler.getState()) && !handler.isAwaiting()) {
218
- this.gestureHandlers.splice(i, 1);
219
- this.cleanUpHandler(handler);
220
- }
221
- }
222
- }
223
-
224
- private cleanupAwaitingHandlers(handler: GestureHandler): void {
225
- for (const awaitingHandler of this.awaitingHandlers) {
226
- if (
227
- awaitingHandler.isAwaiting() &&
228
- awaitingHandler.shouldWaitFor(handler)
229
- ) {
230
- this.cleanUpHandler(awaitingHandler);
231
- this.awaitingHandlers.delete(awaitingHandler)
232
- }
233
- }
234
- }
235
-
236
- private cleanUpHandler(handler: GestureHandler) {
237
- handler.reset();
238
- handler.setActive(false);
239
- handler.setAwaiting(false);
240
- handler.setActivationIndex(Number.MAX_VALUE);
241
- }
242
-
243
- public registerHandlerIfNotPresent(handler: GestureHandler) {
244
- this.logger.info("registerHandlerIfNotPresent")
245
- if (this.gestureHandlers.includes(handler)) return;
246
- this.gestureHandlers.push(handler);
247
- handler.setActive(false);
248
- handler.setAwaiting(false);
249
- handler.setActivationIndex(Number.MAX_SAFE_INTEGER);
250
- }
251
-
252
- /**
253
- This function is called when handler receives touchdown event
254
- If handler is using mouse or pen as a pointer and any handler receives touch event,
255
- mouse/pen event disappears - it doesn't send onPointerCancel nor onPointerUp (and others)
256
- This became a problem because handler was left at active state without any signal to end or fail
257
- To handle this, when new touch event is received, we loop through active handlers and check which type of
258
- pointer they're using. If there are any handler with mouse/pen as a pointer, we cancel them
259
- */
260
- public cancelMouseAndPenGestures(currentHandler: GestureHandler): void {
261
- this.logger.info("cancelMouseAndPenGestures")
262
- this.gestureHandlers.forEach((handler: GestureHandler) => {
263
- if (handler.getPointerType() !== PointerType.MOUSE && handler.getPointerType() !== PointerType.PEN) return;
264
-
265
- if (handler !== currentHandler) {
266
- handler.cancel();
267
- } else {
268
- // Handler that received touch event should have its pointer tracker reset
269
- // This allows handler to smoothly change from mouse/pen to touch
270
- // The drawback is, that when we try to use mouse/pen one more time, it doesn't send onPointerDown at the first time
271
- // so it is required to click two times to get handler to work
272
- //
273
- // However, handler will receive manually created onPointerEnter that is triggered in EventManager in onPointerMove method.
274
- // There may be possibility to use that fact to make handler respond properly to first mouse click
275
- handler.getTracker().resetTracker();
276
- }
277
- });
278
- }
279
- }
280
-
1
+ import { GestureHandler } from "./GestureHandler"
2
+ import { State } from "./State"
3
+ import { PointerType } from "./Event"
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
+ this.logger.info("onHandlerStateChange")
17
+ if (this.shouldCancelStateChange(handler, sendIfDisabled)) return;
18
+ if (this.isFinishedState(newState)) {
19
+ this.handleChangingToFinishedState(handler, newState)
20
+ }
21
+ if (newState === State.ACTIVE) {
22
+ this.tryActivate(handler)
23
+ } else if (oldState === State.ACTIVE || oldState === State.END) {
24
+ if (handler.isActive()) {
25
+ handler.sendEvent({ newState, oldState })
26
+ } else if (oldState === State.ACTIVE && (newState === State.CANCELLED || newState === State.FAILED)) {
27
+ // Handle edge case where handler awaiting for another one tries to activate but finishes
28
+ // before the other would not send state change event upon ending. Note that we only want
29
+ // to do this if the newState is either CANCELLED or FAILED, if it is END we still want to
30
+ // wait for the other handler to finish as in that case synthetic events will be sent by the
31
+ // makeActive method.
32
+ handler.sendEvent({ newState, oldState: State.BEGAN })
33
+ }
34
+ } else if (newState !== State.CANCELLED || oldState !== State.UNDETERMINED) {
35
+ // If handler is changing state from UNDETERMINED to CANCELLED, the state change event shouldn't
36
+ // be sent. Handler hasn't yet began so it may not be initialized which results in crashes.
37
+ // If it doesn't crash, there may be some weird behavior on JS side, as `onFinalize` will be
38
+ // called without calling `onBegin` first.
39
+ handler.sendEvent({ newState, oldState })
40
+ }
41
+ this.cleanUpHandlers(handler)
42
+ }
43
+
44
+ private isFinishedState(state: State) {
45
+ return [State.END, State.FAILED, State.CANCELLED].includes(state)
46
+ }
47
+
48
+ private shouldCancelStateChange(handler: GestureHandler, sendIfDisabled?: boolean) {
49
+ const isHandlerDisabled = !handler.isEnabled()
50
+ return!sendIfDisabled && isHandlerDisabled
51
+ }
52
+
53
+ private handleChangingToFinishedState(handler: GestureHandler, newState: State) {
54
+ this.awaitingHandlers.forEach(awaitingHandler => {
55
+ if (handler.shouldWaitFor(awaitingHandler)) {
56
+ if (newState === State.END) {
57
+ awaitingHandler.cancel()
58
+ if (awaitingHandler.getState() === State.END) {
59
+ // Handle edge case, where discrete gestures end immediately after activation thus
60
+ // their state is set to END and when the gesture they are waiting for activates they
61
+ // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
62
+ // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
63
+ awaitingHandler.sendEvent({ newState: State.CANCELLED, oldState: State.BEGAN })
64
+ }
65
+ awaitingHandler.setAwaiting(false)
66
+ } else {
67
+ this.tryActivate(awaitingHandler)
68
+ }
69
+ }
70
+ })
71
+ }
72
+
73
+ private tryActivate(handler: GestureHandler): void {
74
+ if (this.hasOtherHandlerToWaitFor(handler)) {
75
+ this.addAwaitingHandler(handler)
76
+ } else if (handler.getState() !== State.CANCELLED && handler.getState() !== State.FAILED) {
77
+ if (this.shouldActivate(handler)) {
78
+ this.makeActive(handler);
79
+ } else {
80
+ switch (handler.getState()) {
81
+ case State.ACTIVE:
82
+ handler.fail();
83
+ break;
84
+ case State.BEGAN:
85
+ handler.cancel();
86
+ break;
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ private hasOtherHandlerToWaitFor(handler: GestureHandler): boolean {
93
+ for (const otherHandler of this.gestureHandlers) {
94
+ if (!this.isFinishedState(otherHandler.getState()) && otherHandler.shouldWaitFor(handler)) {
95
+ return true
96
+ }
97
+ }
98
+ return false;
99
+ }
100
+
101
+ private addAwaitingHandler(handler: GestureHandler) {
102
+ if (!this.awaitingHandlers.has(handler)) {
103
+ this.awaitingHandlers.add(handler)
104
+ handler.setAwaiting(true)
105
+ handler.setActivationIndex(this.activationIndex++)
106
+ }
107
+ }
108
+
109
+ private shouldActivate(handler: GestureHandler) {
110
+ for (const otherHandler of this.gestureHandlers) {
111
+ if (this.shouldHandlerBeCancelledByOtherHandler({ handler, otherHandler })) {
112
+ return false
113
+ }
114
+ }
115
+ return true
116
+ }
117
+
118
+ private shouldHandlerBeCancelledByOtherHandler({handler, otherHandler}: {
119
+ handler: GestureHandler,
120
+ otherHandler: GestureHandler
121
+ }): boolean {
122
+ if (this.canRunSimultaneously(handler, otherHandler))
123
+ return false;
124
+ if (handler !== otherHandler && (handler.isAwaiting() || handler.getState() === State.ACTIVE))
125
+ return handler.shouldBeCancelledByOther(otherHandler)
126
+ return this.checkOverlap(handler, otherHandler)
127
+ }
128
+
129
+ private canRunSimultaneously(handlerA: GestureHandler, handlerB: GestureHandler) {
130
+ return handlerA === handlerB
131
+ || handlerA.shouldRecognizeSimultaneously(handlerB)
132
+ || handlerB.shouldRecognizeSimultaneously(handlerA)
133
+ }
134
+
135
+ private checkOverlap(
136
+ handler: GestureHandler,
137
+ otherHandler: GestureHandler
138
+ ): boolean {
139
+ // If handlers don't have common pointers, default return value is false.
140
+ // However, if at least on pointer overlaps with both handlers, we return true
141
+ // This solves issue in overlapping parents example
142
+
143
+ // TODO: Find better way to handle that issue, for example by activation order and handler cancelling
144
+
145
+ const handlerPointers: number[] = handler.getTrackedPointersID();
146
+ const otherPointers: number[] = otherHandler.getTrackedPointersID();
147
+ let overlap = false;
148
+ handlerPointers.forEach((pointer: number) => {
149
+ const handlerX: number = handler.getTracker().getLastX(pointer);
150
+ const handlerY: number = handler.getTracker().getLastY(pointer);
151
+ if (
152
+ handler.getView().isPositionInBounds({ x: handlerX, y: handlerY }) &&
153
+ otherHandler.getView().isPositionInBounds({ x: handlerX, y: handlerY })
154
+ ) {
155
+ overlap = true;
156
+ }
157
+ });
158
+ otherPointers.forEach((pointer: number) => {
159
+ const otherX: number = otherHandler.getTracker().getLastX(pointer);
160
+ const otherY: number = otherHandler.getTracker().getLastY(pointer);
161
+ if (
162
+ handler.getView().isPositionInBounds({ x: otherX, y: otherY }) &&
163
+ otherHandler.getView().isPositionInBounds({ x: otherX, y: otherY })
164
+ ) {
165
+ overlap = true;
166
+ }
167
+ });
168
+ return overlap;
169
+ }
170
+
171
+ private makeActive(handler: GestureHandler): void {
172
+ handler.setActive(true)
173
+ handler.setShouldResetProgress(true)
174
+ handler.setActivationIndex(this.activationIndex++)
175
+ for (const otherHandler of this.gestureHandlers) {
176
+ if (this.shouldHandlerBeCancelledByOtherHandler({ handler: otherHandler, otherHandler: handler })) {
177
+ this.handlersToCancel.push(otherHandler)
178
+ }
179
+ }
180
+ for (let i = this.handlersToCancel.length - 1; i >= 0; --i) {
181
+ this.handlersToCancel[i]?.cancel();
182
+ }
183
+ this.handlersToCancel = []
184
+ for (const awaitingHandler of this.awaitingHandlers) {
185
+ if (this.shouldHandlerBeCancelledByOtherHandler({ handler: awaitingHandler, otherHandler: handler })) {
186
+ awaitingHandler.cancel();
187
+ awaitingHandler.setAwaiting(true);
188
+ }
189
+ }
190
+ const currentState = handler.getState()
191
+ handler.sendEvent({ newState: State.ACTIVE, oldState: State.BEGAN })
192
+ if (currentState !== State.ACTIVE) {
193
+ handler.sendEvent({ newState: State.END, oldState: State.ACTIVE })
194
+ if (currentState !== State.END) {
195
+ handler.sendEvent({ newState: State.UNDETERMINED, oldState: State.END })
196
+ }
197
+ }
198
+ if (handler.isAwaiting()) {
199
+ handler.setAwaiting(false)
200
+ this.awaitingHandlers.delete(handler)
201
+ }
202
+ }
203
+
204
+ private cleanUpHandlers(handler: GestureHandler) {
205
+ this.cleanUpFinishedHandlers()
206
+ if (this.awaitingHandlers.has(handler)) {
207
+ this.cleanupAwaitingHandlers(handler);
208
+ }
209
+ }
210
+
211
+ private cleanUpFinishedHandlers(): void {
212
+ for (let i = this.gestureHandlers.length - 1; i >= 0; --i) {
213
+ const handler = this.gestureHandlers[i];
214
+ if (!handler) {
215
+ continue;
216
+ }
217
+ if (this.isFinishedState(handler.getState()) && !handler.isAwaiting()) {
218
+ this.gestureHandlers.splice(i, 1);
219
+ this.cleanUpHandler(handler);
220
+ }
221
+ }
222
+ }
223
+
224
+ private cleanupAwaitingHandlers(handler: GestureHandler): void {
225
+ for (const awaitingHandler of this.awaitingHandlers) {
226
+ if (
227
+ awaitingHandler.isAwaiting() &&
228
+ awaitingHandler.shouldWaitFor(handler)
229
+ ) {
230
+ this.cleanUpHandler(awaitingHandler);
231
+ this.awaitingHandlers.delete(awaitingHandler)
232
+ }
233
+ }
234
+ }
235
+
236
+ private cleanUpHandler(handler: GestureHandler) {
237
+ handler.reset();
238
+ handler.setActive(false);
239
+ handler.setAwaiting(false);
240
+ handler.setActivationIndex(Number.MAX_VALUE);
241
+ }
242
+
243
+ public registerHandlerIfNotPresent(handler: GestureHandler) {
244
+ this.logger.info("registerHandlerIfNotPresent")
245
+ if (this.gestureHandlers.includes(handler)) return;
246
+ this.gestureHandlers.push(handler);
247
+ handler.setActive(false);
248
+ handler.setAwaiting(false);
249
+ handler.setActivationIndex(Number.MAX_SAFE_INTEGER);
250
+ }
251
+
252
+ /**
253
+ This function is called when handler receives touchdown event
254
+ If handler is using mouse or pen as a pointer and any handler receives touch event,
255
+ mouse/pen event disappears - it doesn't send onPointerCancel nor onPointerUp (and others)
256
+ This became a problem because handler was left at active state without any signal to end or fail
257
+ To handle this, when new touch event is received, we loop through active handlers and check which type of
258
+ pointer they're using. If there are any handler with mouse/pen as a pointer, we cancel them
259
+ */
260
+ public cancelMouseAndPenGestures(currentHandler: GestureHandler): void {
261
+ this.logger.info("cancelMouseAndPenGestures")
262
+ this.gestureHandlers.forEach((handler: GestureHandler) => {
263
+ if (handler.getPointerType() !== PointerType.MOUSE && handler.getPointerType() !== PointerType.PEN) return;
264
+
265
+ if (handler !== currentHandler) {
266
+ handler.cancel();
267
+ } else {
268
+ // Handler that received touch event should have its pointer tracker reset
269
+ // This allows handler to smoothly change from mouse/pen to touch
270
+ // The drawback is, that when we try to use mouse/pen one more time, it doesn't send onPointerDown at the first time
271
+ // so it is required to click two times to get handler to work
272
+ //
273
+ // However, handler will receive manually created onPointerEnter that is triggered in EventManager in onPointerMove method.
274
+ // There may be possibility to use that fact to make handler respond properly to first mouse click
275
+ handler.getTracker().resetTracker();
276
+ }
277
+ });
278
+ }
279
+ }
280
+
@@ -1,22 +1,22 @@
1
- import {RNPackage, TurboModuleContext, TurboModulesFactory} from 'rnoh/ts';
2
- import type {TurboModule} from 'rnoh/ts';
3
- import {RNGestureHandlerModule} from './RNGestureHandlerModule';
4
-
5
- class GestureHandlerTurboModulesFactory extends TurboModulesFactory {
6
- createTurboModule(name: string): TurboModule | null {
7
- if (name === RNGestureHandlerModule.NAME) {
8
- return new RNGestureHandlerModule(this.ctx);
9
- }
10
- return null;
11
- }
12
-
13
- hasTurboModule(name: string): boolean {
14
- return name === 'RNGestureHandlerModule';
15
- }
16
- }
17
-
18
- export class GestureHandlerPackage extends RNPackage {
19
- createTurboModulesFactory(ctx: TurboModuleContext): TurboModulesFactory {
20
- return new GestureHandlerTurboModulesFactory(ctx);
21
- }
22
- }
1
+ import {RNPackage, TurboModuleContext, TurboModulesFactory} from 'rnoh/ts';
2
+ import type {TurboModule} from 'rnoh/ts';
3
+ import {RNGestureHandlerModule} from './RNGestureHandlerModule';
4
+
5
+ class GestureHandlerTurboModulesFactory extends TurboModulesFactory {
6
+ createTurboModule(name: string): TurboModule | null {
7
+ if (name === RNGestureHandlerModule.NAME) {
8
+ return new RNGestureHandlerModule(this.ctx);
9
+ }
10
+ return null;
11
+ }
12
+
13
+ hasTurboModule(name: string): boolean {
14
+ return name === 'RNGestureHandlerModule';
15
+ }
16
+ }
17
+
18
+ export class GestureHandlerPackage extends RNPackage {
19
+ createTurboModulesFactory(ctx: TurboModuleContext): TurboModulesFactory {
20
+ return new GestureHandlerTurboModulesFactory(ctx);
21
+ }
22
+ }
@@ -1,28 +1,28 @@
1
- import { GestureHandler } from "./GestureHandler"
2
- import { View } from "./View"
3
-
4
- export class GestureHandlerRegistry {
5
- private gestureHandlerByHandlerTag: Map<number, GestureHandler> = new Map()
6
- private gestureHandlersByViewTag: Map<number, Set<GestureHandler>> = new Map()
7
-
8
- public addGestureHandler(gestureHandler: GestureHandler) {
9
- this.gestureHandlerByHandlerTag.set(gestureHandler.getTag(), gestureHandler)
10
- }
11
-
12
- public bindGestureHandlerWithView(gestureHandlerTag: number, view: View) {
13
- const viewTag = view.getTag()
14
- if (!this.gestureHandlersByViewTag.has(viewTag))
15
- this.gestureHandlersByViewTag.set(viewTag, new Set())
16
- const gestureHandler = this.gestureHandlerByHandlerTag.get(gestureHandlerTag)
17
- this.gestureHandlersByViewTag.get(viewTag).add(gestureHandler)
18
- gestureHandler.onViewAttached(view)
19
- }
20
-
21
- public getGestureHandlersByViewTag(viewTag: number): GestureHandler[] {
22
- return Array.from(this.gestureHandlersByViewTag.get(viewTag) ?? [])
23
- }
24
-
25
- public getGestureHandlerByHandlerTag(handlerTag: number): GestureHandler {
26
- return this.gestureHandlerByHandlerTag.get(handlerTag)
27
- }
1
+ import { GestureHandler } from "./GestureHandler"
2
+ import { View } from "./View"
3
+
4
+ export class GestureHandlerRegistry {
5
+ private gestureHandlerByHandlerTag: Map<number, GestureHandler> = new Map()
6
+ private gestureHandlersByViewTag: Map<number, Set<GestureHandler>> = new Map()
7
+
8
+ public addGestureHandler(gestureHandler: GestureHandler) {
9
+ this.gestureHandlerByHandlerTag.set(gestureHandler.getTag(), gestureHandler)
10
+ }
11
+
12
+ public bindGestureHandlerWithView(gestureHandlerTag: number, view: View) {
13
+ const viewTag = view.getTag()
14
+ if (!this.gestureHandlersByViewTag.has(viewTag))
15
+ this.gestureHandlersByViewTag.set(viewTag, new Set())
16
+ const gestureHandler = this.gestureHandlerByHandlerTag.get(gestureHandlerTag)
17
+ this.gestureHandlersByViewTag.get(viewTag).add(gestureHandler)
18
+ gestureHandler.onViewAttached(view)
19
+ }
20
+
21
+ public getGestureHandlersByViewTag(viewTag: number): GestureHandler[] {
22
+ return Array.from(this.gestureHandlersByViewTag.get(viewTag) ?? [])
23
+ }
24
+
25
+ public getGestureHandlerByHandlerTag(handlerTag: number): GestureHandler {
26
+ return this.gestureHandlerByHandlerTag.get(handlerTag)
27
+ }
28
28
  }