@multiplayer-app/session-recorder-react-native 1.0.1-beta.4 → 1.0.1-beta.6

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.
Files changed (180) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/AndroidManifest.xml +2 -2
  3. package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/SessionRecorderNativeConfig.kt +1 -1
  4. package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/SessionRecorderNativeModule.kt +9 -9
  5. package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/SessionRecorderNativePackage.kt +2 -2
  6. package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/model/TargetInfo.kt +1 -1
  7. package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/util/ViewUtils.kt +2 -2
  8. package/lib/module/SessionRecorderNativeSpec.js +5 -0
  9. package/lib/module/SessionRecorderNativeSpec.js.map +1 -0
  10. package/lib/module/components/SessionRecorderWidget/ErrorBanner.js.map +1 -1
  11. package/lib/module/components/SessionRecorderWidget/ModalHeader.js.map +1 -1
  12. package/lib/module/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -1
  13. package/lib/module/components/SessionRecorderWidget/icons.js.map +1 -1
  14. package/lib/module/components/SessionRecorderWidget/styles.js.map +1 -1
  15. package/lib/module/config/constants.js.map +1 -1
  16. package/lib/module/config/defaults.js.map +1 -1
  17. package/lib/module/config/masking.js.map +1 -1
  18. package/lib/module/config/session-recorder.js.map +1 -1
  19. package/lib/module/config/validators.js.map +1 -1
  20. package/lib/module/config/widget.js.map +1 -1
  21. package/lib/module/context/SessionRecorderStore.js.map +1 -1
  22. package/lib/module/context/useSessionRecorderStore.js.map +1 -1
  23. package/lib/module/context/useStoreSelector.js.map +1 -1
  24. package/lib/module/native/SessionRecorderNative.js +16 -11
  25. package/lib/module/native/SessionRecorderNative.js.map +1 -1
  26. package/lib/module/native/index.js.map +1 -1
  27. package/lib/module/otel/helpers.js +1 -1
  28. package/lib/module/otel/helpers.js.map +1 -1
  29. package/lib/module/otel/index.js.map +1 -1
  30. package/lib/module/otel/instrumentations/index.js.map +1 -1
  31. package/lib/module/patch/xhr.js.map +1 -1
  32. package/lib/module/recorder/eventExporter.js.map +1 -1
  33. package/lib/module/recorder/gestureRecorder.js.map +1 -1
  34. package/lib/module/recorder/index.js.map +1 -1
  35. package/lib/module/recorder/navigationTracker.js.map +1 -1
  36. package/lib/module/recorder/screenRecorder.js.map +1 -1
  37. package/lib/module/services/api.service.js.map +1 -1
  38. package/lib/module/services/network.service.js.map +1 -1
  39. package/lib/module/services/screenMaskingService.js +1 -1
  40. package/lib/module/services/screenMaskingService.js.map +1 -1
  41. package/lib/module/services/storage.service.js.map +1 -1
  42. package/lib/module/session-recorder.js.map +1 -1
  43. package/lib/module/types/index.js.map +1 -1
  44. package/lib/module/types/session-recorder.js.map +1 -1
  45. package/lib/module/utils/app-metadata.js +2 -2
  46. package/lib/module/utils/constants.optional.js.map +1 -1
  47. package/lib/module/utils/createStore.js.map +1 -1
  48. package/lib/module/utils/logger.js +0 -8
  49. package/lib/module/utils/logger.js.map +1 -1
  50. package/lib/module/utils/platform.js +1 -1
  51. package/lib/module/utils/platform.js.map +1 -1
  52. package/lib/module/utils/rrweb-events.js.map +1 -1
  53. package/lib/module/utils/session.js.map +1 -1
  54. package/lib/module/utils/shallowEqual.js.map +1 -1
  55. package/lib/module/utils/time.js.map +1 -1
  56. package/lib/module/version.js +1 -1
  57. package/lib/typescript/src/SessionRecorderNativeSpec.d.ts +42 -0
  58. package/lib/typescript/src/SessionRecorderNativeSpec.d.ts.map +1 -0
  59. package/lib/typescript/src/components/ScreenRecorderView/index.d.ts +1 -1
  60. package/lib/typescript/src/components/SessionRecorderWidget/ErrorBanner.d.ts.map +1 -1
  61. package/lib/typescript/src/components/SessionRecorderWidget/ModalHeader.d.ts.map +1 -1
  62. package/lib/typescript/src/components/SessionRecorderWidget/SessionRecorderWidget.d.ts.map +1 -1
  63. package/lib/typescript/src/components/SessionRecorderWidget/icons.d.ts.map +1 -1
  64. package/lib/typescript/src/components/SessionRecorderWidget/index.d.ts +1 -1
  65. package/lib/typescript/src/components/SessionRecorderWidget/styles.d.ts.map +1 -1
  66. package/lib/typescript/src/components/index.d.ts.map +1 -1
  67. package/lib/typescript/src/config/constants.d.ts.map +1 -1
  68. package/lib/typescript/src/config/defaults.d.ts.map +1 -1
  69. package/lib/typescript/src/config/index.d.ts.map +1 -1
  70. package/lib/typescript/src/config/masking.d.ts.map +1 -1
  71. package/lib/typescript/src/config/session-recorder.d.ts.map +1 -1
  72. package/lib/typescript/src/config/validators.d.ts.map +1 -1
  73. package/lib/typescript/src/config/widget.d.ts +1 -1
  74. package/lib/typescript/src/config/widget.d.ts.map +1 -1
  75. package/lib/typescript/src/context/SessionRecorderStore.d.ts.map +1 -1
  76. package/lib/typescript/src/context/useSessionRecorderStore.d.ts +3 -3
  77. package/lib/typescript/src/context/useSessionRecorderStore.d.ts.map +1 -1
  78. package/lib/typescript/src/context/useStoreSelector.d.ts.map +1 -1
  79. package/lib/typescript/src/index.d.ts.map +1 -1
  80. package/lib/typescript/src/native/SessionRecorderNative.d.ts +3 -54
  81. package/lib/typescript/src/native/SessionRecorderNative.d.ts.map +1 -1
  82. package/lib/typescript/src/native/index.d.ts +1 -1
  83. package/lib/typescript/src/native/index.d.ts.map +1 -1
  84. package/lib/typescript/src/otel/helpers.d.ts.map +1 -1
  85. package/lib/typescript/src/otel/index.d.ts.map +1 -1
  86. package/lib/typescript/src/otel/instrumentations/index.d.ts.map +1 -1
  87. package/lib/typescript/src/patch/index.d.ts.map +1 -1
  88. package/lib/typescript/src/patch/xhr.d.ts.map +1 -1
  89. package/lib/typescript/src/recorder/eventExporter.d.ts.map +1 -1
  90. package/lib/typescript/src/recorder/gestureRecorder.d.ts.map +1 -1
  91. package/lib/typescript/src/recorder/index.d.ts.map +1 -1
  92. package/lib/typescript/src/recorder/navigationTracker.d.ts.map +1 -1
  93. package/lib/typescript/src/recorder/screenRecorder.d.ts.map +1 -1
  94. package/lib/typescript/src/services/api.service.d.ts.map +1 -1
  95. package/lib/typescript/src/services/network.service.d.ts.map +1 -1
  96. package/lib/typescript/src/services/screenMaskingService.d.ts +1 -1
  97. package/lib/typescript/src/services/screenMaskingService.d.ts.map +1 -1
  98. package/lib/typescript/src/services/storage.service.d.ts.map +1 -1
  99. package/lib/typescript/src/session-recorder.d.ts.map +1 -1
  100. package/lib/typescript/src/types/configs.d.ts.map +1 -1
  101. package/lib/typescript/src/types/index.d.ts.map +1 -1
  102. package/lib/typescript/src/types/session-recorder.d.ts +4 -4
  103. package/lib/typescript/src/types/session-recorder.d.ts.map +1 -1
  104. package/lib/typescript/src/types/session.d.ts.map +1 -1
  105. package/lib/typescript/src/utils/app-metadata.d.ts.map +1 -1
  106. package/lib/typescript/src/utils/constants.optional.d.ts.map +1 -1
  107. package/lib/typescript/src/utils/constants.optional.expo.d.ts.map +1 -1
  108. package/lib/typescript/src/utils/createStore.d.ts.map +1 -1
  109. package/lib/typescript/src/utils/index.d.ts.map +1 -1
  110. package/lib/typescript/src/utils/logger.d.ts +1 -1
  111. package/lib/typescript/src/utils/logger.d.ts.map +1 -1
  112. package/lib/typescript/src/utils/platform.d.ts.map +1 -1
  113. package/lib/typescript/src/utils/request-utils.d.ts.map +1 -1
  114. package/lib/typescript/src/utils/rrweb-events.d.ts.map +1 -1
  115. package/lib/typescript/src/utils/session.d.ts.map +1 -1
  116. package/lib/typescript/src/utils/shallowEqual.d.ts.map +1 -1
  117. package/lib/typescript/src/utils/time.d.ts.map +1 -1
  118. package/lib/typescript/src/utils/type-utils.d.ts.map +1 -1
  119. package/lib/typescript/src/version.d.ts.map +1 -1
  120. package/package.json +2 -2
  121. package/src/SessionRecorderNativeSpec.ts +53 -0
  122. package/src/components/ScreenRecorderView/index.ts +1 -1
  123. package/src/components/SessionRecorderWidget/ErrorBanner.tsx +14 -14
  124. package/src/components/SessionRecorderWidget/ModalHeader.tsx +11 -9
  125. package/src/components/SessionRecorderWidget/SessionRecorderWidget.tsx +70 -56
  126. package/src/components/SessionRecorderWidget/icons.tsx +58 -30
  127. package/src/components/SessionRecorderWidget/index.ts +1 -1
  128. package/src/components/SessionRecorderWidget/styles.ts +17 -18
  129. package/src/components/index.ts +2 -2
  130. package/src/config/constants.ts +19 -20
  131. package/src/config/defaults.ts +35 -31
  132. package/src/config/index.ts +5 -5
  133. package/src/config/masking.ts +44 -18
  134. package/src/config/session-recorder.ts +54 -26
  135. package/src/config/validators.ts +43 -20
  136. package/src/config/widget.ts +24 -15
  137. package/src/context/SessionRecorderStore.ts +19 -18
  138. package/src/context/useSessionRecorderStore.ts +17 -10
  139. package/src/context/useStoreSelector.ts +20 -18
  140. package/src/index.ts +7 -7
  141. package/src/native/SessionRecorderNative.ts +68 -112
  142. package/src/native/index.ts +5 -1
  143. package/src/otel/helpers.ts +109 -93
  144. package/src/otel/index.ts +46 -49
  145. package/src/otel/instrumentations/index.ts +44 -41
  146. package/src/patch/index.ts +1 -1
  147. package/src/patch/xhr.ts +77 -78
  148. package/src/recorder/eventExporter.ts +63 -68
  149. package/src/recorder/gestureRecorder.ts +359 -212
  150. package/src/recorder/index.ts +75 -62
  151. package/src/recorder/navigationTracker.ts +120 -97
  152. package/src/recorder/screenRecorder.ts +214 -163
  153. package/src/services/api.service.ts +49 -48
  154. package/src/services/network.service.ts +67 -58
  155. package/src/services/screenMaskingService.ts +81 -50
  156. package/src/services/storage.service.ts +99 -70
  157. package/src/session-recorder.ts +270 -214
  158. package/src/types/configs.ts +53 -31
  159. package/src/types/expo-constants.d.ts +2 -2
  160. package/src/types/index.ts +16 -18
  161. package/src/types/session-recorder.ts +106 -111
  162. package/src/types/session.ts +45 -45
  163. package/src/utils/app-metadata.ts +9 -9
  164. package/src/utils/constants.optional.expo.ts +3 -3
  165. package/src/utils/constants.optional.ts +14 -12
  166. package/src/utils/createStore.ts +23 -20
  167. package/src/utils/index.ts +7 -7
  168. package/src/utils/logger.ts +87 -58
  169. package/src/utils/platform.ts +149 -118
  170. package/src/utils/request-utils.ts +15 -15
  171. package/src/utils/rrweb-events.ts +47 -34
  172. package/src/utils/session.ts +15 -12
  173. package/src/utils/shallowEqual.ts +16 -10
  174. package/src/utils/time.ts +7 -4
  175. package/src/utils/type-utils.ts +36 -36
  176. package/src/version.ts +1 -1
  177. package/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativeModuleSpec.kt +0 -51
  178. package/android/src/main/java/com/xxx/XxxModule.kt +0 -23
  179. package/ios/Xxx.h +0 -5
  180. package/ios/Xxx.mm +0 -21
