@react-native-oh-tpl/react-native-gesture-handler 2.14.8-rc.1 → 2.14.14
Sign up to get free protection for your applications and to get access to all the features.
- package/DrawerLayout/index.ts +2 -2
- package/Swipeable/index.ts +2 -2
- package/harmony/gesture_handler/BuildProfile.ets +17 -0
- package/harmony/gesture_handler/build-profile.json5 +19 -0
- package/harmony/gesture_handler/hvigorfile.ts +2 -0
- package/harmony/gesture_handler/index.ets +2 -0
- package/harmony/gesture_handler/oh-package-lock.json5 +18 -0
- package/harmony/gesture_handler/oh-package.json5 +12 -0
- package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -0
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +12 -0
- package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.cpp +123 -0
- package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.h +15 -0
- package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerButtonComponentInstance.h +27 -0
- package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +245 -0
- package/harmony/gesture_handler/src/main/ets/RNOHPackage.ets +17 -0
- package/harmony/gesture_handler/src/main/ets/core/CircularBuffer.ts +42 -0
- package/harmony/gesture_handler/src/main/ets/core/GestureHandler.ts +739 -0
- package/harmony/gesture_handler/src/main/ets/core/GestureHandlerOrchestrator.ts +344 -0
- package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +63 -0
- package/harmony/gesture_handler/src/main/ets/core/IncomingEvent.ts +78 -0
- package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +144 -0
- package/harmony/gesture_handler/src/main/ets/core/LeastSquareSolver.ts +182 -0
- package/harmony/gesture_handler/src/main/ets/core/Multiset.ts +26 -0
- package/harmony/gesture_handler/src/main/ets/core/OutgoingEvent.ts +34 -0
- package/harmony/gesture_handler/src/main/ets/core/OutgoingEventDispatcher.ts +12 -0
- package/harmony/gesture_handler/src/main/ets/core/PointerTracker.ts +239 -0
- package/harmony/gesture_handler/src/main/ets/core/RNGHError.ts +5 -0
- package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +16 -0
- package/harmony/gesture_handler/src/main/ets/core/State.ts +47 -0
- package/harmony/gesture_handler/src/main/ets/core/Vector2D.ts +80 -0
- package/harmony/gesture_handler/src/main/ets/core/VelocityTracker.ts +106 -0
- package/harmony/gesture_handler/src/main/ets/core/View.ts +21 -0
- package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +7 -0
- package/harmony/gesture_handler/src/main/ets/core/index.ts +15 -0
- package/harmony/gesture_handler/src/main/ets/detectors/ScaleGestureDetector.ts +169 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +219 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +67 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +139 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +50 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/NativeViewGestureHandler.ts +124 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/PanGestureHandler.ts +361 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +174 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +172 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/TapGestureHandler.ts +216 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/detectors/RotationGestureDetector.ts +167 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/index.ts +1 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerPackage.ts +25 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +107 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +94 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootViewController.ts +182 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHView.ts +62 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHViewController.ts +262 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHViewRegistry.ts +19 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerModule.ts +267 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +15 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +25 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/types.ts +25 -0
- package/harmony/gesture_handler/src/main/module.json5 +9 -0
- package/harmony/gesture_handler/src/main/resources/base/element/color.json +8 -0
- package/harmony/gesture_handler/src/main/resources/base/element/string.json +16 -0
- package/harmony/gesture_handler/src/main/resources/base/media/icon.png +0 -0
- package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -0
- package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +16 -0
- package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +16 -0
- package/harmony/gesture_handler/ts.ts +2 -0
- package/harmony/gesture_handler.har +0 -0
- package/lib/commonjs/RNGestureHandlerModule.js +3 -2
- package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
- package/lib/commonjs/components/GestureHandlerRootView.js +3 -3
- package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
- package/lib/commonjs/handlers/createHandler.js +18 -15
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/index.js +36 -8
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/NativeRNGestureHandlerModule.js +2 -1
- package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
- package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js +3 -2
- package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js +3 -2
- package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.js.map +1 -1
- package/lib/module/components/GestureHandlerRootView.js.map +1 -1
- package/lib/module/handlers/createHandler.js +15 -12
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/index.js +5 -7
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
- package/lib/module/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/module/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/typescript/RNGestureHandlerModule.d.ts +2 -2
- package/lib/typescript/components/GestureHandlerRootView.d.ts +6 -6
- package/lib/typescript/handlers/createHandler.d.ts +11 -11
- package/lib/typescript/index.d.ts +47 -42
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +14 -14
- package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +14 -14
- package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts +6 -6
- package/package.json +78 -70
- package/src/RNGestureHandlerModule.ts +4 -4
- package/src/components/GestureHandlerRootView.tsx +23 -23
- package/src/handlers/createHandler.tsx +534 -534
- package/src/index.ts +172 -172
- package/src/specs/NativeRNGestureHandlerModule.ts +26 -26
- package/src/specs/RNGestureHandlerButtonNativeComponent.ts +18 -18
- package/src/specs/RNGestureHandlerRootViewNativeComponent.ts +6 -6
package/harmony/gesture_handler/src/main/ets/gesture-handlers/detectors/RotationGestureDetector.ts
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
import { PointerTracker, IncomingEvent, EventType } from '../../core';
|
2
|
+
|
3
|
+
export interface RotationGestureListener {
|
4
|
+
onRotationBegin: (detector: RotationGestureDetector) => boolean;
|
5
|
+
onRotation: (detector: RotationGestureDetector) => boolean;
|
6
|
+
onRotationEnd: (detector: RotationGestureDetector) => void;
|
7
|
+
}
|
8
|
+
|
9
|
+
export default class RotationGestureDetector
|
10
|
+
implements RotationGestureListener
|
11
|
+
{
|
12
|
+
onRotationBegin: (detector: RotationGestureDetector) => boolean;
|
13
|
+
onRotation: (detector: RotationGestureDetector) => boolean;
|
14
|
+
onRotationEnd: (detector: RotationGestureDetector) => void;
|
15
|
+
|
16
|
+
private currentTime = 0;
|
17
|
+
private previousTime = 0;
|
18
|
+
|
19
|
+
private previousAngle = 0;
|
20
|
+
private rotation = 0;
|
21
|
+
|
22
|
+
private anchorX = 0;
|
23
|
+
private anchorY = 0;
|
24
|
+
|
25
|
+
private isInProgress = false;
|
26
|
+
|
27
|
+
private keyPointers: number[] = [NaN, NaN];
|
28
|
+
|
29
|
+
constructor(callbacks: RotationGestureListener) {
|
30
|
+
this.onRotationBegin = callbacks.onRotationBegin;
|
31
|
+
this.onRotation = callbacks.onRotation;
|
32
|
+
this.onRotationEnd = callbacks.onRotationEnd;
|
33
|
+
}
|
34
|
+
|
35
|
+
private updateCurrent(event: IncomingEvent, tracker: PointerTracker): void {
|
36
|
+
this.previousTime = this.currentTime;
|
37
|
+
this.currentTime = event.time;
|
38
|
+
|
39
|
+
const [firstPointerID, secondPointerID] = this.keyPointers;
|
40
|
+
|
41
|
+
const firstPointerX: number = tracker.getLastX(firstPointerID);
|
42
|
+
const firstPointerY: number = tracker.getLastY(firstPointerID);
|
43
|
+
const secondPointerX: number = tracker.getLastX(secondPointerID);
|
44
|
+
const secondPointerY: number = tracker.getLastY(secondPointerID);
|
45
|
+
|
46
|
+
const vectorX: number = secondPointerX - firstPointerX;
|
47
|
+
const vectorY: number = secondPointerY - firstPointerY;
|
48
|
+
|
49
|
+
this.anchorX = (firstPointerX + secondPointerX) / 2;
|
50
|
+
this.anchorY = (firstPointerY + secondPointerY) / 2;
|
51
|
+
|
52
|
+
//Angle diff should be positive when rotating in clockwise direction
|
53
|
+
const angle: number = -Math.atan2(vectorY, vectorX);
|
54
|
+
|
55
|
+
this.rotation = Number.isNaN(this.previousAngle)
|
56
|
+
? 0
|
57
|
+
: this.previousAngle - angle;
|
58
|
+
|
59
|
+
this.previousAngle = angle;
|
60
|
+
|
61
|
+
if (this.rotation > Math.PI) {
|
62
|
+
this.rotation -= Math.PI;
|
63
|
+
} else if (this.rotation < -Math.PI) {
|
64
|
+
this.rotation += Math.PI;
|
65
|
+
}
|
66
|
+
|
67
|
+
if (this.rotation > Math.PI / 2) {
|
68
|
+
this.rotation -= Math.PI;
|
69
|
+
} else if (this.rotation < -Math.PI / 2) {
|
70
|
+
this.rotation += Math.PI;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
private finish(): void {
|
75
|
+
if (!this.isInProgress) {
|
76
|
+
return;
|
77
|
+
}
|
78
|
+
|
79
|
+
this.isInProgress = false;
|
80
|
+
this.keyPointers = [NaN, NaN];
|
81
|
+
this.onRotationEnd(this);
|
82
|
+
}
|
83
|
+
|
84
|
+
private setKeyPointers(tracker: PointerTracker): void {
|
85
|
+
if (this.keyPointers[0] && this.keyPointers[1]) {
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
const pointerIDs: IterableIterator<number> = tracker.getData().keys();
|
90
|
+
|
91
|
+
this.keyPointers[0] = pointerIDs.next().value as number;
|
92
|
+
this.keyPointers[1] = pointerIDs.next().value as number;
|
93
|
+
}
|
94
|
+
|
95
|
+
public onTouchEvent(event: IncomingEvent, tracker: PointerTracker): boolean {
|
96
|
+
switch (event.eventType) {
|
97
|
+
case EventType.DOWN:
|
98
|
+
this.isInProgress = false;
|
99
|
+
break;
|
100
|
+
|
101
|
+
case EventType.ADDITIONAL_POINTER_DOWN:
|
102
|
+
if (this.isInProgress) {
|
103
|
+
break;
|
104
|
+
}
|
105
|
+
this.isInProgress = true;
|
106
|
+
|
107
|
+
this.previousTime = event.time;
|
108
|
+
this.previousAngle = NaN;
|
109
|
+
|
110
|
+
this.setKeyPointers(tracker);
|
111
|
+
|
112
|
+
this.updateCurrent(event, tracker);
|
113
|
+
this.onRotationBegin(this);
|
114
|
+
break;
|
115
|
+
|
116
|
+
case EventType.MOVE:
|
117
|
+
if (!this.isInProgress) {
|
118
|
+
break;
|
119
|
+
}
|
120
|
+
|
121
|
+
this.updateCurrent(event, tracker);
|
122
|
+
this.onRotation(this);
|
123
|
+
|
124
|
+
break;
|
125
|
+
|
126
|
+
case EventType.ADDITIONAL_POINTER_UP:
|
127
|
+
if (!this.isInProgress) {
|
128
|
+
break;
|
129
|
+
}
|
130
|
+
|
131
|
+
if (this.keyPointers.indexOf(event.pointerId) >= 0) {
|
132
|
+
this.finish();
|
133
|
+
}
|
134
|
+
|
135
|
+
break;
|
136
|
+
|
137
|
+
case EventType.UP:
|
138
|
+
if (this.isInProgress) {
|
139
|
+
this.finish();
|
140
|
+
}
|
141
|
+
break;
|
142
|
+
}
|
143
|
+
|
144
|
+
return true;
|
145
|
+
}
|
146
|
+
|
147
|
+
public getTimeDelta(): number {
|
148
|
+
return this.currentTime + this.previousTime;
|
149
|
+
}
|
150
|
+
|
151
|
+
public getAnchorX(): number {
|
152
|
+
return this.anchorX;
|
153
|
+
}
|
154
|
+
|
155
|
+
public getAnchorY(): number {
|
156
|
+
return this.anchorY;
|
157
|
+
}
|
158
|
+
|
159
|
+
public getRotation(): number {
|
160
|
+
return this.rotation;
|
161
|
+
}
|
162
|
+
|
163
|
+
public reset(): void {
|
164
|
+
this.keyPointers = [NaN, NaN];
|
165
|
+
this.isInProgress = false;
|
166
|
+
}
|
167
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from "./GestureHandlerFactory"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import {RNPackage, TurboModulesFactory} from "@rnoh/react-native-openharmony/ts";
|
2
|
+
import type {TurboModule, TurboModuleContext} from "@rnoh/react-native-openharmony/ts";
|
3
|
+
import {RNGestureHandlerModule} from './RNGestureHandlerModule';
|
4
|
+
|
5
|
+
class GestureHandlerTurboModuleFactory 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.NAME;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* @deprecated: Use the package class exported from ../RNOHPackage.ets (2024-10-10)
|
20
|
+
*/
|
21
|
+
export class GestureHandlerPackage extends RNPackage {
|
22
|
+
createUITurboModuleFactory(ctx: TurboModuleContext): TurboModulesFactory {
|
23
|
+
return new GestureHandlerTurboModuleFactory(ctx);
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
import { RNOHContext } from '@rnoh/react-native-openharmony/ts';
|
2
|
+
import { RNGHLogger, RNGHLoggerMessage } from "../core"
|
3
|
+
import hiTrace from "@ohos.hiTraceMeter"
|
4
|
+
|
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 {
|
26
|
+
constructor(
|
27
|
+
protected rnohLogger: RNOHContext['logger'],
|
28
|
+
protected prefix: string,
|
29
|
+
protected tracer: Tracer = new Tracer(),
|
30
|
+
) {
|
31
|
+
}
|
32
|
+
|
33
|
+
error(msg: string) {
|
34
|
+
this.log("error", msg);
|
35
|
+
}
|
36
|
+
|
37
|
+
warn(msg: string) {
|
38
|
+
this.log("warn", msg);
|
39
|
+
}
|
40
|
+
|
41
|
+
info(msg: string) {
|
42
|
+
this.log("info", msg);
|
43
|
+
}
|
44
|
+
|
45
|
+
debug(msg: RNGHLoggerMessage) {
|
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
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
private stringifyMsg(msg: RNGHLoggerMessage): string {
|
72
|
+
if (typeof msg === "string") {
|
73
|
+
return msg
|
74
|
+
} else {
|
75
|
+
return JSON.stringify(msg)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
cloneAndJoinPrefix(prefix: string) {
|
80
|
+
return new DevelopmentRNGHLogger(this.rnohLogger, `${this.prefix}::${prefix}`, this.tracer);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
export class ProductionRNGHLogger extends DevelopmentRNGHLogger {
|
85
|
+
override debug(msg: string) {
|
86
|
+
// NOOP
|
87
|
+
}
|
88
|
+
|
89
|
+
override cloneAndJoinPrefix(prefix: string) {
|
90
|
+
return new ProductionRNGHLogger(this.rnohLogger, `${this.prefix}::${prefix}`, this.tracer);
|
91
|
+
}
|
92
|
+
|
93
|
+
override startTracing(): () => void {
|
94
|
+
const startTime = Date.now()
|
95
|
+
const currentOffset = this.tracer.getActiveTracesCount() * 2
|
96
|
+
|
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
|
+
}
|
106
|
+
}
|
107
|
+
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
import { RNInstance } from '@rnoh/react-native-openharmony/ts';
|
2
|
+
import {
|
3
|
+
OutgoingEventDispatcher,
|
4
|
+
GestureStateChangeEvent,
|
5
|
+
GestureUpdateEvent,
|
6
|
+
GestureTouchEvent,
|
7
|
+
RNGHLogger
|
8
|
+
} from "../core"
|
9
|
+
|
10
|
+
export class JSEventDispatcher implements OutgoingEventDispatcher {
|
11
|
+
private logger: RNGHLogger
|
12
|
+
|
13
|
+
constructor(private rnInstance: RNInstance, logger: RNGHLogger) {
|
14
|
+
this.logger = logger.cloneAndJoinPrefix("JSEventDispatcher")
|
15
|
+
}
|
16
|
+
|
17
|
+
public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
|
18
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing();
|
19
|
+
this.rnInstance.emitDeviceEvent('onGestureHandlerStateChange', event);
|
20
|
+
stopTracing()
|
21
|
+
}
|
22
|
+
|
23
|
+
public onGestureHandlerEvent(
|
24
|
+
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
25
|
+
) {
|
26
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
|
27
|
+
this.rnInstance.emitDeviceEvent('onGestureHandlerEvent', event);
|
28
|
+
stopTracing()
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
export class AnimatedEventDispatcher implements OutgoingEventDispatcher {
|
33
|
+
private logger: RNGHLogger
|
34
|
+
|
35
|
+
constructor(
|
36
|
+
private rnInstance: RNInstance,
|
37
|
+
logger: RNGHLogger,
|
38
|
+
private viewTag: number,
|
39
|
+
) {
|
40
|
+
this.logger = logger.cloneAndJoinPrefix("AnimatedEventDispatcher")
|
41
|
+
}
|
42
|
+
|
43
|
+
public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
|
44
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing()
|
45
|
+
this.rnInstance.emitDeviceEvent('onGestureHandlerStateChange', event);
|
46
|
+
stopTracing()
|
47
|
+
}
|
48
|
+
|
49
|
+
public onGestureHandlerEvent(
|
50
|
+
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
51
|
+
) {
|
52
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
|
53
|
+
this.rnInstance.emitComponentEvent(
|
54
|
+
this.viewTag,
|
55
|
+
'onGestureHandlerEvent',
|
56
|
+
event,
|
57
|
+
);
|
58
|
+
stopTracing()
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
export class ReanimatedEventDispatcher implements OutgoingEventDispatcher {
|
63
|
+
private logger: RNGHLogger
|
64
|
+
|
65
|
+
constructor(
|
66
|
+
private rnInstance: RNInstance,
|
67
|
+
logger: RNGHLogger,
|
68
|
+
private viewTag: number,
|
69
|
+
) {
|
70
|
+
this.logger = logger.cloneAndJoinPrefix("ReanimatedEventDispatcher")
|
71
|
+
}
|
72
|
+
|
73
|
+
public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
|
74
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing();
|
75
|
+
this.rnInstance.emitComponentEvent(
|
76
|
+
this.viewTag,
|
77
|
+
'onGestureHandlerStateChange',
|
78
|
+
event,
|
79
|
+
);
|
80
|
+
stopTracing()
|
81
|
+
}
|
82
|
+
|
83
|
+
public onGestureHandlerEvent(
|
84
|
+
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
85
|
+
) {
|
86
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
|
87
|
+
this.rnInstance.emitComponentEvent(
|
88
|
+
this.viewTag,
|
89
|
+
'onGestureHandlerEvent',
|
90
|
+
event,
|
91
|
+
);
|
92
|
+
stopTracing()
|
93
|
+
}
|
94
|
+
}
|
@@ -0,0 +1,182 @@
|
|
1
|
+
import { TouchEvent as TouchEventArkTS, TouchType, TouchObject } from './types';
|
2
|
+
import { RNGHLogger, View, Multiset, GestureHandlerRegistry } from '../core';
|
3
|
+
import { RawTouchableView } 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
|
63
|
+
for (const view of views) {
|
64
|
+
for (const handler of this.gestureHandlerRegistry.getGestureHandlersByViewTag(
|
65
|
+
view.getTag(),
|
66
|
+
)) {
|
67
|
+
this.logger.info(
|
68
|
+
`Found GestureHandler ${handler.getTag()} for view ${view.getTag()}`,
|
69
|
+
);
|
70
|
+
|
71
|
+
// create view touch handler if necessary
|
72
|
+
if (!this.viewControllerByViewTag.has(view.getTag())) {
|
73
|
+
this.viewControllerByViewTag.set(
|
74
|
+
view.getTag(),
|
75
|
+
new RNGHViewController(
|
76
|
+
view,
|
77
|
+
this.logger,
|
78
|
+
),
|
79
|
+
);
|
80
|
+
}
|
81
|
+
|
82
|
+
// attach handler (there might be multiple handlers per view)
|
83
|
+
this.viewControllerByViewTag.get(view.getTag())!.attachGestureHandler(handler) // TODO: detachGestureHandler
|
84
|
+
|
85
|
+
// register active view tag
|
86
|
+
if (e.type === TouchType.Down) {
|
87
|
+
this.activeViewTags.add(view.getTag());
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
// send touch to gesture handlers, prioritize handling touch events for child components
|
93
|
+
if (this.activeViewTags.size > 0) {
|
94
|
+
const tags = Array.from(this.activeViewTags);
|
95
|
+
for (let i = tags.length - 1; i >= 0; i--) {
|
96
|
+
const tag = tags[i];
|
97
|
+
const viewController = this.viewControllerByViewTag.get(tag);
|
98
|
+
if (viewController) {
|
99
|
+
viewController.handleTouch(e);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
if (touchEvent.type === TouchType.Up || touchEvent.type === TouchType.Cancel) {
|
106
|
+
touchableViews.forEach(view => this.touchableViewsMultiset.remove(view));
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
cancelTouches() {
|
111
|
+
for (const activeViewTag of this.activeViewTags) {
|
112
|
+
this.gestureHandlerRegistry.getGestureHandlersByViewTag(activeViewTag).forEach(gh => {
|
113
|
+
gh.cancel()
|
114
|
+
gh.reset()
|
115
|
+
})
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
const CACHED_RAW_TOUCH_POINT_BY_POINTER_ID = new Map<number, RawTouchPoint>();
|
122
|
+
let LAST_CHANGED_POINTER_ID: number | null = null;
|
123
|
+
const MAX_CACHE_SIZE = 10;
|
124
|
+
|
125
|
+
function rawTouchEventToTouchEventArkTS(raw: RawTouchEvent): TouchEventArkTS {
|
126
|
+
const touchType = touchTypeFromAction(raw.action);
|
127
|
+
const actionTouch = raw.actionTouch;
|
128
|
+
|
129
|
+
let lastChangedTouch: RawTouchPoint = actionTouch;
|
130
|
+
if (CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.has(actionTouch.pointerId)) {
|
131
|
+
if (!areRawTouchPointsEqual(actionTouch,
|
132
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.get(actionTouch.pointerId) as RawTouchPoint)) {
|
133
|
+
LAST_CHANGED_POINTER_ID = actionTouch.pointerId;
|
134
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.set(actionTouch.pointerId, actionTouch);
|
135
|
+
}
|
136
|
+
} else {
|
137
|
+
// remove first element if the cache is full
|
138
|
+
if (CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.size >= MAX_CACHE_SIZE) {
|
139
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.delete(CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.keys().next().value);
|
140
|
+
}
|
141
|
+
LAST_CHANGED_POINTER_ID = actionTouch.pointerId;
|
142
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.set(actionTouch.pointerId, actionTouch);
|
143
|
+
}
|
144
|
+
lastChangedTouch = CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.get(LAST_CHANGED_POINTER_ID as number) as RawTouchPoint
|
145
|
+
return {
|
146
|
+
type: touchTypeFromAction(raw.action),
|
147
|
+
touches: raw.touchPoints.map(tp =>
|
148
|
+
touchObjectFromTouchPoint(tp, touchType),
|
149
|
+
),
|
150
|
+
changedTouches: [
|
151
|
+
touchObjectFromTouchPoint(lastChangedTouch, touchType),
|
152
|
+
],
|
153
|
+
timestamp: raw.timestamp / Math.pow(10, 6),
|
154
|
+
};
|
155
|
+
}
|
156
|
+
|
157
|
+
function touchTypeFromAction(action: number): TouchType {
|
158
|
+
switch (action) {
|
159
|
+
case 1:
|
160
|
+
return TouchType.Down;
|
161
|
+
case 2:
|
162
|
+
return TouchType.Move;
|
163
|
+
case 3:
|
164
|
+
return TouchType.Up;
|
165
|
+
default:
|
166
|
+
return TouchType.Cancel;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
function touchObjectFromTouchPoint(
|
171
|
+
touchPoint: RawTouchPoint,
|
172
|
+
touchType: TouchType,
|
173
|
+
): TouchObject {
|
174
|
+
return {
|
175
|
+
id: touchPoint.pointerId,
|
176
|
+
windowX: touchPoint.windowX,
|
177
|
+
windowY: touchPoint.windowY,
|
178
|
+
x: touchPoint.windowX,
|
179
|
+
y: touchPoint.windowY,
|
180
|
+
type: touchType,
|
181
|
+
};
|
182
|
+
}
|
@@ -0,0 +1,62 @@
|
|
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
|
+
|
24
|
+
constructor({ tag, buttonRole, ...boundingBox }: RawTouchableView) {
|
25
|
+
this.tag = tag
|
26
|
+
this.buttonRole = buttonRole
|
27
|
+
this.boundingBox = boundingBox
|
28
|
+
}
|
29
|
+
|
30
|
+
getTag(): number {
|
31
|
+
return this.tag
|
32
|
+
}
|
33
|
+
|
34
|
+
getBoundingRect(): BoundingBox {
|
35
|
+
return { ...this.boundingBox }
|
36
|
+
}
|
37
|
+
|
38
|
+
isPositionInBounds({ x, y }: {
|
39
|
+
x: number;
|
40
|
+
y: number
|
41
|
+
}): boolean {
|
42
|
+
const rect = this.getBoundingRect();
|
43
|
+
return (
|
44
|
+
x >= rect.x &&
|
45
|
+
x <= rect.x + rect.width &&
|
46
|
+
y >= rect.y &&
|
47
|
+
y <= rect.y + rect.height
|
48
|
+
);
|
49
|
+
}
|
50
|
+
|
51
|
+
updateBoundingBox(boundingBox: BoundingBox) {
|
52
|
+
this.boundingBox = boundingBox
|
53
|
+
}
|
54
|
+
|
55
|
+
setButtonRole(buttonRole: boolean) {
|
56
|
+
this.buttonRole = buttonRole
|
57
|
+
}
|
58
|
+
|
59
|
+
hasButtonRole(): boolean {
|
60
|
+
return this.buttonRole
|
61
|
+
}
|
62
|
+
}
|