@react-native-oh-tpl/react-native-gesture-handler 2.14.13 → 2.14.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. package/harmony/gesture_handler/BuildProfile.ets +1 -1
  2. package/harmony/gesture_handler/build-profile.json5 +0 -7
  3. package/harmony/gesture_handler/index.ets +1 -2
  4. package/harmony/gesture_handler/oh-package-lock.json5 +1 -1
  5. package/harmony/gesture_handler/oh-package.json5 +2 -2
  6. package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +1 -1
  7. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +9 -18
  8. package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.cpp +157 -0
  9. package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.h +21 -0
  10. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerButtonComponentInstance.h +16 -16
  11. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +202 -199
  12. package/harmony/gesture_handler/src/main/ets/RNOHPackage.ets +17 -0
  13. package/harmony/gesture_handler/src/main/ets/core/GestureHandler.ts +84 -35
  14. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerOrchestrator.ts +20 -11
  15. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +2 -2
  16. package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +4 -4
  17. package/harmony/gesture_handler/src/main/ets/core/Multiset.ts +26 -0
  18. package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +7 -3
  19. package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +1 -2
  20. package/harmony/gesture_handler/src/main/ets/core/index.ts +2 -2
  21. package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +12 -4
  22. package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +8 -5
  23. package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +14 -2
  24. package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +9 -1
  25. package/harmony/gesture_handler/src/main/ets/gesture-handlers/NativeViewGestureHandler.ts +13 -4
  26. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PanGestureHandler.ts +45 -12
  27. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +145 -130
  28. package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +9 -1
  29. package/harmony/gesture_handler/src/main/ets/gesture-handlers/TapGestureHandler.ts +15 -5
  30. package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerPackage.ts +6 -3
  31. package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +74 -16
  32. package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +35 -12
  33. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootViewController.ts +196 -0
  34. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHView.ts +85 -0
  35. package/harmony/gesture_handler/src/main/ets/rnoh/{GestureHandlerArkUIAdapter.ts → RNGHViewController.ts} +45 -30
  36. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHViewRegistry.ts +19 -0
  37. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerModule.ts +127 -93
  38. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +0 -9
  39. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +1 -8
  40. package/harmony/gesture_handler.har +0 -0
  41. package/package.json +7 -3
  42. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +0 -149
  43. package/harmony/gesture_handler/src/main/ets/core/ViewFinder.ts +0 -11
  44. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerArkTS.ts +0 -98
  45. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerCAPI.ts +0 -110
  46. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerButton.ets +0 -38
  47. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerRootView.ets +0 -53
  48. package/harmony/gesture_handler/src/main/ets/rnoh/View.ts +0 -134
  49. package/harmony/gesture_handler/src/main/ets/rnoh/ViewRegistry.ts +0 -97
@@ -1,23 +1,71 @@
1
1
  import { RNOHContext } from '@rnoh/react-native-openharmony/ts';
2
2
  import { RNGHLogger, RNGHLoggerMessage } from "../core"
3
+ import hiTrace from "@ohos.hiTraceMeter"
3
4
 
