@akhilpulse/samadhaan-session-replay 0.6.3 → 0.6.5
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 +59 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akhilpulse/samadhaan-session-replay",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "React Native SDK for Samadhaan Guided Support — session recording, live remote screen-share, take-control, guided-tour overlays, and Shake-to-Assist AI voice guide.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -56,7 +56,7 @@ let pixelCopyDisabled = false; // turned true after repeated runtime failures to
|
|
|
56
56
|
let pixelCopyFailStreak = 0; // consecutive non-busy failures; resets on success
|
|
57
57
|
|
|
58
58
|
const STORAGE_KEY = "@akhilpulse/samadhaan-session-replay/sessionId";
|
|
59
|
-
const SDK_VERSION = "0.6.
|
|
59
|
+
const SDK_VERSION = "0.6.5";
|
|
60
60
|
|
|
61
61
|
// ---- Module-level session singleton --------------------------------------
|
|
62
62
|
// Multiple SessionReplayProvider mounts (intentional or via React StrictMode's
|
|
@@ -877,20 +877,31 @@ export function SessionReplayProvider({ config, children }: { config: Config; ch
|
|
|
877
877
|
</Animated.View>
|
|
878
878
|
)}
|
|
879
879
|
|
|
880
|
-
{/* Shake-to-Assist: bottom
|
|
880
|
+
{/* Shake-to-Assist: Siri-style bottom overlay — a white translucent
|
|
881
|
+
gradient rising from the bottom edge (no dark pill bar) with the
|
|
882
|
+
multicolor voice wave + status text floating over it, and a small
|
|
883
|
+
frosted ✕ to end the session. Gradient is built from stacked
|
|
884
|
+
strips so we don't need a native linear-gradient dependency. */}
|
|
881
885
|
{assistantActive && (
|
|
882
886
|
<View style={styles.assistDock} pointerEvents="box-none">
|
|
883
|
-
<View style={
|
|
887
|
+
<View style={StyleSheet.absoluteFill} pointerEvents="none">
|
|
888
|
+
{ASSIST_GRADIENT_STOPS.map((o, i) => (
|
|
889
|
+
<View key={i} style={{ flex: 1, backgroundColor: "#ffffff", opacity: o }} />
|
|
890
|
+
))}
|
|
891
|
+
</View>
|
|
892
|
+
<View style={styles.assistStatusRow} pointerEvents="box-none">
|
|
884
893
|
<VoiceWave phase={assistantPhase} />
|
|
885
|
-
<Text style={styles.assistStatusText}>
|
|
894
|
+
<Text style={styles.assistStatusText} numberOfLines={1}>
|
|
886
895
|
{assistantStatusLabel(assistantPhase, assistMicStatus)}
|
|
887
896
|
</Text>
|
|
888
897
|
<Pressable
|
|
889
898
|
onPress={endAssist}
|
|
890
899
|
style={({ pressed }) => [styles.assistClose, pressed && styles.btnPressed]}
|
|
891
|
-
hitSlop={
|
|
900
|
+
hitSlop={12}
|
|
901
|
+
accessibilityRole="button"
|
|
902
|
+
accessibilityLabel="End voice help"
|
|
892
903
|
>
|
|
893
|
-
<Text style={styles.assistCloseText}
|
|
904
|
+
<Text style={styles.assistCloseText}>✕</Text>
|
|
894
905
|
</Pressable>
|
|
895
906
|
</View>
|
|
896
907
|
</View>
|
|
@@ -916,6 +927,15 @@ export function SessionReplayProvider({ config, children }: { config: Config; ch
|
|
|
916
927
|
|
|
917
928
|
// ---- Shake-to-Assist UI bits ----
|
|
918
929
|
|
|
930
|
+
// Opacity stops for the Siri-style white gradient (top → bottom). Many thin
|
|
931
|
+
// strips fake a smooth linear gradient without a native gradient dependency.
|
|
932
|
+
const ASSIST_GRADIENT_STOPS = [
|
|
933
|
+
0, 0.03, 0.07, 0.13, 0.2, 0.29, 0.39, 0.5, 0.61, 0.71, 0.8, 0.87, 0.92, 0.95,
|
|
934
|
+
];
|
|
935
|
+
|
|
936
|
+
// Apple-ish multicolor voice wave bars.
|
|
937
|
+
const SIRI_WAVE_COLORS = ["#0A84FF", "#64D2FF", "#BF5AF2", "#FF375F", "#5E5CE6"];
|
|
938
|
+
|
|
919
939
|
/**
|
|
920
940
|
* Pulsing arrow + label bubble pointing at the next element to tap.
|
|
921
941
|
* - Halo pulses continuously so the target is hard to miss.
|
|
@@ -939,10 +959,19 @@ function AssistArrowOverlay({
|
|
|
939
959
|
|
|
940
960
|
const px = nx * (w || 0);
|
|
941
961
|
const py = ny * (h || 0);
|
|
942
|
-
//
|
|
943
|
-
|
|
944
|
-
//
|
|
945
|
-
|
|
962
|
+
// Bubble placement:
|
|
963
|
+
// - target near the TOP edge -> bubble just below the target
|
|
964
|
+
// - target near the BOTTOM -> bubble pinned to the top of the screen, so it
|
|
965
|
+
// never covers the target or the app's bottom UI
|
|
966
|
+
// (bottom sheets / nav bars live there)
|
|
967
|
+
// - otherwise -> bubble just above the target
|
|
968
|
+
const nearTop = py < 96;
|
|
969
|
+
const nearBottom = py > (h || 0) - 260;
|
|
970
|
+
const bubblePos: any = nearTop
|
|
971
|
+
? { top: py + 36 }
|
|
972
|
+
: nearBottom
|
|
973
|
+
? { top: 70 }
|
|
974
|
+
: { bottom: (h || 0) - py + 36 };
|
|
946
975
|
const scale = pulse.interpolate({ inputRange: [0, 1], outputRange: [1, 1.45] });
|
|
947
976
|
const opacity = pulse.interpolate({ inputRange: [0, 1], outputRange: [1, 0.35] });
|
|
948
977
|
|
|
@@ -956,13 +985,13 @@ function AssistArrowOverlay({
|
|
|
956
985
|
<View
|
|
957
986
|
style={[
|
|
958
987
|
styles.assistArrow,
|
|
959
|
-
|
|
988
|
+
nearTop
|
|
960
989
|
? { left: px - 9, top: py + 12 }
|
|
961
990
|
: { left: px - 9, top: py - 30, transform: [{ rotate: "180deg" }] },
|
|
962
991
|
]}
|
|
963
992
|
/>
|
|
964
993
|
{!!(label || instruction) && (
|
|
965
|
-
<View style={[styles.assistBubble, { left: 16, right: 16,
|
|
994
|
+
<View style={[styles.assistBubble, { left: 16, right: 16, ...bubblePos }]}>
|
|
966
995
|
{!!label && <Text style={styles.assistBubbleLabel}>{label}</Text>}
|
|
967
996
|
{!!instruction && <Text style={styles.assistBubbleText}>{instruction}</Text>}
|
|
968
997
|
</View>
|
|
@@ -1016,7 +1045,11 @@ function VoiceWave({ phase }: { phase: AssistantPhase }) {
|
|
|
1016
1045
|
key={i}
|
|
1017
1046
|
style={[
|
|
1018
1047
|
styles.waveBar,
|
|
1019
|
-
{
|
|
1048
|
+
{
|
|
1049
|
+
backgroundColor: SIRI_WAVE_COLORS[i % SIRI_WAVE_COLORS.length],
|
|
1050
|
+
transform: [{ scaleY: b }],
|
|
1051
|
+
opacity: active ? 1 : 0.5,
|
|
1052
|
+
},
|
|
1020
1053
|
]}
|
|
1021
1054
|
/>
|
|
1022
1055
|
))}
|
|
@@ -1157,23 +1190,25 @@ const styles = StyleSheet.create({
|
|
|
1157
1190
|
},
|
|
1158
1191
|
assistBubbleLabel: { color: "#93c5fd", fontSize: 12, fontWeight: "700", marginBottom: 2 },
|
|
1159
1192
|
assistBubbleText: { color: "#fff", fontSize: 14, lineHeight: 19 },
|
|
1160
|
-
// ---- Shake-to-Assist bottom
|
|
1193
|
+
// ---- Shake-to-Assist Siri-style bottom overlay ----
|
|
1161
1194
|
assistDock: {
|
|
1162
1195
|
position: "absolute", left: 0, right: 0, bottom: 0,
|
|
1163
|
-
|
|
1196
|
+
height: 140, justifyContent: "flex-end",
|
|
1164
1197
|
},
|
|
1165
|
-
|
|
1166
|
-
flexDirection: "row", alignItems: "center",
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1198
|
+
assistStatusRow: {
|
|
1199
|
+
flexDirection: "row", alignItems: "center", justifyContent: "center",
|
|
1200
|
+
paddingBottom: 30, paddingHorizontal: 20,
|
|
1201
|
+
},
|
|
1202
|
+
assistStatusText: {
|
|
1203
|
+
color: "#111827", fontSize: 15, fontWeight: "600",
|
|
1204
|
+
marginHorizontal: 12, flexShrink: 1,
|
|
1170
1205
|
},
|
|
1171
|
-
assistStatusText: { color: "#e5e7eb", fontSize: 14, fontWeight: "600", marginHorizontal: 12, flexShrink: 1 },
|
|
1172
1206
|
assistClose: {
|
|
1173
|
-
|
|
1174
|
-
|
|
1207
|
+
width: 30, height: 30, borderRadius: 15,
|
|
1208
|
+
backgroundColor: "rgba(17,24,39,0.10)",
|
|
1209
|
+
alignItems: "center", justifyContent: "center",
|
|
1175
1210
|
},
|
|
1176
|
-
assistCloseText: { color: "#
|
|
1211
|
+
assistCloseText: { color: "#374151", fontSize: 13, fontWeight: "700", lineHeight: 16 },
|
|
1177
1212
|
assistFab: {
|
|
1178
1213
|
position: "absolute", top: 96, right: 12,
|
|
1179
1214
|
width: 44, height: 44, borderRadius: 22,
|