@@ -1,117 +1,153 @@
1
- import { Dimensions, Platform } from 'react-native'
2
- import { trace, SpanStatusCode, type Span } from '@opentelemetry/api'
3
- import { logger } from '../utils'
4
- import { type GestureEvent, type RecorderConfig, type EventRecorder } from '../types'
5
- import { MouseInteractions, type eventWithTime, EventType, IncrementalSource } from '@rrweb/types'
6
- import { type NativeGestureEvent, SessionRecorderNative, gestureEventEmitter } from '../native'
1
+ import { Dimensions, Platform } from 'react-native';
2
+ import { trace, SpanStatusCode, type Span } from '@opentelemetry/api';
3
+ import { logger } from '../utils';
4
+ import {
5
+ type GestureEvent,
6
+ type RecorderConfig,
7
+ type EventRecorder,
8
+ } from '../types';
9
+ import {
10
+ MouseInteractions,
11
+ type eventWithTime,
12
+ EventType,
13
+ IncrementalSource,
14
+ } from '@rrweb/types';
15
+ import {
16
+ type NativeGestureEvent,
17
+ SessionRecorderNative,
18
+ gestureEventEmitter,
19
+ } from '../native';
7
20
  // Force TypeScript recompilation
8
21
 
9
-
10
22
  export class GestureRecorder implements EventRecorder {
11
23
  // @ts-ignore
12
- private config?: RecorderConfig
13
- private isRecording = false
14
- private events: GestureEvent[] = []
15
- private screenDimensions: { width: number; height: number } | null = null
16
- private lastGestureTime: number = 0
17
- private gestureThrottleMs: number = 50 // Throttle gestures to avoid spam
18
- private lastTouchTime: number = 0
19
- private touchThrottleMs: number = 100 // Throttle touch events to max 10 per second
20
- private eventRecorder?: EventRecorder
21
- private imageNodeId: number = 1 // ID of the image node for touch interactions
22
- private screenRecorder?: any // Reference to screen recorder for force capture
23
- private gestureEventListener?: any // Native event listener
24
- private currentPanSpan?: Span // Aggregated span for pan gesture
25
- private panMoveCount: number = 0
26
-
27
- init(config: RecorderConfig, eventRecorder?: EventRecorder, screenRecorder?: any): void {
28
- this.config = config
29
- this.eventRecorder = eventRecorder
30
- this.screenRecorder = screenRecorder
31
- this._getScreenDimensions()
24
+ private config?: RecorderConfig;
25
+ private isRecording = false;
26
+ private events: GestureEvent[] = [];
27
+ private screenDimensions: { width: number; height: number } | null = null;
28
+ private lastGestureTime: number = 0;
29
+ private gestureThrottleMs: number = 50; // Throttle gestures to avoid spam
30
+ private lastTouchTime: number = 0;
31
+ private touchThrottleMs: number = 100; // Throttle touch events to max 10 per second
32
+ private eventRecorder?: EventRecorder;
33
+ private imageNodeId: number = 1; // ID of the image node for touch interactions
34
+ private screenRecorder?: any; // Reference to screen recorder for force capture
35
+ private gestureEventListener?: any; // Native event listener
36
+ private currentPanSpan?: Span; // Aggregated span for pan gesture
37
+ private panMoveCount: number = 0;
38
+
39
+ init(
40
+ config: RecorderConfig,
41
+ eventRecorder?: EventRecorder,
42
+ screenRecorder?: any
43
+ ): void {
44
+ this.config = config;
45
+ this.eventRecorder = eventRecorder;
46
+ this.screenRecorder = screenRecorder;
47
+ this._getScreenDimensions();
32
48
  }
33
49
 
34
50
  start(): void {
35
- logger.info('GestureRecorder', 'Native gesture recording started')
36
- this.isRecording = true
37
- this.events = []
51
+ logger.info('GestureRecorder', 'Native gesture recording started');
52
+ this.isRecording = true;
53
+ this.events = [];
38
54
 
39
55
  // Check if we're on web platform
40
56
  if (Platform.OS === 'web') {
41
- logger.warn('GestureRecorder', 'Native gesture recording not available on web platform')
42
- return
57
+ logger.warn(
58
+ 'GestureRecorder',
59
+ 'Native gesture recording not available on web platform'
60
+ );
61
+ return;
43
62
  }
44
63
 
45
64
  // Start native gesture recording
46
65
  SessionRecorderNative.startGestureRecording()
47
66
  .then(() => {
48
- logger.info('GestureRecorder', 'Native gesture recording started successfully')
49
- this._setupGestureEventListener()
67
+ logger.info(
68
+ 'GestureRecorder',
69
+ 'Native gesture recording started successfully'
70
+ );
71
+ this._setupGestureEventListener();
50
72
  })
51
73
  .catch((error) => {
52
- logger.error('GestureRecorder', 'Failed to start native gesture recording', error)
53
- })
74
+ logger.error(
75
+ 'GestureRecorder',
76
+ 'Failed to start native gesture recording',
77
+ error
78
+ );
79
+ });
54
80
  }
