@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,663 +1,663 @@
1
- import type { GestureHandlerOrchestrator } from "./GestureHandlerOrchestrator"
2
- import type { PointerTracker } from "./PointerTracker"
3
- import type { View } from "./View"
4
- import type { EventDispatcher } from "./EventDispatcher"
5
- import type { InteractionManager } from "./InteractionManager"
6
- import type { RNGHLogger } from './RNGHLogger'
7
- import { State, getStateName } from "./State"
8
- import { HitSlop, Directions, AdaptedEvent, PointerType, TouchEventType, EventType } from "./Event"
9
- import { GestureStateChangeEvent, GestureTouchEvent, TouchData } from "./OutgoingEvent"
10
-
11
-
12
- export interface Handler {
13
- handlerTag: number;
14
- }
15
-
16
- export const DEFAULT_TOUCH_SLOP = 15;
17
-
18
- export interface GestureConfig {
19
- enabled?: boolean;
20
- simultaneousHandlers?: Handler[] | null;
21
- waitFor?: Handler[] | null;
22
- hitSlop?: HitSlop;
23
- shouldCancelWhenOutside?: boolean;
24
- activateAfterLongPress?: number;
25
- failOffsetXStart?: number;
26
- failOffsetYStart?: number;
27
- failOffsetXEnd?: number;
28
- failOffsetYEnd?: number;
29
- activeOffsetXStart?: number;
30
- activeOffsetXEnd?: number;
31
- activeOffsetYStart?: number;
32
- activeOffsetYEnd?: number;
33
- minPointers?: number;
34
- maxPointers?: number;
35
- minDist?: number;
36
- minDistSq?: number;
37
- minVelocity?: number;
38
- minVelocityX?: number;
39
- minVelocityY?: number;
40
- minVelocitySq?: number;
41
- maxDist?: number;
42
- maxDistSq?: number;
43
- numberOfPointers?: number;
44
- minDurationMs?: number;
45
- numberOfTaps?: number;
46
- maxDurationMs?: number;
47
- maxDelayMs?: number;
48
- maxDeltaX?: number;
49
- maxDeltaY?: number;
50
- shouldActivateOnStart?: boolean;
51
- disallowInterruption?: boolean;
52
- direction?: typeof Directions;
53
- needsPointerData?: boolean
54
- // --- Tap
55
- minNumberOfPointers?: number
56
- }
57
-
58
- type PointerId = number
59
-
60
- export interface ScrollLocker {
61
- lockScrollContainingViewTag(viewTag: number): () => void
62
- }
63
-
64
- export type GestureHandlerDependencies = {
65
- handlerTag: number
66
- orchestrator: GestureHandlerOrchestrator
67
- tracker: PointerTracker
68
- interactionManager: InteractionManager
69
- logger: RNGHLogger
70
- scrollLocker: ScrollLocker
71
- }
72
-
73
- export abstract class GestureHandler<TGestureConfig extends GestureConfig = GestureConfig> {
74
- protected config: TGestureConfig = this.getDefaultConfig()
75
- protected currentState: State = State.UNDETERMINED
76
- protected view: View | undefined = undefined
77
- protected lastSentState: State | undefined = undefined
78
- protected shouldCancelWhenOutside = false
79
-
80
- protected isActivated = false
81
- protected isAwaiting_ = false
82
- protected pointerType: PointerType
83
- protected activationIndex = 0
84
- protected shouldResetProgress = false;
85
-
86
- protected handlerTag: number
87
- protected orchestrator: GestureHandlerOrchestrator
88
- protected tracker: PointerTracker
89
- protected eventDispatcher: EventDispatcher
90
- protected interactionManager: InteractionManager
91
- protected logger: RNGHLogger
92
- protected scrollLocker: ScrollLocker
93
-
94
- constructor(deps: GestureHandlerDependencies
95
- ) {
96
- this.handlerTag = deps.handlerTag
97
- this.orchestrator = deps.orchestrator
98
- this.tracker = deps.tracker
99
- this.interactionManager = deps.interactionManager
100
- this.logger = deps.logger
101
- this.scrollLocker = deps.scrollLocker
102
- }
103
-
104
- public setEventDispatcher(eventDispatcher: EventDispatcher) {
105
- // TurboModule provides info about kind of event dispatcher when attaching GH to a view, not when GH is created.
106
- // This method must be called before any other
107
- this.eventDispatcher = eventDispatcher
108
- }
109
-
110
- public onPointerDown(e: AdaptedEvent) {
111
- this.logger.info("onPointerDown")
112
- this.orchestrator.registerHandlerIfNotPresent(this);
113
- this.pointerType = e.pointerType;
114
- if (this.pointerType === PointerType.TOUCH) {
115
- this.orchestrator.cancelMouseAndPenGestures(this);
116
- }
117
- if (this.config.needsPointerData) {
118
- this.sendTouchEvent(e);
119
- }
120
- }
121
-
122
- protected sendTouchEvent(e: AdaptedEvent) {
123
- if (!this.config.enabled) {
124
- return;
125
- }
126
-
127
-
128
- const touchEvent: GestureTouchEvent | undefined =
129
- this.transformToTouchEvent(e);
130
-
131
- if (touchEvent) {
132
- this.eventDispatcher.onGestureHandlerEvent(touchEvent)
133
- }
134
- }
135
-
136
- protected transformToTouchEvent(event: AdaptedEvent): GestureTouchEvent | undefined {
137
- const rect = this.view.getBoundingRect();
138
-
139
- const all: TouchData[] = [];
140
- const changed: TouchData[] = [];
141
-
142
- const trackerData = this.tracker.getData();
143
-
144
- // This if handles edge case where all pointers have been cancelled
145
- // When pointercancel is triggered, reset method is called. This means that tracker will be reset after first pointer being cancelled
146
- // The problem is, that handler will receive another pointercancel event from the rest of the pointers
147
- // To avoid crashing, we don't send event if tracker tracks no pointers, i.e. has been reset
148
- if (trackerData.size === 0 || !trackerData.has(event.pointerId)) {
149
- return;
150
- }
151
-
152
- trackerData.forEach((element, key): void => {
153
- const id: number = this.tracker.getMappedTouchEventId(key);
154
-
155
- all.push({
156
- id: id,
157
- x: element.lastX - rect.x,
158
- y: element.lastY - rect.y,
159
- absoluteX: element.lastX,
160
- absoluteY: element.lastY,
161
- });
162
- });
163
-
164
- // Each pointer sends its own event, so we want changed touches to contain only the pointer that has changed.
165
- // However, if the event is cancel, we want to cancel all pointers to avoid crashes
166
- if (event.eventType !== EventType.CANCEL) {
167
- changed.push({
168
- id: this.tracker.getMappedTouchEventId(event.pointerId),
169
- x: event.x - rect.x,
170
- y: event.y - rect.y,
171
- absoluteX: event.x,
172
- absoluteY: event.y,
173
- });
174
- } else {
175
- trackerData.forEach((element, key: number): void => {
176
- const id: number = this.tracker.getMappedTouchEventId(key);
177
-
178
- changed.push({
179
- id: id,
180
- x: element.lastX - rect.x,
181
- y: element.lastY - rect.y,
182
- absoluteX: element.lastX,
183
- absoluteY: element.lastY,
184
- });
185
- });
186
- }
187
-
188
- let eventType: TouchEventType = TouchEventType.UNDETERMINED;
189
-
190
- switch (event.eventType) {
191
- case EventType.DOWN:
192
- case EventType.ADDITIONAL_POINTER_DOWN:
193
- eventType = TouchEventType.DOWN;
194
- break;
195
- case EventType.UP:
196
- case EventType.ADDITIONAL_POINTER_UP:
197
- eventType = TouchEventType.UP;
198
- break;
199
- case EventType.MOVE:
200
- eventType = TouchEventType.MOVE;
201
- break;
202
- case EventType.CANCEL:
203
- eventType = TouchEventType.CANCELLED;
204
- break;
205
- }
206
-
207
- // Here, when we receive up event, we want to decrease number of touches
208
- // That's because we want handler to send information that there's one pointer less
209
- // However, we still want this pointer to be present in allTouches array, so that its data can be accessed
210
- let numberOfTouches: number = all.length;
211
-
212
- if (
213
- event.eventType === EventType.UP ||
214
- event.eventType === EventType.ADDITIONAL_POINTER_UP
215
- ) {
216
- --numberOfTouches;
217
- }
218
-
219
- return {
220
- handlerTag: this.handlerTag,
221
- state: this.currentState,
222
- eventType: event.touchEventType ?? eventType,
223
- changedTouches: changed,
224
- allTouches: all,
225
- numberOfTouches: numberOfTouches,
226
- };
227
- }
228
-
229
- public onPointerUp(e: AdaptedEvent): void {
230
- this.logger.info("onPointerUp")
231
- if (this.config.needsPointerData) this.sendTouchEvent(e)
232
- }
233
-
234
- public onAdditionalPointerAdd(e: AdaptedEvent): void {
235
- this.logger.info("onAdditionalPointerAdd")
236
- if (this.config.needsPointerData) this.sendTouchEvent(e)
237
- }
238
-
239
- public onAdditionalPointerRemove(e: AdaptedEvent): void {
240
- this.logger.info("onAdditionalPointerRemove")
241
- if (this.config.needsPointerData) this.sendTouchEvent(e)
242
- }
243
-
244
- public onPointerMove(e: AdaptedEvent): void {
245
- this.logger.info("onPointerMove")
246
- this.tryToSendMoveEvent(false);
247
- if (this.config.needsPointerData) {
248
- this.sendTouchEvent(e);
249
- }
250
- }
251
-
252
- private tryToSendMoveEvent(out: boolean): void {
253
- this.logger.info(`tryToSendMoveEvent ${JSON.stringify({
254
- out,
255
- enabled: this.config.enabled,
256
- isActivated: this.isActivated,
257
- shouldCancelWhenOutside: this.shouldCancelWhenOutside
258
- })}`)
259
- if (
260
- this.config.enabled &&
261
- this.isActivated &&
262
- (!out || (out && !this.shouldCancelWhenOutside))
263
- ) {
264
- this.sendEvent({ newState: this.currentState, oldState: this.currentState });
265
- }
266
- }
267
-
268
- public onPointerEnter(e: AdaptedEvent): void {
269
- this.logger.info("onPointerEnter")
270
- if (this.config.needsPointerData) {
271
- this.sendTouchEvent(e)
272
- }
273
- }
274
-
275
- public onPointerOut(e: AdaptedEvent): void {
276
- this.logger.info("onPointerOut")
277
- if (this.shouldCancelWhenOutside) {
278
- switch (this.currentState) {
279
- case State.ACTIVE:
280
- this.cancel();
281
- break;
282
- case State.BEGAN:
283
- this.fail();
284
- break;
285
- }
286
- return;
287
- }
288
- if (this.config.needsPointerData) {
289
- this.sendTouchEvent(e);
290
- }
291
- }
292
-
293
- public onPointerCancel(e: AdaptedEvent): void {
294
- this.logger.info("onPointerCancel")
295
- if (this.config.needsPointerData) {
296
- this.sendTouchEvent(e);
297
- }
298
- this.cancel();
299
- this.reset();
300
- }
301
-
302
- public onPointerOutOfBounds(e: AdaptedEvent): void {
303
- this.logger.info("onPointerOutOfBounds")
304
- this.tryToSendMoveEvent(true);
305
- if (this.config.needsPointerData) {
306
- this.sendTouchEvent(e);
307
- }
308
- }
309
-
310
- public onViewAttached(view: View) {
311
- this.logger.info("onViewAttached")
312
- this.view = view
313
- }
314
-
315
- public getTag(): number {
316
- return this.handlerTag
317
- }
318
-
319
- public getTracker() {
320
- return this.tracker
321
- }
322
-
323
- public getView() {
324
- return this.view
325
- }
326
-
327
- protected begin(): void {
328
- this.logger.info("begin")
329
- if (!this.isWithinHitSlop()) return;
330
- if (this.currentState === State.UNDETERMINED) {
331
- this.moveToState(State.BEGAN);
332
- }
333
- }
334
-
335
- private isWithinHitSlop(): boolean {
336
- if (!this.config.hitSlop) {
337
- return true;
338
- }
339
-
340
- const width = this.view.getBoundingRect().width;
341
- const height = this.view.getBoundingRect().height;
342
-
343
- let left = 0;
344
- let top = 0;
345
- let right: number = width;
346
- let bottom: number = height;
347
-
348
- if (this.config.hitSlop.horizontal !== undefined) {
349
- left -= this.config.hitSlop.horizontal;
350
- right += this.config.hitSlop.horizontal;
351
- }
352
-
353
- if (this.config.hitSlop.vertical !== undefined) {
354
- top -= this.config.hitSlop.vertical;
355
- bottom += this.config.hitSlop.vertical;
356
- }
357
-
358
- if (this.config.hitSlop.left !== undefined) {
359
- left = -this.config.hitSlop.left;
360
- }
361
-
362
- if (this.config.hitSlop.right !== undefined) {
363
- right = width + this.config.hitSlop.right;
364
- }
365
-
366
- if (this.config.hitSlop.top !== undefined) {
367
- top = -this.config.hitSlop.top;
368
- }
369
-
370
- if (this.config.hitSlop.bottom !== undefined) {
371
- bottom = width + this.config.hitSlop.bottom;
372
- }
373
- if (this.config.hitSlop.width !== undefined) {
374
- if (this.config.hitSlop.left !== undefined) {
375
- right = left + this.config.hitSlop.width;
376
- } else if (this.config.hitSlop.right !== undefined) {
377
- left = right - this.config.hitSlop.width;
378
- }
379
- }
380
-
381
- if (this.config.hitSlop.height !== undefined) {
382
- if (this.config.hitSlop.top !== undefined) {
383
- bottom = top + this.config.hitSlop.height;
384
- } else if (this.config.hitSlop.bottom !== undefined) {
385
- top = bottom - this.config.hitSlop.height;
386
- }
387
- }
388
-
389
- const rect = this.view.getBoundingRect();
390
- const offsetX: number = this.tracker.getLastX() - rect.x;
391
- const offsetY: number = this.tracker.getLastY() - rect.y;
392
-
393
- if (
394
- offsetX >= left &&
395
- offsetX <= right &&
396
- offsetY >= top &&
397
- offsetY <= bottom
398
- ) {
399
- return true;
400
- }
401
- return false;
402
- }
403
-
404
- protected activate(): void {
405
- this.logger.info("activate")
406
- if (this.currentState === State.UNDETERMINED || this.currentState === State.BEGAN) {
407
- this.moveToState(State.ACTIVE)
408
- }
409
- }
410
-
411
- protected moveToState(state: State) {
412
- this.logger.info(`moveToState ${getStateName(state)}`)
413
- if (state === this.currentState) return;
414
- const oldState = this.currentState
415
- this.currentState = state;
416
- if (this.tracker.getTrackedPointersCount() > 0 && this.config.needsPointerData && this.isFinished()) {
417
- this.cancelTouches()
418
- }
419
- this.orchestrator.onHandlerStateChange(this, state, oldState)
420
- this.stateDidChange(state, oldState)
421
- }
422
-
423
- private isFinished() {
424
- return (
425
- this.currentState === State.END ||
426
- this.currentState === State.FAILED ||
427
- this.currentState === State.CANCELLED
428
- );
429
- }
430
-
431
- private cancelTouches(): void {
432
- const rect = this.view.getBoundingRect();
433
- const all: TouchData[] = [];
434
- const changed: TouchData[] = [];
435
- const trackerData = this.tracker.getData();
436
- if (trackerData.size === 0) {
437
- return;
438
- }
439
- trackerData.forEach((element, key): void => {
440
- const id: number = this.tracker.getMappedTouchEventId(key);
441
- all.push({
442
- id: id,
443
- x: element.lastX - rect.x,
444
- y: element.lastY - rect.y,
445
- absoluteX: element.lastX,
446
- absoluteY: element.lastY,
447
- });
448
- changed.push({
449
- id: id,
450
- x: element.lastX - rect.x,
451
- y: element.lastY - rect.y,
452
- absoluteX: element.lastX,
453
- absoluteY: element.lastY,
454
- });
455
- });
456
- const cancelEvent: GestureTouchEvent = {
457
- handlerTag: this.handlerTag,
458
- state: this.currentState,
459
- eventType: TouchEventType.CANCELLED,
460
- changedTouches: changed,
461
- allTouches: all,
462
- numberOfTouches: all.length,
463
- };
464
- this.eventDispatcher.onGestureHandlerEvent(cancelEvent)
465
- }
466
-
467
- protected stateDidChange(newState: State, oldState: State) {
468
- this.logger.info(`stateDidChange from ${getStateName(oldState)} to ${getStateName(newState)}`)
469
- }
470
-
471
-
472
- public updateGestureConfig(config: TGestureConfig): void {
473
- this.config = { enabled: true, ...config }
474
- if (this.config.shouldCancelWhenOutside !== undefined) {
475
- this.setShouldCancelWhenOutside(this.config.shouldCancelWhenOutside);
476
- }
477
-
478
- // this.validateHitSlops();
479
- if (this.config.enabled) {
480
- return;
481
- }
482
- // switch (this.currentState) {
483
- // case State.ACTIVE:
484
- // this.fail(true);
485
- // break;
486
- // case State.UNDETERMINED:
487
- // this.orchestrator.removeHandlerFromOrchestrator(this);
488
- // break;
489
- // default:
490
- // this.cancel(true);
491
- // break;
492
- }
493
-
494
- protected resetConfig(): void {
495
- this.config = this.getDefaultConfig()
496
- }
497
-
498
- abstract getDefaultConfig(): TGestureConfig
499
-
500
-
501
- public isEnabled(): boolean {
502
- return Boolean(this.config.enabled)
503
- }
504
-
505
- public isActive(): boolean {
506
- return this.isActivated
507
- }
508
-
509
- public cancel(): void {
510
- this.logger.info(`cancel`)
511
- if (
512
- this.currentState === State.ACTIVE ||
513
- this.currentState === State.UNDETERMINED ||
514
- this.currentState === State.BEGAN
515
- ) {
516
- this.onCancel();
517
- this.moveToState(State.CANCELLED);
518
- }
519
- }
520
-
521
- protected onCancel(): void {
522
- }
523
-
524
- protected onReset(): void {
525
- }
526
-
527
- protected resetProgress(): void {
528
- }
529
-
530
- public getState(): State {
531
- return this.currentState
532
- }
533
-
534
- public sendEvent({newState, oldState}: {
535
- oldState: State,
536
- newState: State
537
- }): void {
538
- this.logger.info(`sendEvent`)
539
- const stateChangeEvent = this.createStateChangeEvent(newState, oldState);
540
- if (this.lastSentState !== newState) {
541
- this.lastSentState = newState;
542
- this.eventDispatcher.onGestureHandlerStateChange(stateChangeEvent);
543
- }
544
- if (this.currentState === State.ACTIVE) {
545
- stateChangeEvent.oldState = undefined;
546
- this.eventDispatcher.onGestureHandlerEvent(stateChangeEvent);
547
- }
548
- }
549
-
550
- private createStateChangeEvent(newState: State, oldState: State): GestureStateChangeEvent {
551
- return {
552
- numberOfPointers: this.tracker.getTrackedPointersCount(),
553
- state: newState,
554
- pointerInside: this.view.isPositionInBounds({
555
- x: this.tracker.getLastAvgX(),
556
- y: this.tracker.getLastAvgY(),
557
- }),
558
- ...this.transformNativeEvent(),
559
- handlerTag: this.handlerTag,
560
- target: this.view.getTag(),
561
- oldState: newState !== oldState ? oldState : undefined,
562
- };
563
- }
564
-
565
- protected transformNativeEvent() {
566
- return {};
567
- }
568
-
569
- setAwaiting(isAwaiting: boolean): void {
570
- this.isAwaiting_ = isAwaiting
571
- }
572
-
573
- shouldWaitForHandlerFailure(handler: GestureHandler): boolean {
574
- if (handler === this)
575
- return false;
576
- return this.interactionManager.shouldWaitForHandlerFailure(this, handler);
577
- }
578
-
579
- shouldRequireToWaitForFailure(handler: GestureHandler): boolean {
580
- if (handler === this)
581
- return false;
582
- return this.interactionManager.shouldRequireHandlerToWaitForFailure(this, handler);
583
- }
584
-
585
- shouldWaitFor(otherHandler: GestureHandler): boolean {
586
- return (
587
- this !== otherHandler &&
588
- (this.shouldWaitForHandlerFailure(otherHandler) ||
589
- otherHandler.shouldRequireToWaitForFailure(this))
590
- );
591
- }
592
-
593
- reset(): void {
594
- this.logger.info("reset")
595
- this.tracker.resetTracker();
596
- this.onReset();
597
- this.resetProgress();
598
- // TODO: reset ArkUIAdapters
599
- // this.eventManagers.forEach((manager: EventManager) =>
600
- // manager.resetManager()
601
- // );
602
- this.currentState = State.UNDETERMINED;
603
- }
604
-
605
- isAwaiting(): boolean {
606
- return this.isAwaiting_
607
- }
608
-
609
- setActive(isActivated: boolean): void {
610
- this.isActivated = isActivated
611
- }
612
-
613
- setActivationIndex(value: number): void {
614
- this.activationIndex = value
615
- }
616
-
617
- setShouldResetProgress(value: boolean): void {
618
- this.shouldResetProgress = value;
619
- }
620
-
621
- fail(): void {
622
- this.logger.info('fail')
623
- if (
624
- this.currentState === State.ACTIVE ||
625
- this.currentState === State.BEGAN
626
- ) {
627
- this.moveToState(State.FAILED);
628
- }
629
- this.resetProgress();
630
- }
631
-
632
- shouldBeCancelledByOther(otherHandler: GestureHandler): boolean {
633
- if (otherHandler === this)
634
- return false;
635
- return this.interactionManager.shouldHandlerBeCancelledBy(this, otherHandler);
636
- }
637
-
638
- getTrackedPointersID(): PointerId[] {
639
- return this.tracker.getTrackedPointersID()
640
- }
641
-
642
- shouldRecognizeSimultaneously(otherHandler: GestureHandler): boolean {
643
- if (otherHandler === this)
644
- return true;
645
- return this.interactionManager.shouldRecognizeSimultaneously(this, otherHandler);
646
- }
647
-
648
- public getPointerType(): PointerType {
649
- return this.pointerType
650
- }
651
-
652
- protected setShouldCancelWhenOutside(shouldCancel: boolean) {
653
- this.shouldCancelWhenOutside = shouldCancel
654
- }
655
-
656
- public end() {
657
- this.logger.info("end")
658
- if (this.currentState === State.BEGAN || this.currentState === State.ACTIVE) {
659
- this.moveToState(State.END);
660
- }
661
- this.resetProgress();
662
- }
663
- }
1
+ import type { GestureHandlerOrchestrator } from "./GestureHandlerOrchestrator"
2
+ import type { PointerTracker } from "./PointerTracker"
3
+ import type { View } from "./View"
4
+ import type { EventDispatcher } from "./EventDispatcher"
5
+ import type { InteractionManager } from "./InteractionManager"
6
+ import type { RNGHLogger } from './RNGHLogger'
7
+ import { State, getStateName } from "./State"
8
+ import { HitSlop, Directions, AdaptedEvent, PointerType, TouchEventType, EventType } from "./Event"
9
+ import { GestureStateChangeEvent, GestureTouchEvent, TouchData } from "./OutgoingEvent"
10
+
11
+
12
+ export interface Handler {
13
+ handlerTag: number;
14
+ }
15
+
16
+ export const DEFAULT_TOUCH_SLOP = 15;
17
+
18
+ export interface GestureConfig {
19
+ enabled?: boolean;
20
+ simultaneousHandlers?: Handler[] | null;
21
+ waitFor?: Handler[] | null;
22
+ hitSlop?: HitSlop;
23
+ shouldCancelWhenOutside?: boolean;
24
+ activateAfterLongPress?: number;
25
+ failOffsetXStart?: number;
26
+ failOffsetYStart?: number;
27
+ failOffsetXEnd?: number;
28
+ failOffsetYEnd?: number;
29
+ activeOffsetXStart?: number;
30
+ activeOffsetXEnd?: number;
31
+ activeOffsetYStart?: number;
32
+ activeOffsetYEnd?: number;
33
+ minPointers?: number;
34
+ maxPointers?: number;
35
+ minDist?: number;
36
+ minDistSq?: number;
37
+ minVelocity?: number;
38
+ minVelocityX?: number;
39
+ minVelocityY?: number;
40
+ minVelocitySq?: number;
41
+ maxDist?: number;
42
+ maxDistSq?: number;
43
+ numberOfPointers?: number;
44
+ minDurationMs?: number;
45
+ numberOfTaps?: number;
46
+ maxDurationMs?: number;
47
+ maxDelayMs?: number;
48
+ maxDeltaX?: number;
49
+ maxDeltaY?: number;
50
+ shouldActivateOnStart?: boolean;
51
+ disallowInterruption?: boolean;
52
+ direction?: typeof Directions;
53
+ needsPointerData?: boolean
54
+ // --- Tap
55
+ minNumberOfPointers?: number
56
+ }
57
+
58
+ type PointerId = number
59
+
60
+ export interface ScrollLocker {
61
+ lockScrollContainingViewTag(viewTag: number): () => void
62
+ }
63
+
64
+ export type GestureHandlerDependencies = {
65
+ handlerTag: number
66
+ orchestrator: GestureHandlerOrchestrator
67
+ tracker: PointerTracker
68
+ interactionManager: InteractionManager
69
+ logger: RNGHLogger
70
+ scrollLocker: ScrollLocker
71
+ }
72
+
73
+ export abstract class GestureHandler<TGestureConfig extends GestureConfig = GestureConfig> {
74
+ protected config: TGestureConfig = this.getDefaultConfig()
75
+ protected currentState: State = State.UNDETERMINED
76
+ protected view: View | undefined = undefined
77
+ protected lastSentState: State | undefined = undefined
78
+ protected shouldCancelWhenOutside = false
79
+
80
+ protected isActivated = false
81
+ protected isAwaiting_ = false
82
+ protected pointerType: PointerType
83
+ protected activationIndex = 0
84
+ protected shouldResetProgress = false;
85
+
86
+ protected handlerTag: number
87
+ protected orchestrator: GestureHandlerOrchestrator
88
+ protected tracker: PointerTracker
89
+ protected eventDispatcher: EventDispatcher
90
+ protected interactionManager: InteractionManager
91
+ protected logger: RNGHLogger
92
+ protected scrollLocker: ScrollLocker
93
+
94
+ constructor(deps: GestureHandlerDependencies
95
+ ) {
96
+ this.handlerTag = deps.handlerTag
97
+ this.orchestrator = deps.orchestrator
98
+ this.tracker = deps.tracker
99
+ this.interactionManager = deps.interactionManager
100
+ this.logger = deps.logger
101
+ this.scrollLocker = deps.scrollLocker
102
+ }
103
+
104
+ public setEventDispatcher(eventDispatcher: EventDispatcher) {
105
+ // TurboModule provides info about kind of event dispatcher when attaching GH to a view, not when GH is created.
106
+ // This method must be called before any other
107
+ this.eventDispatcher = eventDispatcher
108
+ }
109
+
110
+ public onPointerDown(e: AdaptedEvent) {
111
+ this.logger.info("onPointerDown")
112
+ this.orchestrator.registerHandlerIfNotPresent(this);
113
+ this.pointerType = e.pointerType;
114
+ if (this.pointerType === PointerType.TOUCH) {
115
+ this.orchestrator.cancelMouseAndPenGestures(this);
116
+ }
117
+ if (this.config.needsPointerData) {
118
+ this.sendTouchEvent(e);
119
+ }
120
+ }
121
+
122
+ protected sendTouchEvent(e: AdaptedEvent) {
123
+ if (!this.config.enabled) {
124
+ return;
125
+ }
126
+
127
+
128
+ const touchEvent: GestureTouchEvent | undefined =
129
+ this.transformToTouchEvent(e);
130
+
131
+ if (touchEvent) {
132
+ this.eventDispatcher.onGestureHandlerEvent(touchEvent)
133
+ }
134
+ }
135
+
136
+ protected transformToTouchEvent(event: AdaptedEvent): GestureTouchEvent | undefined {
137
+ const rect = this.view.getBoundingRect();
138
+
139
+ const all: TouchData[] = [];
140
+ const changed: TouchData[] = [];
141
+
142
+ const trackerData = this.tracker.getData();
143
+
144
+ // This if handles edge case where all pointers have been cancelled
145
+ // When pointercancel is triggered, reset method is called. This means that tracker will be reset after first pointer being cancelled
146
+ // The problem is, that handler will receive another pointercancel event from the rest of the pointers
147
+ // To avoid crashing, we don't send event if tracker tracks no pointers, i.e. has been reset
148
+ if (trackerData.size === 0 || !trackerData.has(event.pointerId)) {
149
+ return;
150
+ }
151
+
152
+ trackerData.forEach((element, key): void => {
153
+ const id: number = this.tracker.getMappedTouchEventId(key);
154
+
155
+ all.push({
156
+ id: id,
157
+ x: element.lastX - rect.x,
158
+ y: element.lastY - rect.y,
159
+ absoluteX: element.lastX,
160
+ absoluteY: element.lastY,
161
+ });
162
+ });
163
+
164
+ // Each pointer sends its own event, so we want changed touches to contain only the pointer that has changed.
165
+ // However, if the event is cancel, we want to cancel all pointers to avoid crashes
166
+ if (event.eventType !== EventType.CANCEL) {
167
+ changed.push({
168
+ id: this.tracker.getMappedTouchEventId(event.pointerId),
169
+ x: event.x - rect.x,
170
+ y: event.y - rect.y,
171
+ absoluteX: event.x,
172
+ absoluteY: event.y,
173
+ });
174
+ } else {
175
+ trackerData.forEach((element, key: number): void => {
176
+ const id: number = this.tracker.getMappedTouchEventId(key);
177
+
178
+ changed.push({
179
+ id: id,
180
+ x: element.lastX - rect.x,
181
+ y: element.lastY - rect.y,
182
+ absoluteX: element.lastX,
183
+ absoluteY: element.lastY,
184
+ });
185
+ });
186
+ }
187
+
188
+ let eventType: TouchEventType = TouchEventType.UNDETERMINED;
189
+
190
+ switch (event.eventType) {
191
+ case EventType.DOWN:
192
+ case EventType.ADDITIONAL_POINTER_DOWN:
193
+ eventType = TouchEventType.DOWN;
194
+ break;
195
+ case EventType.UP:
196
+ case EventType.ADDITIONAL_POINTER_UP:
197
+ eventType = TouchEventType.UP;
198
+ break;
199
+ case EventType.MOVE:
200
+ eventType = TouchEventType.MOVE;
201
+ break;
202
+ case EventType.CANCEL:
203
+ eventType = TouchEventType.CANCELLED;
204
+ break;
205
+ }
206
+
207
+ // Here, when we receive up event, we want to decrease number of touches
208
+ // That's because we want handler to send information that there's one pointer less
209
+ // However, we still want this pointer to be present in allTouches array, so that its data can be accessed
210
+ let numberOfTouches: number = all.length;
211
+
212
+ if (
213
+ event.eventType === EventType.UP ||
214
+ event.eventType === EventType.ADDITIONAL_POINTER_UP
215
+ ) {
216
+ --numberOfTouches;
217
+ }
218
+
219
+ return {
220
+ handlerTag: this.handlerTag,
221
+ state: this.currentState,
222
+ eventType: event.touchEventType ?? eventType,
223
+ changedTouches: changed,
224
+ allTouches: all,
225
+ numberOfTouches: numberOfTouches,
226
+ };
227
+ }
228
+
229
+ public onPointerUp(e: AdaptedEvent): void {
230
+ this.logger.info("onPointerUp")
231
+ if (this.config.needsPointerData) this.sendTouchEvent(e)
232
+ }
233
+
234
+ public onAdditionalPointerAdd(e: AdaptedEvent): void {
235
+ this.logger.info("onAdditionalPointerAdd")
236
+ if (this.config.needsPointerData) this.sendTouchEvent(e)
237
+ }
238
+
239
+ public onAdditionalPointerRemove(e: AdaptedEvent): void {
240
+ this.logger.info("onAdditionalPointerRemove")
241
+ if (this.config.needsPointerData) this.sendTouchEvent(e)
242
+ }
243
+
244
+ public onPointerMove(e: AdaptedEvent): void {
245
+ this.logger.info("onPointerMove")
246
+ this.tryToSendMoveEvent(false);
247
+ if (this.config.needsPointerData) {
248
+ this.sendTouchEvent(e);
249
+ }
250
+ }
251
+
252
+ private tryToSendMoveEvent(out: boolean): void {
253
+ this.logger.info(`tryToSendMoveEvent ${JSON.stringify({
254
+ out,
255
+ enabled: this.config.enabled,
256
+ isActivated: this.isActivated,
257
+ shouldCancelWhenOutside: this.shouldCancelWhenOutside
258
+ })}`)
259
+ if (
260
+ this.config.enabled &&
261
+ this.isActivated &&
262
+ (!out || (out && !this.shouldCancelWhenOutside))
263
+ ) {
264
+ this.sendEvent({ newState: this.currentState, oldState: this.currentState });
265
+ }
266
+ }
267
+
268
+ public onPointerEnter(e: AdaptedEvent): void {
269
+ this.logger.info("onPointerEnter")
270
+ if (this.config.needsPointerData) {
271
+ this.sendTouchEvent(e)
272
+ }
273
+ }
274
+
275
+ public onPointerOut(e: AdaptedEvent): void {
276
+ this.logger.info("onPointerOut")
277
+ if (this.shouldCancelWhenOutside) {
278
+ switch (this.currentState) {
279
+ case State.ACTIVE:
280
+ this.cancel();
281
+ break;
282
+ case State.BEGAN:
283
+ this.fail();
284
+ break;
285
+ }
286
+ return;
287
+ }
288
+ if (this.config.needsPointerData) {
289
+ this.sendTouchEvent(e);
290
+ }
291
+ }
292
+
293
+ public onPointerCancel(e: AdaptedEvent): void {
294
+ this.logger.info("onPointerCancel")
295
+ if (this.config.needsPointerData) {
296
+ this.sendTouchEvent(e);
297
+ }
298
+ this.cancel();
299
+ this.reset();
300
+ }
301
+
302
+ public onPointerOutOfBounds(e: AdaptedEvent): void {
303
+ this.logger.info("onPointerOutOfBounds")
304
+ this.tryToSendMoveEvent(true);
305
+ if (this.config.needsPointerData) {
306
+ this.sendTouchEvent(e);
307
+ }
308
+ }
309
+
310
+ public onViewAttached(view: View) {
311
+ this.logger.info("onViewAttached")
312
+ this.view = view
313
+ }
314
+
315
+ public getTag(): number {
316
+ return this.handlerTag
317
+ }
318
+
319
+ public getTracker() {
320
+ return this.tracker
321
+ }
322
+
323
+ public getView() {
324
+ return this.view
325
+ }
326
+
327
+ protected begin(): void {
328
+ this.logger.info("begin")
329
+ if (!this.isWithinHitSlop()) return;
330
+ if (this.currentState === State.UNDETERMINED) {
331
+ this.moveToState(State.BEGAN);
332
+ }
333
+ }
334
+
335
+ private isWithinHitSlop(): boolean {
336
+ if (!this.config.hitSlop) {
337
+ return true;
338
+ }
339
+
340
+ const width = this.view.getBoundingRect().width;
341
+ const height = this.view.getBoundingRect().height;
342
+
343
+ let left = 0;
344
+ let top = 0;
345
+ let right: number = width;
346
+ let bottom: number = height;
347
+
348
+ if (this.config.hitSlop.horizontal !== undefined) {
349
+ left -= this.config.hitSlop.horizontal;
350
+ right += this.config.hitSlop.horizontal;
351
+ }
352
+
353
+ if (this.config.hitSlop.vertical !== undefined) {
354
+ top -= this.config.hitSlop.vertical;
355
+ bottom += this.config.hitSlop.vertical;
356
+ }
357
+
358
+ if (this.config.hitSlop.left !== undefined) {
359
+ left = -this.config.hitSlop.left;
360
+ }
361
+
362
+ if (this.config.hitSlop.right !== undefined) {
363
+ right = width + this.config.hitSlop.right;
364
+ }
365
+
366
+ if (this.config.hitSlop.top !== undefined) {
367
+ top = -this.config.hitSlop.top;
368
+ }
369
+
370
+ if (this.config.hitSlop.bottom !== undefined) {
371
+ bottom = width + this.config.hitSlop.bottom;
372
+ }
373
+ if (this.config.hitSlop.width !== undefined) {
374
+ if (this.config.hitSlop.left !== undefined) {
375
+ right = left + this.config.hitSlop.width;
376
+ } else if (this.config.hitSlop.right !== undefined) {
377
+ left = right - this.config.hitSlop.width;
378
+ }
379
+ }
380
+
381
+ if (this.config.hitSlop.height !== undefined) {
382
+ if (this.config.hitSlop.top !== undefined) {
383
+ bottom = top + this.config.hitSlop.height;
384
+ } else if (this.config.hitSlop.bottom !== undefined) {
385
+ top = bottom - this.config.hitSlop.height;
386
+ }
387
+ }
388
+
389
+ const rect = this.view.getBoundingRect();
390
+ const offsetX: number = this.tracker.getLastX() - rect.x;
391
+ const offsetY: number = this.tracker.getLastY() - rect.y;
392
+
393
+ if (
394
+ offsetX >= left &&
395
+ offsetX <= right &&
396
+ offsetY >= top &&
397
+ offsetY <= bottom
398
+ ) {
399
+ return true;
400
+ }
401
+ return false;
402
+ }
403
+
404
+ protected activate(): void {
405
+ this.logger.info("activate")
406
+ if (this.currentState === State.UNDETERMINED || this.currentState === State.BEGAN) {
407
+ this.moveToState(State.ACTIVE)
408
+ }
409
+ }
410
+
411
+ protected moveToState(state: State) {
412
+ this.logger.info(`moveToState ${getStateName(state)}`)
413
+ if (state === this.currentState) return;
414
+ const oldState = this.currentState
415
+ this.currentState = state;
416
+ if (this.tracker.getTrackedPointersCount() > 0 && this.config.needsPointerData && this.isFinished()) {
417
+ this.cancelTouches()
418
+ }
419
+ this.orchestrator.onHandlerStateChange(this, state, oldState)
420
+ this.stateDidChange(state, oldState)
421
+ }
422
+
423
+ private isFinished() {
424
+ return (
425
+ this.currentState === State.END ||
426
+ this.currentState === State.FAILED ||
427
+ this.currentState === State.CANCELLED
428
+ );
429
+ }
430
+
431
+ private cancelTouches(): void {
432
+ const rect = this.view.getBoundingRect();
433
+ const all: TouchData[] = [];
434
+ const changed: TouchData[] = [];
435
+ const trackerData = this.tracker.getData();
436
+ if (trackerData.size === 0) {
437
+ return;
438
+ }
439
+ trackerData.forEach((element, key): void => {
440
+ const id: number = this.tracker.getMappedTouchEventId(key);
441
+ all.push({
442
+ id: id,
443
+ x: element.lastX - rect.x,
444
+ y: element.lastY - rect.y,
445
+ absoluteX: element.lastX,
446
+ absoluteY: element.lastY,
447
+ });
448
+ changed.push({
449
+ id: id,
450
+ x: element.lastX - rect.x,
451
+ y: element.lastY - rect.y,
452
+ absoluteX: element.lastX,
453
+ absoluteY: element.lastY,
454
+ });
455
+ });
456
+ const cancelEvent: GestureTouchEvent = {
457
+ handlerTag: this.handlerTag,
458
+ state: this.currentState,
459
+ eventType: TouchEventType.CANCELLED,
460
+ changedTouches: changed,
461
+ allTouches: all,
462
+ numberOfTouches: all.length,
463
+ };
464
+ this.eventDispatcher.onGestureHandlerEvent(cancelEvent)
465
+ }
466
+
467
+ protected stateDidChange(newState: State, oldState: State) {
468
+ this.logger.info(`stateDidChange from ${getStateName(oldState)} to ${getStateName(newState)}`)
469
+ }
470
+
471
+
472
+ public updateGestureConfig(config: TGestureConfig): void {
473
+ this.config = { enabled: true, ...config }
474
+ if (this.config.shouldCancelWhenOutside !== undefined) {
475
+ this.setShouldCancelWhenOutside(this.config.shouldCancelWhenOutside);
476
+ }
477
+
478
+ // this.validateHitSlops();
479
+ if (this.config.enabled) {
480
+ return;
481
+ }
482
+ // switch (this.currentState) {
483
+ // case State.ACTIVE:
484
+ // this.fail(true);
485
+ // break;
486
+ // case State.UNDETERMINED:
487
+ // this.orchestrator.removeHandlerFromOrchestrator(this);
488
+ // break;
489
+ // default:
490
+ // this.cancel(true);
491
+ // break;
492
+ }
493
+
494
+ protected resetConfig(): void {
495
+ this.config = this.getDefaultConfig()
496
+ }
497
+
498
+ abstract getDefaultConfig(): TGestureConfig
499
+
500
+
501
+ public isEnabled(): boolean {
502
+ return Boolean(this.config.enabled)
503
+ }
504
+
505
+ public isActive(): boolean {
506
+ return this.isActivated
507
+ }
508
+
509
+ public cancel(): void {
510
+ this.logger.info(`cancel`)
511
+ if (
512
+ this.currentState === State.ACTIVE ||
513
+ this.currentState === State.UNDETERMINED ||
514
+ this.currentState === State.BEGAN
515
+ ) {
516
+ this.onCancel();
517
+ this.moveToState(State.CANCELLED);
518
+ }
519
+ }
520
+
521
+ protected onCancel(): void {
522
+ }
523
+
524
+ protected onReset(): void {
525
+ }
526
+
527
+ protected resetProgress(): void {
528
+ }
529
+
530
+ public getState(): State {
531
+ return this.currentState
532
+ }
533
+
534
+ public sendEvent({newState, oldState}: {
535
+ oldState: State,
536
+ newState: State
537
+ }): void {
538
+ this.logger.info(`sendEvent`)
539
+ const stateChangeEvent = this.createStateChangeEvent(newState, oldState);
540
+ if (this.lastSentState !== newState) {
541
+ this.lastSentState = newState;
542
+ this.eventDispatcher.onGestureHandlerStateChange(stateChangeEvent);
543
+ }
544
+ if (this.currentState === State.ACTIVE) {
545
+ stateChangeEvent.oldState = undefined;
546
+ this.eventDispatcher.onGestureHandlerEvent(stateChangeEvent);
547
+ }
548
+ }
549
+
550
+ private createStateChangeEvent(newState: State, oldState: State): GestureStateChangeEvent {
551
+ return {
552
+ numberOfPointers: this.tracker.getTrackedPointersCount(),
553
+ state: newState,
554
+ pointerInside: this.view.isPositionInBounds({
555
+ x: this.tracker.getLastAvgX(),
556
+ y: this.tracker.getLastAvgY(),
557
+ }),
558
+ ...this.transformNativeEvent(),
559
+ handlerTag: this.handlerTag,
560
+ target: this.view.getTag(),
561
+ oldState: newState !== oldState ? oldState : undefined,
562
+ };
563
+ }
564
+
565
+ protected transformNativeEvent() {
566
+ return {};
567
+ }
568
+
569
+ setAwaiting(isAwaiting: boolean): void {
570
+ this.isAwaiting_ = isAwaiting
571
+ }
572
+
573
+ shouldWaitForHandlerFailure(handler: GestureHandler): boolean {
574
+ if (handler === this)
575
+ return false;
576
+ return this.interactionManager.shouldWaitForHandlerFailure(this, handler);
577
+ }
578
+
579
+ shouldRequireToWaitForFailure(handler: GestureHandler): boolean {
580
+ if (handler === this)
581
+ return false;
582
+ return this.interactionManager.shouldRequireHandlerToWaitForFailure(this, handler);
583
+ }
584
+
585
+ shouldWaitFor(otherHandler: GestureHandler): boolean {
586
+ return (
587
+ this !== otherHandler &&
588
+ (this.shouldWaitForHandlerFailure(otherHandler) ||
589
+ otherHandler.shouldRequireToWaitForFailure(this))
590
+ );
591
+ }
592
+
593
+ reset(): void {
594
+ this.logger.info("reset")
595
+ this.tracker.resetTracker();
596
+ this.onReset();
597
+ this.resetProgress();
598
+ // TODO: reset ArkUIAdapters
599
+ // this.eventManagers.forEach((manager: EventManager) =>
600
+ // manager.resetManager()
601
+ // );
602
+ this.currentState = State.UNDETERMINED;
603
+ }
604
+
605
+ isAwaiting(): boolean {
606
+ return this.isAwaiting_
607
+ }
608
+
609
+ setActive(isActivated: boolean): void {
610
+ this.isActivated = isActivated
611
+ }
612
+
613
+ setActivationIndex(value: number): void {
614
+ this.activationIndex = value
615
+ }
616
+
617
+ setShouldResetProgress(value: boolean): void {
618
+ this.shouldResetProgress = value;
619
+ }
620
+
621
+ fail(): void {
622
+ this.logger.info('fail')
623
+ if (
624
+ this.currentState === State.ACTIVE ||
625
+ this.currentState === State.BEGAN
626
+ ) {
627
+ this.moveToState(State.FAILED);
628
+ }
629
+ this.resetProgress();
630
+ }
631
+
632
+ shouldBeCancelledByOther(otherHandler: GestureHandler): boolean {
633
+ if (otherHandler === this)
634
+ return false;
635
+ return this.interactionManager.shouldHandlerBeCancelledBy(this, otherHandler);
636
+ }
637
+
638
+ getTrackedPointersID(): PointerId[] {
639
+ return this.tracker.getTrackedPointersID()
640
+ }
641
+
642
+ shouldRecognizeSimultaneously(otherHandler: GestureHandler): boolean {
643
+ if (otherHandler === this)
644
+ return true;
645
+ return this.interactionManager.shouldRecognizeSimultaneously(this, otherHandler);
646
+ }
647
+
648
+ public getPointerType(): PointerType {
649
+ return this.pointerType
650
+ }
651
+
652
+ protected setShouldCancelWhenOutside(shouldCancel: boolean) {
653
+ this.shouldCancelWhenOutside = shouldCancel
654
+ }
655
+
656
+ public end() {
657
+ this.logger.info("end")
658
+ if (this.currentState === State.BEGAN || this.currentState === State.ACTIVE) {
659
+ this.moveToState(State.END);
660
+ }
661
+ this.resetProgress();
662
+ }
663
+ }