@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 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: { userId: "user_123", email: "user@example.com" },
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.6",
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.6";
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));