55
81
 
56
82
  stop(): void {
57
- this.isRecording = false
58
- this._removeGestureEventListener()
83
+ this.isRecording = false;
84
+ this._removeGestureEventListener();
59
85
 
60
86
  // Check if we're on web platform
61
87
  if (Platform.OS === 'web') {
62
- logger.warn('GestureRecorder', 'Native gesture recording not available on web platform')
63
- return
88
+ logger.warn(
89
+ 'GestureRecorder',
90
+ 'Native gesture recording not available on web platform'
91
+ );
92
+ return;
64
93
  }
65
94
 
66
95
  // Stop native gesture recording
67
96
  SessionRecorderNative.stopGestureRecording()
68
97
  .then(() => {
69
- logger.info('GestureRecorder', 'Native gesture recording stopped successfully')
98
+ logger.info(
99
+ 'GestureRecorder',
100
+ 'Native gesture recording stopped successfully'
101
+ );
70
102
  })
71
103
  .catch((error) => {
72
- logger.error('GestureRecorder', 'Failed to stop native gesture recording', error)
73
- })
104
+ logger.error(
105
+ 'GestureRecorder',
106
+ 'Failed to stop native gesture recording',
107
+ error
108
+ );
109
+ });
74
110
  }
75
111
 
76
112
  private _getScreenDimensions(): void {
77
113
  try {
78
- this.screenDimensions = Dimensions.get('window')
114
+ this.screenDimensions = Dimensions.get('window');
79
115
  } catch (error) {
80
116
  // Failed to get screen dimensions - silently continue
81
- this.screenDimensions = { width: 375, height: 667 } // Default fallback
117
+ this.screenDimensions = { width: 375, height: 667 }; // Default fallback
82
118
  }
83
119
  }
