@multiplayer-app/session-recorder-react-native 0.0.1-alpha.7 → 0.0.1-alpha.8
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/dist/components/GestureCaptureWrapper.d.ts +6 -0
- package/dist/components/GestureCaptureWrapper.js +1 -0
- package/dist/components/GestureCaptureWrapper.js.map +1 -0
- package/dist/context/SessionRecorderContext.d.ts +1 -2
- package/dist/context/SessionRecorderContext.js +1 -1
- package/dist/context/SessionRecorderContext.js.map +1 -1
- package/dist/otel/helpers.js +1 -1
- package/dist/otel/helpers.js.map +1 -1
- package/dist/otel/instrumentations/index.js +1 -1
- package/dist/otel/instrumentations/index.js.map +1 -1
- package/dist/otel/instrumentations/reactNativeInstrumentation.js +1 -1
- package/dist/otel/instrumentations/reactNativeInstrumentation.js.map +1 -1
- package/dist/recorder/eventExporter.js +1 -1
- package/dist/recorder/eventExporter.js.map +1 -1
- package/dist/recorder/gestureHandlerRecorder.d.ts +19 -0
- package/dist/recorder/gestureHandlerRecorder.js +1 -0
- package/dist/recorder/gestureHandlerRecorder.js.map +1 -0
- package/dist/recorder/gestureRecorder.d.ts +13 -1
- package/dist/recorder/gestureRecorder.js +1 -1
- package/dist/recorder/gestureRecorder.js.map +1 -1
- package/dist/recorder/index.d.ts +1 -2
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.js.map +1 -1
- package/dist/recorder/navigationTracker.js +1 -1
- package/dist/recorder/navigationTracker.js.map +1 -1
- package/dist/recorder/screenRecorder.d.ts +31 -6
- package/dist/recorder/screenRecorder.js +1 -1
- package/dist/recorder/screenRecorder.js.map +1 -1
- package/dist/session-recorder.d.ts +3 -1
- package/dist/session-recorder.js +1 -1
- package/dist/session-recorder.js.map +1 -1
- package/dist/types/index.d.ts +32 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/rrweb.d.ts +10 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.d.ts +112 -0
- package/dist/utils/logger.js +1 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/rrweb-events.d.ts +65 -0
- package/dist/utils/rrweb-events.js +1 -0
- package/dist/utils/rrweb-events.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -1
- package/src/components/GestureCaptureWrapper.tsx +110 -0
- package/src/context/SessionRecorderContext.tsx +76 -81
- package/src/otel/helpers.ts +2 -1
- package/src/otel/instrumentations/index.ts +5 -4
- package/src/otel/instrumentations/reactNativeInstrumentation.ts +2 -1
- package/src/recorder/eventExporter.ts +4 -1
- package/src/recorder/gestureHandlerRecorder.ts +157 -0
- package/src/recorder/gestureRecorder.ts +93 -19
- package/src/recorder/index.ts +13 -16
- package/src/recorder/navigationTracker.ts +2 -0
- package/src/recorder/screenRecorder.ts +125 -82
- package/src/session-recorder.ts +12 -5
- package/src/types/index.ts +44 -1
- package/src/utils/index.ts +2 -0
- package/src/utils/logger.ts +225 -0
- package/src/utils/rrweb-events.ts +311 -0
- package/src/version.ts +1 -1
- package/src/types/rrweb.ts +0 -122
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized logger utility for the session recorder
|
|
3
|
+
* Provides consistent logging across all components
|
|
4
|
+
*/
|
|
5
|
+
export declare enum LogLevel {
|
|
6
|
+
DEBUG = 0,
|
|
7
|
+
INFO = 1,
|
|
8
|
+
WARN = 2,
|
|
9
|
+
ERROR = 3
|
|
10
|
+
}
|
|
11
|
+
export interface LoggerConfig {
|
|
12
|
+
level: LogLevel;
|
|
13
|
+
enableConsole: boolean;
|
|
14
|
+
enablePrefix: boolean;
|
|
15
|
+
prefix: string;
|
|
16
|
+
}
|
|
17
|
+
declare class Logger {
|
|
18
|
+
private config;
|
|
19
|
+
private componentPrefixes;
|
|
20
|
+
/**
|
|
21
|
+
* Configure the logger
|
|
22
|
+
* @param config - Logger configuration
|
|
23
|
+
*/
|
|
24
|
+
configure(config: Partial<LoggerConfig>): void;
|
|
25
|
+
/**
|
|
26
|
+
* Set the log level
|
|
27
|
+
* @param level - Log level to set
|
|
28
|
+
*/
|
|
29
|
+
setLevel(level: LogLevel): void;
|
|
30
|
+
/**
|
|
31
|
+
* Enable or disable console output
|
|
32
|
+
* @param enabled - Whether to enable console output
|
|
33
|
+
*/
|
|
34
|
+
setConsoleEnabled(enabled: boolean): void;
|
|
35
|
+
/**
|
|
36
|
+
* Add or update a component prefix
|
|
37
|
+
* @param component - Component name
|
|
38
|
+
* @param emoji - Emoji prefix for the component
|
|
39
|
+
*/
|
|
40
|
+
setComponentPrefix(component: string, emoji: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get the formatted prefix for a component
|
|
43
|
+
* @param component - Component name
|
|
44
|
+
* @returns Formatted prefix string
|
|
45
|
+
*/
|
|
46
|
+
private getPrefix;
|
|
47
|
+
/**
|
|
48
|
+
* Check if a log level should be output
|
|
49
|
+
* @param level - Log level to check
|
|
50
|
+
* @returns True if should output
|
|
51
|
+
*/
|
|
52
|
+
private shouldLog;
|
|
53
|
+
/**
|
|
54
|
+
* Format the log message
|
|
55
|
+
* @param component - Component name
|
|
56
|
+
* @param level - Log level
|
|
57
|
+
* @param message - Log message
|
|
58
|
+
* @param data - Additional data to log
|
|
59
|
+
* @returns Formatted log message
|
|
60
|
+
*/
|
|
61
|
+
private formatMessage;
|
|
62
|
+
/**
|
|
63
|
+
* Log a debug message
|
|
64
|
+
* @param component - Component name
|
|
65
|
+
* @param message - Log message
|
|
66
|
+
* @param data - Additional data to log
|
|
67
|
+
*/
|
|
68
|
+
debug(component: string, message: string, data?: any): void;
|
|
69
|
+
/**
|
|
70
|
+
* Log an info message
|
|
71
|
+
* @param component - Component name
|
|
72
|
+
* @param message - Log message
|
|
73
|
+
* @param data - Additional data to log
|
|
74
|
+
*/
|
|
75
|
+
info(component: string, message: string, data?: any): void;
|
|
76
|
+
/**
|
|
77
|
+
* Log a warning message
|
|
78
|
+
* @param component - Component name
|
|
79
|
+
* @param message - Log message
|
|
80
|
+
* @param data - Additional data to log
|
|
81
|
+
*/
|
|
82
|
+
warn(component: string, message: string, data?: any): void;
|
|
83
|
+
/**
|
|
84
|
+
* Log an error message
|
|
85
|
+
* @param component - Component name
|
|
86
|
+
* @param message - Log message
|
|
87
|
+
* @param data - Additional data to log
|
|
88
|
+
*/
|
|
89
|
+
error(component: string, message: string, data?: any): void;
|
|
90
|
+
/**
|
|
91
|
+
* Log a success message (info level with success emoji)
|
|
92
|
+
* @param component - Component name
|
|
93
|
+
* @param message - Log message
|
|
94
|
+
* @param data - Additional data to log
|
|
95
|
+
*/
|
|
96
|
+
success(component: string, message: string, data?: any): void;
|
|
97
|
+
/**
|
|
98
|
+
* Log a failure message (error level with failure emoji)
|
|
99
|
+
* @param component - Component name
|
|
100
|
+
* @param message - Log message
|
|
101
|
+
* @param data - Additional data to log
|
|
102
|
+
*/
|
|
103
|
+
failure(component: string, message: string, data?: any): void;
|
|
104
|
+
}
|
|
105
|
+
export declare const logger: Logger;
|
|
106
|
+
export declare const logDebug: (component: string, message: string, data?: any) => void;
|
|
107
|
+
export declare const logInfo: (component: string, message: string, data?: any) => void;
|
|
108
|
+
export declare const logWarn: (component: string, message: string, data?: any) => void;
|
|
109
|
+
export declare const logError: (component: string, message: string, data?: any) => void;
|
|
110
|
+
export declare const logSuccess: (component: string, message: string, data?: any) => void;
|
|
111
|
+
export declare const logFailure: (component: string, message: string, data?: any) => void;
|
|
112
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.logger=exports.logWarn=exports.logSuccess=exports.logInfo=exports.logFailure=exports.logError=exports.logDebug=exports.LogLevel=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _classCallCheck2=_interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2=_interopRequireDefault(require("@babel/runtime/helpers/createClass"));function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){(0,_defineProperty2["default"])(e,r,t[r]);}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));});}return e;}var LogLevel;(function(LogLevel){LogLevel[LogLevel["DEBUG"]=0]="DEBUG";LogLevel[LogLevel["INFO"]=1]="INFO";LogLevel[LogLevel["WARN"]=2]="WARN";LogLevel[LogLevel["ERROR"]=3]="ERROR";})(LogLevel||(exports.LogLevel=LogLevel={}));var Logger=function(){function Logger(){(0,_classCallCheck2["default"])(this,Logger);this.config={level:LogLevel.INFO,enableConsole:true,enablePrefix:true,prefix:'[SessionRecorder]'};this.componentPrefixes=new Map([['ScreenRecorder','📸'],['GestureRecorder','👆'],['GestureCaptureWrapper','📸'],['SessionRecorderContext','🎯'],['EventExporter','📤'],['NavigationTracker','📸'],['RecorderReactNativeSDK','📤'],['DEBUGGER_LIB','🔍']]);}return(0,_createClass2["default"])(Logger,[{key:"configure",value:function configure(config){this.config=_objectSpread(_objectSpread({},this.config),config);}},{key:"setLevel",value:function setLevel(level){this.config.level=level;}},{key:"setConsoleEnabled",value:function setConsoleEnabled(enabled){this.config.enableConsole=enabled;}},{key:"setComponentPrefix",value:function setComponentPrefix(component,emoji){this.componentPrefixes.set(component,emoji);}},{key:"getPrefix",value:function getPrefix(component){if(!this.config.enablePrefix)return'';var emoji=this.componentPrefixes.get(component)||'📝';return"".concat(this.config.prefix," ").concat(emoji," [").concat(component,"]");}},{key:"shouldLog",value:function shouldLog(level){return level>=this.config.level&&this.config.enableConsole;}},{key:"formatMessage",value:function formatMessage(component,level,message,data){var prefix=this.getPrefix(component);var timestamp=new Date().toISOString();var levelName=LogLevel[level];var formattedMessage="".concat(prefix," ").concat(levelName," ").concat(message);if(data!==undefined){formattedMessage+=" ".concat(JSON.stringify(data));}return formattedMessage;}},{key:"debug",value:function debug(component,message,data){if(!this.shouldLog(LogLevel.DEBUG))return;var formattedMessage=this.formatMessage(component,LogLevel.DEBUG,message,data);console.log(formattedMessage);}},{key:"info",value:function info(component,message,data){if(!this.shouldLog(LogLevel.INFO))return;var formattedMessage=this.formatMessage(component,LogLevel.INFO,message,data);console.log(formattedMessage);}},{key:"warn",value:function warn(component,message,data){if(!this.shouldLog(LogLevel.WARN))return;var formattedMessage=this.formatMessage(component,LogLevel.WARN,message,data);console.warn(formattedMessage);}},{key:"error",value:function error(component,message,data){if(!this.shouldLog(LogLevel.ERROR))return;var formattedMessage=this.formatMessage(component,LogLevel.ERROR,message,data);console.error(formattedMessage);}},{key:"success",value:function success(component,message,data){if(!this.shouldLog(LogLevel.INFO))return;var prefix=this.getPrefix(component);var timestamp=new Date().toISOString();var formattedMessage="".concat(prefix," \u2705 ").concat(message);var fullMessage=formattedMessage;if(data!==undefined){fullMessage+=" ".concat(JSON.stringify(data));}console.log(fullMessage);}},{key:"failure",value:function failure(component,message,data){if(!this.shouldLog(LogLevel.ERROR))return;var prefix=this.getPrefix(component);var timestamp=new Date().toISOString();var formattedMessage="".concat(prefix," \u274C ").concat(message);var fullMessage=formattedMessage;if(data!==undefined){fullMessage+=" ".concat(JSON.stringify(data));}console.error(fullMessage);}}]);}();var logger=exports.logger=new Logger();var logDebug=exports.logDebug=function logDebug(component,message,data){return logger.debug(component,message,data);};var logInfo=exports.logInfo=function logInfo(component,message,data){return logger.info(component,message,data);};var logWarn=exports.logWarn=function logWarn(component,message,data){return logger.warn(component,message,data);};var logError=exports.logError=function logError(component,message,data){return logger.error(component,message,data);};var logSuccess=exports.logSuccess=function logSuccess(component,message,data){return logger.success(component,message,data);};var logFailure=exports.logFailure=function logFailure(component,message,data){return logger.failure(component,message,data);};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { eventWithTime, serializedNodeWithId } from '@rrweb/types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a meta event to mark the start of recording
|
|
4
|
+
* @param sessionId - The session ID
|
|
5
|
+
* @param sessionType - The type of session (PLAIN or CONTINUOUS)
|
|
6
|
+
* @param additionalData - Additional data to include in the meta event
|
|
7
|
+
* @returns MetaEvent object
|
|
8
|
+
*/
|
|
9
|
+
export declare function createRecordingMetaEvent(): eventWithTime;
|
|
10
|
+
/**
|
|
11
|
+
* Create a full snapshot event with the given base64 image
|
|
12
|
+
* @param base64Image - Base64 encoded image data
|
|
13
|
+
* @param width - Screen width
|
|
14
|
+
* @param height - Screen height
|
|
15
|
+
* @param captureFormat - Image format (png, jpg, etc.)
|
|
16
|
+
* @param nodeIdCounter - Starting node ID counter (will be modified)
|
|
17
|
+
* @returns Full snapshot event
|
|
18
|
+
*/
|
|
19
|
+
export declare function createFullSnapshotEvent(base64Image: string, width: number, height: number, captureFormat: string | undefined, nodeIdCounter: {
|
|
20
|
+
current: number;
|
|
21
|
+
}): eventWithTime;
|
|
22
|
+
/**
|
|
23
|
+
* Create an incremental snapshot event with mutation data to update image src
|
|
24
|
+
* @param base64Image - New base64 encoded image data
|
|
25
|
+
* @param imageNodeId - ID of the image node to update
|
|
26
|
+
* @param captureFormat - Image format (png, jpg, etc.)
|
|
27
|
+
* @returns Incremental snapshot event with mutation data
|
|
28
|
+
*/
|
|
29
|
+
export declare function createIncrementalSnapshotWithImageUpdate(base64Image: string, imageNodeId: number, captureFormat?: string): eventWithTime;
|
|
30
|
+
/**
|
|
31
|
+
* Create a simple image node for React Native screen capture
|
|
32
|
+
* @param base64Image - Base64 encoded image data
|
|
33
|
+
* @param width - Image width
|
|
34
|
+
* @param height - Image height
|
|
35
|
+
* @param captureFormat - Image format (png, jpg, etc.)
|
|
36
|
+
* @param nodeId - Node ID for the image
|
|
37
|
+
* @returns Serialized node with ID
|
|
38
|
+
*/
|
|
39
|
+
export declare function createImageNode(base64Image: string, width: number, height: number, captureFormat: string | undefined, nodeId: number): serializedNodeWithId;
|
|
40
|
+
/**
|
|
41
|
+
* Create a document node for React Native screen capture
|
|
42
|
+
* @param imageNode - The image node to include
|
|
43
|
+
* @param width - Screen width
|
|
44
|
+
* @param height - Screen height
|
|
45
|
+
* @param nodeIdCounter - Node ID counter (will be modified)
|
|
46
|
+
* @returns Document node
|
|
47
|
+
*/
|
|
48
|
+
export declare function createDocumentNode(imageNode: serializedNodeWithId, width: number, height: number, nodeIdCounter: {
|
|
49
|
+
current: number;
|
|
50
|
+
}): serializedNodeWithId;
|
|
51
|
+
/**
|
|
52
|
+
* Generate a simple hash for screen comparison
|
|
53
|
+
* This is a lightweight hash that focuses on the beginning and end of the base64 string
|
|
54
|
+
* to detect changes without doing a full comparison
|
|
55
|
+
* @param base64Image - Base64 encoded image
|
|
56
|
+
* @param sampleSize - Number of characters to sample from each part
|
|
57
|
+
* @returns Hash string for comparison
|
|
58
|
+
*/
|
|
59
|
+
export declare function generateScreenHash(base64Image: string, sampleSize?: number): string;
|
|
60
|
+
/**
|
|
61
|
+
* Simple hash function for string comparison
|
|
62
|
+
* @param str - String to hash
|
|
63
|
+
* @returns Hash value as string
|
|
64
|
+
*/
|
|
65
|
+
export declare function simpleHash(str: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.createDocumentNode=createDocumentNode;exports.createFullSnapshotEvent=createFullSnapshotEvent;exports.createImageNode=createImageNode;exports.createIncrementalSnapshotWithImageUpdate=createIncrementalSnapshotWithImageUpdate;exports.createRecordingMetaEvent=createRecordingMetaEvent;exports.generateScreenHash=generateScreenHash;exports.simpleHash=simpleHash;var _reactNative=require("react-native");var _types=require("@rrweb/types");function createRecordingMetaEvent(){var screenDimensions=_reactNative.Dimensions.get('window');return{type:_types.EventType.Meta,data:{href:'https://go.multiplayer.app/session-recorder-react-native',width:screenDimensions.width,height:screenDimensions.height},timestamp:Date.now()};}function createFullSnapshotEvent(base64Image,width,height){var captureFormat=arguments.length>3&&arguments[3]!==undefined?arguments[3]:'jpg';var nodeIdCounter=arguments.length>4?arguments[4]:undefined;var imageNodeId=nodeIdCounter.current++;var imageNode={type:_types.NodeType.Element,id:imageNodeId,tagName:'img',attributes:{src:"data:image/".concat(captureFormat,";base64,").concat(base64Image),width:width.toString(),height:height.toString(),style:"width: ".concat(width,"px; height: ").concat(height,"px;")},childNodes:[]};var rootNode={type:_types.NodeType.Element,id:nodeIdCounter.current++,tagName:'div',attributes:{style:"width: ".concat(width,"px; height: ").concat(height,"px; position: relative;")},childNodes:[imageNode]};var domNode={type:_types.NodeType.Document,childNodes:[{type:_types.NodeType.DocumentType,name:'html',publicId:'',systemId:'',id:nodeIdCounter.current++},{type:_types.NodeType.Element,tagName:'html',attributes:{},childNodes:[{type:_types.NodeType.Element,tagName:'head',attributes:{},childNodes:[{type:_types.NodeType.Element,tagName:'meta',attributes:{charset:'utf-8'},childNodes:[],id:nodeIdCounter.current++},{type:_types.NodeType.Element,tagName:'meta',attributes:{name:'viewport',content:'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'},childNodes:[],id:nodeIdCounter.current++}],id:nodeIdCounter.current++},{type:_types.NodeType.Element,tagName:'body',attributes:{},childNodes:[rootNode],id:nodeIdCounter.current++}],id:nodeIdCounter.current++}],id:nodeIdCounter.current++};return{type:_types.EventType.FullSnapshot,data:{node:domNode,initialOffset:{left:0,top:0}},timestamp:Date.now()};}function createIncrementalSnapshotWithImageUpdate(base64Image,imageNodeId){var captureFormat=arguments.length>2&&arguments[2]!==undefined?arguments[2]:'jpg';var mutationData={source:_types.IncrementalSource.Mutation,texts:[],attributes:[{id:imageNodeId,attributes:{src:"data:image/".concat(captureFormat,";base64,").concat(base64Image)}}],removes:[],adds:[]};return{type:_types.EventType.IncrementalSnapshot,data:mutationData,timestamp:Date.now()};}function createImageNode(base64Image,width,height){var captureFormat=arguments.length>3&&arguments[3]!==undefined?arguments[3]:'jpg';var nodeId=arguments.length>4?arguments[4]:undefined;return{type:_types.NodeType.Element,id:nodeId,tagName:'img',attributes:{src:"data:image/".concat(captureFormat,";base64,").concat(base64Image),width:width.toString(),height:height.toString(),style:"width: ".concat(width,"px; height: ").concat(height,"px;")},childNodes:[]};}function createDocumentNode(imageNode,width,height,nodeIdCounter){var rootNode={type:_types.NodeType.Element,id:nodeIdCounter.current++,tagName:'div',attributes:{style:"width: ".concat(width,"px; height: ").concat(height,"px; position: relative;")},childNodes:[imageNode]};return{type:_types.NodeType.Document,childNodes:[{type:_types.NodeType.DocumentType,name:'html',publicId:'',systemId:'',id:nodeIdCounter.current++},{type:_types.NodeType.Element,tagName:'html',attributes:{},childNodes:[{type:_types.NodeType.Element,tagName:'head',attributes:{},childNodes:[{type:_types.NodeType.Element,tagName:'meta',attributes:{charset:'utf-8'},childNodes:[],id:nodeIdCounter.current++},{type:_types.NodeType.Element,tagName:'meta',attributes:{name:'viewport',content:'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'},childNodes:[],id:nodeIdCounter.current++}],id:nodeIdCounter.current++},{type:_types.NodeType.Element,tagName:'body',attributes:{},childNodes:[rootNode],id:nodeIdCounter.current++}],id:nodeIdCounter.current++}],id:nodeIdCounter.current++};}function generateScreenHash(base64Image){var sampleSize=arguments.length>1&&arguments[1]!==undefined?arguments[1]:100;var start=base64Image.substring(0,sampleSize);var middle=base64Image.substring(Math.floor(base64Image.length/2)-sampleSize/2,Math.floor(base64Image.length/2)+sampleSize/2);var end=base64Image.substring(base64Image.length-sampleSize);var combined=start+middle+end;return simpleHash(combined);}function simpleHash(str){var hash=0;for(var i=0;i<str.length;i++){var _char=str.charCodeAt(i);hash=(hash<<5)-hash+_char;hash=hash&hash;}return Math.abs(hash).toString(36);}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rrweb-events.js","sourceRoot":"","sources":["../../src/utils/rrweb-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,SAAS,EAAiB,QAAQ,EAAwB,iBAAiB,EAAgB,MAAM,cAAc,CAAA;AAExH;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAEjD,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,IAAI,EAAE;YACJ,IAAI,EAAE,0DAA0D;YAChE,KAAK,EAAE,gBAAgB,CAAC,KAAK;YAC7B,MAAM,EAAE,gBAAgB,CAAC,MAAM;SAChC;QACD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CACrC,WAAmB,EACnB,KAAa,EACb,MAAc,EACd,gBAAwB,KAAK,EAC7B,aAAkC;IAElC,gEAAgE;IAChE,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,EAAE,CAAA;IAC3C,MAAM,SAAS,GAAyB;QACtC,IAAI,EAAE,QAAQ,CAAC,OAAO;QACtB,EAAE,EAAE,WAAW;QACf,OAAO,EAAE,KAAK;QACd,UAAU,EAAE;YACV,GAAG,EAAE,cAAc,aAAa,WAAW,WAAW,EAAE;YACxD,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;YACvB,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;YACzB,KAAK,EAAE,UAAU,KAAK,eAAe,MAAM,KAAK;SACjD;QACD,UAAU,EAAE,EAAE;KACf,CAAA;IAED,4BAA4B;IAC5B,MAAM,QAAQ,GAAyB;QACrC,IAAI,EAAE,QAAQ,CAAC,OAAO;QACtB,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;QAC3B,OAAO,EAAE,KAAK;QACd,UAAU,EAAE;YACV,KAAK,EAAE,UAAU,KAAK,eAAe,MAAM,yBAAyB;SACrE;QACD,UAAU,EAAE,CAAC,SAAS,CAAC;KACxB,CAAA;IAED,MAAM,OAAO,GAAyB;QACpC,IAAI,EAAE,QAAQ,CAAC,QAAQ;QACvB,UAAU,EAAE;YACV;gBACE,IAAI,EAAE,QAAQ,CAAC,YAAY;gBAC3B,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,EAAE;gBACZ,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;aAC5B;YACD;gBACE,IAAI,EAAE,QAAQ,CAAC,OAAO;gBACtB,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;gBACd,UAAU,EAAE;oBACV;wBACE,IAAI,EAAE,QAAQ,CAAC,OAAO;wBACtB,OAAO,EAAE,MAAM;wBACf,UAAU,EAAE,EAAE;wBACd,UAAU,EAAE;4BACV;gCACE,IAAI,EAAE,QAAQ,CAAC,OAAO;gCACtB,OAAO,EAAE,MAAM;gCACf,UAAU,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE;gCAChC,UAAU,EAAE,EAAE;gCACd,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;6BAC5B;4BACD;gCACE,IAAI,EAAE,QAAQ,CAAC,OAAO;gCACtB,OAAO,EAAE,MAAM;gCACf,UAAU,EAAE;oCACV,IAAI,EAAE,UAAU;oCAChB,OAAO,EAAE,4EAA4E;iCACtF;gCACD,UAAU,EAAE,EAAE;gCACd,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;6BAC5B;yBACF;wBACD,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;qBAC5B;oBACD;wBACE,IAAI,EAAE,QAAQ,CAAC,OAAO;wBACtB,OAAO,EAAE,MAAM;wBACf,UAAU,EAAE,EAAE;wBACd,UAAU,EAAE,CAAC,QAAQ,CAAC;wBACtB,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;qBAC5B;iBACF;gBACD,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;aAC5B;SACF;QACD,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;KAC5B,CAAA;IAED,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,YAAY;QAC5B,IAAI,EAAE;YACJ,IAAI,EAAE,OAAO;YACb,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;SACnC;QACD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wCAAwC,CACtD,WAAmB,EACnB,WAAmB,EACnB,gBAAwB,KAAK;IAE7B,MAAM,YAAY,GAAiB;QACjC,MAAM,EAAE,iBAAiB,CAAC,QAAQ;QAClC,KAAK,EAAE,EAAE;QACT,UAAU,EAAE;YACV;gBACE,EAAE,EAAE,WAAW;gBACf,UAAU,EAAE;oBACV,GAAG,EAAE,cAAc,aAAa,WAAW,WAAW,EAAE;iBACzD;aACF;SACF;QACD,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,EAAE;KACT,CAAA;IAED,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,mBAAmB;QACnC,IAAI,EAAE,YAAY;QAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,WAAmB,EACnB,KAAa,EACb,MAAc,EACd,gBAAwB,KAAK,EAC7B,MAAc;IAEd,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,OAAO;QACtB,EAAE,EAAE,MAAM;QACV,OAAO,EAAE,KAAK;QACd,UAAU,EAAE;YACV,GAAG,EAAE,cAAc,aAAa,WAAW,WAAW,EAAE;YACxD,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;YACvB,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;YACzB,KAAK,EAAE,UAAU,KAAK,eAAe,MAAM,KAAK;SACjD;QACD,UAAU,EAAE,EAAE;KACf,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAA+B,EAC/B,KAAa,EACb,MAAc,EACd,aAAkC;IAElC,4BAA4B;IAC5B,MAAM,QAAQ,GAAyB;QACrC,IAAI,EAAE,QAAQ,CAAC,OAAO;QACtB,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;QAC3B,OAAO,EAAE,KAAK;QACd,UAAU,EAAE;YACV,KAAK,EAAE,UAAU,KAAK,eAAe,MAAM,yBAAyB;SACrE;QACD,UAAU,EAAE,CAAC,SAAS,CAAC;KACxB,CAAA;IAED,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,QAAQ;QACvB,UAAU,EAAE;YACV;gBACE,IAAI,EAAE,QAAQ,CAAC,YAAY;gBAC3B,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,EAAE;gBACZ,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;aAC5B;YACD;gBACE,IAAI,EAAE,QAAQ,CAAC,OAAO;gBACtB,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;gBACd,UAAU,EAAE;oBACV;wBACE,IAAI,EAAE,QAAQ,CAAC,OAAO;wBACtB,OAAO,EAAE,MAAM;wBACf,UAAU,EAAE,EAAE;wBACd,UAAU,EAAE;4BACV;gCACE,IAAI,EAAE,QAAQ,CAAC,OAAO;gCACtB,OAAO,EAAE,MAAM;gCACf,UAAU,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE;gCAChC,UAAU,EAAE,EAAE;gCACd,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;6BAC5B;4BACD;gCACE,IAAI,EAAE,QAAQ,CAAC,OAAO;gCACtB,OAAO,EAAE,MAAM;gCACf,UAAU,EAAE;oCACV,IAAI,EAAE,UAAU;oCAChB,OAAO,EAAE,4EAA4E;iCACtF;gCACD,UAAU,EAAE,EAAE;gCACd,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;6BAC5B;yBACF;wBACD,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;qBAC5B;oBACD;wBACE,IAAI,EAAE,QAAQ,CAAC,OAAO;wBACtB,OAAO,EAAE,MAAM;wBACf,UAAU,EAAE,EAAE;wBACd,UAAU,EAAE,CAAC,QAAQ,CAAC;wBACtB,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;qBAC5B;iBACF;gBACD,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;aAC5B;SACF;QACD,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE;KAC5B,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,aAAqB,GAAG;IAC9E,qFAAqF;IACrF,uDAAuD;IACvD,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IAClD,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAClC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,EACnD,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,CACpD,CAAA;IACD,MAAM,GAAG,GAAG,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC,CAAA;IAElE,2CAA2C;IAC3C,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,GAAG,CAAA;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAA;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAC9B,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;QAChC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA,CAAC,4BAA4B;IACjD,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AACpC,CAAC"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "0.0.1-alpha.
|
|
1
|
+
export declare const version = "0.0.1-alpha.8";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.version=void 0;var version=exports.version="0.0.1-alpha.
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.version=void 0;var version=exports.version="0.0.1-alpha.8";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplayer-app/session-recorder-react-native",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.8",
|
|
4
4
|
"description": "Multiplayer Fullstack Session Recorder for React Native",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Multiplayer Software, Inc.",
|
|
@@ -79,11 +79,13 @@
|
|
|
79
79
|
"@react-native-async-storage/async-storage": "^1.21.0",
|
|
80
80
|
"@react-native-community/netinfo": "^11.1.0",
|
|
81
81
|
"@rrweb/packer": "^2.0.0-alpha.15",
|
|
82
|
+
"@rrweb/types": "^2.0.0-alpha.18",
|
|
82
83
|
"lib0": "0.2.82",
|
|
83
84
|
"react-native-gesture-handler": "^2.14.0",
|
|
84
85
|
"react-native-mmkv": "^2.11.0",
|
|
85
86
|
"react-native-reanimated": "^3.6.0",
|
|
86
87
|
"react-native-view-shot": "^4.0.3",
|
|
88
|
+
"rrweb": "^2.0.0-alpha.15",
|
|
87
89
|
"socket.io-client": "4.7.5"
|
|
88
90
|
},
|
|
89
91
|
"peerDependencies": {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React, { ReactNode, useCallback, useEffect, useMemo, useRef } from 'react'
|
|
2
|
+
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'
|
|
3
|
+
import { GestureInstrumentation } from '../otel/instrumentations/gestureInstrumentation'
|
|
4
|
+
import { logger } from '../utils'
|
|
5
|
+
|
|
6
|
+
export interface GestureCaptureWrapperProps {
|
|
7
|
+
children: ReactNode
|
|
8
|
+
onGestureRecord: (gestureType: string, data: any) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const GestureCaptureWrapper: React.FC<GestureCaptureWrapperProps> = ({ children, onGestureRecord }) => {
|
|
12
|
+
const gestureInstrumentation = useRef(new GestureInstrumentation())
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
gestureInstrumentation.current.enable()
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
const recordGesture = useCallback(
|
|
19
|
+
(gestureType: string, data: any) => {
|
|
20
|
+
// Record with OpenTelemetry
|
|
21
|
+
logger.debug('GestureCaptureWrapper', 'Recording gesture', { gestureType, data })
|
|
22
|
+
switch (gestureType) {
|
|
23
|
+
case 'tap':
|
|
24
|
+
gestureInstrumentation.current.recordTap(data.x, data.y)
|
|
25
|
+
break
|
|
26
|
+
case 'pan_start':
|
|
27
|
+
case 'pan_update':
|
|
28
|
+
case 'pan_end':
|
|
29
|
+
gestureInstrumentation.current.recordPan(data.translationX || 0, data.translationY || 0)
|
|
30
|
+
break
|
|
31
|
+
case 'long_press':
|
|
32
|
+
gestureInstrumentation.current.recordLongPress(data.duration, undefined)
|
|
33
|
+
break
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Record with session recorder
|
|
37
|
+
onGestureRecord(gestureType, data)
|
|
38
|
+
},
|
|
39
|
+
[onGestureRecord]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
// Create tap gesture
|
|
43
|
+
const tapGesture = useMemo(() => {
|
|
44
|
+
return Gesture.Tap()
|
|
45
|
+
.runOnJS(true)
|
|
46
|
+
.onStart((event) => {
|
|
47
|
+
recordGesture('tap', {
|
|
48
|
+
x: event.x,
|
|
49
|
+
y: event.y,
|
|
50
|
+
timestamp: Date.now()
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
}, [recordGesture])
|
|
54
|
+
|
|
55
|
+
// Create pan gesture (for swipes and drags)
|
|
56
|
+
const panGesture = useMemo(() => {
|
|
57
|
+
return Gesture.Pan()
|
|
58
|
+
.runOnJS(true)
|
|
59
|
+
.onStart((event) => {
|
|
60
|
+
recordGesture('pan_start', {
|
|
61
|
+
x: event.x,
|
|
62
|
+
y: event.y,
|
|
63
|
+
timestamp: Date.now()
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
.onUpdate((event) => {
|
|
67
|
+
recordGesture('pan_update', {
|
|
68
|
+
x: event.x,
|
|
69
|
+
y: event.y,
|
|
70
|
+
translationX: event.translationX,
|
|
71
|
+
translationY: event.translationY,
|
|
72
|
+
velocityX: event.velocityX,
|
|
73
|
+
velocityY: event.velocityY,
|
|
74
|
+
timestamp: Date.now()
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
.onEnd((event) => {
|
|
78
|
+
recordGesture('pan_end', {
|
|
79
|
+
x: event.x,
|
|
80
|
+
y: event.y,
|
|
81
|
+
translationX: event.translationX,
|
|
82
|
+
translationY: event.translationY,
|
|
83
|
+
velocityX: event.velocityX,
|
|
84
|
+
velocityY: event.velocityY,
|
|
85
|
+
timestamp: Date.now()
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
}, [recordGesture])
|
|
89
|
+
|
|
90
|
+
// Create long press gesture
|
|
91
|
+
const longPressGesture = useMemo(() => {
|
|
92
|
+
return Gesture.LongPress()
|
|
93
|
+
.runOnJS(true)
|
|
94
|
+
.minDuration(500)
|
|
95
|
+
.onStart((event) => {
|
|
96
|
+
recordGesture('long_press', {
|
|
97
|
+
x: event.x,
|
|
98
|
+
y: event.y,
|
|
99
|
+
duration: 500,
|
|
100
|
+
timestamp: Date.now()
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
}, [recordGesture])
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
107
|
+
<GestureDetector gesture={Gesture.Simultaneous(tapGesture, panGesture, longPressGesture)}>{children}</GestureDetector>
|
|
108
|
+
</GestureHandlerRootView>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
@@ -1,46 +1,50 @@
|
|
|
1
|
-
import React, { createContext, useContext, ReactNode, PropsWithChildren,
|
|
1
|
+
import React, { createContext, useContext, ReactNode, PropsWithChildren, useState, useEffect, useRef, useCallback } from 'react'
|
|
2
2
|
import { Pressable, Text, View } from 'react-native'
|
|
3
3
|
import { SessionRecorderOptions, SessionState } from '../types'
|
|
4
4
|
import SessionRecorder from '../session-recorder'
|
|
5
|
+
import { GestureCaptureWrapper } from '../components/GestureCaptureWrapper'
|
|
6
|
+
import sessionRecorder from '../session-recorder'
|
|
7
|
+
import { logger } from '../utils'
|
|
5
8
|
|
|
6
9
|
interface SessionRecorderContextType {
|
|
7
|
-
|
|
10
|
+
instance: typeof SessionRecorder
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
const SessionRecorderContext = createContext<SessionRecorderContextType | null>(null)
|
|
11
14
|
|
|
12
15
|
export interface SessionRecorderProviderProps extends PropsWithChildren {
|
|
13
16
|
options: SessionRecorderOptions
|
|
14
|
-
client?: typeof SessionRecorder
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
export const SessionRecorderProvider: React.FC<SessionRecorderProviderProps> = ({ children,
|
|
19
|
+
export const SessionRecorderProvider: React.FC<SessionRecorderProviderProps> = ({ children, options }) => {
|
|
18
20
|
const [sessionState, setSessionState] = useState<SessionState | null>(null)
|
|
21
|
+
const optionsRef = useRef<string>()
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const newOptions = JSON.stringify(options)
|
|
25
|
+
if (optionsRef.current === JSON.stringify(options)) return
|
|
26
|
+
optionsRef.current = newOptions
|
|
22
27
|
SessionRecorder.init(options)
|
|
23
|
-
|
|
24
|
-
}, [])
|
|
28
|
+
}, [options])
|
|
25
29
|
|
|
26
30
|
useEffect(() => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
setSessionState(SessionRecorder.sessionState)
|
|
32
|
+
SessionRecorder.on('state-change', (state: SessionState) => {
|
|
33
|
+
setSessionState(state)
|
|
34
|
+
})
|
|
35
|
+
}, [])
|
|
30
36
|
|
|
31
37
|
const onToggleSession = () => {
|
|
32
|
-
if (sessionState === SessionState.started) {
|
|
33
|
-
|
|
34
|
-
sessionRecorder.stop()
|
|
38
|
+
if (SessionRecorder.sessionState === SessionState.started) {
|
|
39
|
+
SessionRecorder.stop()
|
|
35
40
|
} else {
|
|
36
|
-
|
|
37
|
-
sessionRecorder.start()
|
|
41
|
+
SessionRecorder.start()
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
return (
|
|
42
|
-
<SessionRecorderContext.Provider value={{
|
|
43
|
-
<
|
|
46
|
+
<SessionRecorderContext.Provider value={{ instance: sessionRecorder }}>
|
|
47
|
+
<GestureEventCapture>
|
|
44
48
|
{children}
|
|
45
49
|
<Pressable onPress={onToggleSession}>
|
|
46
50
|
<View
|
|
@@ -60,82 +64,73 @@ export const SessionRecorderProvider: React.FC<SessionRecorderProviderProps> = (
|
|
|
60
64
|
<Text style={{ color: 'white' }}>{sessionState === SessionState.started ? 'Stop' : 'Start'}</Text>
|
|
61
65
|
</View>
|
|
62
66
|
</Pressable>
|
|
63
|
-
</
|
|
67
|
+
</GestureEventCapture>
|
|
64
68
|
</SessionRecorderContext.Provider>
|
|
65
69
|
)
|
|
66
70
|
}
|
|
67
71
|
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}, [context?.client])
|
|
79
|
-
|
|
80
|
-
// Callback ref to set the viewshot ref immediately when available
|
|
81
|
-
const setViewShotRef = (ref: View | null) => {
|
|
82
|
-
if (ref && context?.client) {
|
|
83
|
-
context.client.setViewShotRef?.(ref)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const handleTouchStart = (event: any) => {
|
|
88
|
-
if (!context?.client || context.client.sessionState !== SessionState.started) return // SessionState.started
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
const { pageX, pageY, target } = event.nativeEvent
|
|
92
|
-
const pressure = event.nativeEvent.force || 1.0
|
|
93
|
-
|
|
94
|
-
// Record touch start event automatically
|
|
95
|
-
context.client.recordTouchStart?.(pageX, pageY, target?.toString(), pressure)
|
|
96
|
-
} catch (error) {
|
|
97
|
-
console.warn('Failed to record touch start event:', error)
|
|
72
|
+
// Gesture-based event capture component
|
|
73
|
+
const GestureEventCapture: React.FC<{ children: ReactNode }> = ({ children }) => {
|
|
74
|
+
// Set up gesture recording callback
|
|
75
|
+
const handleGestureRecord = useCallback((gestureType: string, data: any) => {
|
|
76
|
+
if (SessionRecorder.sessionState !== SessionState.started) {
|
|
77
|
+
logger.debug('SessionRecorderContext', 'Gesture recording skipped', {
|
|
78
|
+
client: !!SessionRecorder.sessionState,
|
|
79
|
+
sessionState: SessionRecorder.sessionState
|
|
80
|
+
})
|
|
81
|
+
return
|
|
98
82
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const handleTouchMove = (event: any) => {
|
|
102
|
-
if (!context?.client || context.client.sessionState !== SessionState.started) return // SessionState.started
|
|
103
|
-
|
|
83
|
+
logger.debug('SessionRecorderContext', 'Gesture recorded', { gestureType, data })
|
|
104
84
|
try {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
85
|
+
// Record gesture as appropriate touch events
|
|
86
|
+
switch (gestureType) {
|
|
87
|
+
case 'tap':
|
|
88
|
+
// For tap, record both touch start and end
|
|
89
|
+
logger.debug('SessionRecorderContext', 'Recording tap as touch start + end')
|
|
90
|
+
SessionRecorder.recordTouchStart?.(data.x, data.y, undefined, 1.0)
|
|
91
|
+
SessionRecorder.recordTouchEnd?.(data.x, data.y, undefined, 1.0)
|
|
92
|
+
break
|
|
93
|
+
|
|
94
|
+
case 'pan_start':
|
|
95
|
+
logger.debug('SessionRecorderContext', 'Recording pan_start as touch start')
|
|
96
|
+
SessionRecorder.recordTouchStart?.(data.x, data.y, undefined, 1.0)
|
|
97
|
+
break
|
|
98
|
+
|
|
99
|
+
case 'pan_update':
|
|
100
|
+
logger.debug('SessionRecorderContext', 'Recording pan_update as touch move')
|
|
101
|
+
SessionRecorder.recordTouchMove?.(data.x, data.y, undefined, 1.0)
|
|
102
|
+
break
|
|
103
|
+
|
|
104
|
+
case 'pan_end':
|
|
105
|
+
logger.debug('SessionRecorderContext', 'Recording pan_end as touch end')
|
|
106
|
+
SessionRecorder.recordTouchEnd?.(data.x, data.y, undefined, 1.0)
|
|
107
|
+
break
|
|
108
|
+
|
|
109
|
+
case 'long_press':
|
|
110
|
+
logger.debug('SessionRecorderContext', 'Recording long_press as touch start + end')
|
|
111
|
+
SessionRecorder.recordTouchStart?.(data.x, data.y, undefined, 1.0)
|
|
112
|
+
SessionRecorder.recordTouchEnd?.(data.x, data.y, undefined, 1.0)
|
|
113
|
+
break
|
|
114
|
+
default:
|
|
115
|
+
}
|
|
110
116
|
} catch (error) {
|
|
111
|
-
|
|
117
|
+
logger.error('SessionRecorderContext', 'Failed to record gesture event', error)
|
|
112
118
|
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const handleTouchEnd = (event: any) => {
|
|
116
|
-
if (!context?.client || context.client.sessionState !== SessionState.started) return // SessionState.started
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
const { pageX, pageY, target } = event.nativeEvent
|
|
120
|
-
const pressure = event.nativeEvent.force || 1.0
|
|
119
|
+
}, [])
|
|
121
120
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
// Callback ref to set the viewshot ref immediately when available
|
|
122
|
+
const setViewShotRef = (ref: View | null) => {
|
|
123
|
+
if (ref) {
|
|
124
|
+
SessionRecorder.setViewShotRef?.(ref)
|
|
126
125
|
}
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
return (
|
|
130
|
-
<
|
|
131
|
-
ref={setViewShotRef}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
onTouchEnd={handleTouchEnd}
|
|
136
|
-
>
|
|
137
|
-
{children}
|
|
138
|
-
</View>
|
|
129
|
+
<GestureCaptureWrapper onGestureRecord={handleGestureRecord}>
|
|
130
|
+
<View ref={setViewShotRef} style={{ flex: 1 }}>
|
|
131
|
+
{children}
|
|
132
|
+
</View>
|
|
133
|
+
</GestureCaptureWrapper>
|
|
139
134
|
)
|
|
140
135
|
}
|
|
141
136
|
|
package/src/otel/helpers.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY,
|
|
8
8
|
ATTR_MULTIPLAYER_HTTP_RESPONSE_HEADERS,
|
|
9
9
|
} from '@multiplayer-app/session-recorder-common'
|
|
10
|
+
import { logger } from '../utils'
|
|
10
11
|
import { SessionRecorderSdk } from '@multiplayer-app/session-recorder-common'
|
|
11
12
|
import { TracerReactNativeConfig } from '../types'
|
|
12
13
|
|
|
@@ -249,7 +250,7 @@ export async function extractResponseBody(response: Response): Promise<string |
|
|
|
249
250
|
} catch (error) {
|
|
250
251
|
// If cloning fails (body already consumed), return null
|
|
251
252
|
// eslint-disable-next-line no-console
|
|
252
|
-
|
|
253
|
+
logger.warn('DEBUGGER_LIB', 'Failed to extract response body', error)
|
|
253
254
|
return null
|
|
254
255
|
}
|
|
255
256
|
}
|
|
@@ -4,6 +4,7 @@ import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xm
|
|
|
4
4
|
import { OTEL_IGNORE_URLS } from '../../config'
|
|
5
5
|
import { TracerReactNativeConfig } from '../../types'
|
|
6
6
|
import { extractResponseBody, headersToObject, processHttpPayload } from '../helpers'
|
|
7
|
+
import { logger } from '../../utils'
|
|
7
8
|
|
|
8
9
|
export function getInstrumentations(config: TracerReactNativeConfig) {
|
|
9
10
|
|
|
@@ -47,13 +48,13 @@ export function getInstrumentations(config: TracerReactNativeConfig) {
|
|
|
47
48
|
processHttpPayload(payload, config, span)
|
|
48
49
|
} catch (error) {
|
|
49
50
|
// eslint-disable-next-line
|
|
50
|
-
|
|
51
|
+
logger.error('DEBUGGER_LIB', 'Failed to capture fetch payload', error)
|
|
51
52
|
}
|
|
52
53
|
},
|
|
53
54
|
})
|
|
54
55
|
)
|
|
55
56
|
} catch (error) {
|
|
56
|
-
|
|
57
|
+
logger.warn('DEBUGGER_LIB', 'Fetch instrumentation not available', error)
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
// XMLHttpRequest instrumentation
|
|
@@ -94,13 +95,13 @@ export function getInstrumentations(config: TracerReactNativeConfig) {
|
|
|
94
95
|
processHttpPayload(payload, config, span)
|
|
95
96
|
} catch (error) {
|
|
96
97
|
// eslint-disable-next-line
|
|
97
|
-
|
|
98
|
+
logger.error('DEBUGGER_LIB', 'Failed to capture xml-http payload', error)
|
|
98
99
|
}
|
|
99
100
|
},
|
|
100
101
|
})
|
|
101
102
|
)
|
|
102
103
|
} catch (error) {
|
|
103
|
-
|
|
104
|
+
logger.warn('DEBUGGER_LIB', 'XMLHttpRequest instrumentation not available', error)
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
// Custom React Native instrumentations
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { InstrumentationBase } from '@opentelemetry/instrumentation'
|
|
2
|
+
import { logger } from '../../utils'
|
|
2
3
|
import { trace, SpanStatusCode } from '@opentelemetry/api'
|
|
3
4
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
4
5
|
|
|
@@ -18,7 +19,7 @@ export class ReactNativeInstrumentation extends InstrumentationBase {
|
|
|
18
19
|
this._wrap(AsyncStorage, 'setItem', this._wrapAsyncStorage)
|
|
19
20
|
}
|
|
20
21
|
} catch (error) {
|
|
21
|
-
|
|
22
|
+
logger.warn('DEBUGGER_LIB', '@react-native-async-storage/async-storage is not available. AsyncStorage instrumentation will be disabled.')
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|