4
- export class StandardRNGHLogger implements RNGHLogger {
5
+ class Tracer {
6
+ private activeTracesCount: number = 0
7
+
8
+ public startTrace(name: string) {
9
+ /**
10
+ * hiTrace.startTrace creates a new lane which makes the traces useless
11
+ */
12
+ hiTrace.startTrace(name, 0)
13
+ this.activeTracesCount++
14
+ return () => {
15
+ hiTrace.finishTrace(name, 0)
16
+ this.activeTracesCount--
17
+ }
18
+ }
19
+
20
+ public getActiveTracesCount(): number {
21
+ return this.activeTracesCount
22
+ }
23
+ }
24
+
25
+ export class DevelopmentRNGHLogger implements RNGHLogger {
5
26
  constructor(
6
- private rnohLogger: RNOHContext['logger'],
7
- private prefix: string,
27
+ protected rnohLogger: RNOHContext['logger'],
28
+ protected prefix: string,
29
+ protected tracer: Tracer = new Tracer(),
8
30
  ) {
9
31
  }
10
32
 
11
33
  error(msg: string) {
12
- this.rnohLogger.error(`${this.prefix}::${msg}`);
34
+ this.log("error", msg);
35
+ }
36
+
37
+ warn(msg: string) {
38
+ this.log("warn", msg);
13
39
  }
14
40
 
15
41
  info(msg: string) {
16
- this.rnohLogger.info(`${this.prefix}::${msg}`);
42
+ this.log("info", msg);
17
43
  }
18
44
 
19
45
  debug(msg: RNGHLoggerMessage) {
20
- this.rnohLogger.debug(`${this.prefix}::${this.stringifyMsg(msg)}`);
46
+ this.log("debug", typeof msg === "string" ? msg : JSON.stringify(msg));
47
+ }
48
+
49
+ protected log(type: "debug" | "info" | "warn" | "error", msg: string, offset: number | undefined = undefined) {
50
+ this.rnohLogger[type](" ".repeat(offset ?? this.tracer.getActiveTracesCount() * 2),
51
+ `${this.prefix}: ${this.stringifyMsg(msg)}`)
52
+ }
53
+
54
+ startTracing(): () => void {
55
+ const startTime = Date.now()
56
+ const currentOffset = this.tracer.getActiveTracesCount() * 2
57
+ this.log("debug", "START", currentOffset)
58
+ const stopTrace = this.tracer.startTrace(this.prefix)
59
+ return () => {
60
+ stopTrace()
61
+ const stopTime = Date.now()
62
+ const durationInMs = stopTime - startTime
63
+ if (durationInMs < 16) {
64
+ this.log("debug", "STOP", currentOffset)
65
+ } else {
66
+ this.log("debug", `STOP (${durationInMs} ms)`, currentOffset)
67
+ }
68
+ }
21
69
  }
22
70
 
23
71
  private stringifyMsg(msg: RNGHLoggerMessage): string {
@@ -28,22 +76,32 @@ export class StandardRNGHLogger implements RNGHLogger {
28
76
  }
29
77
  }
30
78
 
31
- cloneWithPrefix(prefix: string) {
32
- return new StandardRNGHLogger(this.rnohLogger, `${this.prefix}::${prefix}`);
79
+ cloneAndJoinPrefix(prefix: string) {
80
+ return new DevelopmentRNGHLogger(this.rnohLogger, `${this.prefix}::${prefix}`, this.tracer);
33
81
  }
34
82
  }
35
83
 
36
- export class FakeRNGHLogger implements RNGHLogger {
37
- info(msg: string) {
84
+ export class ProductionRNGHLogger extends DevelopmentRNGHLogger {
85
+ override debug(msg: string) {
86
+ // NOOP
38
87
  }
39
88
 
40
- debug(msg: string) {
89
+ override cloneAndJoinPrefix(prefix: string) {
90
+ return new ProductionRNGHLogger(this.rnohLogger, `${this.prefix}::${prefix}`, this.tracer);
41
91
  }
42
92
 
43
- error(msg: string): void {
44
- }
93
+ override startTracing(): () => void {
94
+ const startTime = Date.now()
95
+ const currentOffset = this.tracer.getActiveTracesCount() * 2
45
96
 
46
- cloneWithPrefix(prefix: string) {
47
- return new FakeRNGHLogger();
97
+ const stopTrace = this.tracer.startTrace(this.prefix)
98
+ return () => {
99
+ stopTrace()
100
+ const stopTime = Date.now()
101
+ const durationInMs = stopTime - startTime
102
+ if (durationInMs > 16) {
103
+ this.log("warn", `STOP (${durationInMs} ms)`, currentOffset)
104
+ }
105
+ }
48
106
  }
49
- }
107
+ }
@@ -1,71 +1,94 @@
1
1
  import { RNInstance } from '@rnoh/react-native-openharmony/ts';
2
- import { OutgoingEventDispatcher, GestureStateChangeEvent, GestureUpdateEvent, GestureTouchEvent, RNGHLogger } from "../core"
2
+ import {
3
+ OutgoingEventDispatcher,
4
+ GestureStateChangeEvent,
5
+ GestureUpdateEvent,
6
+ GestureTouchEvent,
7
+ RNGHLogger
8
+ } from "../core"
3
9
 
4
10
  export class JSEventDispatcher implements OutgoingEventDispatcher {
5
- constructor(private rnInstance: RNInstance, private logger: RNGHLogger) {
11
+ private logger: RNGHLogger
12
+
13
+ constructor(private rnInstance: RNInstance, logger: RNGHLogger) {
14
+ this.logger = logger.cloneAndJoinPrefix("JSEventDispatcher")
6
15
  }
7
16
 
8
17
  public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
9
- this.logger.info(`onGestureHandlerStateChange`);
18
+ const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing();
10
19
  this.rnInstance.emitDeviceEvent('onGestureHandlerStateChange', event);
20
+ stopTracing()
11
21
  }
12
22
 
13
23
  public onGestureHandlerEvent(
14
24
  event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
15
25
  ) {
16
- this.logger.info(`onGestureHandlerEvent`);
26
+ const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
17
27
  this.rnInstance.emitDeviceEvent('onGestureHandlerEvent', event);
28
+ stopTracing()
18
29
  }
19
30
  }
20
31
 
21
32
  export class AnimatedEventDispatcher implements OutgoingEventDispatcher {
33
+ private logger: RNGHLogger
34
+
22
35
  constructor(
23
36
  private rnInstance: RNInstance,
24
- private logger: RNGHLogger,
37
+ logger: RNGHLogger,
25
38
  private viewTag: number,
26
- ) {}
39
+ ) {
40
+ this.logger = logger.cloneAndJoinPrefix("AnimatedEventDispatcher")
41
+ }
27
42
 
28
43
  public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
29
- this.logger.info(`onGestureHandlerStateChange`);
44
+ const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing()
30
45
  this.rnInstance.emitDeviceEvent('onGestureHandlerStateChange', event);
46
+ stopTracing()
31
47
  }
32
48
 
33
49
  public onGestureHandlerEvent(
34
50
  event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
35
51
  ) {
36
- this.logger.info(`onGestureHandlerEvent`);
52
+ const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
37
53
  this.rnInstance.emitComponentEvent(
38
54
  this.viewTag,
39
55
  'onGestureHandlerEvent',
40
56
  event,
41
57
  );
58
+ stopTracing()
42
59
  }
43
60
  }
44
61
 
45
62
  export class ReanimatedEventDispatcher implements OutgoingEventDispatcher {
63
+ private logger: RNGHLogger
64
+
46
65
  constructor(
47
66
  private rnInstance: RNInstance,
48
- private logger: RNGHLogger,
67
+ logger: RNGHLogger,
49
68
  private viewTag: number,
50
- ) {}
69
+ ) {
70
+ this.logger = logger.cloneAndJoinPrefix("ReanimatedEventDispatcher")
71
+ }
51
72
 
52
73
  public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
53
- this.logger.info(`onGestureHandlerStateChange`);
74
+ const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing();
54
75
  this.rnInstance.emitComponentEvent(
55
76
  this.viewTag,
56
77
  'onGestureHandlerStateChange',
57
78
  event,
58
79
  );
80
+ stopTracing()
59
81
  }
60
82
 
61
83
  public onGestureHandlerEvent(
62
84
  event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
63
85
  ) {
64
- this.logger.info(`onGestureHandlerEvent`);
86
+ const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
65
87
  this.rnInstance.emitComponentEvent(
66
88
  this.viewTag,
67
89
  'onGestureHandlerEvent',
68
90
  event,
69
91
  );
92
+ stopTracing()
70
93
  }
71
94
  }
@@ -0,0 +1,196 @@
1
+ import { TouchEvent as TouchEventArkTS, TouchType, TouchObject } from './types';
2
+ import { RNGHLogger, View, Multiset, GestureHandlerRegistry } from '../core';
3
+ import { RawTouchableView, RNGHView } from "./RNGHView"
4
+ import { RNGHViewController } from './RNGHViewController';
5
+
6
+ type RawTouchPoint = {
7
+ pointerId: number;
8
+ windowX: number;
9
+ windowY: number;
10
+ };
11
+
12
+ export type RawTouchEvent = {
13
+ action: number;
14
+ actionTouch: RawTouchPoint;
15
+ touchPoints: RawTouchPoint[];
16
+ sourceType: number;
17
+ timestamp: number;
18
+ /** TouchableViews is a list of views from the root to the leaf which contain within their boundaries the touch point specified by `actionTouch`. */
19
+ touchableViews: RawTouchableView[]
20
+ };
21
+
22
+
23
+ const areRawTouchPointsEqual = (a: RawTouchPoint, b: RawTouchPoint) =>
24
+ a.pointerId === b.pointerId &&
25
+ a.windowX === b.windowX &&
26
+ a.windowY === b.windowY;
27
+
28
+
29
+ export class RNGHRootViewController {
30
+ private logger: RNGHLogger;
31
+ // This multiset keeps track of touchable views that were detected
32
+ // at the beginning of the gesture to ensure they aren't overridden
33
+ // during move touch events, which could prevent the gesture handler
34
+ // from updating its state correctly.
35
+ private touchableViewsMultiset: Multiset<View> = new Multiset();
36
+ private viewControllerByViewTag: Map<number, RNGHViewController> =
37
+ new Map(); // TODO: remove entry when view is removed
38
+ /**
39
+ * A view is ACTIVE, if it recently received POINTER_DOWN event
40
+ */
41
+ private activeViewTags = new Set<number>();
42
+
43
+ constructor(
44
+ logger: RNGHLogger,
45
+ private gestureHandlerRegistry: GestureHandlerRegistry
46
+ ) {
47
+ this.logger = logger.cloneAndJoinPrefix('RNGHRootTouchHandlerCAPI');
48
+ }
49
+
50
+ handleTouch(rawTouchEvent: RawTouchEvent, touchableViews: View[]) {
51
+ /**
52
+ * NOTE: TouchEventArkTS was used in ArkTS RNOH architecture. Currently only C-API architecture is supported.
53
+ */
54
+ const touchEvent = rawTouchEventToTouchEventArkTS(rawTouchEvent);
55
+ if (touchEvent.type === TouchType.Down) {
56
+ touchableViews.forEach(view => this.touchableViewsMultiset.add(view));
57
+ }
58
+ const e = touchEvent;
59
+ if (e.type === TouchType.Down) {
60
+ this.activeViewTags.clear();
61
+ }
62
+ const views = touchableViews as RNGHView[]
63
+ for (let i = 0; i < views.length; i++) {
64
+ const view = views[i];
65
+ for (const handler of this.gestureHandlerRegistry.getGestureHandlersByViewTag(
66
+ view.getTag(),
67
+ )) {
68
+ this.logger.info(
69
+ `Found GestureHandler ${handler.getTag()} for view ${view.getTag()}`,
70
+ );
71
+
72
+ // create view touch handler if necessary
73
+ if (!this.viewControllerByViewTag.has(view.getTag())) {
74
+ this.viewControllerByViewTag.set(
75
+ view.getTag(),
76
+ new RNGHViewController(
77
+ view,
78
+ this.logger,
79
+ ),
80
+ );
81
+ }
82
+
83
+ // attach handler (there might be multiple handlers per view)
84
+ this.viewControllerByViewTag.get(view.getTag())!.attachGestureHandler(handler) // TODO: detachGestureHandler
85
+
86
+ // register active view tag
87
+ if (e.type === TouchType.Down) {
88
+ this.activeViewTags.add(view.getTag());
89
+ }
90
+ }
91
+
92
+ // If the pointer is inside the view but it overflows its parent, handlers attached to the parent
93
+ // might not have been called correctly (wrong bounding box). Extending the parent bounding box
94
+ // with the child bounding box ensures that the parent handlers are called correctly.
95
+ // This approach is slightly different from Android RNGH implementation (extracting parent gesture handlers),
96
+ // however, the outcome is the same.
97
+ for (let j = i; j > 1; j--) {
98
+ const currentView = views[j];
99
+ const parentView = views[j-1];
100
+ if (parentView.intersectsWith(currentView)) {
101
+ parentView.attachChildrenBoundingRects(currentView);
102
+ }
103
+ }
104
+ }
105
+
106
+ // send touch to gesture handlers, prioritize handling touch events for child components
107
+ if (this.activeViewTags.size > 0) {
108
+ const tags = Array.from(this.activeViewTags);
109
+ for (let i = tags.length - 1; i >= 0; i--) {
110
+ const tag = tags[i];
111
+ const viewController = this.viewControllerByViewTag.get(tag);
112
+ if (viewController) {
113
+ viewController.handleTouch(e);
114
+ }
115
+ }
116
+ }
117
+
118
+
119
+ if (touchEvent.type === TouchType.Up || touchEvent.type === TouchType.Cancel) {
120
+ touchableViews.forEach(view => this.touchableViewsMultiset.remove(view));
121
+ }
122
+ }
123
+
124
+ cancelTouches() {
125
+ for (const activeViewTag of this.activeViewTags) {
126
+ this.gestureHandlerRegistry.getGestureHandlersByViewTag(activeViewTag).forEach(gh => {
127
+ gh.cancel()
128
+ gh.reset()
129
+ })
130
+ }
131
+ }
132
+ }
133
+
134
+
135
+ const CACHED_RAW_TOUCH_POINT_BY_POINTER_ID = new Map<number, RawTouchPoint>();
136
+ let LAST_CHANGED_POINTER_ID: number | null = null;
137
+ const MAX_CACHE_SIZE = 10;
138
+
139
+ function rawTouchEventToTouchEventArkTS(raw: RawTouchEvent): TouchEventArkTS {
140
+ const touchType = touchTypeFromAction(raw.action);
141
+ const actionTouch = raw.actionTouch;
142
+
143
+ let lastChangedTouch: RawTouchPoint = actionTouch;
144
+ if (CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.has(actionTouch.pointerId)) {
145
+ if (!areRawTouchPointsEqual(actionTouch,
146
+ CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.get(actionTouch.pointerId) as RawTouchPoint)) {
147
+ LAST_CHANGED_POINTER_ID = actionTouch.pointerId;
148
+ CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.set(actionTouch.pointerId, actionTouch);
149
+ }
150
+ } else {
151
+ // remove first element if the cache is full
152
+ if (CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.size >= MAX_CACHE_SIZE) {
153
+ CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.delete(CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.keys().next().value);
154
+ }
155
+ LAST_CHANGED_POINTER_ID = actionTouch.pointerId;
156
+ CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.set(actionTouch.pointerId, actionTouch);
157
+ }
158
+ lastChangedTouch = CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.get(LAST_CHANGED_POINTER_ID as number) as RawTouchPoint
159
+ return {
160
+ type: touchTypeFromAction(raw.action),
161
+ touches: raw.touchPoints.map(tp =>
162
+ touchObjectFromTouchPoint(tp, touchType),
163
+ ),
164
+ changedTouches: [
165
+ touchObjectFromTouchPoint(lastChangedTouch, touchType),
166
+ ],
167
+ timestamp: raw.timestamp / Math.pow(10, 6),
168
+ };
169
+ }
170
+
171
+ function touchTypeFromAction(action: number): TouchType {
172
+ switch (action) {
173
+ case 1:
174
+ return TouchType.Down;
175
+ case 2:
176
+ return TouchType.Move;
177
+ case 3:
178
+ return TouchType.Up;
179
+ default:
180
+ return TouchType.Cancel;
181
+ }
182
+ }
183
+
184
+ function touchObjectFromTouchPoint(
185
+ touchPoint: RawTouchPoint,
186
+ touchType: TouchType,
187
+ ): TouchObject {
188
+ return {
189
+ id: touchPoint.pointerId,
190
+ windowX: touchPoint.windowX,
191
+ windowY: touchPoint.windowY,
192
+ x: touchPoint.windowX,
193
+ y: touchPoint.windowY,
194
+ type: touchType,
195
+ };
196
+ }
@@ -0,0 +1,85 @@
1
+ import { View, BoundingBox } from "../core"
2
+
3
+
4
+ export type RawTouchableView = {
5
+ tag: number,
6
+ /**
7
+ * Relative to application window.
8
+ */
9
+ x: number,
10
+ /**
11
+ * Relative to application window.
12
+ */
13
+ y: number,
14
+ width: number,
15
+ height: number,
16
+ buttonRole: boolean,
17
+ }
18
+
19
+ export class RNGHView implements View {
20
+ private tag: number
21
+ private buttonRole: boolean
22
+ private boundingBox: BoundingBox
23
+ private childrenBoundingBoxes: Set<BoundingBox> = new Set()
24
+
25
+ constructor({ tag, buttonRole, ...boundingBox }: RawTouchableView) {
26
+ this.tag = tag
27
+ this.buttonRole = buttonRole
28
+ this.boundingBox = boundingBox
29
+ }
30
+
31
+ getTag(): number {
32
+ return this.tag
33
+ }
34
+
35
+ getBoundingRect(): BoundingBox {
36
+ return { ...this.boundingBox }
37
+ }
38
+
39
+ getChildrenBoundingRects(): BoundingBox[] {
40
+ return Array.from(this.childrenBoundingBoxes)
41
+ }
42
+
43
+ isPositionInBounds({ x, y }: {
44
+ x: number;
45
+ y: number
46
+ }): boolean {
47
+ const rects = [this.boundingBox, ...this.childrenBoundingBoxes]
48
+ return rects.some(rect => (
49
+ x >= rect.x &&
50
+ x <= rect.x + rect.width &&
51
+ y >= rect.y &&
52
+ y <= rect.y + rect.height
53
+ ))
54
+ }
55
+
56
+ updateBoundingBox(boundingBox: BoundingBox) {
57
+ this.boundingBox = boundingBox
58
+ }
59
+
60
+ attachChildrenBoundingRects(view: RNGHView) {
61
+ this.childrenBoundingBoxes.add(view.getBoundingRect())
62
+ for (const childBoundingBox of view.getChildrenBoundingRects()) {
63
+ this.childrenBoundingBoxes.add(childBoundingBox)
64
+ }
65
+ }
66
+
67
+ intersectsWith(view: RNGHView): boolean {
68
+ const rect1 = this.getBoundingRect()
69
+ const rect2 = view.getBoundingRect()
70
+ return (
71
+ rect1.x < rect2.x + rect2.width &&
72
+ rect1.x + rect1.width > rect2.x &&
73
+ rect1.y < rect2.y + rect2.height &&
74
+ rect1.y + rect1.height > rect2.y
75
+ )
76
+ }
77
+
78
+ setButtonRole(buttonRole: boolean) {
79
+ this.buttonRole = buttonRole
80
+ }
81
+
82
+ hasButtonRole(): boolean {
83
+ return this.buttonRole
84
+ }
85
+ }
@@ -11,15 +11,16 @@ import {
11
11
  } from '../core';
12
12
  import { TouchEvent, TouchType, TouchObject } from './types';
13
13
 
14
- export class GestureHandlerArkUIAdapter {
14
+
15
+ export class RNGHViewController {
15
16
  private activePointerIds = new Set<number>();
16
- private pointersIdInBounds = new Set<number>();
17
+ private pointerIdsInBounds = new Set<number>();
17
18
  private gestureHandlers = new Set<GestureHandler>();
18
19
  private view: View;
19
20
  private logger: RNGHLogger;
20
21
 
21
22
  constructor(view: View, logger: RNGHLogger) {
22
- this.logger = logger.cloneWithPrefix(`ArkUIAdapter(viewTag: ${view.getTag()})`)
23
+ this.logger = logger.cloneAndJoinPrefix(`RNGHViewTouchHandler`)
23
24
  this.view = view;
24
25
  }
25
26
 
@@ -28,19 +29,23 @@ export class GestureHandlerArkUIAdapter {
28
29
  }
29
30
 
30
31
  handleTouch(e: TouchEvent) {
32
+ const logger = this.logger.cloneAndJoinPrefix("handleTouch")
31
33
  for (const changedTouch of e.changedTouches) {
32
- if (this.shouldSkipTouch(changedTouch)) continue;
33
- const wasInBounds = this.pointersIdInBounds.has(changedTouch.id);
34
+ if (this.shouldSkipTouch(changedTouch)) {
35
+ continue;
36
+ }
37
+ const wasInBounds = this.pointerIdsInBounds.has(changedTouch.id);
34
38
  const isInBounds = this.isInBounds({
35
39
  x: changedTouch.windowX,
36
40
  y: changedTouch.windowY,
37
41
  });
38
- this.logger.info(
39
- `handleTouch: ${JSON.stringify({
42
+ logger.debug(
43
+ {
44
+ viewTag: this.view.getTag(),
40
45
  type: changedTouch.type,
41
46
  wasInBounds,
42
47
  isInBounds,
43
- })}`,
48
+ },
44
49
  );
45
50
  const adaptedEvent = this.adaptTouchEvent(e, changedTouch);
46
51
  this.gestureHandlers.forEach(gh => {
@@ -58,9 +63,11 @@ export class GestureHandlerArkUIAdapter {
58
63
  gh.onAdditionalPointerRemove(adaptedEvent);
59
64
  break;
60
65
  case EventType.MOVE:
61
- if (!wasInBounds && !isInBounds)
66
+ if (!wasInBounds && !isInBounds) {
62
67
  gh.onPointerOutOfBounds(adaptedEvent);
63
- else gh.onPointerMove(adaptedEvent);
68
+ } else {
69
+ gh.onPointerMove(adaptedEvent);
70
+ }
64
71
  break;
65
72
  case EventType.ENTER:
66
73
  gh.onPointerEnter(adaptedEvent);
@@ -97,9 +104,10 @@ export class GestureHandlerArkUIAdapter {
97
104
  changedTouch.type,
98
105
  this.isInBounds({ x: xAbsolute, y: yAbsolute }),
99
106
  changedTouch.id,
100
- this.pointersIdInBounds.has(changedTouch.id),
107
+ this.pointerIdsInBounds.has(changedTouch.id),
101
108
  );
102
- this.logger.cloneWithPrefix("adaptTouchEvent").debug({ eventType, activePointersCount: this.activePointerIds.size })
109
+ this.logger.cloneAndJoinPrefix("adaptTouchEvent")
110
+ .debug({ eventType, activePointersCount: this.activePointerIds.size })
103
111
  this.updateIsInBoundsByPointerId(
104
112
  changedTouch.type,
105
113
  changedTouch.id,
@@ -133,32 +141,33 @@ export class GestureHandlerArkUIAdapter {
133
141
  ) {
134
142
  switch (touchType) {
135
143
  case TouchType.Down:
136
- if (this.isInBounds({ x, y })) this.pointersIdInBounds.add(pointerId);
144
+ if (this.isInBounds({ x, y })) {
145
+ this.pointerIdsInBounds.add(pointerId);
146
+ }
137
147
  break;
138
148
  case TouchType.Move:
139
- if (this.isInBounds({ x, y })) this.pointersIdInBounds.add(pointerId);
140
- else this.pointersIdInBounds.delete(pointerId);
149
+ if (this.isInBounds({
150
+ x,
151
+ y
152
+ })) {
153
+ this.pointerIdsInBounds.add(pointerId);
154
+ } else {
155
+ this.pointerIdsInBounds.delete(pointerId);
156
+ }
141
157
  break;
142
158
  case TouchType.Up:
143
- this.pointersIdInBounds.delete(pointerId);
159
+ this.pointerIdsInBounds.delete(pointerId);
144
160
  break;
145
161
  case TouchType.Cancel:
146
- this.pointersIdInBounds.delete(pointerId);
162
+ this.pointerIdsInBounds.delete(pointerId);
147
163
  break;
148
164
  }
149
165
  }
150
166
 
151
167
  private isInBounds(point: Point): boolean {
152
- const x = point.x;
153
- const y = point.y;
154
168
  const rect = this.view.getBoundingRect();
155
- this.logger.cloneWithPrefix("isInBounds").debug({ rect })
156
- const result =
157
- x >= rect.x &&
158
- x <= rect.x + rect.width &&
159
- y >= rect.y &&
160
- y <= rect.y + rect.height;
161
- return result;
169
+ this.logger.cloneAndJoinPrefix("isInBounds").debug({ rect })
170
+ return this.view.isPositionInBounds(point);
162
171
  }
163
172
 
164
173
  private updateActivePointers(touchType: TouchType, pointerId: number): void {
@@ -204,11 +213,17 @@ export class GestureHandlerArkUIAdapter {
204
213
 
205
214
  switch (touchType) {
206
215
  case TouchType.Down:
207
- if (activePointersCount > 0) return EventType.ADDITIONAL_POINTER_DOWN;
208
- else return EventType.DOWN;
216
+ if (activePointersCount > 0) {
217
+ return EventType.ADDITIONAL_POINTER_DOWN;
218
+ } else {
219
+ return EventType.DOWN;
220
+ }
209
221
  case TouchType.Up:
210
- if (activePointersCount > 1) return EventType.ADDITIONAL_POINTER_UP;
211
- else return EventType.UP;
222
+ if (activePointersCount > 1) {
223
+ return EventType.ADDITIONAL_POINTER_UP;
224
+ } else {
225
+ return EventType.UP;
226
+ }
212
227
  case TouchType.Move:
213
228
  if (isCurrentlyInBounds) {
214
229
  return wasInBounds ? EventType.MOVE : EventType.ENTER;
@@ -0,0 +1,19 @@
1
+ import { Tag, } from '@rnoh/react-native-openharmony/ts';
2
+ import { View, ViewRegistry } from '../core';
3
+
4
+
5
+ export class RNGHViewRegistry implements ViewRegistry {
6
+ private viewByTag = new Map<Tag, View>()
7
+
8
+ save(view: View) {
9
+ this.viewByTag.set(view.getTag(), view)
10
+ }
11
+
12
+ deleteByTag(viewTag: Tag) {
13
+ this.viewByTag.delete(viewTag)
14
+ }
15
+
16
+ getViewByTag(viewTag: Tag) {
17
+ return this.viewByTag.get(viewTag);
18
+ }
19
+ }