84
120
 
85
121
  private _setupGestureEventListener(): void {
86
122
  if (!gestureEventEmitter) {
87
- logger.warn('GestureRecorder', 'Gesture event emitter not available')
88
- return
123
+ logger.warn('GestureRecorder', 'Gesture event emitter not available');
124
+ return;
89
125
  }
90
126
 
91
127
  this.gestureEventListener = gestureEventEmitter.addListener(
92
128
  'onGestureDetected',
93
129
  (nativeGesture: any) => {
94
- this._handleNativeGesture(nativeGesture as NativeGestureEvent)
130
+ this._handleNativeGesture(nativeGesture as NativeGestureEvent);
95
131
  }
96
- )
132
+ );
97
133
  }
98
134
 
99
135
  private _removeGestureEventListener(): void {
100
136
  if (this.gestureEventListener) {
101
- this.gestureEventListener.remove()
102
- this.gestureEventListener = undefined
137
+ this.gestureEventListener.remove();
138
+ this.gestureEventListener = undefined;
103
139
  }
104
140
  }
105
141
 
106
142
  private _handleNativeGesture(nativeGesture: NativeGestureEvent): void {
107
- if (!this.isRecording) return
143
+ if (!this.isRecording) return;
108
144
 
109
145
  // Throttle gestures to avoid spam
110
- const now = Date.now()
146
+ const now = Date.now();
111
147
  if (now - this.lastGestureTime < this.gestureThrottleMs) {
112
- return
148
+ return;
113
149
  }
114
- this.lastGestureTime = now
150
+ this.lastGestureTime = now;
115
151
 
116
152
  // Convert native gesture to our format
117
153
  const gesture: GestureEvent = {
@@ -125,58 +161,74 @@ export class GestureRecorder implements EventRecorder {
125
161
  screenWidth: this.screenDimensions?.width,
126
162
  screenHeight: this.screenDimensions?.height,
127
163
  },
128
- }
164
+ };
129
165
 
130
- this.events.push(gesture)
131
- this._sendEvent(gesture)
132
- this._recordOpenTelemetrySpan(gesture)
166
+ this.events.push(gesture);
167
+ this._sendEvent(gesture);
168
+ this._recordOpenTelemetrySpan(gesture);
133
169
 
134
170
  // Handle specific gesture types
135
171
  switch (nativeGesture.type) {
136
172
  case 'tap':
137
- this._handleTapGesture(nativeGesture)
138
- break
173
+ this._handleTapGesture(nativeGesture);
174
+ break;
139
175
  case 'pan_start':
140
- this._handlePanStartGesture(nativeGesture)
141
- break
176
+ this._handlePanStartGesture(nativeGesture);
177
+ break;
142
178
  case 'pan_move':
143
- this._handlePanMoveGesture(nativeGesture)
144
- break
179
+ this._handlePanMoveGesture(nativeGesture);
180
+ break;
145
181
  case 'pan_end':
146
- this._handlePanEndGesture(nativeGesture)
147
- break
182
+ this._handlePanEndGesture(nativeGesture);
183
+ break;
148
184
  case 'long_press':
149
- this._handleLongPressGesture(nativeGesture)
150
- break
185
+ this._handleLongPressGesture(nativeGesture);
186
+ break;
151
187
  case 'pinch':
152
- this._handlePinchGesture(nativeGesture)
153
- break
188
+ this._handlePinchGesture(nativeGesture);
189
+ break;
154
190
  case 'swipe':
155
- this._handleSwipeGesture(nativeGesture)
156
- break
191
+ this._handleSwipeGesture(nativeGesture);
192
+ break;
157
193
  }
158
194
  }
159
195
 
160
196
  private _handleTapGesture(nativeGesture: NativeGestureEvent): void {
161
- this.recordTouchStart(nativeGesture.x, nativeGesture.y, nativeGesture.target)
162
- this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target)
197
+ this.recordTouchStart(
198
+ nativeGesture.x,
199
+ nativeGesture.y,
200
+ nativeGesture.target
201
+ );
202
+ this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target);
163
203
  }
164
204
 
165
205
  private _handlePanStartGesture(nativeGesture: NativeGestureEvent): void {
166
- this.recordTouchStart(nativeGesture.x, nativeGesture.y, nativeGesture.target)
206
+ this.recordTouchStart(
207
+ nativeGesture.x,
208
+ nativeGesture.y,
209
+ nativeGesture.target
210
+ );
167
211
  }
168
212
 
169
213
  private _handlePanMoveGesture(nativeGesture: NativeGestureEvent): void {
170
- this.recordTouchMove(nativeGesture.x, nativeGesture.y, nativeGesture.target)
214
+ this.recordTouchMove(
215
+ nativeGesture.x,
216
+ nativeGesture.y,
217
+ nativeGesture.target
218
+ );
171
219
  }
172
220
 
173
221
  private _handlePanEndGesture(nativeGesture: NativeGestureEvent): void {
174
- this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target)
222
+ this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target);
175
223
  }
176
224
 
177
225
  private _handleLongPressGesture(nativeGesture: NativeGestureEvent): void {
178
- this.recordTouchStart(nativeGesture.x, nativeGesture.y, nativeGesture.target)
179
- this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target)
226
+ this.recordTouchStart(
227
+ nativeGesture.x,
228
+ nativeGesture.y,
229
+ nativeGesture.target
230
+ );
231
+ this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target);
180
232
  }
181
233
 
182
234
  private _handlePinchGesture(nativeGesture: NativeGestureEvent): void {
@@ -184,7 +236,7 @@ export class GestureRecorder implements EventRecorder {
184
236
  nativeGesture.metadata?.scale || 1.0,
185
237
  nativeGesture.target,
186
238
  nativeGesture.metadata?.velocity || 0
187
- )
239
+ );
188
240
  }
189
241
 
190
242
  private _handleSwipeGesture(nativeGesture: NativeGestureEvent): void {
@@ -192,12 +244,15 @@ export class GestureRecorder implements EventRecorder {
192
244
  nativeGesture.metadata?.direction || 'unknown',
193
245
  nativeGesture.target,
194
246
  nativeGesture.metadata?.velocity || 0
195
- )
247
+ );
196
248
  }
