@multiplayer-app/session-recorder-react-native 0.0.1-alpha.8 → 0.0.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.
Files changed (84) hide show
  1. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.d.ts +6 -0
  2. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js +1 -0
  3. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js.map +1 -0
  4. package/dist/components/GestureCaptureWrapper/index.d.ts +1 -0
  5. package/dist/components/GestureCaptureWrapper/index.js +1 -0
  6. package/dist/components/GestureCaptureWrapper/index.js.map +1 -0
  7. package/dist/components/GestureCaptureWrapper.js +1 -1
  8. package/dist/components/GestureCaptureWrapper.js.map +1 -1
  9. package/dist/components/ScreenRecorderView/ScreenRecorderView.d.ts +5 -0
  10. package/dist/components/ScreenRecorderView/ScreenRecorderView.js +1 -0
  11. package/dist/components/ScreenRecorderView/ScreenRecorderView.js.map +1 -0
  12. package/dist/components/ScreenRecorderView/index.d.ts +1 -0
  13. package/dist/components/ScreenRecorderView/index.js +1 -0
  14. package/dist/components/ScreenRecorderView/index.js.map +1 -0
  15. package/dist/components/index.d.ts +1 -0
  16. package/dist/components/index.js +1 -0
  17. package/dist/components/index.js.map +1 -0
  18. package/dist/context/SessionRecorderContext.js +1 -1
  19. package/dist/context/SessionRecorderContext.js.map +1 -1
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/otel/index.d.ts +0 -2
  24. package/dist/otel/index.js.map +1 -1
  25. package/dist/otel/instrumentations/gestureInstrumentation.js +1 -1
  26. package/dist/otel/instrumentations/gestureInstrumentation.js.map +1 -1
  27. package/dist/otel/instrumentations/index.d.ts +0 -3
  28. package/dist/otel/instrumentations/index.js +1 -1
  29. package/dist/otel/instrumentations/index.js.map +1 -1
  30. package/dist/patch/xhr.js +1 -1
  31. package/dist/patch/xhr.js.map +1 -1
  32. package/dist/recorder/gestureRecorder.d.ts +0 -9
  33. package/dist/recorder/gestureRecorder.js +1 -1
  34. package/dist/recorder/gestureRecorder.js.map +1 -1
  35. package/dist/recorder/index.d.ts +4 -3
  36. package/dist/recorder/index.js +1 -1
  37. package/dist/recorder/index.js.map +1 -1
  38. package/dist/recorder/screenRecorder.d.ts +1 -6
  39. package/dist/recorder/screenRecorder.js +1 -1
  40. package/dist/recorder/screenRecorder.js.map +1 -1
  41. package/dist/session-recorder.d.ts +3 -2
  42. package/dist/session-recorder.js.map +1 -1
  43. package/dist/types/index.d.ts +2 -16
  44. package/dist/types/index.js +1 -1
  45. package/dist/types/index.js.map +1 -1
  46. package/dist/utils/app-metadata.d.ts +16 -0
  47. package/dist/utils/app-metadata.js +1 -0
  48. package/dist/utils/app-metadata.js.map +1 -0
  49. package/dist/utils/platform.d.ts +35 -3
  50. package/dist/utils/platform.js +1 -1
  51. package/dist/utils/platform.js.map +1 -1
  52. package/dist/utils/rrweb-events.d.ts +1 -1
  53. package/dist/utils/rrweb-events.js +1 -1
  54. package/dist/utils/rrweb-events.js.map +1 -1
  55. package/dist/version.d.ts +1 -1
  56. package/dist/version.js +1 -1
  57. package/dist/version.js.map +1 -1
  58. package/docs/AUTO_METADATA_DETECTION.md +108 -0
  59. package/package.json +6 -9
  60. package/scripts/generate-app-metadata.js +173 -0
  61. package/src/components/{GestureCaptureWrapper.tsx → GestureCaptureWrapper/GestureCaptureWrapper.tsx} +1 -25
  62. package/src/components/GestureCaptureWrapper/index.ts +1 -0
  63. package/src/components/ScreenRecorderView/ScreenRecorderView.tsx +72 -0
  64. package/src/components/ScreenRecorderView/index.ts +1 -0
  65. package/src/components/index.ts +1 -0
  66. package/src/context/SessionRecorderContext.tsx +21 -89
  67. package/src/index.ts +8 -0
  68. package/src/otel/index.ts +1 -12
  69. package/src/otel/instrumentations/index.ts +1 -6
  70. package/src/patch/xhr.ts +2 -2
  71. package/src/recorder/gestureRecorder.ts +10 -134
  72. package/src/recorder/index.ts +9 -7
  73. package/src/recorder/screenRecorder.ts +6 -14
  74. package/src/session-recorder.ts +2 -3
  75. package/src/types/index.ts +2 -20
  76. package/src/utils/app-metadata.ts +31 -0
  77. package/src/utils/platform.ts +303 -6
  78. package/src/utils/rrweb-events.ts +2 -4
  79. package/src/version.ts +1 -1
  80. package/example-usage.tsx +0 -174
  81. package/src/otel/instrumentations/gestureInstrumentation.ts +0 -141
  82. package/src/otel/instrumentations/reactNativeInstrumentation.ts +0 -77
  83. package/src/otel/instrumentations/reactNavigationInstrumentation.ts +0 -119
  84. package/src/recorder/gestureHandlerRecorder.ts +0 -157
