@multiplayer-app/session-recorder-react-native 1.0.1-beta.4 → 1.0.1-beta.5
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/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativeModule.kt +2 -2
- package/lib/module/components/SessionRecorderWidget/ErrorBanner.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/ModalHeader.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/icons.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/styles.js.map +1 -1
- package/lib/module/config/constants.js.map +1 -1
- package/lib/module/config/defaults.js.map +1 -1
- package/lib/module/config/masking.js.map +1 -1
- package/lib/module/config/session-recorder.js.map +1 -1
- package/lib/module/config/validators.js.map +1 -1
- package/lib/module/config/widget.js.map +1 -1
- package/lib/module/context/SessionRecorderStore.js.map +1 -1
- package/lib/module/context/useSessionRecorderStore.js.map +1 -1
- package/lib/module/context/useStoreSelector.js.map +1 -1
- package/lib/module/native/SessionRecorderNative.js.map +1 -1
- package/lib/module/native/index.js.map +1 -1
- package/lib/module/otel/helpers.js +1 -1
- package/lib/module/otel/helpers.js.map +1 -1
- package/lib/module/otel/index.js.map +1 -1
- package/lib/module/otel/instrumentations/index.js.map +1 -1
- package/lib/module/patch/xhr.js.map +1 -1
- package/lib/module/recorder/eventExporter.js.map +1 -1
- package/lib/module/recorder/gestureRecorder.js.map +1 -1
- package/lib/module/recorder/index.js.map +1 -1
- package/lib/module/recorder/navigationTracker.js.map +1 -1
- package/lib/module/recorder/screenRecorder.js.map +1 -1
- package/lib/module/services/api.service.js.map +1 -1
- package/lib/module/services/network.service.js.map +1 -1
- package/lib/module/services/screenMaskingService.js.map +1 -1
- package/lib/module/services/storage.service.js.map +1 -1
- package/lib/module/session-recorder.js.map +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/module/types/session-recorder.js.map +1 -1
- package/lib/module/utils/app-metadata.js +2 -2
- package/lib/module/utils/constants.optional.js.map +1 -1
- package/lib/module/utils/createStore.js.map +1 -1
- package/lib/module/utils/logger.js +0 -8
- package/lib/module/utils/logger.js.map +1 -1
- package/lib/module/utils/platform.js +1 -1
- package/lib/module/utils/platform.js.map +1 -1
- package/lib/module/utils/rrweb-events.js.map +1 -1
- package/lib/module/utils/session.js.map +1 -1
- package/lib/module/utils/shallowEqual.js.map +1 -1
- package/lib/module/utils/time.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/components/ScreenRecorderView/index.d.ts +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/ErrorBanner.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/ModalHeader.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/SessionRecorderWidget.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/icons.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/index.d.ts +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/config/constants.d.ts.map +1 -1
- package/lib/typescript/src/config/defaults.d.ts.map +1 -1
- package/lib/typescript/src/config/index.d.ts.map +1 -1
- package/lib/typescript/src/config/masking.d.ts.map +1 -1
- package/lib/typescript/src/config/session-recorder.d.ts.map +1 -1
- package/lib/typescript/src/config/validators.d.ts.map +1 -1
- package/lib/typescript/src/config/widget.d.ts +1 -1
- package/lib/typescript/src/config/widget.d.ts.map +1 -1
- package/lib/typescript/src/context/SessionRecorderStore.d.ts.map +1 -1
- package/lib/typescript/src/context/useSessionRecorderStore.d.ts +3 -3
- package/lib/typescript/src/context/useSessionRecorderStore.d.ts.map +1 -1
- package/lib/typescript/src/context/useStoreSelector.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native/SessionRecorderNative.d.ts.map +1 -1
- package/lib/typescript/src/native/index.d.ts +1 -1
- package/lib/typescript/src/native/index.d.ts.map +1 -1
- package/lib/typescript/src/otel/helpers.d.ts.map +1 -1
- package/lib/typescript/src/otel/index.d.ts.map +1 -1
- package/lib/typescript/src/otel/instrumentations/index.d.ts.map +1 -1
- package/lib/typescript/src/patch/index.d.ts.map +1 -1
- package/lib/typescript/src/patch/xhr.d.ts.map +1 -1
- package/lib/typescript/src/recorder/eventExporter.d.ts.map +1 -1
- package/lib/typescript/src/recorder/gestureRecorder.d.ts.map +1 -1
- package/lib/typescript/src/recorder/index.d.ts.map +1 -1
- package/lib/typescript/src/recorder/navigationTracker.d.ts.map +1 -1
- package/lib/typescript/src/recorder/screenRecorder.d.ts.map +1 -1
- package/lib/typescript/src/services/api.service.d.ts.map +1 -1
- package/lib/typescript/src/services/network.service.d.ts.map +1 -1
- package/lib/typescript/src/services/screenMaskingService.d.ts.map +1 -1
- package/lib/typescript/src/services/storage.service.d.ts.map +1 -1
- package/lib/typescript/src/session-recorder.d.ts.map +1 -1
- package/lib/typescript/src/types/configs.d.ts.map +1 -1
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/lib/typescript/src/types/session-recorder.d.ts +4 -4
- package/lib/typescript/src/types/session-recorder.d.ts.map +1 -1
- package/lib/typescript/src/types/session.d.ts.map +1 -1
- package/lib/typescript/src/utils/app-metadata.d.ts.map +1 -1
- package/lib/typescript/src/utils/constants.optional.d.ts.map +1 -1
- package/lib/typescript/src/utils/constants.optional.expo.d.ts.map +1 -1
- package/lib/typescript/src/utils/createStore.d.ts.map +1 -1
- package/lib/typescript/src/utils/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/logger.d.ts +1 -1
- package/lib/typescript/src/utils/logger.d.ts.map +1 -1
- package/lib/typescript/src/utils/platform.d.ts.map +1 -1
- package/lib/typescript/src/utils/request-utils.d.ts.map +1 -1
- package/lib/typescript/src/utils/rrweb-events.d.ts.map +1 -1
- package/lib/typescript/src/utils/session.d.ts.map +1 -1
- package/lib/typescript/src/utils/shallowEqual.d.ts.map +1 -1
- package/lib/typescript/src/utils/time.d.ts.map +1 -1
- package/lib/typescript/src/utils/type-utils.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ScreenRecorderView/index.ts +1 -1
- package/src/components/SessionRecorderWidget/ErrorBanner.tsx +14 -14
- package/src/components/SessionRecorderWidget/ModalHeader.tsx +11 -9
- package/src/components/SessionRecorderWidget/SessionRecorderWidget.tsx +70 -56
- package/src/components/SessionRecorderWidget/icons.tsx +58 -30
- package/src/components/SessionRecorderWidget/index.ts +1 -1
- package/src/components/SessionRecorderWidget/styles.ts +17 -18
- package/src/components/index.ts +2 -2
- package/src/config/constants.ts +19 -20
- package/src/config/defaults.ts +35 -31
- package/src/config/index.ts +5 -5
- package/src/config/masking.ts +44 -18
- package/src/config/session-recorder.ts +54 -26
- package/src/config/validators.ts +43 -20
- package/src/config/widget.ts +24 -15
- package/src/context/SessionRecorderStore.ts +19 -18
- package/src/context/useSessionRecorderStore.ts +17 -10
- package/src/context/useStoreSelector.ts +20 -18
- package/src/index.ts +7 -7
- package/src/native/SessionRecorderNative.ts +83 -67
- package/src/native/index.ts +5 -1
- package/src/otel/helpers.ts +109 -93
- package/src/otel/index.ts +46 -49
- package/src/otel/instrumentations/index.ts +44 -41
- package/src/patch/index.ts +1 -1
- package/src/patch/xhr.ts +77 -78
- package/src/recorder/eventExporter.ts +63 -68
- package/src/recorder/gestureRecorder.ts +359 -212
- package/src/recorder/index.ts +75 -62
- package/src/recorder/navigationTracker.ts +120 -97
- package/src/recorder/screenRecorder.ts +214 -163
- package/src/services/api.service.ts +49 -48
- package/src/services/network.service.ts +67 -58
- package/src/services/screenMaskingService.ts +81 -50
- package/src/services/storage.service.ts +99 -70
- package/src/session-recorder.ts +270 -214
- package/src/types/configs.ts +53 -31
- package/src/types/expo-constants.d.ts +2 -2
- package/src/types/index.ts +16 -18
- package/src/types/session-recorder.ts +106 -111
- package/src/types/session.ts +45 -45
- package/src/utils/app-metadata.ts +9 -9
- package/src/utils/constants.optional.expo.ts +3 -3
- package/src/utils/constants.optional.ts +14 -12
- package/src/utils/createStore.ts +23 -20
- package/src/utils/index.ts +7 -7
- package/src/utils/logger.ts +87 -58
- package/src/utils/platform.ts +149 -118
- package/src/utils/request-utils.ts +15 -15
- package/src/utils/rrweb-events.ts +47 -34
- package/src/utils/session.ts +15 -12
- package/src/utils/shallowEqual.ts +16 -10
- package/src/utils/time.ts +7 -4
- package/src/utils/type-utils.ts +36 -36
- package/src/version.ts +1 -1
- package/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativeModuleSpec.kt +0 -51
- package/android/src/main/java/com/xxx/XxxModule.kt +0 -23
- package/ios/Xxx.h +0 -5
- package/ios/Xxx.mm +0 -21
|
@@ -1,38 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type IResourceAttributes,
|
|
3
|
+
type ISessionAttributes,
|
|
4
|
+
type ApiServiceConfig,
|
|
5
|
+
} from '../types';
|
|
2
6
|
|
|
3
7
|
export interface StartSessionRequest {
|
|
4
|
-
name?: string
|
|
5
|
-
stoppedAt?: string | number
|
|
6
|
-
sessionAttributes?: ISessionAttributes
|
|
7
|
-
resourceAttributes?: IResourceAttributes
|
|
8
|
-
debugSessionData?: Record<string, any
|
|
9
|
-
tags?: { key?: string
|
|
8
|
+
name?: string;
|
|
9
|
+
stoppedAt?: string | number;
|
|
10
|
+
sessionAttributes?: ISessionAttributes;
|
|
11
|
+
resourceAttributes?: IResourceAttributes;
|
|
12
|
+
debugSessionData?: Record<string, any>;
|
|
13
|
+
tags?: { key?: string; value: string }[];
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
export interface StopSessionRequest {
|
|
13
|
-
sessionAttributes?: ISessionAttributes
|
|
14
|
-
stoppedAt: string | number
|
|
17
|
+
sessionAttributes?: ISessionAttributes;
|
|
18
|
+
stoppedAt: string | number;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
export class ApiService {
|
|
18
|
-
private config?: ApiServiceConfig
|
|
19
|
-
private baseUrl: string = 'https://api.multiplayer.app'
|
|
22
|
+
private config?: ApiServiceConfig;
|
|
23
|
+
private baseUrl: string = 'https://api.multiplayer.app';
|
|
20
24
|
|
|
21
25
|
constructor() {
|
|
22
26
|
this.config = {
|
|
23
27
|
apiKey: '',
|
|
24
28
|
apiBaseUrl: '',
|
|
25
29
|
exporterEndpoint: '',
|
|
26
|
-
}
|
|
30
|
+
};
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
init(config: ApiServiceConfig): void {
|
|
30
34
|
this.config = {
|
|
31
35
|
...this.config,
|
|
32
36
|
...config,
|
|
33
|
-
}
|
|
37
|
+
};
|
|
34
38
|
if (config.apiBaseUrl) {
|
|
35
|
-
this.baseUrl = config.apiBaseUrl
|
|
39
|
+
this.baseUrl = config.apiBaseUrl;
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
42
|
|
|
@@ -42,7 +46,7 @@ export class ApiService {
|
|
|
42
46
|
*/
|
|
43
47
|
public updateConfigs(config: Partial<ApiServiceConfig>) {
|
|
44
48
|
if (this.config) {
|
|
45
|
-
this.config = { ...this.config, ...config }
|
|
49
|
+
this.config = { ...this.config, ...config };
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
|
|
@@ -52,7 +56,7 @@ export class ApiService {
|
|
|
52
56
|
*/
|
|
53
57
|
setApiKey(apiKey: string): void {
|
|
54
58
|
if (this.config) {
|
|
55
|
-
this.config.apiKey = apiKey
|
|
59
|
+
this.config.apiKey = apiKey;
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -67,9 +71,9 @@ export class ApiService {
|
|
|
67
71
|
path: string,
|
|
68
72
|
method: string,
|
|
69
73
|
body?: any,
|
|
70
|
-
signal?: AbortSignal
|
|
74
|
+
signal?: AbortSignal
|
|
71
75
|
): Promise<any> {
|
|
72
|
-
const url = `${this.baseUrl}/v0/radar${path}
|
|
76
|
+
const url = `${this.baseUrl}/v0/radar${path}`;
|
|
73
77
|
const params = {
|
|
74
78
|
method,
|
|
75
79
|
body: body ? JSON.stringify(body) : null,
|
|
@@ -77,28 +81,28 @@ export class ApiService {
|
|
|
77
81
|
'Content-Type': 'application/json',
|
|
78
82
|
...(this.config?.apiKey && { 'X-Api-Key': this.config.apiKey }),
|
|
79
83
|
},
|
|
80
|
-
}
|
|
84
|
+
};
|
|
81
85
|
|
|
82
86
|
try {
|
|
83
87
|
const response = await fetch(url, {
|
|
84
88
|
...params,
|
|
85
89
|
signal,
|
|
86
|
-
})
|
|
90
|
+
});
|
|
87
91
|
|
|
88
92
|
if (!response.ok) {
|
|
89
|
-
throw new Error('Network response was not ok: ' + response.statusText)
|
|
93
|
+
throw new Error('Network response was not ok: ' + response.statusText);
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
if (response.status === 204) {
|
|
93
|
-
return null
|
|
97
|
+
return null;
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
return await response.json()
|
|
100
|
+
return await response.json();
|
|
97
101
|
} catch (error: any) {
|
|
98
102
|
if (error?.name === 'AbortError') {
|
|
99
|
-
throw new Error('Request aborted')
|
|
103
|
+
throw new Error('Request aborted');
|
|
100
104
|
}
|
|
101
|
-
throw new Error('Error making request: ' + error.message)
|
|
105
|
+
throw new Error('Error making request: ' + error.message);
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
108
|
|
|
@@ -109,18 +113,18 @@ export class ApiService {
|
|
|
109
113
|
*/
|
|
110
114
|
async startSession(
|
|
111
115
|
request: StartSessionRequest,
|
|
112
|
-
signal?: AbortSignal
|
|
116
|
+
signal?: AbortSignal
|
|
113
117
|
): Promise<any> {
|
|
114
118
|
try {
|
|
115
119
|
const res = await this.makeRequest(
|
|
116
120
|
'/debug-sessions/start',
|
|
117
121
|
'POST',
|
|
118
122
|
request,
|
|
119
|
-
signal
|
|
120
|
-
)
|
|
121
|
-
return res
|
|
123
|
+
signal
|
|
124
|
+
);
|
|
125
|
+
return res;
|
|
122
126
|
} catch (error: any) {
|
|
123
|
-
throw error
|
|
127
|
+
throw error;
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
|
|
@@ -131,13 +135,13 @@ export class ApiService {
|
|
|
131
135
|
*/
|
|
132
136
|
async stopSession(
|
|
133
137
|
sessionId: string,
|
|
134
|
-
request: StopSessionRequest
|
|
138
|
+
request: StopSessionRequest
|
|
135
139
|
): Promise<any> {
|
|
136
140
|
return this.makeRequest(
|
|
137
141
|
`/debug-sessions/${sessionId}/stop`,
|
|
138
142
|
'PATCH',
|
|
139
|
-
request
|
|
140
|
-
)
|
|
143
|
+
request
|
|
144
|
+
);
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
/**
|
|
@@ -145,10 +149,7 @@ export class ApiService {
|
|
|
145
149
|
* @param sessionId - ID of the session to cancel
|
|
146
150
|
*/
|
|
147
151
|
async cancelSession(sessionId: string): Promise<any> {
|
|
148
|
-
return this.makeRequest(
|
|
149
|
-
`/debug-sessions/${sessionId}/cancel`,
|
|
150
|
-
'DELETE',
|
|
151
|
-
)
|
|
152
|
+
return this.makeRequest(`/debug-sessions/${sessionId}/cancel`, 'DELETE');
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
/**
|
|
@@ -158,14 +159,14 @@ export class ApiService {
|
|
|
158
159
|
*/
|
|
159
160
|
async startContinuousDebugSession(
|
|
160
161
|
request: StartSessionRequest,
|
|
161
|
-
signal?: AbortSignal
|
|
162
|
+
signal?: AbortSignal
|
|
162
163
|
): Promise<any> {
|
|
163
164
|
return this.makeRequest(
|
|
164
165
|
'/continuous-debug-sessions/start',
|
|
165
166
|
'POST',
|
|
166
167
|
request,
|
|
167
|
-
signal
|
|
168
|
-
)
|
|
168
|
+
signal
|
|
169
|
+
);
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
/**
|
|
@@ -177,14 +178,14 @@ export class ApiService {
|
|
|
177
178
|
async saveContinuousDebugSession(
|
|
178
179
|
sessionId: string,
|
|
179
180
|
request: StartSessionRequest,
|
|
180
|
-
signal?: AbortSignal
|
|
181
|
+
signal?: AbortSignal
|
|
181
182
|
): Promise<any> {
|
|
182
183
|
return this.makeRequest(
|
|
183
184
|
`/continuous-debug-sessions/${sessionId}/save`,
|
|
184
185
|
'POST',
|
|
185
186
|
request,
|
|
186
|
-
signal
|
|
187
|
-
)
|
|
187
|
+
signal
|
|
188
|
+
);
|
|
188
189
|
}
|
|
189
190
|
|
|
190
191
|
/**
|
|
@@ -194,8 +195,8 @@ export class ApiService {
|
|
|
194
195
|
async stopContinuousDebugSession(sessionId: string): Promise<any> {
|
|
195
196
|
return this.makeRequest(
|
|
196
197
|
`/continuous-debug-sessions/${sessionId}/cancel`,
|
|
197
|
-
'DELETE'
|
|
198
|
-
)
|
|
198
|
+
'DELETE'
|
|
199
|
+
);
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
/**
|
|
@@ -203,13 +204,13 @@ export class ApiService {
|
|
|
203
204
|
*/
|
|
204
205
|
async checkRemoteSession(
|
|
205
206
|
requestBody: StartSessionRequest,
|
|
206
|
-
signal?: AbortSignal
|
|
207
|
+
signal?: AbortSignal
|
|
207
208
|
): Promise<{ state: 'START' | 'STOP' }> {
|
|
208
209
|
return this.makeRequest(
|
|
209
210
|
'/remote-debug-session/check',
|
|
210
211
|
'POST',
|
|
211
212
|
requestBody,
|
|
212
|
-
signal
|
|
213
|
-
)
|
|
213
|
+
signal
|
|
214
|
+
);
|
|
214
215
|
}
|
|
215
216
|
}
|
|
@@ -1,45 +1,46 @@
|
|
|
1
|
-
import { Platform } from 'react-native'
|
|
2
|
-
import { logger } from '../utils'
|
|
3
|
-
import { sessionRecorderStore } from '../context/SessionRecorderStore'
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { logger } from '../utils';
|
|
3
|
+
import { sessionRecorderStore } from '../context/SessionRecorderStore';
|
|
4
4
|
|
|
5
5
|
// Safe import for NetInfo with web fallback
|
|
6
|
-
let NetInfo: any = null
|
|
7
|
-
const isWeb = Platform.OS === 'web'
|
|
6
|
+
let NetInfo: any = null;
|
|
7
|
+
const isWeb = Platform.OS === 'web';
|
|
8
8
|
|
|
9
9
|
if (!isWeb) {
|
|
10
10
|
try {
|
|
11
|
-
NetInfo = require('@react-native-community/netinfo').default
|
|
11
|
+
NetInfo = require('@react-native-community/netinfo').default;
|
|
12
12
|
} catch (error) {
|
|
13
|
-
console.warn('NetInfo not available:', error)
|
|
13
|
+
console.warn('NetInfo not available:', error);
|
|
14
14
|
}
|
|
15
15
|
} else {
|
|
16
16
|
// Web fallback using navigator.onLine
|
|
17
17
|
NetInfo = {
|
|
18
|
-
fetch: () =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
fetch: () =>
|
|
19
|
+
Promise.resolve({
|
|
20
|
+
isConnected: true, // Default to connected for web
|
|
21
|
+
type: 'unknown',
|
|
22
|
+
isInternetReachable: true,
|
|
23
|
+
}),
|
|
23
24
|
addEventListener: (_callback: (state: any) => void) => {
|
|
24
25
|
// Return a no-op function for web
|
|
25
|
-
return () => {
|
|
26
|
-
}
|
|
27
|
-
}
|
|
26
|
+
return () => {};
|
|
27
|
+
},
|
|
28
|
+
};
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export interface NetworkState {
|
|
31
|
-
isConnected: boolean
|
|
32
|
-
type: string | null
|
|
33
|
-
isInternetReachable: boolean | null
|
|
32
|
+
isConnected: boolean;
|
|
33
|
+
type: string | null;
|
|
34
|
+
isInternetReachable: boolean | null;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
export type NetworkStateChangeCallback = (state: NetworkState) => void
|
|
37
|
+
export type NetworkStateChangeCallback = (state: NetworkState) => void;
|
|
37
38
|
|
|
38
39
|
export class NetworkService {
|
|
39
|
-
private static instance: NetworkService | null = null
|
|
40
|
-
private _isOnline = true
|
|
41
|
-
private unsubscribe: (() => void) | null = null
|
|
42
|
-
private callbacks: NetworkStateChangeCallback[] = []
|
|
40
|
+
private static instance: NetworkService | null = null;
|
|
41
|
+
private _isOnline = true;
|
|
42
|
+
private unsubscribe: (() => void) | null = null;
|
|
43
|
+
private callbacks: NetworkStateChangeCallback[] = [];
|
|
43
44
|
|
|
44
45
|
private constructor() {
|
|
45
46
|
// Private constructor for singleton
|
|
@@ -47,9 +48,9 @@ export class NetworkService {
|
|
|
47
48
|
|
|
48
49
|
static getInstance(): NetworkService {
|
|
49
50
|
if (!NetworkService.instance) {
|
|
50
|
-
NetworkService.instance = new NetworkService()
|
|
51
|
+
NetworkService.instance = new NetworkService();
|
|
51
52
|
}
|
|
52
|
-
return NetworkService.instance
|
|
53
|
+
return NetworkService.instance;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
/**
|
|
@@ -58,45 +59,49 @@ export class NetworkService {
|
|
|
58
59
|
async init(): Promise<void> {
|
|
59
60
|
try {
|
|
60
61
|
// Get initial network state
|
|
61
|
-
const initialState = await NetInfo.fetch()
|
|
62
|
-
this._isOnline = initialState.isConnected ?? true
|
|
62
|
+
const initialState = await NetInfo.fetch();
|
|
63
|
+
this._isOnline = initialState.isConnected ?? true;
|
|
63
64
|
|
|
64
65
|
// Update store with initial state
|
|
65
|
-
sessionRecorderStore.setState({ isOnline: this._isOnline })
|
|
66
|
+
sessionRecorderStore.setState({ isOnline: this._isOnline });
|
|
66
67
|
|
|
67
68
|
// Notify callbacks
|
|
68
69
|
this.notifyCallbacks({
|
|
69
70
|
isConnected: this._isOnline,
|
|
70
71
|
type: initialState.type,
|
|
71
72
|
isInternetReachable: initialState.isInternetReachable,
|
|
72
|
-
})
|
|
73
|
+
});
|
|
73
74
|
|
|
74
75
|
// Listen for network state changes
|
|
75
76
|
this.unsubscribe = NetInfo.addEventListener((state: any) => {
|
|
76
|
-
const wasOnline = this._isOnline
|
|
77
|
-
this._isOnline = state.isConnected ?? true
|
|
77
|
+
const wasOnline = this._isOnline;
|
|
78
|
+
this._isOnline = state.isConnected ?? true;
|
|
78
79
|
|
|
79
80
|
// Update store
|
|
80
|
-
sessionRecorderStore.setState({ isOnline: this._isOnline })
|
|
81
|
+
sessionRecorderStore.setState({ isOnline: this._isOnline });
|
|
81
82
|
|
|
82
83
|
// Notify callbacks
|
|
83
84
|
this.notifyCallbacks({
|
|
84
85
|
isConnected: this._isOnline,
|
|
85
86
|
type: state.type,
|
|
86
87
|
isInternetReachable: state.isInternetReachable,
|
|
87
|
-
})
|
|
88
|
+
});
|
|
88
89
|
|
|
89
90
|
// Log state changes
|
|
90
91
|
if (wasOnline && !this._isOnline) {
|
|
91
|
-
logger.info('NetworkService', 'Network went offline')
|
|
92
|
+
logger.info('NetworkService', 'Network went offline');
|
|
92
93
|
} else if (!wasOnline && this._isOnline) {
|
|
93
|
-
logger.info('NetworkService', 'Network came back online')
|
|
94
|
+
logger.info('NetworkService', 'Network came back online');
|
|
94
95
|
}
|
|
95
|
-
})
|
|
96
|
+
});
|
|
96
97
|
|
|
97
|
-
logger.info('NetworkService', 'Network monitoring initialized')
|
|
98
|
+
logger.info('NetworkService', 'Network monitoring initialized');
|
|
98
99
|
} catch (error) {
|
|
99
|
-
logger.error(
|
|
100
|
+
logger.error(
|
|
101
|
+
'NetworkService',
|
|
102
|
+
'Failed to initialize network monitoring',
|
|
103
|
+
error
|
|
104
|
+
);
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
|
|
@@ -108,41 +113,45 @@ export class NetworkService {
|
|
|
108
113
|
isConnected: this._isOnline,
|
|
109
114
|
type: null, // We don't store this in the service
|
|
110
115
|
isInternetReachable: null, // We don't store this in the service
|
|
111
|
-
}
|
|
116
|
+
};
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
/**
|
|
115
120
|
* Check if device is online
|
|
116
121
|
*/
|
|
117
122
|
isOnline(): boolean {
|
|
118
|
-
return this._isOnline
|
|
123
|
+
return this._isOnline;
|
|
119
124
|
}
|
|
120
125
|
|
|
121
126
|
/**
|
|
122
127
|
* Add callback for network state changes
|
|
123
128
|
*/
|
|
124
129
|
addCallback(callback: NetworkStateChangeCallback): void {
|
|
125
|
-
this.callbacks.push(callback)
|
|
130
|
+
this.callbacks.push(callback);
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
/**
|
|
129
134
|
* Remove callback for network state changes
|
|
130
135
|
*/
|
|
131
136
|
removeCallback(callback: NetworkStateChangeCallback): void {
|
|
132
|
-
this.callbacks = this.callbacks.filter(cb => cb !== callback)
|
|
137
|
+
this.callbacks = this.callbacks.filter((cb) => cb !== callback);
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
/**
|
|
136
141
|
* Notify all callbacks of network state change
|
|
137
142
|
*/
|
|
138
143
|
private notifyCallbacks(state: NetworkState): void {
|
|
139
|
-
this.callbacks.forEach(callback => {
|
|
144
|
+
this.callbacks.forEach((callback) => {
|
|
140
145
|
try {
|
|
141
|
-
callback(state)
|
|
146
|
+
callback(state);
|
|
142
147
|
} catch (error) {
|
|
143
|
-
logger.error(
|
|
148
|
+
logger.error(
|
|
149
|
+
'NetworkService',
|
|
150
|
+
'Error in network state callback',
|
|
151
|
+
error
|
|
152
|
+
);
|
|
144
153
|
}
|
|
145
|
-
})
|
|
154
|
+
});
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
/**
|
|
@@ -150,11 +159,11 @@ export class NetworkService {
|
|
|
150
159
|
*/
|
|
151
160
|
cleanup(): void {
|
|
152
161
|
if (this.unsubscribe) {
|
|
153
|
-
this.unsubscribe()
|
|
154
|
-
this.unsubscribe = null
|
|
162
|
+
this.unsubscribe();
|
|
163
|
+
this.unsubscribe = null;
|
|
155
164
|
}
|
|
156
|
-
this.callbacks = []
|
|
157
|
-
logger.info('NetworkService', 'Network monitoring cleaned up')
|
|
165
|
+
this.callbacks = [];
|
|
166
|
+
logger.info('NetworkService', 'Network monitoring cleaned up');
|
|
158
167
|
}
|
|
159
168
|
|
|
160
169
|
/**
|
|
@@ -162,21 +171,21 @@ export class NetworkService {
|
|
|
162
171
|
*/
|
|
163
172
|
async refresh(): Promise<NetworkState> {
|
|
164
173
|
try {
|
|
165
|
-
const state = await NetInfo.fetch()
|
|
166
|
-
this._isOnline = state.isConnected ?? true
|
|
167
|
-
sessionRecorderStore.setState({ isOnline: this._isOnline })
|
|
174
|
+
const state = await NetInfo.fetch();
|
|
175
|
+
this._isOnline = state.isConnected ?? true;
|
|
176
|
+
sessionRecorderStore.setState({ isOnline: this._isOnline });
|
|
168
177
|
|
|
169
178
|
const networkState: NetworkState = {
|
|
170
179
|
isConnected: this._isOnline,
|
|
171
180
|
type: state.type,
|
|
172
181
|
isInternetReachable: state.isInternetReachable,
|
|
173
|
-
}
|
|
182
|
+
};
|
|
174
183
|
|
|
175
|
-
this.notifyCallbacks(networkState)
|
|
176
|
-
return networkState
|
|
184
|
+
this.notifyCallbacks(networkState);
|
|
185
|
+
return networkState;
|
|
177
186
|
} catch (error) {
|
|
178
|
-
logger.error('NetworkService', 'Failed to refresh network state', error)
|
|
179
|
-
throw error
|
|
187
|
+
logger.error('NetworkService', 'Failed to refresh network state', error);
|
|
188
|
+
throw error;
|
|
180
189
|
}
|
|
181
190
|
}
|
|
182
191
|
}
|
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
import SessionRecorderNative, {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import SessionRecorderNative, {
|
|
2
|
+
type MaskingOptions,
|
|
3
|
+
} from '../native/SessionRecorderNative';
|
|
4
|
+
import { logger } from '../utils';
|
|
4
5
|
|
|
5
6
|
export interface ScreenMaskingConfig {
|
|
6
7
|
/** Whether screen masking is enabled */
|
|
7
|
-
enabled: boolean
|
|
8
|
+
enabled: boolean;
|
|
8
9
|
/** Whether to mask text inputs (UITextField, UITextView, React Native text components) */
|
|
9
|
-
maskTextInputs?: boolean
|
|
10
|
+
maskTextInputs?: boolean;
|
|
10
11
|
/** Whether to mask images (UIImageView, React Native Image components) */
|
|
11
|
-
maskImages?: boolean
|
|
12
|
+
maskImages?: boolean;
|
|
12
13
|
/** Whether to mask buttons (UIButton) */
|
|
13
|
-
maskButtons?: boolean
|
|
14
|
+
maskButtons?: boolean;
|
|
14
15
|
/** Whether to mask labels (UILabel) */
|
|
15
|
-
maskLabels?: boolean
|
|
16
|
+
maskLabels?: boolean;
|
|
16
17
|
/** Whether to mask web views (WKWebView) */
|
|
17
|
-
maskWebViews?: boolean
|
|
18
|
+
maskWebViews?: boolean;
|
|
18
19
|
/** Whether to mask sandboxed views (system views that don't belong to current process) */
|
|
19
|
-
maskSandboxedViews?: boolean
|
|
20
|
+
maskSandboxedViews?: boolean;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export class ScreenMaskingService {
|
|
23
|
-
private config: ScreenMaskingConfig
|
|
24
|
-
private isAvailable: boolean = false
|
|
24
|
+
private config: ScreenMaskingConfig;
|
|
25
|
+
private isAvailable: boolean = false;
|
|
25
26
|
|
|
26
|
-
constructor(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
constructor(
|
|
28
|
+
config: ScreenMaskingConfig = {
|
|
29
|
+
enabled: true,
|
|
30
|
+
maskTextInputs: true,
|
|
31
|
+
maskImages: false,
|
|
32
|
+
maskButtons: false,
|
|
33
|
+
maskLabels: false,
|
|
34
|
+
maskWebViews: false,
|
|
35
|
+
maskSandboxedViews: false,
|
|
36
|
+
}
|
|
37
|
+
) {
|
|
38
|
+
this.config = config;
|
|
39
|
+
this.checkAvailability();
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
/**
|
|
@@ -42,17 +45,29 @@ export class ScreenMaskingService {
|
|
|
42
45
|
private checkAvailability(): void {
|
|
43
46
|
try {
|
|
44
47
|
// Try to access the native module to check if it's available
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
if (
|
|
49
|
+
SessionRecorderNative &&
|
|
50
|
+
typeof SessionRecorderNative.captureAndMask === 'function'
|
|
51
|
+
) {
|
|
52
|
+
this.isAvailable = true;
|
|
53
|
+
logger.info(
|
|
54
|
+
'ScreenMaskingService',
|
|
55
|
+
'Screen masking native module is available'
|
|
56
|
+
);
|
|
48
57
|
} else {
|
|
49
|
-
this.isAvailable = false
|
|
50
|
-
logger.warn(
|
|
51
|
-
|
|
58
|
+
this.isAvailable = false;
|
|
59
|
+
logger.warn(
|
|
60
|
+
'ScreenMaskingService',
|
|
61
|
+
'Screen masking native module is not available - auto-linking may still be in progress'
|
|
62
|
+
);
|
|
52
63
|
}
|
|
53
64
|
} catch (error) {
|
|
54
|
-
this.isAvailable = false
|
|
55
|
-
logger.error(
|
|
65
|
+
this.isAvailable = false;
|
|
66
|
+
logger.error(
|
|
67
|
+
'ScreenMaskingService',
|
|
68
|
+
'Error checking screen masking availability:',
|
|
69
|
+
error
|
|
70
|
+
);
|
|
56
71
|
}
|
|
57
72
|
}
|
|
58
73
|
|
|
@@ -61,19 +76,28 @@ export class ScreenMaskingService {
|
|
|
61
76
|
*/
|
|
62
77
|
async captureMaskedScreen(options: MaskingOptions): Promise<string | null> {
|
|
63
78
|
if (!this.isAvailable || !this.config.enabled) {
|
|
64
|
-
logger.warn(
|
|
65
|
-
|
|
79
|
+
logger.warn(
|
|
80
|
+
'ScreenMaskingService',
|
|
81
|
+
'Screen masking is not available or disabled'
|
|
82
|
+
);
|
|
83
|
+
return null;
|
|
66
84
|
}
|
|
67
85
|
|
|
68
86
|
try {
|
|
69
87
|
const maskingOptions: MaskingOptions = {
|
|
70
|
-
...this.config,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
88
|
+
...this.config,
|
|
89
|
+
...options,
|
|
90
|
+
};
|
|
91
|
+
const maskedImageBase64 =
|
|
92
|
+
await SessionRecorderNative.captureAndMaskWithOptions(maskingOptions);
|
|
93
|
+
return maskedImageBase64;
|
|
74
94
|
} catch (error) {
|
|
75
|
-
logger.error(
|
|
76
|
-
|
|
95
|
+
logger.error(
|
|
96
|
+
'ScreenMaskingService',
|
|
97
|
+
'Failed to capture masked screen:',
|
|
98
|
+
error
|
|
99
|
+
);
|
|
100
|
+
return null;
|
|
77
101
|
}
|
|
78
102
|
}
|
|
79
103
|
|
|
@@ -82,16 +106,23 @@ export class ScreenMaskingService {
|
|
|
82
106
|
*/
|
|
83
107
|
async captureMaskedScreenBasic(): Promise<string | null> {
|
|
84
108
|
if (!this.isAvailable || !this.config.enabled) {
|
|
85
|
-
logger.warn(
|
|
86
|
-
|
|
109
|
+
logger.warn(
|
|
110
|
+
'ScreenMaskingService',
|
|
111
|
+
'Screen masking is not available or disabled'
|
|
112
|
+
);
|
|
113
|
+
return null;
|
|
87
114
|
}
|
|
88
115
|
|
|
89
116
|
try {
|
|
90
|
-
const maskedImageBase64 = await SessionRecorderNative.captureAndMask()
|
|
91
|
-
return maskedImageBase64
|
|
117
|
+
const maskedImageBase64 = await SessionRecorderNative.captureAndMask();
|
|
118
|
+
return maskedImageBase64;
|
|
92
119
|
} catch (error) {
|
|
93
|
-
logger.error(
|
|
94
|
-
|
|
120
|
+
logger.error(
|
|
121
|
+
'ScreenMaskingService',
|
|
122
|
+
'Failed to capture masked screen (basic):',
|
|
123
|
+
error
|
|
124
|
+
);
|
|
125
|
+
return null;
|
|
95
126
|
}
|
|
96
127
|
}
|
|
97
128
|
|
|
@@ -99,24 +130,24 @@ export class ScreenMaskingService {
|
|
|
99
130
|
* Update the masking configuration
|
|
100
131
|
*/
|
|
101
132
|
updateConfig(config: Partial<ScreenMaskingConfig>): void {
|
|
102
|
-
this.config = { ...this.config, ...config }
|
|
103
|
-
logger.info('ScreenMaskingService', 'Screen masking configuration updated')
|
|
133
|
+
this.config = { ...this.config, ...config };
|
|
134
|
+
logger.info('ScreenMaskingService', 'Screen masking configuration updated');
|
|
104
135
|
}
|
|
105
136
|
|
|
106
137
|
/**
|
|
107
138
|
* Check if screen masking is available
|
|
108
139
|
*/
|
|
109
140
|
isScreenMaskingAvailable(): boolean {
|
|
110
|
-
return this.isAvailable && this.config.enabled
|
|
141
|
+
return this.isAvailable && this.config.enabled;
|
|
111
142
|
}
|
|
112
143
|
|
|
113
144
|
/**
|
|
114
145
|
* Get the current configuration
|
|
115
146
|
*/
|
|
116
147
|
getConfig(): ScreenMaskingConfig {
|
|
117
|
-
return { ...this.config }
|
|
148
|
+
return { ...this.config };
|
|
118
149
|
}
|
|
119
150
|
}
|
|
120
151
|
|
|
121
152
|
// Create a singleton instance
|
|
122
|
-
export const screenMaskingService = new ScreenMaskingService()
|
|
153
|
+
export const screenMaskingService = new ScreenMaskingService();
|