197
249
 
198
250
  private _sendEvent(event: GestureEvent): void {
199
251
  // Send event to backend or store locally
200
- logger.debug('GestureRecorder', 'Gesture event recorded', { type: event.type, target: event.target })
252
+ logger.debug('GestureRecorder', 'Gesture event recorded', {
253
+ type: event.type,
254
+ target: event.target,
255
+ });
201
256
  }
202
257
 
203
258
  private _recordOpenTelemetrySpan(event: GestureEvent): void {
@@ -206,67 +261,79 @@ export class GestureRecorder implements EventRecorder {
206
261
  type: event.type,
207
262
  target: event.target,
208
263
  targetInfo: event.targetInfo,
209
- hasTargetInfo: !!event.targetInfo
210
- })
264
+ hasTargetInfo: !!event.targetInfo,
265
+ });
211
266
  // Special handling to aggregate pan gestures into a single span
212
267
  if (event.type === 'pan_start') {
213
268
  // End any previously dangling pan span defensively
214
269
  if (this.currentPanSpan) {
215
- this.currentPanSpan.setStatus({ code: SpanStatusCode.OK })
216
- this.currentPanSpan.end()
270
+ this.currentPanSpan.setStatus({ code: SpanStatusCode.OK });
271
+ this.currentPanSpan.end();
217
272
  }
218
- this.panMoveCount = 0
273
+ this.panMoveCount = 0;
219
274
  const panSpan = trace
220
275
  .getTracer('@opentelemetry/instrumentation-user-interaction')
221
276
  .startSpan('NativeGesture.pan', {
222
277
  startTime: event.timestamp,
223
- })
278
+ });
224
279
 
225
- panSpan.setAttribute('gesture.type', 'pan')
226
- panSpan.setAttribute('gesture.timestamp', event.timestamp)
227
- panSpan.setAttribute('gesture.platform', 'react-native')
228
- panSpan.setAttribute('gesture.source', 'native-module')
280
+ panSpan.setAttribute('gesture.type', 'pan');
281
+ panSpan.setAttribute('gesture.timestamp', event.timestamp);
282
+ panSpan.setAttribute('gesture.platform', 'react-native');
283
+ panSpan.setAttribute('gesture.source', 'native-module');
229
284
 
230
285
  if (event.coordinates) {
231
- panSpan.setAttribute('gesture.start.x', event.coordinates.x)
232
- panSpan.setAttribute('gesture.start.y', event.coordinates.y)
286
+ panSpan.setAttribute('gesture.start.x', event.coordinates.x);
287
+ panSpan.setAttribute('gesture.start.y', event.coordinates.y);
233
288
  }
234
289
  if (event.target) {
235
- panSpan.setAttribute('gesture.target', this._truncateText(event.target, 50))
290
+ panSpan.setAttribute(
291
+ 'gesture.target',
292
+ this._truncateText(event.target, 50)
293
+ );
236
294
  }
237
295
  // Enrich with target info if provided
238
- const info = event.targetInfo
296
+ const info = event.targetInfo;
239
297
  if (info) {
240
298
  if (info.label) {
241
- const truncatedLabel = this._truncateText(String(info.label), 50)
242
- panSpan.setAttribute('gesture.target.label', truncatedLabel)
299
+ const truncatedLabel = this._truncateText(String(info.label), 50);
300
+ panSpan.setAttribute('gesture.target.label', truncatedLabel);
243
301
  }
244
302
  if (info.role) {
245
- panSpan.setAttribute('gesture.target.role', String(info.role))
303
+ panSpan.setAttribute('gesture.target.role', String(info.role));
246
304
  }
247
305
  if (info.testId) {
248
- panSpan.setAttribute('gesture.target.test_id', String(info.testId))
306
+ panSpan.setAttribute('gesture.target.test_id', String(info.testId));
249
307
  }
250
308
  if (info.text) {
251
- const truncatedText = this._truncateText(String(info.text), 50)
252
- panSpan.setAttribute('gesture.target.text', truncatedText)
309
+ const truncatedText = this._truncateText(String(info.text), 50);
310
+ panSpan.setAttribute('gesture.target.text', truncatedText);
253
311
  }
254
312
  }
255
313
  // Save the span for subsequent move/end events
256
- this.currentPanSpan = panSpan
257
- return
314
+ this.currentPanSpan = panSpan;
315
+ return;
258
316
  }
259
317
 
260
318
  if (event.type === 'pan_move') {
261
319
  if (this.currentPanSpan) {
262
- this.panMoveCount += 1
263
- this.currentPanSpan.setAttribute('gesture.pan.move_count', this.panMoveCount)
320
+ this.panMoveCount += 1;
321
+ this.currentPanSpan.setAttribute(
322
+ 'gesture.pan.move_count',
323
+ this.panMoveCount
324
+ );
264
325
  if (event.coordinates) {
265
- this.currentPanSpan.setAttribute('gesture.last.x', event.coordinates.x)
266
- this.currentPanSpan.setAttribute('gesture.last.y', event.coordinates.y)
326
+ this.currentPanSpan.setAttribute(
327
+ 'gesture.last.x',
328
+ event.coordinates.x
329
+ );
330
+ this.currentPanSpan.setAttribute(
331
+ 'gesture.last.y',
332
+ event.coordinates.y
333
+ );
267
334
  }
268
335
  // Don't end the span here; just update it
269
- return
336
+ return;
270
337
  }
271
338
  // If we received a move without a start, fall through to single-shot span below
272
339
  }
@@ -274,14 +341,20 @@ export class GestureRecorder implements EventRecorder {
274
341
  if (event.type === 'pan_end') {
275
342
  if (this.currentPanSpan) {
276
343
  if (event.coordinates) {
277
- this.currentPanSpan.setAttribute('gesture.end.x', event.coordinates.x)
278
- this.currentPanSpan.setAttribute('gesture.end.y', event.coordinates.y)
344
+ this.currentPanSpan.setAttribute(
345
+ 'gesture.end.x',
346
+ event.coordinates.x
347
+ );
348
+ this.currentPanSpan.setAttribute(
349
+ 'gesture.end.y',
350
+ event.coordinates.y
351
+ );
279
352
  }
280
- this.currentPanSpan.setStatus({ code: SpanStatusCode.OK })
281
- this.currentPanSpan.end()
282
- this.currentPanSpan = undefined
283
- this.panMoveCount = 0
284
- return
353
+ this.currentPanSpan.setStatus({ code: SpanStatusCode.OK });
354
+ this.currentPanSpan.end();
355
+ this.currentPanSpan = undefined;
356
+ this.panMoveCount = 0;
357
+ return;
285
358
  }
286
359
  // If no current span, fall through and create a single-shot span for the end event
287
360
  }
@@ -297,60 +370,76 @@ export class GestureRecorder implements EventRecorder {
297
370
  'gesture.platform': 'react-native',
298
371
  'gesture.source': 'native-module',
299
372
  },
300
- })
373
+ });
301
374
 
