iidrak-analytics-react 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -58,6 +58,9 @@ const iidrakConfig = {
58
58
 
59
59
  // SDK Configuration
60
60
  config: {
61
+ // Application Name for Session Grouping (Recommended)
62
+ appName: "your-app-name",
63
+
61
64
  // Session Replay Endpoint (Required to enable recording)
62
65
  recordingEndpoint: "https://your-replay-server.com",
63
66
 
@@ -161,6 +164,11 @@ If you see this error, it means the native module `react-native-device-info` is
161
164
  1. Ensure you installed the peer dependency: `npm install react-native-device-info`
162
165
  2. Rebuild your native app: `cd android && ./gradlew clean && cd .. && npx react-native run-android`
163
166
 
167
+ ### "Network request failed" on Android
168
+ If your backend is running on HTTP (not HTTPS), Android will block the connection by default.
169
+ 1. Create a `network_security_config.xml` in `android/app/src/main/res/xml/` allowing cleartext traffic for your domain/IP.
170
+ 2. Or for development, add `android:usesCleartextTraffic="true"` to your `AndroidManifest.xml` `<application>` tag.
171
+
164
172
  ### "Cannot read property 'MetaStreamProvider' of undefined"
165
173
  Ensure you are importing correctly.
166
174
  Correct: `import { MetaStreamProvider } from 'iidrak-analytics-react';`
@@ -114,6 +114,7 @@ class MetaStreamIO {
114
114
  logger: this.logger,
115
115
  network: this.network,
116
116
  config: this.config,
117
+ user: this.userConfig,
117
118
  });
118
119
 
119
120
  // Init global variables
@@ -7,7 +7,7 @@ import { Platform, Dimensions } from "react-native";
7
7
  strf();
8
8
 
9
9
  class MetaStreamIORecorder {
10
- constructor({ constants, logger, network, config } = {}) {
10
+ constructor({ constants, logger, network, config, user } = {}) {
11
11
  this.constant = constants;
12
12
  this.logger = logger;
13
13
  this.network = network;
@@ -24,7 +24,10 @@ class MetaStreamIORecorder {
24
24
  // Use lower quality by default to save bandwidth
25
25
  this.quality = config.quality || 0.5;
26
26
  this.fps = config.fps || 2; // Frames per second (0.5s interval)
27
- this.app_id = config.app_id || "default"; // Default to 'default' app if not specified
27
+ // If user_id is provided in user config, use it as app_id (per user requirement)
28
+ // Otherwise fallback to app_id in general config or "default"
29
+ // Priority: config.appName > user.user_id > config.app_id > "default"
30
+ this.app_id = config.appName ? config.appName : ((user && user.user_id) ? user.user_id : (config.app_id || "default"));
28
31
  this.lastBase64 = null;
29
32
  }
30
33
 
@@ -43,10 +46,13 @@ class MetaStreamIORecorder {
43
46
 
44
47
  // 1. Initialize Session on Python Server
45
48
  // Note: We use a separate fetch here because the payload format is different from standard analytics
46
- await fetch(`${this.endpoint}/apps/${this.app_id}/sessions`, {
49
+ const url = `${this.endpoint}/api/apps/${this.app_id}/sessions`;
50
+ this.logger.log("recorder", `Sending session creation request to: ${url}`);
51
+ await fetch(url, {
47
52
  method: 'POST',
48
53
  headers: { 'Content-Type': 'application/json' },
49
54
  body: JSON.stringify({
55
+ session_id: this.sessionId,
50
56
  device_info: {
51
57
  width: Dimensions.get('window').width,
52
58
  height: Dimensions.get('window').height,
@@ -55,19 +61,19 @@ class MetaStreamIORecorder {
55
61
  }
56
62
  })
57
63
  }).then(async res => {
64
+ this.logger.log("recorder", "Session creation response status: " + res.status);
58
65
  if (res.ok) {
59
66
  const data = await res.json();
60
67
  // Server might return its own ID, but we want to map them.
61
- // For simplicity, we assume server respects ours or we track the mapping.
62
- // In this demo, the server generates a timestamp ID. That's fine.
63
68
  this.recorderSessionId = data.session_id;
64
69
  this.isRecording = true;
65
70
  this.startLoop(viewRef);
71
+ this.logger.log("recorder", "Session created successfully with ID: " + this.recorderSessionId);
66
72
  } else {
67
- this.logger.error("recorder", "Failed to start session on recording server");
73
+ this.logger.error("recorder", "Failed to start session on recording server: " + res.status);
68
74
  }
69
- }).catch(err => {
70
- this.logger.error("recorder", "Connection error to recording server: " + err);
75
+ }).catch(e => {
76
+ this.logger.error("recorder", "Connection error to recording server: " + e + " to " + url);
71
77
  });
72
78
 
73
79
  } catch (err) {
@@ -103,11 +109,11 @@ class MetaStreamIORecorder {
103
109
  });
104
110
 
105
111
  let isDuplicate = false;
106
- if(this.lastBase64){
112
+ if (this.lastBase64) {
107
113
  if (this.lastBase64 === base64) {
108
114
  isDuplicate = true;
109
115
  console.log("DBG:: Duplicate frame");
110
- }else{
116
+ } else {
111
117
  console.log("DBG:: New frame");
112
118
  this.lastBase64 = base64;
113
119
  }
@@ -119,9 +125,9 @@ class MetaStreamIORecorder {
119
125
  // If DUPLICATE frame:
120
126
  // Only upload if it's been > 5 seconds since last upload (Keepalive)
121
127
  // This reduces chatter significantly.
122
-
128
+
123
129
  const timeSinceLastUpload = (now - this.lastUploadTime) / 1000;
124
-
130
+
125
131
  if (!isDuplicate || timeSinceLastUpload > 5.0) {
126
132
  console.log("DBG:: Uploading frame");
127
133
  this.uploadFrame(base64, isDuplicate);
@@ -143,7 +149,7 @@ class MetaStreamIORecorder {
143
149
 
144
150
  formData.append('timestamp', String(timestamp));
145
151
  formData.append('duration', String(duration));
146
-
152
+
147
153
  if (isDuplicate) {
148
154
  formData.append('is_duplicate', 'true');
149
155
  } else {
@@ -155,7 +161,7 @@ class MetaStreamIORecorder {
155
161
  }
156
162
 
157
163
  try {
158
- await fetch(`${this.endpoint}/apps/${this.app_id}/sessions/${this.recorderSessionId}/screenshot`, {
164
+ await fetch(`${this.endpoint}/api/apps/${this.app_id}/sessions/${this.recorderSessionId}/screenshot`, {
159
165
  method: 'POST',
160
166
  body: formData,
161
167
  headers: {
@@ -182,7 +188,7 @@ class MetaStreamIORecorder {
182
188
  };
183
189
 
184
190
  try {
185
- fetch(`${this.endpoint}/apps/${this.app_id}/sessions/${this.recorderSessionId}/events`, {
191
+ fetch(`${this.endpoint}/api/apps/${this.app_id}/sessions/${this.recorderSessionId}/events`, {
186
192
  method: 'POST',
187
193
  headers: { 'Content-Type': 'application/json' },
188
194
  body: JSON.stringify([event])
@@ -8,6 +8,10 @@ export class ConfigConstructorModel {
8
8
  sessionLength = null,
9
9
  silentMode = null,
10
10
  allowTrackCategories = [],
11
+ appName = null,
12
+ quality = null,
13
+ fps = null,
14
+ recordingEndpoint = null,
11
15
  } = {}) {
12
16
  this.logging = logging;
13
17
  this.loggingLevel = loggingLevel;
@@ -17,6 +21,11 @@ export class ConfigConstructorModel {
17
21
  this.sessionLength = sessionLength;
18
22
  this.silentMode = silentMode;
19
23
  this.allowTrackCategories = allowTrackCategories;
24
+ // correctly assign appName
25
+ this.appName = appName;
26
+ this.quality = quality;
27
+ this.fps = fps;
28
+ this.recordingEndpoint = recordingEndpoint;
20
29
  }
21
30
  json() {
22
31
  return {
@@ -28,6 +37,10 @@ export class ConfigConstructorModel {
28
37
  sessionLength: this.sessionLength,
29
38
  silentMode: this.silentMode,
30
39
  allowTrackCategories: this.allowTrackCategories,
40
+ appName: this.appName,
41
+ quality: this.quality,
42
+ fps: this.fps,
43
+ recordingEndpoint: this.recordingEndpoint,
31
44
  };
32
45
  }
33
46
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iidrak-analytics-react",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "react native client for metastreamio",
5
5
  "peerDependencies": {
6
6
  "@react-native-async-storage/async-storage": ">=2.2.0",