iidrak-analytics-react 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { strf } from "./string.format.js";
|
|
4
|
-
import
|
|
4
|
+
import { captureRef } from "react-native-view-shot";
|
|
5
5
|
import { Platform, Dimensions } from "react-native";
|
|
6
6
|
|
|
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,6 +24,11 @@ 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
|
+
// 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"));
|
|
31
|
+
this.lastBase64 = null;
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
setSessionId(id) {
|
|
@@ -41,7 +46,7 @@ class MetaStreamIORecorder {
|
|
|
41
46
|
|
|
42
47
|
// 1. Initialize Session on Python Server
|
|
43
48
|
// Note: We use a separate fetch here because the payload format is different from standard analytics
|
|
44
|
-
await fetch(`${this.endpoint}/sessions`, {
|
|
49
|
+
await fetch(`${this.endpoint}/apps/${this.app_id}/sessions`, {
|
|
45
50
|
method: 'POST',
|
|
46
51
|
headers: { 'Content-Type': 'application/json' },
|
|
47
52
|
body: JSON.stringify({
|
|
@@ -84,25 +89,55 @@ class MetaStreamIORecorder {
|
|
|
84
89
|
|
|
85
90
|
startLoop(viewRef) {
|
|
86
91
|
const intervalMs = 1000 / this.fps;
|
|
87
|
-
|
|
92
|
+
this.lastUploadTime = 0;
|
|
93
|
+
console.log("Starting loop");
|
|
88
94
|
this.intervalId = setInterval(async () => {
|
|
89
95
|
if (!viewRef.current) return;
|
|
90
96
|
|
|
91
97
|
try {
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
// Capture as base64 for comparison and direct upload
|
|
99
|
+
// Resize to width 400px (height maintained automatically) to reduce size
|
|
100
|
+
// Use PNG to ensure deterministic output for diffing
|
|
101
|
+
const base64 = await captureRef(viewRef, {
|
|
102
|
+
format: "png",
|
|
94
103
|
quality: this.quality,
|
|
95
|
-
|
|
104
|
+
width: 400,
|
|
105
|
+
result: "base64"
|
|
96
106
|
});
|
|
97
107
|
|
|
98
|
-
|
|
108
|
+
let isDuplicate = false;
|
|
109
|
+
if (this.lastBase64) {
|
|
110
|
+
if (this.lastBase64 === base64) {
|
|
111
|
+
isDuplicate = true;
|
|
112
|
+
console.log("DBG:: Duplicate frame");
|
|
113
|
+
} else {
|
|
114
|
+
console.log("DBG:: New frame");
|
|
115
|
+
this.lastBase64 = base64;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
// Logic:
|
|
121
|
+
// If NEW frame: Upload immediately.
|
|
122
|
+
// If DUPLICATE frame:
|
|
123
|
+
// Only upload if it's been > 5 seconds since last upload (Keepalive)
|
|
124
|
+
// This reduces chatter significantly.
|
|
125
|
+
|
|
126
|
+
const timeSinceLastUpload = (now - this.lastUploadTime) / 1000;
|
|
127
|
+
|
|
128
|
+
if (!isDuplicate || timeSinceLastUpload > 5.0) {
|
|
129
|
+
console.log("DBG:: Uploading frame");
|
|
130
|
+
this.uploadFrame(base64, isDuplicate);
|
|
131
|
+
this.lastUploadTime = now;
|
|
132
|
+
this.lastBase64 = base64;
|
|
133
|
+
}
|
|
99
134
|
} catch (e) {
|
|
100
135
|
// Silent fail on capture error to avoid log spam
|
|
101
136
|
}
|
|
102
137
|
}, intervalMs);
|
|
103
138
|
}
|
|
104
139
|
|
|
105
|
-
async uploadFrame(
|
|
140
|
+
async uploadFrame(data, isDuplicate) {
|
|
106
141
|
if (!this.recorderSessionId) return;
|
|
107
142
|
|
|
108
143
|
const formData = new FormData();
|
|
@@ -111,14 +146,19 @@ class MetaStreamIORecorder {
|
|
|
111
146
|
|
|
112
147
|
formData.append('timestamp', String(timestamp));
|
|
113
148
|
formData.append('duration', String(duration));
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
149
|
+
|
|
150
|
+
if (isDuplicate) {
|
|
151
|
+
formData.append('is_duplicate', 'true');
|
|
152
|
+
} else {
|
|
153
|
+
formData.append('file', {
|
|
154
|
+
uri: 'data:image/png;base64,' + data,
|
|
155
|
+
type: 'image/png',
|
|
156
|
+
name: 'screenshot.png',
|
|
157
|
+
});
|
|
158
|
+
}
|
|
119
159
|
|
|
120
160
|
try {
|
|
121
|
-
await fetch(`${this.endpoint}/sessions/${this.recorderSessionId}/screenshot`, {
|
|
161
|
+
await fetch(`${this.endpoint}/apps/${this.app_id}/sessions/${this.recorderSessionId}/screenshot`, {
|
|
122
162
|
method: 'POST',
|
|
123
163
|
body: formData,
|
|
124
164
|
headers: {
|
|
@@ -145,7 +185,7 @@ class MetaStreamIORecorder {
|
|
|
145
185
|
};
|
|
146
186
|
|
|
147
187
|
try {
|
|
148
|
-
fetch(`${this.endpoint}/sessions/${this.recorderSessionId}/events`, {
|
|
188
|
+
fetch(`${this.endpoint}/apps/${this.app_id}/sessions/${this.recorderSessionId}/events`, {
|
|
149
189
|
method: 'POST',
|
|
150
190
|
headers: { 'Content-Type': 'application/json' },
|
|
151
191
|
body: JSON.stringify([event])
|
|
@@ -8,6 +8,7 @@ export class ConfigConstructorModel {
|
|
|
8
8
|
sessionLength = null,
|
|
9
9
|
silentMode = null,
|
|
10
10
|
allowTrackCategories = [],
|
|
11
|
+
appName = null,
|
|
11
12
|
} = {}) {
|
|
12
13
|
this.logging = logging;
|
|
13
14
|
this.loggingLevel = loggingLevel;
|
|
@@ -17,6 +18,7 @@ export class ConfigConstructorModel {
|
|
|
17
18
|
this.sessionLength = sessionLength;
|
|
18
19
|
this.silentMode = silentMode;
|
|
19
20
|
this.allowTrackCategories = allowTrackCategories;
|
|
21
|
+
this.appName = appName;
|
|
20
22
|
}
|
|
21
23
|
json() {
|
|
22
24
|
return {
|