302
375
  if (event.coordinates) {
303
- span.setAttribute('gesture.coordinates.x', event.coordinates.x)
304
- span.setAttribute('gesture.coordinates.y', event.coordinates.y)
376
+ span.setAttribute('gesture.coordinates.x', event.coordinates.x);
377
+ span.setAttribute('gesture.coordinates.y', event.coordinates.y);
305
378
 
306
379
  // Calculate relative position
307
380
  if (this.screenDimensions) {
308
- const relativeX = event.coordinates.x / this.screenDimensions.width
309
- const relativeY = event.coordinates.y / this.screenDimensions.height
310
- span.setAttribute('gesture.coordinates.relative_x', relativeX)
311
- span.setAttribute('gesture.coordinates.relative_y', relativeY)
381
+ const relativeX = event.coordinates.x / this.screenDimensions.width;
382
+ const relativeY = event.coordinates.y / this.screenDimensions.height;
383
+ span.setAttribute('gesture.coordinates.relative_x', relativeX);
384
+ span.setAttribute('gesture.coordinates.relative_y', relativeY);
312
385
  }
313
386
  }
314
387
 
315
388
  if (event.target) {
316
- span.setAttribute('gesture.target', this._truncateText(event.target, 100))
389
+ span.setAttribute(
390
+ 'gesture.target',
391
+ this._truncateText(event.target, 100)
392
+ );
317
393
  }
318
394
 
319
395
  // Enrich with target info if provided
320
- const info = event.targetInfo
396
+ const info = event.targetInfo;
321
397
  if (info) {
322
398
  if (info.label) {
323
- const truncatedLabel = this._truncateText(String(info.label), 100)
324
- span.setAttribute('gesture.target.label', truncatedLabel)
399
+ const truncatedLabel = this._truncateText(String(info.label), 100);
400
+ span.setAttribute('gesture.target.label', truncatedLabel);
325
401
  }
326
402
  if (info.role) {
327
- span.setAttribute('gesture.target.role', String(info.role))
403
+ span.setAttribute('gesture.target.role', String(info.role));
328
404
  }
329
405
  if (info.testId) {
330
- span.setAttribute('gesture.target.test_id', String(info.testId))
406
+ span.setAttribute('gesture.target.test_id', String(info.testId));
331
407
  }
332
408
  if (info.text) {
333
- const truncatedText = this._truncateText(String(info.text), 200)
334
- span.setAttribute('gesture.target.text', truncatedText)
409
+ const truncatedText = this._truncateText(String(info.text), 200);
410
+ span.setAttribute('gesture.target.text', truncatedText);
335
411
  }
336
412
  }
337
413
 
338
414
  if (event.metadata) {
339
415
  Object.entries(event.metadata).forEach(([key, value]) => {
340
- span.setAttribute(`gesture.metadata.${key}`, String(value))
341
- })
416
+ span.setAttribute(`gesture.metadata.${key}`, String(value));
417
+ });
342
418
  }
343
419
 
344
- span.setStatus({ code: SpanStatusCode.OK })
345
- span.end()
346
- logger.debug('GestureRecorder', 'OTEL span created and ended successfully')
420
+ span.setStatus({ code: SpanStatusCode.OK });
421
+ span.end();
422
+ logger.debug(
423
+ 'GestureRecorder',
424
+ 'OTEL span created and ended successfully'
425
+ );
347
426
  } catch (error) {
348
- logger.error('GestureRecorder', 'Failed to record OpenTelemetry span for native gesture', error)
427
+ logger.error(
428
+ 'GestureRecorder',
429
+ 'Failed to record OpenTelemetry span for native gesture',
430
+ error
431
+ );
349
432
  }
350
433
  }
351
434
 
352
435
  // Public methods for manual event recording (same as before)
353
- recordTap(x: number, y: number, target?: string, pressure?: number, timestamp?: number): void {
436
+ recordTap(
437
+ x: number,
438
+ y: number,
439
+ target?: string,
440
+ pressure?: number,
441
+ timestamp?: number
442
+ ): void {
354
443
  const event: GestureEvent = {
355
444
  type: 'tap',
356
445
  timestamp: timestamp || Date.now(),
@@ -361,12 +450,17 @@ export class GestureRecorder implements EventRecorder {
361
450
  screenWidth: this.screenDimensions?.width,
362
451
  screenHeight: this.screenDimensions?.height,
363
452
  },
364
- }
453
+ };
365
454
 
366
- this._recordEvent(event)
455
+ this._recordEvent(event);
367
456
  }
368
457
 
369
- recordSwipe(direction: string, target?: string, velocity?: number, distance?: number): void {
458
+ recordSwipe(
459
+ direction: string,
460
+ target?: string,
461
+ velocity?: number,
462
+ distance?: number
463
+ ): void {
370
464
  const event: GestureEvent = {
371
465
  type: 'swipe',
372
466
  timestamp: Date.now(),
@@ -378,9 +472,9 @@ export class GestureRecorder implements EventRecorder {
378
472
  screenWidth: this.screenDimensions?.width,
379
473
  screenHeight: this.screenDimensions?.height,
380
474
  },
381
- }
475
+ };
382
476
 
383
- this._recordEvent(event)
477
+ this._recordEvent(event);
384
478
  }
385
479
 
386
480
  recordPinch(scale: number, target?: string, velocity?: number): void {
@@ -394,12 +488,17 @@ export class GestureRecorder implements EventRecorder {
394
488
  screenWidth: this.screenDimensions?.width,
395
489
  screenHeight: this.screenDimensions?.height,
396
490
  },
397
- }
491
+ };
398
492
 
399
- this._recordEvent(event)
493
+ this._recordEvent(event);
400
494
  }
401
495
 