@@ -1,6 +1,14 @@
1
1
  import { IResourceAttributes } from '../types'
2
2
  import Constants from 'expo-constants'
3
- import { Platform } from 'react-native'
3
+ import { Platform, Dimensions, PixelRatio } from 'react-native'
4
+ import { version } from '../version'
5
+ import { getAutoDetectedAppMetadata } from './app-metadata'
6
+
7
+ // Global app metadata configuration for non-Expo apps
8
+ let globalAppMetadata: { name?: string; version?: string; bundleId?: string } = {}
9
+
10
+ // Cache for auto-detected metadata to avoid repeated file reads
11
+ let autoDetectedMetadata: { name?: string; version?: string; bundleId?: string } | null = null
4
12
 
5
13
  export interface PlatformInfo {
6
14
  isExpo: boolean
@@ -52,7 +60,7 @@ export function getPlatformAttributes(): Record<string, any> {
52
60
  const platformInfo = detectPlatform()
53
61
 
54
62
  const attributes: Record<string, any> = {
55
- 'platform': platformInfo.isExpo ? 'expo' : 'react-native',
63
+ platform: platformInfo.isExpo ? 'expo' : 'react-native',
56
64
  'device.type': platformInfo.deviceType,
57
65
  }
58
66
 
@@ -75,13 +83,302 @@ export function isReactNativeEnvironment(): boolean {
75
83
  return detectPlatform().isReactNative
76
84
  }
77
85
 
86
+ /**
87
+ * Configure app metadata for non-Expo React Native apps
88
+ * Call this function in your app initialization to provide app information
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * import { configureAppMetadata } from '@multiplayer-app/session-recorder-react-native'
93
+ *
94
+ * // In your App.tsx or index.js
95
+ * configureAppMetadata({
96
+ * name: 'My Awesome App',
97
+ * version: '1.2.3',
98
+ * bundleId: 'com.mycompany.myapp',
99
+ * buildNumber: '123',
100
+ * displayName: 'My App',
101
+ * })
102
+ * ```
103
+ */
104
+ export function configureAppMetadata(metadata: {
105
+ name?: string
106
+ version?: string
107
+ bundleId?: string
108
+ buildNumber?: string
109
+ displayName?: string
110
+ }): void {
111
+ globalAppMetadata = { ...globalAppMetadata, ...metadata }
112
+ }
113
+
114
+ /**
115
+ * Get configured app metadata
116
+ */
117
+ export function getConfiguredAppMetadata(): { name?: string, version?: string, bundleId?: string, buildNumber?: string, displayName?: string, } {
118
+ return { ...globalAppMetadata }
119
+ }
120
+
121
+ /**
122
+ * Automatically detect app metadata from common configuration files
123
+ * This runs without developer intervention
124
+ */
125
+ function autoDetectAppMetadata(): { name?: string; version?: string; bundleId?: string } {
126
+ if (autoDetectedMetadata) {
127
+ return autoDetectedMetadata
128
+ }
129
+
130
+ try {
131
+ // Get auto-detected metadata from build-time generated file
132
+ const autoMetadata = getAutoDetectedAppMetadata()
133
+
134
+ // Filter out undefined values
135
+ const metadata: { name?: string; version?: string; bundleId?: string } = {}
136
+ if (autoMetadata.name) metadata.name = autoMetadata.name
137
+ if (autoMetadata.version) metadata.version = autoMetadata.version
138
+ if (autoMetadata.bundleId) metadata.bundleId = autoMetadata.bundleId
139
+
140
+ autoDetectedMetadata = metadata
141
+ return metadata
142
+ } catch (error) {
143
+ // Silently fail - this is optional auto-detection
144
+ autoDetectedMetadata = {}
145
+ return {}
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Enhanced app metadata detection with automatic fallbacks
151
+ */
152
+ function getAppMetadata(): { name?: string; version?: string; bundleId?: string } {
153
+ // Priority order:
154
+ // 1. Expo config (if available)
155
+ // 2. Manually configured metadata
156
+ // 3. Auto-detected metadata
157
+ // 4. Fallbacks
158
+
159
+ const expoMetadata = getExpoMetadata()
160
+ const configuredMetadata = getConfiguredAppMetadata()
161
+ const autoMetadata = autoDetectAppMetadata()
162
+
163
+ return {
164
+ name: expoMetadata.name || configuredMetadata.name || autoMetadata.name,
165
+ version: expoMetadata.version || configuredMetadata.version || autoMetadata.version,
166
+ bundleId: expoMetadata.bundleId || configuredMetadata.bundleId || autoMetadata.bundleId,
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Get metadata from Expo config
172
+ */
173
+ function getExpoMetadata(): { name?: string; version?: string; bundleId?: string } {
174
+ const expoConfig = Constants.default?.expoConfig || Constants.expoConfig
175
+ if (!expoConfig) return {}
176
+
177
+ return {
178
+ name: expoConfig.name,
179
+ version: expoConfig.version,
180
+ bundleId: expoConfig.ios?.bundleIdentifier || expoConfig.android?.package,
181
+ }
182
+ }
78
183
 
79
184
  export const getNavigatorInfo = (): IResourceAttributes => {
185
+ const platformInfo = detectPlatform()
186
+ const screenData = Dimensions.get('window')
187
+ const screenDataScreen = Dimensions.get('screen')
188
+ const pixelRatio = PixelRatio.get()
189
+
190
+ // Get device type based on screen dimensions
191
+ const getDeviceType = (): string => {
192
+ const { width, height } = screenData
193
+ const minDimension = Math.min(width, height)
194
+ const maxDimension = Math.max(width, height)
195
+
196
+ // Rough device type detection based on screen size
197
+ if (maxDimension >= 1024) {
198
+ return 'Tablet'
199
+ } else if (minDimension >= 600) {
200
+ return 'Large Phone'
201
+ } else {
202
+ return 'Phone'
203
+ }
204
+ }
205
+
206
+ // Get orientation
207
+ const getOrientation = (): string => {
208
+ const { width, height } = screenData
209
+ return width > height ? 'Landscape' : 'Portrait'
210
+ }
211
+
212
+ // Get OS version details
213
+ const getOSInfo = (): string => {
214
+ if (platformInfo.isExpo) {
215
+ const platform = Constants.default?.platform || Constants.platform
216
+ if (platform?.ios) {
217
+ return `iOS ${Platform.Version}`
218
+ } else if (platform?.android) {
219
+ return `Android ${Platform.Version}`
220
+ }
221
+ }
222
+
223
+ if (Platform.OS === 'ios') {
224
+ return `iOS ${Platform.Version}`
225
+ } else if (Platform.OS === 'android') {
226
+ return `Android ${Platform.Version}`
227
+ }
228
+
229
+ return `${Platform.OS} ${Platform.Version || 'Unknown'}`
230
+ }
231
+
232
+ // Get device info string
233
+ const getDeviceInfo = (): string => {
234
+ const deviceType = getDeviceType()
235
+ const osInfo = getOSInfo()
236
+ return `${deviceType} - ${osInfo}`
237
+ }
238
+
239
+ // Get browser/runtime info
240
+ const getBrowserInfo = (): string => {
241
+ if (platformInfo.isExpo) {
242
+ return `Expo ${platformInfo.expoVersion || 'Unknown'} - React Native`
243
+ }
244
+ return 'React Native'
245
+ }
246
+
247
+ // Get screen size string
248
+ const getScreenSize = (): string => {
249
+ return `${Math.round(screenData.width)}x${Math.round(screenData.height)}`
250
+ }
251
+
252
+ // Get app info with fallbacks for non-Expo apps
253
+ const getAppInfo = (): string => {
254
+ const appName = getAppName()
255
+ const appVersion = getAppVersion()
256
+ return `${appName} v${appVersion}`
257
+ }
258
+
259
+ // Get app name with automatic detection
260
+ const getAppName = (): string => {
261
+ const metadata = getAppMetadata()
262
+ if (metadata.name) return metadata.name
263
+
264
+ // Try configured display name as fallback
265
+ const configuredMetadata = getConfiguredAppMetadata()
266
+ if (configuredMetadata.displayName) return configuredMetadata.displayName
267
+
268
+ // Final fallback
269
+ return 'React Native App'
270
+ }
271
+
272
+ // Get app version with automatic detection
273
+ const getAppVersion = (): string => {
274
+ const metadata = getAppMetadata()
275
+ if (metadata.version) return metadata.version
276
+
277
+ // Final fallback
278
+ return 'Unknown'
279
+ }
280
+
281
+ // Get bundle ID with automatic detection
282
+ const getBundleId = (): string => {
283
+ const metadata = getAppMetadata()
284
+ if (metadata.bundleId) return metadata.bundleId
285
+
286
+ // Fallback
287
+ return 'com.reactnative.app'
288
+ }
289
+
290
+ // Get build number with multiple fallback strategies
291
+ const getBuildNumber = (): string => {
292
+ // Try Expo config first
293
+ const expoBuildNumber =
294
+ Constants.default?.expoConfig?.ios?.buildNumber ||
295
+ Constants.expoConfig?.ios?.buildNumber ||
296
+ Constants.default?.expoConfig?.android?.versionCode ||
297
+ Constants.expoConfig?.android?.versionCode
298
+ if (expoBuildNumber) return expoBuildNumber.toString()
299
+
300
+ // Try configured metadata for non-Expo apps
301
+ const configuredMetadata = getConfiguredAppMetadata()
302
+ if (configuredMetadata.buildNumber) return configuredMetadata.buildNumber
303
+
304
+ // Fallback
305
+ return '1'
306
+ }
307
+
308
+ // Get network info (basic)
309
+ const getNetworkInfo = (): string => {
310
+ // This is a basic implementation - in a real app you might want to use @react-native-community/netinfo
311
+ return 'Unknown'
312
+ }
313
+
314
+ // Get hardware info
315
+ const getHardwareInfo = (): string => {
316
+ const pixelRatioInfo = `Pixel Ratio: ${pixelRatio}`
317
+ const screenDensity = PixelRatio.getFontScale()
318
+ return `${pixelRatioInfo}, Font Scale: ${screenDensity}`
319
+ }
320
+
80
321
  return {
81
- platform: 'react-native',
82
- userAgent: 'React Native',
83
- language: 'en',
322
+ // Core platform info
323
+ platform: platformInfo.isExpo ? 'expo' : 'react-native',
324
+ userAgent: getBrowserInfo(),
325
+ language: 'en', // Could be enhanced with react-native-localize if available
84
326
  timestamp: new Date().toISOString(),
327
+
328
+ // Device and OS information
329
+ deviceInfo: getDeviceInfo(),
330
+ osInfo: getOSInfo(),
331
+ browserInfo: getBrowserInfo(),
332
+
333
+ // Screen information
334
+ screenSize: getScreenSize(),
335
+ pixelRatio: pixelRatio,
336
+ orientation: getOrientation(),
337
+ screenWidth: Math.round(screenData.width),
338
+ screenHeight: Math.round(screenData.height),
339
+ screenScale: pixelRatio,
340
+
341
+ // Device capabilities
342
+ hardwareConcurrency: 1, // React Native doesn't expose CPU cores directly
343
+ cookiesEnabled: 'N/A', // Not applicable in React Native
344
+
345
+ // App information
346
+ packageVersion: version,
347
+ appInfo: getAppInfo(),
348
+ appName: getAppName(),
349
+ appVersion: getAppVersion(),
350
+ bundleId: getBundleId(),
351
+ buildNumber: getBuildNumber(),
352
+
353
+ // Platform specific
354
+ platformType: platformInfo.platform,
355
+ platformVersion: platformInfo.platformVersion,
356
+ expoVersion: platformInfo.expoVersion,
357
+ deviceType: getDeviceType(),
358
+
359
+ // Additional device info
360
+ deviceModel: Platform.OS === 'ios' ? 'iOS Device' : 'Android Device',
361
+ deviceManufacturer: Platform.OS === 'ios' ? 'Apple' : 'Android Manufacturer',
362
+ deviceBrand: Platform.OS === 'ios' ? 'Apple' : 'Android Brand',
363
+
364
+ // Performance and hardware
365
+ hardwareInfo: getHardwareInfo(),
366
+ networkInfo: getNetworkInfo(),
367
+
368
+ // Screen details
369
+ screenDensity: PixelRatio.getFontScale(),
370
+ screenScaleFactor: pixelRatio,
371
+ windowWidth: Math.round(screenData.width),
372
+ windowHeight: Math.round(screenData.height),
373
+ fullScreenWidth: Math.round(screenDataScreen.width),
374
+ fullScreenHeight: Math.round(screenDataScreen.height),
375
+
376
+ // Environment info
377
+ isExpo: platformInfo.isExpo,
378
+ isReactNative: platformInfo.isReactNative,
379
+ environment: platformInfo.isExpo ? 'expo' : 'react-native',
380
+
381
+ // Additional platform attributes
85
382
  ...getPlatformAttributes(),
86
383
  }
87
- }
384
+ }
@@ -39,10 +39,9 @@ export function createFullSnapshotEvent(
39
39
  nodeIdCounter: { current: number },
40
40
  ): eventWithTime {
41
41
  // Create a virtual DOM node representing the screen as an image
42
- const imageNodeId = nodeIdCounter.current++
43
42
  const imageNode: serializedNodeWithId = {
44
43
  type: NodeType.Element,
45
- id: imageNodeId,
44
+ id: 0,
46
45
  tagName: 'img',
47
46
  attributes: {
48
47
  src: `data:image/${captureFormat};base64,${base64Image}`,
@@ -137,7 +136,6 @@ export function createFullSnapshotEvent(
137
136
  */
138
137
  export function createIncrementalSnapshotWithImageUpdate(
139
138
  base64Image: string,
140
- imageNodeId: number,
141
139
  captureFormat: string = 'jpg',
142
140
  ): eventWithTime {
143
141
  const mutationData: mutationData = {
@@ -145,7 +143,7 @@ export function createIncrementalSnapshotWithImageUpdate(
145
143
  texts: [],
146
144
  attributes: [
147
145
  {
148
- id: imageNodeId,
146
+ id: 0,
149
147
  attributes: {
150
148
  src: `data:image/${captureFormat};base64,${base64Image}`,
151
149
  },
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "0.0.1-alpha.8"
1
+ export const version = "0.0.1"
package/example-usage.tsx DELETED
@@ -1,174 +0,0 @@
1
- /**
2
- * Example usage of the React Native Session Recorder with rrweb integration
3
- * This file demonstrates how to use the updated session recorder system
4
- */
5
-
6
- import React from 'react'
7
- import { View, Text, Button, StyleSheet, Alert } from 'react-native'
8
- import { SessionRecorderProvider, useSessionRecorder } from './src/context/SessionRecorderContext'
9
- import { EventType } from './src/types'
10
-
11
- // Example app component
12
- function App() {
13
- return (
14
- <SessionRecorderProvider
15
- options={{
16
- apiKey: 'your-api-key-here',
17
- version: '1.0.0',
18
- application: 'ExampleApp',
19
- environment: 'development',
20
- recordScreen: true,
21
- recordGestures: true,
22
- recordNavigation: true
23
- }}
24
- >
25
- <MainContent />
26
- </SessionRecorderProvider>
27
- )
28
- }
29
-
30
- // Main content component that will be wrapped by TouchEventCapture
31
- function MainContent() {
32
- const { client } = useSessionRecorder()
33
-
34
- const handleStartSession = () => {
35
- try {
36
- client.start()
37
- Alert.alert('Session Started', 'Recording has begun!')
38
- } catch (error) {
39
- Alert.alert('Error', `Failed to start session: ${error}`)
40
- }
41
- }
42
-
43
- const handleStopSession = () => {
44
- try {
45
- client.stop()
46
- Alert.alert('Session Stopped', 'Recording has ended!')
47
- } catch (error) {
48
- Alert.alert('Error', `Failed to stop session: ${error}`)
49
- }
50
- }
51
-
52
- const handleRecordCustomEvent = () => {
53
- // Example of recording a custom rrweb event
54
- const customEvent = {
55
- type: EventType.Custom,
56
- data: {
57
- customType: 'button_click',
58
- buttonId: 'example_button',
59
- timestamp: Date.now()
60
- },
61
- timestamp: Date.now()
62
- }
63
-
64
- client.recordEvent(customEvent)
65
- Alert.alert('Custom Event', 'Custom event recorded!')
66
- }
67
-
68
- const handleGetRecordingStats = () => {
69
- // This would need to be implemented in the SessionRecorder
70
- // const stats = client.getRecordingStats()
71
- // Alert.alert('Recording Stats', `Events recorded: ${stats.totalEvents}`)
72
- Alert.alert('Recording Stats', 'Feature coming soon!')
73
- }
74
-
75
- return (
76
- <View style={styles.container}>
77
- <Text style={styles.title}>Session Recorder Example</Text>
78
- <Text style={styles.subtitle}>This app demonstrates rrweb-compatible session recording for React Native</Text>
79
-
80
- <View style={styles.buttonContainer}>
81
- <Button title='Start Recording' onPress={handleStartSession} color='#4CAF50' />
82
- </View>
83
-
84
- <View style={styles.buttonContainer}>
85
- <Button title='Stop Recording' onPress={handleStopSession} color='#F44336' />
86
- </View>
87
-
88
- <View style={styles.buttonContainer}>
89
- <Button title='Record Custom Event' onPress={handleRecordCustomEvent} color='#2196F3' />
90
- </View>
91
-
92
- <View style={styles.buttonContainer}>
93
- <Button title='Get Recording Stats' onPress={handleGetRecordingStats} color='#FF9800' />
94
- </View>
95
-
96
- <Text style={styles.instructions}>
97
- Recording is now AUTOMATIC! When you start a session, the system will automatically:
98
- {'\n'}• Capture screen snapshots periodically
99
- {'\n'}• Record all touch interactions (start, move, end)
100
- {'\n'}• Generate rrweb-compatible events
101
- {'\n'}• No manual setup required!
102
- </Text>
103
- </View>
104
- )
105
- }
106
-
107
- const styles = StyleSheet.create({
108
- container: {
109
- flex: 1,
110
- padding: 20,
111
- backgroundColor: '#f5f5f5',
112
- justifyContent: 'center'
113
- },
114
- title: {
115
- fontSize: 24,
116
- fontWeight: 'bold',
117
- textAlign: 'center',
118
- marginBottom: 10,
119
- color: '#333'
120
- },
121
- subtitle: {
122
- fontSize: 16,
123
- textAlign: 'center',
124
- marginBottom: 30,
125
- color: '#666'
126
- },
127
- buttonContainer: {
128
- marginVertical: 10
129
- },
130
- instructions: {
131
- fontSize: 14,
132
- textAlign: 'center',
133
- marginTop: 30,
134
- color: '#888',
135
- fontStyle: 'italic'
136
- }
137
- })
138
-
139
- export default App
140
-
141
- /**
142
- * AUTOMATIC RECORDING INTEGRATION:
143
- *
144
- * 1. Screen Capture (AUTOMATIC with react-native-view-shot):
145
- * - Install: npm install react-native-view-shot
146
- * - iOS: Add to Podfile and run pod install
147
- * - Android: No additional setup needed
148
- * - Screen capture happens automatically when session starts
149
- * - Captures the same View element that handles touch events
150
- *
151
- * 2. Touch Events (AUTOMATIC):
152
- * - TouchEventCapture automatically wraps your app content
153
- * - Touch events are automatically converted to rrweb MouseInteraction events
154
- * - Coordinates are automatically mapped from React Native to rrweb format
155
- * - No manual setup required!
156
- *
157
- * 3. Event Recording (AUTOMATIC):
158
- * - All events are automatically stored in the RecorderReactNativeSDK
159
- * - Events can be exported using getRecordedEvents()
160
- * - Events are compatible with standard rrweb players
161
- * - Recording starts/stops automatically with session
162
- *
163
- * 4. ViewShot Integration (AUTOMATIC):
164
- * - The TouchEventCapture View is automatically used for screen capture
165
- * - No need to manually set up viewshot refs
166
- * - Screen captures include all touch interactions
167
- * - Perfect synchronization between touch events and screen captures
168
- *
169
- * 5. Customization (Optional):
170
- * - Modify capture intervals in ScreenRecorder
171
- * - Adjust touch event throttling in GestureRecorder
172
- * - Add custom event types as needed
173
- * - All core functionality works automatically out of the box
174
- */
@@ -1,141 +0,0 @@
1
- import { InstrumentationBase } from '@opentelemetry/instrumentation'
2
- import { trace, SpanStatusCode } from '@opentelemetry/api'
3
-
4
- export class GestureInstrumentation extends InstrumentationBase {
5
- private _isEnabled = false
6
-
7
- constructor() {
8
- super('react-native-gesture', '1.0.0', {})
9
- }
10
-
11
- init(): void {
12
- // Initialize the instrumentation
13
- }
14
-
15
- enable(): void {
16
- this._isEnabled = true
17
- }
18
-
19
- disable(): void {
20
- this._isEnabled = false
21
- }
22
-
23
- isEnabled(): boolean {
24
- return this._isEnabled
25
- }
26
-
27
- // Manual gesture tracking methods
28
- recordTap(x: number, y: number, target?: string) {
29
- if (!this._isEnabled) return
30
-
31
- const span = trace.getTracer('gesture').startSpan('Gesture.tap', {
32
- attributes: {
33
- 'gesture.type': 'tap',
34
- 'gesture.coordinates.x': x,
35
- 'gesture.coordinates.y': y,
36
- 'gesture.timestamp': Date.now(),
37
- },
38
- })
39
-
40
- if (target) {
41
- span.setAttribute('gesture.target', target)
42
- }
43
-
44
- span.setStatus({ code: SpanStatusCode.OK })
45
- span.end()
46
- }
47
-
48
- recordSwipe(direction: string, target?: string) {
49
- if (!this._isEnabled) return
50
-
51
- const span = trace.getTracer('gesture').startSpan('Gesture.swipe', {
52
- attributes: {
53
- 'gesture.type': 'swipe',
54
- 'gesture.direction': direction,
55
- 'gesture.timestamp': Date.now(),
56
- },
57
- })
58
-
59
- if (target) {
60
- span.setAttribute('gesture.target', target)
61
- }
62
-
63
- span.setStatus({ code: SpanStatusCode.OK })
64
- span.end()
65
- }
66
-
67
- recordPinch(scale: number, target?: string) {
68
- if (!this._isEnabled) return
69
-
70
- const span = trace.getTracer('gesture').startSpan('Gesture.pinch', {
71
- attributes: {
72
- 'gesture.type': 'pinch',
73
- 'gesture.scale': scale,
74
- 'gesture.timestamp': Date.now(),
75
- },
76
- })
77
-
78
- if (target) {
79
- span.setAttribute('gesture.target', target)
80
- }
81
-
82
- span.setStatus({ code: SpanStatusCode.OK })
83
- span.end()
84
- }
85
-
86
- recordPan(deltaX: number, deltaY: number, target?: string) {
87
- if (!this._isEnabled) return
88
-
89
- const span = trace.getTracer('gesture').startSpan('Gesture.pan', {
90
- attributes: {
91
- 'gesture.type': 'pan',
92
- 'gesture.delta_x': deltaX,
93
- 'gesture.delta_y': deltaY,
94
- 'gesture.timestamp': Date.now(),
95
- },
96
- })
97
-
98
- if (target) {
99
- span.setAttribute('gesture.target', target)
100
- }
101
-
102
- span.setStatus({ code: SpanStatusCode.OK })
103
- span.end()
104
- }
105
-
106
- recordLongPress(duration: number, target?: string) {
107
- if (!this._isEnabled) return
108
-
109
- const span = trace.getTracer('gesture').startSpan('Gesture.longPress', {
110
- attributes: {
111
- 'gesture.type': 'longPress',
112
- 'gesture.duration': duration,
113
- 'gesture.timestamp': Date.now(),
114
- },
115
- })
116
-
117
- if (target) {
118
- span.setAttribute('gesture.target', target)
119
- }
120
-
121
- span.setStatus({ code: SpanStatusCode.OK })
122
- span.end()
123
- }
124
-
125
- // Error tracking for gesture failures
126
- recordGestureError(error: Error, gestureType: string) {
127
- if (!this._isEnabled) return
128
-
129
- const span = trace.getTracer('gesture').startSpan(`Gesture.${gestureType}.error`, {
130
- attributes: {
131
- 'gesture.type': gestureType,
132
- 'gesture.error': true,
133
- 'gesture.timestamp': Date.now(),
134
- },
135
- })
136
-
137
- span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })
138
- span.recordException(error)
139
- span.end()
140
- }
141
- }