@multiplayer-app/session-recorder-react-native 0.0.1-beta.9 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +708 -83
- package/SessionRecorderNative.podspec +26 -0
- package/android/build.gradle +2 -0
- package/copy-react-native-dist.sh +33 -9
- package/dist/components/ScreenRecorderView/ScreenRecorderView.js +1 -1
- package/dist/components/ScreenRecorderView/ScreenRecorderView.js.map +1 -1
- package/dist/components/SessionRecorderWidget/ErrorBanner.d.ts +7 -0
- package/dist/components/SessionRecorderWidget/ErrorBanner.js +1 -0
- package/dist/components/SessionRecorderWidget/ErrorBanner.js.map +1 -0
- package/dist/components/SessionRecorderWidget/FinalPopover.d.ts +4 -3
- package/dist/components/SessionRecorderWidget/FinalPopover.js +1 -1
- package/dist/components/SessionRecorderWidget/FinalPopover.js.map +1 -1
- package/dist/components/SessionRecorderWidget/InitialPopover.d.ts +6 -3
- package/dist/components/SessionRecorderWidget/InitialPopover.js +1 -1
- package/dist/components/SessionRecorderWidget/InitialPopover.js.map +1 -1
- package/dist/components/SessionRecorderWidget/ModalContainer.js +1 -1
- package/dist/components/SessionRecorderWidget/ModalContainer.js.map +1 -1
- package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js +1 -1
- package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -1
- package/dist/components/SessionRecorderWidget/styles.d.ts +27 -7
- package/dist/components/SessionRecorderWidget/styles.js +1 -1
- package/dist/components/SessionRecorderWidget/styles.js.map +1 -1
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.js +1 -1
- package/dist/components/index.js.map +1 -1
- package/dist/config/constants.js +1 -1
- package/dist/config/constants.js.map +1 -1
- package/dist/config/defaults.d.ts +4 -4
- package/dist/config/defaults.js +1 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/masking.d.ts +2 -2
- package/dist/config/masking.js +1 -1
- package/dist/config/masking.js.map +1 -1
- package/dist/config/session-recorder.js +1 -1
- package/dist/config/session-recorder.js.map +1 -1
- package/dist/config/validators.d.ts +1 -1
- package/dist/config/validators.js +1 -1
- package/dist/config/validators.js.map +1 -1
- package/dist/config/widget.d.ts +9 -0
- package/dist/config/widget.js +1 -0
- package/dist/config/widget.js.map +1 -0
- package/dist/context/SessionRecorderContext.d.ts +11 -4
- package/dist/context/SessionRecorderContext.js +1 -1
- package/dist/context/SessionRecorderContext.js.map +1 -1
- package/dist/context/SessionRecorderStore.d.ts +12 -0
- package/dist/context/SessionRecorderStore.js +1 -0
- package/dist/context/SessionRecorderStore.js.map +1 -0
- package/dist/context/useSessionRecorderStore.d.ts +8 -0
- package/dist/context/useSessionRecorderStore.js +1 -0
- package/dist/context/useSessionRecorderStore.js.map +1 -0
- package/dist/context/useStoreSelector.d.ts +4 -0
- package/dist/context/useStoreSelector.js +1 -0
- package/dist/context/useStoreSelector.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/native/GestureRecorderNative.d.ts +57 -0
- package/dist/native/GestureRecorderNative.js +1 -0
- package/dist/native/GestureRecorderNative.js.map +1 -0
- package/dist/native/SessionRecorderNative.d.ts +17 -5
- package/dist/native/SessionRecorderNative.js +1 -1
- package/dist/native/SessionRecorderNative.js.map +1 -1
- package/dist/native/index.d.ts +2 -0
- package/dist/native/index.js +1 -0
- package/dist/native/index.js.map +1 -0
- package/dist/otel/index.js +1 -1
- package/dist/otel/index.js.map +1 -1
- package/dist/patch/xhr.js +1 -1
- package/dist/patch/xhr.js.map +1 -1
- package/dist/recorder/eventExporter.d.ts +4 -1
- package/dist/recorder/eventExporter.js +1 -1
- package/dist/recorder/eventExporter.js.map +1 -1
- package/dist/recorder/gestureRecorder.d.ts +28 -62
- package/dist/recorder/gestureRecorder.js +1 -1
- package/dist/recorder/gestureRecorder.js.map +1 -1
- package/dist/recorder/index.d.ts +2 -0
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.js.map +1 -1
- package/dist/recorder/navigationTracker.d.ts +4 -19
- package/dist/recorder/navigationTracker.js +1 -1
- package/dist/recorder/navigationTracker.js.map +1 -1
- package/dist/recorder/screenRecorder.d.ts +10 -5
- package/dist/recorder/screenRecorder.js +1 -1
- package/dist/recorder/screenRecorder.js.map +1 -1
- package/dist/services/api.service.d.ts +12 -3
- package/dist/services/api.service.js +1 -1
- package/dist/services/api.service.js.map +1 -1
- package/dist/services/network.service.d.ts +46 -0
- package/dist/services/network.service.js +1 -0
- package/dist/services/network.service.js.map +1 -0
- package/dist/services/screenMaskingService.d.ts +13 -5
- package/dist/services/screenMaskingService.js +1 -1
- package/dist/services/screenMaskingService.js.map +1 -1
- package/dist/services/storage.service.js +1 -1
- package/dist/services/storage.service.js.map +1 -1
- package/dist/session-recorder.d.ts +17 -33
- package/dist/session-recorder.js +1 -1
- package/dist/session-recorder.js.map +1 -1
- package/dist/types/configs.d.ts +85 -0
- package/dist/types/configs.js +1 -0
- package/dist/types/configs.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/session-recorder.d.ts +105 -138
- package/dist/types/session-recorder.js +1 -1
- package/dist/types/session-recorder.js.map +1 -1
- package/dist/utils/constants.optional.d.ts +21 -0
- package/dist/utils/constants.optional.expo.d.ts +3 -0
- package/dist/utils/constants.optional.expo.js +1 -0
- package/dist/utils/constants.optional.expo.js.map +1 -0
- package/dist/utils/constants.optional.js +1 -0
- package/dist/utils/constants.optional.js.map +1 -0
- package/dist/utils/createStore.d.ts +8 -0
- package/dist/utils/createStore.js +1 -0
- package/dist/utils/createStore.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -7
- package/dist/utils/logger.js +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/platform.d.ts +8 -0
- package/dist/utils/platform.js +1 -1
- package/dist/utils/platform.js.map +1 -1
- package/dist/utils/rrweb-events.d.ts +4 -3
- package/dist/utils/rrweb-events.js +1 -1
- package/dist/utils/rrweb-events.js.map +1 -1
- package/dist/utils/session.d.ts +2 -1
- package/dist/utils/session.js +1 -1
- package/dist/utils/session.js.map +1 -1
- package/dist/utils/shallowEqual.d.ts +1 -0
- package/dist/utils/shallowEqual.js +1 -0
- package/dist/utils/shallowEqual.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/AUTO_METADATA_DETECTION.md +108 -0
- package/ios/GestureRecorderNative.m +21 -0
- package/ios/GestureRecorderNative.swift +316 -0
- package/ios/SessionRecorderNative.m +5 -0
- package/ios/SessionRecorderNative.swift +478 -84
- package/package.json +13 -27
- package/react-native.config.js +7 -10
- package/app.plugin.js +0 -42
- package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.d.ts +0 -6
- package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js +0 -1
- package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js.map +0 -1
- package/dist/components/GestureCaptureWrapper/index.d.ts +0 -1
- package/dist/components/GestureCaptureWrapper/index.js +0 -1
- package/dist/components/GestureCaptureWrapper/index.js.map +0 -1
- package/dist/components/MaskableComponent.d.ts +0 -22
- package/dist/components/MaskableComponent.js +0 -1
- package/dist/components/MaskableComponent.js.map +0 -1
- package/dist/components/MaskableTextInput.d.ts +0 -14
- package/dist/components/MaskableTextInput.js +0 -1
- package/dist/components/MaskableTextInput.js.map +0 -1
- package/dist/native/ScreenMasking.d.ts +0 -21
- package/dist/native/ScreenMasking.js +0 -1
- package/dist/native/ScreenMasking.js.map +0 -1
- package/dist/recorder/screenshotManager.d.ts +0 -10
- package/dist/recorder/screenshotManager.js +0 -1
- package/dist/recorder/screenshotManager.js.map +0 -1
- package/dist/utils/componentRegistry.d.ts +0 -64
- package/dist/utils/componentRegistry.js +0 -1
- package/dist/utils/componentRegistry.js.map +0 -1
- package/dist/utils/nativeModuleTest.d.ts +0 -8
- package/dist/utils/nativeModuleTest.js +0 -1
- package/dist/utils/nativeModuleTest.js.map +0 -1
- package/dist/utils/reactNativeHierarchyExtractor.d.ts +0 -38
- package/dist/utils/reactNativeHierarchyExtractor.js +0 -1
- package/dist/utils/reactNativeHierarchyExtractor.js.map +0 -1
- package/dist/utils/screenshotMasker.d.ts +0 -96
- package/dist/utils/screenshotMasker.js +0 -1
- package/dist/utils/screenshotMasker.js.map +0 -1
- package/dist/utils/viewHierarchyTracker.d.ts +0 -89
- package/dist/utils/viewHierarchyTracker.js +0 -1
- package/dist/utils/viewHierarchyTracker.js.map +0 -1
- package/docs/NATIVE_MODULE_SETUP.md +0 -177
- package/plugin/package.json +0 -20
- package/plugin/src/index.js +0 -42
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
import React
|
|
3
|
+
|
|
4
|
+
// Temporary solution: Embed GestureTargetFinder functionality directly
|
|
5
|
+
// TODO: Fix module linking to properly separate these files
|
|
6
|
+
struct GestureTargetInfo {
|
|
7
|
+
let identifier: String
|
|
8
|
+
let label: String?
|
|
9
|
+
let role: String?
|
|
10
|
+
let testId: String?
|
|
11
|
+
let text: String?
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
enum GestureTargetFinder {
|
|
15
|
+
static func findTargetView(at point: CGPoint, in view: UIView) -> GestureTargetInfo {
|
|
16
|
+
let targetView = view.hitTest(point, with: nil)
|
|
17
|
+
|
|
18
|
+
guard let target = targetView else {
|
|
19
|
+
return GestureTargetInfo(identifier: "unknown", label: nil, role: nil, testId: nil, text: nil)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let identifier = target.accessibilityIdentifier ?? target.accessibilityLabel ?? "view-\(target.hash)"
|
|
23
|
+
let label = target.accessibilityLabel
|
|
24
|
+
let role = roleFromAccessibilityTraits(target.accessibilityTraits)
|
|
25
|
+
let testId = target.accessibilityIdentifier
|
|
26
|
+
|
|
27
|
+
var text: String?
|
|
28
|
+
if let labelView = target as? UILabel {
|
|
29
|
+
text = labelView.text
|
|
30
|
+
} else if let button = target as? UIButton {
|
|
31
|
+
text = button.titleLabel?.text
|
|
32
|
+
} else if let textField = target as? UITextField {
|
|
33
|
+
text = textField.text ?? textField.placeholder
|
|
34
|
+
} else if let textView = target as? UITextView {
|
|
35
|
+
text = textView.text
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return GestureTargetInfo(identifier: identifier, label: label, role: role, testId: testId, text: text)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static func roleFromAccessibilityTraits(_ traits: UIAccessibilityTraits) -> String? {
|
|
42
|
+
if traits.contains(.button) { return "button" }
|
|
43
|
+
if traits.contains(.link) { return "link" }
|
|
44
|
+
if traits.contains(.image) { return "image" }
|
|
45
|
+
if traits.contains(.staticText) { return "text" }
|
|
46
|
+
if traits.contains(.header) { return "header" }
|
|
47
|
+
if traits.contains(.searchField) { return "search" }
|
|
48
|
+
if traits.contains(.keyboardKey) { return "key" }
|
|
49
|
+
if traits.contains(.adjustable) { return "adjustable" }
|
|
50
|
+
if traits.contains(.tabBar) { return "tabbar" }
|
|
51
|
+
return nil
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@objc(GestureRecorderNative)
|
|
56
|
+
class GestureRecorderNative: RCTEventEmitter {
|
|
57
|
+
|
|
58
|
+
private var isRecording = false
|
|
59
|
+
private var gestureCallback: RCTResponseSenderBlock?
|
|
60
|
+
private var rootViewController: UIViewController?
|
|
61
|
+
|
|
62
|
+
// Gesture recognizers
|
|
63
|
+
private var tapGestureRecognizer: UITapGestureRecognizer?
|
|
64
|
+
private var panGestureRecognizer: UIPanGestureRecognizer?
|
|
65
|
+
private var longPressGestureRecognizer: UILongPressGestureRecognizer?
|
|
66
|
+
private var pinchGestureRecognizer: UIPinchGestureRecognizer?
|
|
67
|
+
|
|
68
|
+
override func supportedEvents() -> [String]! {
|
|
69
|
+
return ["onGestureDetected"]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@objc func startGestureRecording(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
77
|
+
DispatchQueue.main.async {
|
|
78
|
+
guard !self.isRecording else {
|
|
79
|
+
resolve(nil)
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
self.setupGestureRecognizers()
|
|
84
|
+
self.isRecording = true
|
|
85
|
+
resolve(nil)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@objc func stopGestureRecording(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
90
|
+
DispatchQueue.main.async {
|
|
91
|
+
guard self.isRecording else {
|
|
92
|
+
resolve(nil)
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
self.removeGestureRecognizers()
|
|
97
|
+
self.isRecording = false
|
|
98
|
+
resolve(nil)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@objc func isGestureRecordingActive(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
103
|
+
resolve(self.isRecording)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@objc func recordGesture(_ gestureType: String, x: NSNumber, y: NSNumber, target: String?, metadata: NSDictionary?) {
|
|
107
|
+
let gestureEvent: [String: Any] = [
|
|
108
|
+
"type": gestureType,
|
|
109
|
+
"timestamp": Date().timeIntervalSince1970 * 1000, // Convert to milliseconds
|
|
110
|
+
"x": x.doubleValue,
|
|
111
|
+
"y": y.doubleValue,
|
|
112
|
+
"target": target ?? "",
|
|
113
|
+
"metadata": metadata ?? [:]
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
sendEvent(withName: "onGestureDetected", body: gestureEvent)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private func setupGestureRecognizers() {
|
|
120
|
+
guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }),
|
|
121
|
+
let rootViewController = window.rootViewController else {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
self.rootViewController = rootViewController
|
|
126
|
+
|
|
127
|
+
// Tap gesture recognizer
|
|
128
|
+
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
|
|
129
|
+
tapGestureRecognizer?.numberOfTapsRequired = 1
|
|
130
|
+
tapGestureRecognizer?.numberOfTouchesRequired = 1
|
|
131
|
+
rootViewController.view.addGestureRecognizer(tapGestureRecognizer!)
|
|
132
|
+
|
|
133
|
+
// Pan gesture recognizer
|
|
134
|
+
panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
|
|
135
|
+
rootViewController.view.addGestureRecognizer(panGestureRecognizer!)
|
|
136
|
+
|
|
137
|
+
// Long press gesture recognizer
|
|
138
|
+
longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
|
|
139
|
+
longPressGestureRecognizer?.minimumPressDuration = 0.5
|
|
140
|
+
rootViewController.view.addGestureRecognizer(longPressGestureRecognizer!)
|
|
141
|
+
|
|
142
|
+
// Pinch gesture recognizer
|
|
143
|
+
pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
|
|
144
|
+
rootViewController.view.addGestureRecognizer(pinchGestureRecognizer!)
|
|
145
|
+
|
|
146
|
+
// Allow simultaneous recognition
|
|
147
|
+
tapGestureRecognizer?.delegate = self
|
|
148
|
+
panGestureRecognizer?.delegate = self
|
|
149
|
+
longPressGestureRecognizer?.delegate = self
|
|
150
|
+
pinchGestureRecognizer?.delegate = self
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private func removeGestureRecognizers() {
|
|
154
|
+
guard let rootViewController = rootViewController else { return }
|
|
155
|
+
|
|
156
|
+
if let tapGesture = tapGestureRecognizer {
|
|
157
|
+
rootViewController.view.removeGestureRecognizer(tapGesture)
|
|
158
|
+
}
|
|
159
|
+
if let panGesture = panGestureRecognizer {
|
|
160
|
+
rootViewController.view.removeGestureRecognizer(panGesture)
|
|
161
|
+
}
|
|
162
|
+
if let longPressGesture = longPressGestureRecognizer {
|
|
163
|
+
rootViewController.view.removeGestureRecognizer(longPressGesture)
|
|
164
|
+
}
|
|
165
|
+
if let pinchGesture = pinchGestureRecognizer {
|
|
166
|
+
rootViewController.view.removeGestureRecognizer(pinchGesture)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
tapGestureRecognizer = nil
|
|
170
|
+
panGestureRecognizer = nil
|
|
171
|
+
longPressGestureRecognizer = nil
|
|
172
|
+
pinchGestureRecognizer = nil
|
|
173
|
+
self.rootViewController = nil
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
|
|
177
|
+
guard let view = gesture.view else { return }
|
|
178
|
+
let location = gesture.location(in: view)
|
|
179
|
+
let target = GestureTargetFinder.findTargetView(at: location, in: view)
|
|
180
|
+
|
|
181
|
+
let gestureEvent: [String: Any] = [
|
|
182
|
+
"type": "tap",
|
|
183
|
+
"timestamp": Date().timeIntervalSince1970 * 1000,
|
|
184
|
+
"x": location.x,
|
|
185
|
+
"y": location.y,
|
|
186
|
+
"target": target.identifier,
|
|
187
|
+
"targetInfo": [
|
|
188
|
+
"identifier": target.identifier,
|
|
189
|
+
"label": target.label,
|
|
190
|
+
"role": target.role,
|
|
191
|
+
"testId": target.testId,
|
|
192
|
+
"text": target.text
|
|
193
|
+
],
|
|
194
|
+
"metadata": [
|
|
195
|
+
"pressure": 1.0
|
|
196
|
+
]
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
sendEvent(withName: "onGestureDetected", body: gestureEvent)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
|
|
203
|
+
guard let view = gesture.view else { return }
|
|
204
|
+
let location = gesture.location(in: view)
|
|
205
|
+
let velocity = gesture.velocity(in: view)
|
|
206
|
+
let translation = gesture.translation(in: view)
|
|
207
|
+
|
|
208
|
+
let target = GestureTargetFinder.findTargetView(at: location, in: view)
|
|
209
|
+
|
|
210
|
+
var gestureType: String
|
|
211
|
+
switch gesture.state {
|
|
212
|
+
case .began:
|
|
213
|
+
gestureType = "pan_start"
|
|
214
|
+
case .changed:
|
|
215
|
+
gestureType = "pan_move"
|
|
216
|
+
case .ended, .cancelled:
|
|
217
|
+
gestureType = "pan_end"
|
|
218
|
+
default:
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let gestureEvent: [String: Any] = [
|
|
223
|
+
"type": gestureType,
|
|
224
|
+
"timestamp": Date().timeIntervalSince1970 * 1000,
|
|
225
|
+
"x": location.x,
|
|
226
|
+
"y": location.y,
|
|
227
|
+
"target": target.identifier,
|
|
228
|
+
"targetInfo": [
|
|
229
|
+
"identifier": target.identifier,
|
|
230
|
+
"label": target.label,
|
|
231
|
+
"role": target.role,
|
|
232
|
+
"testId": target.testId,
|
|
233
|
+
"text": target.text
|
|
234
|
+
],
|
|
235
|
+
"metadata": [
|
|
236
|
+
"velocity": sqrt(velocity.x * velocity.x + velocity.y * velocity.y),
|
|
237
|
+
"deltaX": translation.x,
|
|
238
|
+
"deltaY": translation.y
|
|
239
|
+
]
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
sendEvent(withName: "onGestureDetected", body: gestureEvent)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@objc private func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
|
|
246
|
+
guard gesture.state == .began else { return }
|
|
247
|
+
|
|
248
|
+
guard let view = gesture.view else { return }
|
|
249
|
+
let location = gesture.location(in: view)
|
|
250
|
+
let target = GestureTargetFinder.findTargetView(at: location, in: view)
|
|
251
|
+
|
|
252
|
+
let gestureEvent: [String: Any] = [
|
|
253
|
+
"type": "long_press",
|
|
254
|
+
"timestamp": Date().timeIntervalSince1970 * 1000,
|
|
255
|
+
"x": location.x,
|
|
256
|
+
"y": location.y,
|
|
257
|
+
"target": target.identifier,
|
|
258
|
+
"targetInfo": [
|
|
259
|
+
"identifier": target.identifier,
|
|
260
|
+
"label": target.label,
|
|
261
|
+
"role": target.role,
|
|
262
|
+
"testId": target.testId,
|
|
263
|
+
"text": target.text
|
|
264
|
+
],
|
|
265
|
+
"metadata": [
|
|
266
|
+
"duration": 0.5,
|
|
267
|
+
"pressure": 1.0
|
|
268
|
+
]
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
sendEvent(withName: "onGestureDetected", body: gestureEvent)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@objc private func handlePinch(_ gesture: UIPinchGestureRecognizer) {
|
|
275
|
+
guard let view = gesture.view else { return }
|
|
276
|
+
let location = gesture.location(in: view)
|
|
277
|
+
let scale = gesture.scale
|
|
278
|
+
let velocity = gesture.velocity
|
|
279
|
+
|
|
280
|
+
let target = GestureTargetFinder.findTargetView(at: location, in: view)
|
|
281
|
+
|
|
282
|
+
let gestureEvent: [String: Any] = [
|
|
283
|
+
"type": "pinch",
|
|
284
|
+
"timestamp": Date().timeIntervalSince1970 * 1000,
|
|
285
|
+
"x": location.x,
|
|
286
|
+
"y": location.y,
|
|
287
|
+
"target": target.identifier,
|
|
288
|
+
"targetInfo": [
|
|
289
|
+
"identifier": target.identifier,
|
|
290
|
+
"label": target.label,
|
|
291
|
+
"role": target.role,
|
|
292
|
+
"testId": target.testId,
|
|
293
|
+
"text": target.text
|
|
294
|
+
],
|
|
295
|
+
"metadata": [
|
|
296
|
+
"scale": scale,
|
|
297
|
+
"velocity": velocity
|
|
298
|
+
]
|
|
299
|
+
]
|
|
300
|
+
|
|
301
|
+
sendEvent(withName: "onGestureDetected", body: gestureEvent)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Target finding extracted to GestureTargetFinder
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// MARK: - UIGestureRecognizerDelegate
|
|
308
|
+
extension GestureRecorderNative: UIGestureRecognizerDelegate {
|
|
309
|
+
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
310
|
+
return true
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
|
314
|
+
return true
|
|
315
|
+
}
|
|
316
|
+
}
|