@akhilpulse/samadhaan-session-replay 0.2.5 → 0.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/package.json +1 -1
- package/src/SessionReplayProvider.tsx +67 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akhilpulse/samadhaan-session-replay",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.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",
|
|
@@ -30,12 +30,13 @@ import {
|
|
|
30
30
|
UIManager,
|
|
31
31
|
findNodeHandle,
|
|
32
32
|
StyleSheet,
|
|
33
|
+
Pressable,
|
|
33
34
|
} from "react-native";
|
|
34
35
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
35
36
|
import { captureRef } from "react-native-view-shot";
|
|
36
37
|
|
|
37
38
|
const STORAGE_KEY = "@akhilpulse/samadhaan-session-replay/sessionId";
|
|
38
|
-
const SDK_VERSION = "0.2.
|
|
39
|
+
const SDK_VERSION = "0.2.6";
|
|
39
40
|
|
|
40
41
|
/** Default Samadhaan production endpoint. Override via `config.serverUrl` for staging. */
|
|
41
42
|
export const DEFAULT_SERVER_URL = "https://samadhaan.pulseenergy.io";
|
|
@@ -412,28 +413,43 @@ export function SessionReplayProvider({ config, children }: { config: Config; ch
|
|
|
412
413
|
/>
|
|
413
414
|
))}
|
|
414
415
|
|
|
415
|
-
{/* Guided tour consent —
|
|
416
|
+
{/* Guided tour consent — centered modal card with backdrop */}
|
|
416
417
|
{tourActiveHere.current && tourState.phase === "consent" && (
|
|
417
|
-
<View style={styles.
|
|
418
|
-
<
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
418
|
+
<View style={styles.consentBackdrop} pointerEvents="auto">
|
|
419
|
+
<View style={styles.consentCard}>
|
|
420
|
+
<View style={styles.consentIconWrap}>
|
|
421
|
+
<View style={styles.consentIconRing} />
|
|
422
|
+
<View style={styles.consentIconDot} />
|
|
423
|
+
</View>
|
|
424
|
+
<Text style={styles.consentTitle}>Guided support request</Text>
|
|
425
|
+
<Text style={styles.consentBody}>
|
|
426
|
+
<Text style={styles.consentEmphasis}>{tourState.agentName || "A support agent"}</Text>
|
|
427
|
+
{" wants to guide you through your screen.\n\nYou'll see a pointer showing where they're pointing. They "}
|
|
428
|
+
<Text style={styles.consentEmphasis}>cannot tap or type for you</Text>
|
|
429
|
+
{" — you stay in full control."}
|
|
430
|
+
</Text>
|
|
431
|
+
<View style={styles.consentRow}>
|
|
432
|
+
<Pressable onPress={() => consentTour(false)} style={({ pressed }) => [styles.btn, styles.btnGhost, pressed && styles.btnPressed]}>
|
|
433
|
+
<Text style={styles.btnGhostText}>Not now</Text>
|
|
434
|
+
</Pressable>
|
|
435
|
+
<Pressable onPress={() => consentTour(true)} style={({ pressed }) => [styles.btn, styles.btnPrimary, pressed && styles.btnPressed]}>
|
|
436
|
+
<Text style={styles.btnPrimaryText}>Allow</Text>
|
|
437
|
+
</Pressable>
|
|
438
|
+
</View>
|
|
423
439
|
</View>
|
|
424
440
|
</View>
|
|
425
441
|
)}
|
|
426
442
|
|
|
427
|
-
{/* Guided tour active overlay — 4 thin edge strips,
|
|
443
|
+
{/* Guided tour active overlay — 4 thin edge strips, end-tour button on top-right (avoids iOS Dynamic Island) */}
|
|
428
444
|
{tourActiveHere.current && tourState.phase === "active" && (
|
|
429
445
|
<>
|
|
430
446
|
<View pointerEvents="none" style={[styles.edge, { top: 0, left: 0, right: 0, height: 4 }]} />
|
|
431
447
|
<View pointerEvents="none" style={[styles.edge, { bottom: 0, left: 0, right: 0, height: 4 }]} />
|
|
432
448
|
<View pointerEvents="none" style={[styles.edge, { top: 0, bottom: 0, left: 0, width: 4 }]} />
|
|
433
449
|
<View pointerEvents="none" style={[styles.edge, { top: 0, bottom: 0, right: 0, width: 4 }]} />
|
|
434
|
-
<
|
|
435
|
-
<Text
|
|
436
|
-
</
|
|
450
|
+
<Pressable onPress={endTourLocal} style={({ pressed }) => [styles.endTourPill, pressed && styles.btnPressed]} hitSlop={8}>
|
|
451
|
+
<Text style={styles.endTourText}>End tour</Text>
|
|
452
|
+
</Pressable>
|
|
437
453
|
{pointer && (
|
|
438
454
|
<>
|
|
439
455
|
<View pointerEvents="none" style={[styles.pointerHalo, { left: pointer.x - 24, top: pointer.y - 24 }]} />
|
|
@@ -495,25 +511,49 @@ const styles = StyleSheet.create({
|
|
|
495
511
|
position: "absolute", width: 40, height: 40, borderRadius: 20,
|
|
496
512
|
backgroundColor: "rgba(34,197,94,0.45)", borderWidth: 2, borderColor: "#22c55e",
|
|
497
513
|
},
|
|
498
|
-
|
|
499
|
-
position: "absolute",
|
|
500
|
-
backgroundColor: "rgba(
|
|
514
|
+
consentBackdrop: {
|
|
515
|
+
position: "absolute", top: 0, left: 0, right: 0, bottom: 0,
|
|
516
|
+
backgroundColor: "rgba(0,0,0,0.55)", justifyContent: "center", alignItems: "center",
|
|
517
|
+
paddingHorizontal: 24, zIndex: 9999,
|
|
518
|
+
},
|
|
519
|
+
consentCard: {
|
|
520
|
+
width: "100%", maxWidth: 360, backgroundColor: "#ffffff", borderRadius: 20,
|
|
521
|
+
paddingVertical: 24, paddingHorizontal: 22, alignItems: "center",
|
|
522
|
+
shadowColor: "#000", shadowOpacity: 0.25, shadowRadius: 24, shadowOffset: { width: 0, height: 12 }, elevation: 12,
|
|
523
|
+
},
|
|
524
|
+
consentIconWrap: {
|
|
525
|
+
width: 56, height: 56, borderRadius: 28, alignItems: "center", justifyContent: "center",
|
|
526
|
+
backgroundColor: "rgba(239,68,68,0.12)", marginBottom: 14,
|
|
527
|
+
},
|
|
528
|
+
consentIconRing: {
|
|
529
|
+
position: "absolute", width: 36, height: 36, borderRadius: 18,
|
|
530
|
+
borderWidth: 2, borderColor: "#ef4444",
|
|
501
531
|
},
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
532
|
+
consentIconDot: {
|
|
533
|
+
width: 14, height: 14, borderRadius: 7, backgroundColor: "#ef4444",
|
|
534
|
+
},
|
|
535
|
+
consentTitle: { color: "#0f172a", fontSize: 18, fontWeight: "700", marginBottom: 8, textAlign: "center" },
|
|
536
|
+
consentBody: { color: "#475569", fontSize: 14, lineHeight: 20, textAlign: "center", marginBottom: 20 },
|
|
537
|
+
consentEmphasis: { color: "#0f172a", fontWeight: "600" },
|
|
538
|
+
consentRow: { flexDirection: "row", justifyContent: "center", gap: 10, width: "100%" },
|
|
539
|
+
btn: {
|
|
540
|
+
flex: 1, paddingVertical: 12, paddingHorizontal: 16, borderRadius: 10,
|
|
541
|
+
alignItems: "center", justifyContent: "center", minHeight: 44,
|
|
542
|
+
},
|
|
543
|
+
btnPressed: { opacity: 0.7 },
|
|
544
|
+
btnGhost: { backgroundColor: "#f1f5f9" },
|
|
545
|
+
btnGhostText: { color: "#475569", fontSize: 15, fontWeight: "600" },
|
|
546
|
+
btnPrimary: { backgroundColor: "#22c55e" },
|
|
547
|
+
btnPrimaryText: { color: "#fff", fontSize: 15, fontWeight: "600" },
|
|
508
548
|
edge: { position: "absolute", backgroundColor: "rgba(34,197,94,0.7)", zIndex: 9998 },
|
|
549
|
+
// End-tour pill: anchored to TOP-RIGHT with safe top inset (~64px) to clear iOS Dynamic Island & status bar.
|
|
509
550
|
endTourPill: {
|
|
510
|
-
position: "absolute", top:
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
color: "#fff", backgroundColor: "rgba(17,24,39,0.92)", paddingVertical: 6, paddingHorizontal: 14,
|
|
515
|
-
borderRadius: 999, fontSize: 13, fontWeight: "600", overflow: "hidden",
|
|
551
|
+
position: "absolute", top: 64, right: 12, zIndex: 9999,
|
|
552
|
+
backgroundColor: "rgba(17,24,39,0.92)", paddingVertical: 8, paddingHorizontal: 14,
|
|
553
|
+
borderRadius: 999, flexDirection: "row", alignItems: "center",
|
|
554
|
+
shadowColor: "#000", shadowOpacity: 0.3, shadowRadius: 6, shadowOffset: { width: 0, height: 2 }, elevation: 6,
|
|
516
555
|
},
|
|
556
|
+
endTourText: { color: "#fff", fontSize: 13, fontWeight: "600" },
|
|
517
557
|
pointer: {
|
|
518
558
|
position: "absolute", width: 24, height: 24, borderRadius: 12,
|
|
519
559
|
backgroundColor: "rgba(239,68,68,1)", borderWidth: 3, borderColor: "#fff",
|