402
- recordPan(deltaX: number, deltaY: number, target?: string, velocity?: number): void {
496
+ recordPan(
497
+ deltaX: number,
498
+ deltaY: number,
499
+ target?: string,
500
+ velocity?: number
501
+ ): void {
403
502
  const event: GestureEvent = {
404
503
  type: 'pan',
405
504
  timestamp: Date.now(),
@@ -411,9 +510,9 @@ export class GestureRecorder implements EventRecorder {
411
510
  screenWidth: this.screenDimensions?.width,
412
511
  screenHeight: this.screenDimensions?.height,
413
512
  },
414
- }
513
+ };
415
514
 
416
- this._recordEvent(event)
515
+ this._recordEvent(event);
417
516
  }
418
517
 
419
518
  recordLongPress(duration: number, target?: string, pressure?: number): void {
@@ -427,9 +526,9 @@ export class GestureRecorder implements EventRecorder {
427
526
  screenWidth: this.screenDimensions?.width,
428
527
  screenHeight: this.screenDimensions?.height,
429
528
  },
430
- }
529
+ };
431
530
 
432
- this._recordEvent(event)
531
+ this._recordEvent(event);
433
532
  }
434
533
 
435
534
  recordDoubleTap(x: number, y: number, target?: string): void {
@@ -442,9 +541,9 @@ export class GestureRecorder implements EventRecorder {
442
541
  screenWidth: this.screenDimensions?.width,
443
542
  screenHeight: this.screenDimensions?.height,
444
543
  },
445
- }
544
+ };
446
545
 
447
- this._recordEvent(event)
546
+ this._recordEvent(event);
448
547
  }
449
548
 
450
549
  recordRotate(rotation: number, target?: string, velocity?: number): void {
@@ -458,9 +557,9 @@ export class GestureRecorder implements EventRecorder {
458
557
  screenWidth: this.screenDimensions?.width,
459
558
  screenHeight: this.screenDimensions?.height,
460
559
  },
461
- }
560
+ };
462
561
 
463
- this._recordEvent(event)
562
+ this._recordEvent(event);
464
563
  }
465
564
 
466
565
  recordFling(direction: string, velocity: number, target?: string): void {
@@ -474,9 +573,9 @@ export class GestureRecorder implements EventRecorder {
474
573
  screenWidth: this.screenDimensions?.width,
475
574
  screenHeight: this.screenDimensions?.height,
476
575
  },
477
- }
576
+ };
478
577
 
479
- this._recordEvent(event)
578
+ this._recordEvent(event);
480
579
  }
481
580
 
482
581
  recordMultiTouch(touchCount: number, target?: string): void {
@@ -489,12 +588,17 @@ export class GestureRecorder implements EventRecorder {
489
588
  screenWidth: this.screenDimensions?.width,
490
589
  screenHeight: this.screenDimensions?.height,
491
590
  },
492
- }
591
+ };
493
592
 
494
- this._recordEvent(event)
593
+ this._recordEvent(event);
495
594
  }
496
595
 
497
- recordScroll(direction: string, distance: number, velocity: number, target?: string): void {
596
+ recordScroll(
597
+ direction: string,
598
+ distance: number,
599
+ velocity: number,
600
+ target?: string
601
+ ): void {
498
602
  const event: GestureEvent = {
499
603
  type: 'scroll',
500
604
  timestamp: Date.now(),
@@ -506,9 +610,9 @@ export class GestureRecorder implements EventRecorder {
506
610
  screenWidth: this.screenDimensions?.width,
507
611
  screenHeight: this.screenDimensions?.height,
508
612
  },
509
- }
613
+ };
510
614
 
511
- this._recordEvent(event)
615
+ this._recordEvent(event);
512
616
  }
513
617
 
514
618
  recordZoom(scale: number, target?: string, velocity?: number): void {
@@ -522,78 +626,121 @@ export class GestureRecorder implements EventRecorder {
522
626
  screenWidth: this.screenDimensions?.width,
523
627
  screenHeight: this.screenDimensions?.height,
524
628
  },
525
- }
629
+ };
526
630
 
527
- this._recordEvent(event)
631
+ this._recordEvent(event);
528
632
  }
529
633
 
530
634
  // Touch event methods (same as before)
