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

Sign up to get free protection for your applications and to get access to all the features.
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
  }