@akhilpulse/samadhaan-session-replay 0.3.6 → 0.3.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 +5 -1
- package/package.json +1 -1
- package/src/SessionReplayProvider.tsx +38 -1
package/README.md
CHANGED
|
@@ -27,7 +27,11 @@ export default function App() {
|
|
|
27
27
|
config={{
|
|
28
28
|
// serverUrl is optional — defaults to https://samadhaan.pulseenergy.io
|
|
29
29
|
appId: "app_xxx",
|
|
30
|
-
user
|
|
30
|
+
// `user` can be omitted at first (anonymous) and supplied later once the
|
|
31
|
+
// user logs in. Update the value passed to `config.user` after OTP login
|
|
32
|
+
// and the SDK automatically backfills the session with the phone/name/
|
|
33
|
+
// email — so the dashboard stops showing "Anonymous".
|
|
34
|
+
user: { userId: "user_123", phone: "+91xxxxxxxxxx", email: "user@example.com" },
|
|
31
35
|
appVersion: "1.4.2",
|
|
32
36
|
}}
|
|
33
37
|
>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akhilpulse/samadhaan-session-replay",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "React Native SDK for Samadhaan Guided Support — session recording, live remote screen-share, take-control, and guided-tour overlays.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -47,7 +47,7 @@ const SessionReplayPixelCopy: PixelCopyNative | undefined =
|
|
|
47
47
|
let pixelCopyDisabled = false; // turned true after a runtime failure to avoid retrying every frame
|
|
48
48
|
|
|
49
49
|
const STORAGE_KEY = "@akhilpulse/samadhaan-session-replay/sessionId";
|
|
50
|
-
const SDK_VERSION = "0.3.
|
|
50
|
+
const SDK_VERSION = "0.3.7";
|
|
51
51
|
|
|
52
52
|
// ---- Module-level session singleton --------------------------------------
|
|
53
53
|
// Multiple SessionReplayProvider mounts (intentional or via React StrictMode's
|
|
@@ -240,6 +240,43 @@ export function SessionReplayProvider({ config, children }: { config: Config; ch
|
|
|
240
240
|
return () => { cancelled = true; };
|
|
241
241
|
}, [config.appId, serverUrl, config.appVersion, config.user, initTick]);
|
|
242
242
|
|
|
243
|
+
// ---- Identify: backfill user identity after login ----
|
|
244
|
+
// A session is usually created while the user is still anonymous (e.g. before
|
|
245
|
+
// OTP login). Once the host app supplies user info via config.user, we PATCH
|
|
246
|
+
// the existing session so the dashboard shows the real phone/name/email
|
|
247
|
+
// instead of "Anonymous". We dedupe on the serialized identity so this only
|
|
248
|
+
// fires when the identity actually changes, and retry on failure.
|
|
249
|
+
const lastIdentitySentRef = useRef<string | null>(null);
|
|
250
|
+
const lastIdentitySessionRef = useRef<string | null>(null);
|
|
251
|
+
useEffect(() => {
|
|
252
|
+
if (!sessionId || !ingestToken) return;
|
|
253
|
+
// A recycled session (server idle-end -> new session) must re-send identity,
|
|
254
|
+
// so reset the dedupe key whenever the session id changes.
|
|
255
|
+
if (lastIdentitySessionRef.current !== sessionId) {
|
|
256
|
+
lastIdentitySessionRef.current = sessionId;
|
|
257
|
+
lastIdentitySentRef.current = null;
|
|
258
|
+
}
|
|
259
|
+
const u = config.user;
|
|
260
|
+
if (!u) return;
|
|
261
|
+
const hasIdentity = !!(u.userId || u.userName || u.email || u.phone);
|
|
262
|
+
if (!hasIdentity) return;
|
|
263
|
+
const key = JSON.stringify({ userId: u.userId, userName: u.userName, email: u.email, phone: u.phone, metadata: u.metadata });
|
|
264
|
+
if (lastIdentitySentRef.current === key) return;
|
|
265
|
+
lastIdentitySentRef.current = key;
|
|
266
|
+
fetch(`${serverUrl}/api/guided-support/sessions/${sessionId}`, {
|
|
267
|
+
method: "PATCH",
|
|
268
|
+
headers: { "Content-Type": "application/json", "x-ingest-token": ingestToken },
|
|
269
|
+
body: JSON.stringify({ user: u }),
|
|
270
|
+
}).then((res) => {
|
|
271
|
+
// Treat non-2xx (e.g. transient 401/5xx) as failure so we retry instead
|
|
272
|
+
// of permanently deduping on an identity the server never stored.
|
|
273
|
+
if (!res.ok) lastIdentitySentRef.current = null;
|
|
274
|
+
}).catch(() => {
|
|
275
|
+
// allow retry on the next render/identity change
|
|
276
|
+
lastIdentitySentRef.current = null;
|
|
277
|
+
});
|
|
278
|
+
}, [sessionId, ingestToken, serverUrl, config.user]);
|
|
279
|
+
|
|
243
280
|
// ---- Keyboard tracking (iOS auto-pause) ----
|
|
244
281
|
useEffect(() => {
|
|
245
282
|
const showSub = Keyboard.addListener(Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow", () => setKeyboardVisible(true));
|