531
- recordTouchStart(x: number, y: number, target?: string, pressure?: number): void {
635
+ recordTouchStart(
636
+ x: number,
637
+ y: number,
638
+ target?: string,
639
+ pressure?: number
640
+ ): void {
532
641
  // Throttle touch events to prevent spam
533
- const now = Date.now()
642
+ const now = Date.now();
534
643
  if (now - this.lastTouchTime < this.touchThrottleMs) {
535
- logger.debug('GestureRecorder', `Touch start throttled (${now - this.lastTouchTime}ms < ${this.touchThrottleMs}ms)`)
536
- return
644
+ logger.debug(
645
+ 'GestureRecorder',
646
+ `Touch start throttled (${now - this.lastTouchTime}ms < ${this.touchThrottleMs}ms)`
647
+ );
648
+ return;
537
649
  }
538
- this.lastTouchTime = now
650
+ this.lastTouchTime = now;
539
651
 
540
- logger.debug('GestureRecorder', 'Touch start recorded', { x, y, target, pressure })
541
- this._createMouseInteractionEvent(x, y, MouseInteractions.TouchStart, now)
652
+ logger.debug('GestureRecorder', 'Touch start recorded', {
653
+ x,
654
+ y,
655
+ target,
656
+ pressure,
657
+ });
658
+ this._createMouseInteractionEvent(x, y, MouseInteractions.TouchStart, now);
542
659
  }
543
660
 
544
- recordTouchMove(x: number, y: number, target?: string, pressure?: number): void {
661
+ recordTouchMove(
662
+ x: number,
663
+ y: number,
664
+ target?: string,
665
+ pressure?: number
666
+ ): void {
545
667
  // Throttle touch move events more aggressively
546
- const now = Date.now()
547
- if (now - this.lastTouchTime < this.touchThrottleMs * 2) { // 200ms throttle for move events
548
- logger.debug('GestureRecorder', `Touch move throttled (${now - this.lastTouchTime}ms < ${this.touchThrottleMs * 2}ms)`)
549
- return
668
+ const now = Date.now();
669
+ if (now - this.lastTouchTime < this.touchThrottleMs * 2) {
670
+ // 200ms throttle for move events
671
+ logger.debug(
672
+ 'GestureRecorder',
673
+ `Touch move throttled (${now - this.lastTouchTime}ms < ${this.touchThrottleMs * 2}ms)`
674
+ );
675
+ return;
550
676
  }
551
- this.lastTouchTime = now
677
+ this.lastTouchTime = now;
552
678
 
553
- logger.debug('GestureRecorder', 'Touch move recorded', { x, y, target, pressure })
554
- this._createMouseMoveEvent(x, y, target)
679
+ logger.debug('GestureRecorder', 'Touch move recorded', {
680
+ x,
681
+ y,
682
+ target,
683
+ pressure,
684
+ });
685
+ this._createMouseMoveEvent(x, y, target);
555
686
  }
556
687
 
557
- recordTouchEnd(x: number, y: number, target?: string, pressure?: number): void {
558
- const timestamp = Date.now()
559
-
560
- logger.debug('GestureRecorder', 'Touch end recorded', { x, y, target, pressure, timestamp })
688
+ recordTouchEnd(
689
+ x: number,
690
+ y: number,
691
+ target?: string,
692
+ pressure?: number
693
+ ): void {
694
+ const timestamp = Date.now();
561
695
 
562
- this.recordTap(x, y, target, pressure, timestamp)
563
- this._createMouseInteractionEvent(x, y, MouseInteractions.TouchEnd, timestamp)
696
+ logger.debug('GestureRecorder', 'Touch end recorded', {
697
+ x,
698
+ y,
699
+ target,
700
+ pressure,
701
+ timestamp,
702
+ });
703
+
704
+ this.recordTap(x, y, target, pressure, timestamp);
705
+ this._createMouseInteractionEvent(
706
+ x,
707
+ y,
708
+ MouseInteractions.TouchEnd,
709
+ timestamp
710
+ );
564
711
 
565
712
  // Only force screen capture on touch end (not on every touch event)
566
- this.screenRecorder?.forceCapture(timestamp)
713
+ this.screenRecorder?.forceCapture(timestamp);
567
714
  }
568
715
 
569
716
  recordTouchCancel(x: number, y: number, _target?: string): void {
570
- this._createMouseInteractionEvent(x, y, MouseInteractions.TouchCancel)
717
+ this._createMouseInteractionEvent(x, y, MouseInteractions.TouchCancel);
571
718
  }
572
719
 
573
720
  setImageNodeId(nodeId: number): void {
574
- this.imageNodeId = nodeId
721
+ this.imageNodeId = nodeId;
575
722
  }
576
723
 
577
724
  private _recordEvent(event: GestureEvent): void {
578
- if (!this.isRecording) return
725
+ if (!this.isRecording) return;
579
726
 
580
727
  // Throttle gestures to avoid spam
581
- const now = Date.now()
728
+ const now = Date.now();
582
729
  if (now - this.lastGestureTime < this.gestureThrottleMs) {
583
- return
730
+ return;
584
731
  }
585
- this.lastGestureTime = now
732
+ this.lastGestureTime = now;
586
733
 
587
- this.events.push(event)
588
- this._sendEvent(event)
589
- this._recordOpenTelemetrySpan(event)
734
+ this.events.push(event);
735
+ this._sendEvent(event);
736
+ this._recordOpenTelemetrySpan(event);
590
737
  }
591
738
 
592
739
  private _createMouseInteractionEvent(
593
740
  x: number,
594
741
  y: number,
595
742
  interactionType: MouseInteractions,
596
- timestamp?: number,
743
+ timestamp?: number
597
744
  ): void {
598
745
  const incrementalSnapshotEvent: eventWithTime = {
599
746
  type: EventType.IncrementalSnapshot,
@@ -606,9 +753,9 @@ export class GestureRecorder implements EventRecorder {
606
753
  pointerType: 2, // 2 = Touch for React Native (0=Mouse, 1=Pen, 2=Touch)
607
754
  },
608
755
  timestamp: timestamp || Date.now(),
609
- }
756
+ };
610
757
 
611
- this.recordEvent(incrementalSnapshotEvent)
758
+ this.recordEvent(incrementalSnapshotEvent);
612
759
  }
613
760
 
614
761
  private _createMouseMoveEvent(x: number, y: number, _target?: string): void {
@@ -626,44 +773,44 @@ export class GestureRecorder implements EventRecorder {
626
773
  ],
627
774
  },
628
775
  timestamp: Date.now(),
629
- }
776
+ };
630
777
 
631
- this.recordEvent(incrementalSnapshotEvent)
778
+ this.recordEvent(incrementalSnapshotEvent);
632
779
  }
633
780
 
634
781
  recordEvent(event: any): void {
635
782
  if (this.eventRecorder) {
636
- this.eventRecorder.recordEvent(event)
783
+ this.eventRecorder.recordEvent(event);
637
784
  }
638
785
  }
639
786
 
640
787
  // Get recorded events
641
788
  getEvents(): GestureEvent[] {
642
- return [...this.events]
789
+ return [...this.events];
643
790
  }
644
791
 
645
792
  // Clear events
646
793
  clearEvents(): void {
647
- this.events = []
794
+ this.events = [];
648
795
  }
649
796
 
650
797
  // Get event statistics
651
798
  getEventStats(): Record<string, number> {
652
- const stats: Record<string, number> = {}
653
- this.events.forEach(event => {
654
- stats[event.type] = (stats[event.type] || 0) + 1
655
- })
656
- return stats
799
+ const stats: Record<string, number> = {};
800
+ this.events.forEach((event) => {
801
+ stats[event.type] = (stats[event.type] || 0) + 1;
802
+ });
803
+ return stats;
657
804
  }
658
805
 
659
806
  // Set gesture throttle
660
807
  setGestureThrottle(throttleMs: number): void {
661
- this.gestureThrottleMs = throttleMs
808
+ this.gestureThrottleMs = throttleMs;
662
809
  }
663
810
 
664
811
  // Get recording status
665
812
  isRecordingEnabled(): boolean {
666
- return this.isRecording
813
+ return this.isRecording;
667
814
  }
668
815
 
669
816
  /**
@@ -674,8 +821,8 @@ export class GestureRecorder implements EventRecorder {
674
821
  */
675
822
  private _truncateText(text: string, maxLength: number = 100): string {
676
823
  if (!text || text.length <= maxLength) {
677
- return text
824
+ return text;
678
825
  }
679
- return text.substring(0, maxLength - 3) + '...'
826
+ return text.substring(0, maxLength - 3) + '...';
680
827
  }
681
828
  }