@ateam-ai-mobile/ui 0.1.2 → 0.1.4
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/dist/index.d.mts +11 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.js +91 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +102 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/chat/JobProgressBar.tsx +57 -28
- package/src/chat/MessageBubble.tsx +26 -4
- package/src/voice/VoiceCallSheet.tsx +4 -2
- package/src/voice/useVoiceCall.ts +51 -6
package/dist/index.d.mts
CHANGED
|
@@ -41,8 +41,11 @@ declare function TypingIndicator(): react_jsx_runtime.JSX.Element;
|
|
|
41
41
|
|
|
42
42
|
interface Props$6 {
|
|
43
43
|
progress: JobProgress;
|
|
44
|
+
/** Standalone placeholder (transparent bubble) — drop the top divider so it
|
|
45
|
+
* floats cleanly over the background. */
|
|
46
|
+
standalone?: boolean;
|
|
44
47
|
}
|
|
45
|
-
declare function JobProgressBar({ progress }: Props$6): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function JobProgressBar({ progress, standalone }: Props$6): react_jsx_runtime.JSX.Element;
|
|
46
49
|
|
|
47
50
|
interface Props$5 {
|
|
48
51
|
columns: string[];
|
|
@@ -174,8 +177,10 @@ declare const useLightboxStore: zustand.UseBoundStore<zustand.StoreApi<LightboxS
|
|
|
174
177
|
interface Props {
|
|
175
178
|
visible: boolean;
|
|
176
179
|
onClose: () => void;
|
|
180
|
+
/** Optional skill to hand the mic to on connect (voice /session → takeMic). */
|
|
181
|
+
skillSlug?: string;
|
|
177
182
|
}
|
|
178
|
-
declare function VoiceCallSheet({ visible, onClose }: Props): react_jsx_runtime.JSX.Element | null;
|
|
183
|
+
declare function VoiceCallSheet({ visible, onClose, skillSlug }: Props): react_jsx_runtime.JSX.Element | null;
|
|
179
184
|
|
|
180
185
|
interface TranscriptEntry {
|
|
181
186
|
role: 'user' | 'ai' | 'tool';
|
|
@@ -183,7 +188,9 @@ interface TranscriptEntry {
|
|
|
183
188
|
ts: number;
|
|
184
189
|
}
|
|
185
190
|
type CallState = 'idle' | 'connecting' | 'connected' | 'error';
|
|
186
|
-
declare function useVoiceCall(
|
|
191
|
+
declare function useVoiceCall({ skillSlug }?: {
|
|
192
|
+
skillSlug?: string;
|
|
193
|
+
}): {
|
|
187
194
|
callState: CallState;
|
|
188
195
|
sessionId: string | null;
|
|
189
196
|
error: string | null;
|
|
@@ -191,7 +198,7 @@ declare function useVoiceCall(): {
|
|
|
191
198
|
aiPartial: string;
|
|
192
199
|
userPartial: string;
|
|
193
200
|
muted: boolean;
|
|
194
|
-
startCall: () => void
|
|
201
|
+
startCall: () => Promise<void>;
|
|
195
202
|
stopCall: () => void;
|
|
196
203
|
toggleMute: () => void;
|
|
197
204
|
handleWebViewMessage: (event: any) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -41,8 +41,11 @@ declare function TypingIndicator(): react_jsx_runtime.JSX.Element;
|
|
|
41
41
|
|
|
42
42
|
interface Props$6 {
|
|
43
43
|
progress: JobProgress;
|
|
44
|
+
/** Standalone placeholder (transparent bubble) — drop the top divider so it
|
|
45
|
+
* floats cleanly over the background. */
|
|
46
|
+
standalone?: boolean;
|
|
44
47
|
}
|
|
45
|
-
declare function JobProgressBar({ progress }: Props$6): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function JobProgressBar({ progress, standalone }: Props$6): react_jsx_runtime.JSX.Element;
|
|
46
49
|
|
|
47
50
|
interface Props$5 {
|
|
48
51
|
columns: string[];
|
|
@@ -174,8 +177,10 @@ declare const useLightboxStore: zustand.UseBoundStore<zustand.StoreApi<LightboxS
|
|
|
174
177
|
interface Props {
|
|
175
178
|
visible: boolean;
|
|
176
179
|
onClose: () => void;
|
|
180
|
+
/** Optional skill to hand the mic to on connect (voice /session → takeMic). */
|
|
181
|
+
skillSlug?: string;
|
|
177
182
|
}
|
|
178
|
-
declare function VoiceCallSheet({ visible, onClose }: Props): react_jsx_runtime.JSX.Element | null;
|
|
183
|
+
declare function VoiceCallSheet({ visible, onClose, skillSlug }: Props): react_jsx_runtime.JSX.Element | null;
|
|
179
184
|
|
|
180
185
|
interface TranscriptEntry {
|
|
181
186
|
role: 'user' | 'ai' | 'tool';
|
|
@@ -183,7 +188,9 @@ interface TranscriptEntry {
|
|
|
183
188
|
ts: number;
|
|
184
189
|
}
|
|
185
190
|
type CallState = 'idle' | 'connecting' | 'connected' | 'error';
|
|
186
|
-
declare function useVoiceCall(
|
|
191
|
+
declare function useVoiceCall({ skillSlug }?: {
|
|
192
|
+
skillSlug?: string;
|
|
193
|
+
}): {
|
|
187
194
|
callState: CallState;
|
|
188
195
|
sessionId: string | null;
|
|
189
196
|
error: string | null;
|
|
@@ -191,7 +198,7 @@ declare function useVoiceCall(): {
|
|
|
191
198
|
aiPartial: string;
|
|
192
199
|
userPartial: string;
|
|
193
200
|
muted: boolean;
|
|
194
|
-
startCall: () => void
|
|
201
|
+
startCall: () => Promise<void>;
|
|
195
202
|
stopCall: () => void;
|
|
196
203
|
toggleMute: () => void;
|
|
197
204
|
handleWebViewMessage: (event: any) => void;
|
package/dist/index.js
CHANGED
|
@@ -81,7 +81,7 @@ var WARM_RED = "#C15545";
|
|
|
81
81
|
var WARM_RED_SOFT = "rgba(193, 85, 69, 0.14)";
|
|
82
82
|
var WARM_AMBER = "#D49A4E";
|
|
83
83
|
var WARM_AMBER_SOFT = "rgba(212, 154, 78, 0.16)";
|
|
84
|
-
function JobProgressBar({ progress }) {
|
|
84
|
+
function JobProgressBar({ progress, standalone }) {
|
|
85
85
|
const pulseAnim = (0, import_react.useRef)(new import_react_native.Animated.Value(0.5)).current;
|
|
86
86
|
const [elapsed, setElapsed] = (0, import_react.useState)(0);
|
|
87
87
|
const isRunning = progress.status === "running";
|
|
@@ -95,8 +95,10 @@ function JobProgressBar({ progress }) {
|
|
|
95
95
|
}
|
|
96
96
|
const anim = import_react_native.Animated.loop(
|
|
97
97
|
import_react_native.Animated.sequence([
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
// Gentle breath — a soft fade rather than a hard blink, so the running
|
|
99
|
+
// indicator recedes into the bubble instead of demanding attention.
|
|
100
|
+
import_react_native.Animated.timing(pulseAnim, { toValue: 0.55, duration: 1100, useNativeDriver: true }),
|
|
101
|
+
import_react_native.Animated.timing(pulseAnim, { toValue: 0.22, duration: 1100, useNativeDriver: true })
|
|
100
102
|
])
|
|
101
103
|
);
|
|
102
104
|
anim.start();
|
|
@@ -117,33 +119,37 @@ function JobProgressBar({ progress }) {
|
|
|
117
119
|
const statusColor = isDone ? WARM_GREEN : isError ? WARM_RED : isPaused ? WARM_AMBER : import_core.ada.orange;
|
|
118
120
|
const statusBg = isDone ? WARM_GREEN_SOFT : isError ? WARM_RED_SOFT : isPaused ? WARM_AMBER_SOFT : import_core.ada.orangeSoft;
|
|
119
121
|
if (isDone || isError) {
|
|
120
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
|
|
122
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.container, standalone && styles.containerStandalone], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
|
|
121
123
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.dot, { backgroundColor: statusColor }] }),
|
|
122
124
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: [styles.label, { color: statusColor }], children: isDone ? "Completed" : "Failed" })
|
|
123
125
|
] }) });
|
|
124
126
|
}
|
|
125
127
|
if (isPaused) {
|
|
126
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
|
|
128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.container, standalone && styles.containerStandalone], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
|
|
127
129
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.dot, { backgroundColor: statusColor }] }),
|
|
128
130
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: [styles.label, { color: statusColor }], children: "Waiting for your reply" })
|
|
129
131
|
] }) });
|
|
130
132
|
}
|
|
131
|
-
const elapsedStr = progress.chainStartedAt ? `${Math.floor(elapsed / 60)}
|
|
133
|
+
const elapsedStr = progress.chainStartedAt ? elapsed < 60 ? `${elapsed}s` : `${Math.floor(elapsed / 60)}m ${elapsed % 60}s` : null;
|
|
132
134
|
const metaParts = [
|
|
133
135
|
progress.iteration != null && progress.iteration > 0 ? `iter ${progress.iteration}` : null,
|
|
134
136
|
elapsedStr
|
|
135
137
|
].filter(Boolean);
|
|
138
|
+
const labels = progress.humanLabels;
|
|
139
|
+
const label = (t) => t && labels?.[t] || t;
|
|
140
|
+
const headline = progress.humanStatus || label(progress.skillSlug) || "Processing...";
|
|
141
|
+
const showRawTool = !progress.humanStatus && !!progress.currentTool;
|
|
136
142
|
const lp = progress.liveProgress;
|
|
137
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.container, children: [
|
|
143
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: [styles.container, standalone && styles.containerStandalone], children: [
|
|
138
144
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
|
|
139
145
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
140
146
|
import_react_native.Animated.View,
|
|
141
147
|
{
|
|
142
|
-
style: [styles.dot,
|
|
148
|
+
style: [styles.dot, styles.dotRunning, { opacity: pulseAnim }]
|
|
143
149
|
}
|
|
144
150
|
),
|
|
145
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.skill, numberOfLines: 1, children:
|
|
146
|
-
|
|
151
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.skill, numberOfLines: 1, children: headline }),
|
|
152
|
+
showRawTool && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.tool, numberOfLines: 1, children: ` \u2192 ${label(progress.currentTool)}` }),
|
|
147
153
|
metaParts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.meta, numberOfLines: 1, children: ` \xB7 ${metaParts.join(" \xB7 ")}` })
|
|
148
154
|
] }),
|
|
149
155
|
!!lp?.message && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.liveProgressRow, children: [
|
|
@@ -156,10 +162,10 @@ function JobProgressBar({ progress }) {
|
|
|
156
162
|
] }),
|
|
157
163
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.liveProgressMsg, numberOfLines: 1, children: lp.message })
|
|
158
164
|
] }),
|
|
159
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style:
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: styles.progressTrack, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
160
166
|
import_react_native.Animated.View,
|
|
161
167
|
{
|
|
162
|
-
style: [styles.progressFill, {
|
|
168
|
+
style: [styles.progressFill, { opacity: pulseAnim }]
|
|
163
169
|
}
|
|
164
170
|
) })
|
|
165
171
|
] });
|
|
@@ -171,6 +177,12 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
171
177
|
borderTopWidth: 1,
|
|
172
178
|
borderTopColor: import_core.ada.border
|
|
173
179
|
},
|
|
180
|
+
// Standalone (transparent-bubble) placeholder — no divider/top spacing.
|
|
181
|
+
containerStandalone: {
|
|
182
|
+
marginTop: 0,
|
|
183
|
+
paddingTop: 0,
|
|
184
|
+
borderTopWidth: 0
|
|
185
|
+
},
|
|
174
186
|
row: {
|
|
175
187
|
flexDirection: "row",
|
|
176
188
|
alignItems: "center",
|
|
@@ -178,21 +190,26 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
178
190
|
overflow: "hidden"
|
|
179
191
|
},
|
|
180
192
|
dot: {
|
|
181
|
-
width:
|
|
182
|
-
height:
|
|
183
|
-
borderRadius:
|
|
193
|
+
width: 6,
|
|
194
|
+
height: 6,
|
|
195
|
+
borderRadius: 3,
|
|
184
196
|
marginRight: 6,
|
|
185
197
|
flexShrink: 0
|
|
186
198
|
},
|
|
199
|
+
// Running dot: soft orange, not the full-saturation accent.
|
|
200
|
+
dotRunning: {
|
|
201
|
+
backgroundColor: "rgba(255, 122, 40, 0.6)"
|
|
202
|
+
},
|
|
187
203
|
label: {
|
|
188
204
|
fontSize: import_core.fontSize.xs,
|
|
189
205
|
fontWeight: "600"
|
|
190
206
|
},
|
|
191
|
-
// Running state text segments
|
|
207
|
+
// Running state text segments — muted so the indicator blends into the
|
|
208
|
+
// bubble rather than shouting in orange.
|
|
192
209
|
skill: {
|
|
193
210
|
fontSize: import_core.fontSize.xs,
|
|
194
|
-
fontWeight: "
|
|
195
|
-
color: import_core.ada.
|
|
211
|
+
fontWeight: "500",
|
|
212
|
+
color: import_core.ada.inkSoft,
|
|
196
213
|
flexShrink: 1
|
|
197
214
|
},
|
|
198
215
|
tool: {
|
|
@@ -218,19 +235,23 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
218
235
|
},
|
|
219
236
|
liveProgressMsg: {
|
|
220
237
|
fontSize: import_core.fontSize.xs,
|
|
221
|
-
color: import_core.ada.
|
|
238
|
+
color: import_core.ada.inkSoft,
|
|
222
239
|
flex: 1
|
|
223
240
|
},
|
|
224
241
|
progressTrack: {
|
|
225
|
-
height:
|
|
226
|
-
borderRadius:
|
|
227
|
-
marginTop:
|
|
228
|
-
overflow: "hidden"
|
|
242
|
+
height: 2,
|
|
243
|
+
borderRadius: 1,
|
|
244
|
+
marginTop: 8,
|
|
245
|
+
overflow: "hidden",
|
|
246
|
+
// Barely-there rail so the bar reads as a hint, not a status meter.
|
|
247
|
+
backgroundColor: "rgba(26, 20, 16, 0.05)"
|
|
229
248
|
},
|
|
230
249
|
progressFill: {
|
|
231
250
|
height: "100%",
|
|
232
|
-
width: "
|
|
233
|
-
borderRadius:
|
|
251
|
+
width: "55%",
|
|
252
|
+
borderRadius: 1,
|
|
253
|
+
// Muted orange — present but recessive.
|
|
254
|
+
backgroundColor: "rgba(255, 122, 40, 0.4)"
|
|
234
255
|
}
|
|
235
256
|
});
|
|
236
257
|
|
|
@@ -1140,6 +1161,8 @@ function MessageBubble({ message }) {
|
|
|
1140
1161
|
const isUser = message.role === "user";
|
|
1141
1162
|
const isSystem = message.role === "system";
|
|
1142
1163
|
const isNotification = !isUser && message.kind === "notification";
|
|
1164
|
+
const st = message.jobProgress?.status;
|
|
1165
|
+
const isProgressOnly = !isUser && (st === "running" || st === "paused") && (!message.content?.trim() || message.content === "Working on it...");
|
|
1143
1166
|
const [copied, setCopied] = (0, import_react7.useState)("");
|
|
1144
1167
|
const showCopied = (0, import_react7.useCallback)((label) => {
|
|
1145
1168
|
setCopied(label);
|
|
@@ -1175,7 +1198,8 @@ function MessageBubble({ message }) {
|
|
|
1175
1198
|
styles6.bubble,
|
|
1176
1199
|
isUser && styles6.bubbleUser,
|
|
1177
1200
|
isSystem && styles6.bubbleSystem,
|
|
1178
|
-
isNotification && styles6.bubbleNotification
|
|
1201
|
+
isNotification && styles6.bubbleNotification,
|
|
1202
|
+
isProgressOnly && styles6.bubbleProgress
|
|
1179
1203
|
],
|
|
1180
1204
|
children: [
|
|
1181
1205
|
isNotification && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.View, { style: styles6.notificationHeader, children: [
|
|
@@ -1208,12 +1232,15 @@ function MessageBubble({ message }) {
|
|
|
1208
1232
|
isUser ? (
|
|
1209
1233
|
// Hide the "See attachment" placeholder when the bubble already shows the photo.
|
|
1210
1234
|
message.content && !(message.content === "See attachment" && message.attachments?.length) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { selectable: true, style: styles6.userText, children: message.content }) : null
|
|
1235
|
+
) : isProgressOnly ? (
|
|
1236
|
+
// No "Working on it…" text — the indicator below is the whole message.
|
|
1237
|
+
null
|
|
1211
1238
|
) : renderAssistantContent(message.content, copyText),
|
|
1212
1239
|
!!copied && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.View, { style: styles6.copiedBadge, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: styles6.copiedText, children: copied }) }),
|
|
1213
1240
|
message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToolCallsBadge, { calls: message.toolCalls }),
|
|
1214
|
-
message.jobProgress && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(JobProgressBar, { progress: message.jobProgress }),
|
|
1241
|
+
message.jobProgress && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(JobProgressBar, { progress: message.jobProgress, standalone: isProgressOnly }),
|
|
1215
1242
|
!isUser && message.actions && message.actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(UIActionsRow, { actions: message.actions }),
|
|
1216
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: [styles6.timeText, isUser && styles6.timeTextUser], children: formatTime(message.timestamp) })
|
|
1243
|
+
!isProgressOnly && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: [styles6.timeText, isUser && styles6.timeTextUser], children: formatTime(message.timestamp) })
|
|
1217
1244
|
]
|
|
1218
1245
|
}
|
|
1219
1246
|
),
|
|
@@ -1336,6 +1363,14 @@ var styles6 = import_react_native7.StyleSheet.create({
|
|
|
1336
1363
|
backgroundColor: import_core9.ada.userBubble,
|
|
1337
1364
|
borderColor: "transparent"
|
|
1338
1365
|
},
|
|
1366
|
+
// Live-chain placeholder: no fill, no border, tighter padding — the
|
|
1367
|
+
// indicator floats over the background instead of sitting in a bubble.
|
|
1368
|
+
bubbleProgress: {
|
|
1369
|
+
backgroundColor: "transparent",
|
|
1370
|
+
borderColor: "transparent",
|
|
1371
|
+
paddingHorizontal: 4,
|
|
1372
|
+
paddingVertical: 2
|
|
1373
|
+
},
|
|
1339
1374
|
bubbleSystem: {
|
|
1340
1375
|
backgroundColor: import_core9.ada.orangeSoft,
|
|
1341
1376
|
borderColor: import_core9.ada.orange,
|
|
@@ -2053,6 +2088,20 @@ var import_plugin_runtime9 = require("@ateam-ai-mobile/plugin-runtime");
|
|
|
2053
2088
|
// src/voice/useVoiceCall.ts
|
|
2054
2089
|
var import_react12 = require("react");
|
|
2055
2090
|
var import_core16 = require("@ateam-ai-mobile/core");
|
|
2091
|
+
var TOKEN_REFRESH_SKEW_MS = 9e4;
|
|
2092
|
+
function tokenNeedsRefresh(token) {
|
|
2093
|
+
if (!token) return true;
|
|
2094
|
+
try {
|
|
2095
|
+
const payloadB64 = token.split(".")[1];
|
|
2096
|
+
const padded = payloadB64.replace(/-/g, "+").replace(/_/g, "/");
|
|
2097
|
+
const json = typeof atob === "function" ? atob(padded) : Buffer.from(padded, "base64").toString("utf8");
|
|
2098
|
+
const exp = JSON.parse(json)?.exp;
|
|
2099
|
+
if (typeof exp !== "number") return false;
|
|
2100
|
+
return Date.now() >= exp * 1e3 - TOKEN_REFRESH_SKEW_MS;
|
|
2101
|
+
} catch {
|
|
2102
|
+
return false;
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2056
2105
|
var INJECT_TRACK_HOOK = `
|
|
2057
2106
|
(function() {
|
|
2058
2107
|
if (window._adaTrackHookInstalled) return;
|
|
@@ -2143,7 +2192,7 @@ var buildMuteScript = (muted) => `
|
|
|
2143
2192
|
console.log('[ada-mute]', muted ? 'MUTED' : 'UNMUTED', 'tracks=', n);
|
|
2144
2193
|
})(${muted}); true;
|
|
2145
2194
|
`;
|
|
2146
|
-
function useVoiceCall() {
|
|
2195
|
+
function useVoiceCall({ skillSlug } = {}) {
|
|
2147
2196
|
const [callState, setCallState] = (0, import_react12.useState)("idle");
|
|
2148
2197
|
const [sessionId, setSessionId] = (0, import_react12.useState)(null);
|
|
2149
2198
|
const [error, setError] = (0, import_react12.useState)(null);
|
|
@@ -2184,12 +2233,18 @@ function useVoiceCall() {
|
|
|
2184
2233
|
} catch {
|
|
2185
2234
|
}
|
|
2186
2235
|
}, []);
|
|
2187
|
-
const startCall = (0, import_react12.useCallback)(() => {
|
|
2188
|
-
setCallState("connecting");
|
|
2236
|
+
const startCall = (0, import_react12.useCallback)(async () => {
|
|
2189
2237
|
setError(null);
|
|
2190
2238
|
setTranscript([]);
|
|
2191
2239
|
setAiPartial("");
|
|
2192
2240
|
setUserPartial("");
|
|
2241
|
+
try {
|
|
2242
|
+
if (tokenNeedsRefresh((0, import_core16.getToken)())) {
|
|
2243
|
+
await (0, import_core16.refreshToken)();
|
|
2244
|
+
}
|
|
2245
|
+
} catch {
|
|
2246
|
+
}
|
|
2247
|
+
setCallState("connecting");
|
|
2193
2248
|
}, []);
|
|
2194
2249
|
const stopCall = (0, import_react12.useCallback)(() => {
|
|
2195
2250
|
webViewRef.current?.injectJavaScript?.("window.hangUp && window.hangUp(); true;");
|
|
@@ -2209,10 +2264,11 @@ function useVoiceCall() {
|
|
|
2209
2264
|
const token = (0, import_core16.getToken)();
|
|
2210
2265
|
const tenant = (0, import_core16.getTenant)();
|
|
2211
2266
|
const actorId = (0, import_core16.getUser)()?.actorId || "";
|
|
2267
|
+
const skillParam = skillSlug ? `&skillSlug=${encodeURIComponent(skillSlug)}` : "";
|
|
2212
2268
|
return {
|
|
2213
|
-
uri: `${(0, import_core16.getVoiceApiUrl)()}/app?mode=mini&embedded=rn&authToken=${encodeURIComponent(token || "")}&tenant=${encodeURIComponent(tenant)}&actorId=${encodeURIComponent(actorId)}`
|
|
2269
|
+
uri: `${(0, import_core16.getVoiceApiUrl)()}/app?mode=mini&embedded=rn&authToken=${encodeURIComponent(token || "")}&tenant=${encodeURIComponent(tenant)}&actorId=${encodeURIComponent(actorId)}${skillParam}`
|
|
2214
2270
|
};
|
|
2215
|
-
}, []);
|
|
2271
|
+
}, [skillSlug]);
|
|
2216
2272
|
return {
|
|
2217
2273
|
callState,
|
|
2218
2274
|
sessionId,
|
|
@@ -2279,7 +2335,7 @@ function HighlightedText({
|
|
|
2279
2335
|
const segments = (0, import_react13.useMemo)(() => highlightSegments(text), [text]);
|
|
2280
2336
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native14.Text, { style: baseStyle, children: segments.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native14.Text, { style: seg.important ? importantStyle : void 0, children: seg.text }, i)) });
|
|
2281
2337
|
}
|
|
2282
|
-
function VoiceCallSheet({ visible, onClose }) {
|
|
2338
|
+
function VoiceCallSheet({ visible, onClose, skillSlug }) {
|
|
2283
2339
|
const {
|
|
2284
2340
|
callState,
|
|
2285
2341
|
aiPartial,
|
|
@@ -2294,7 +2350,7 @@ function VoiceCallSheet({ visible, onClose }) {
|
|
|
2294
2350
|
getWebViewSource,
|
|
2295
2351
|
webViewRef,
|
|
2296
2352
|
injectedTrackHook
|
|
2297
|
-
} = useVoiceCall();
|
|
2353
|
+
} = useVoiceCall({ skillSlug });
|
|
2298
2354
|
const scrollRef = (0, import_react13.useRef)(null);
|
|
2299
2355
|
(0, import_react13.useEffect)(() => {
|
|
2300
2356
|
if (visible && callState === "idle") startCall();
|