@ateam-ai-mobile/ui 0.1.4 → 0.1.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/dist/index.d.mts +325 -21
- package/dist/index.d.ts +325 -21
- package/dist/index.js +1447 -429
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1411 -401
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/WorkspaceBanner.tsx +71 -0
- package/src/auth/HandoffScreen.tsx +94 -0
- package/src/auth/JoinScreen.tsx +145 -0
- package/src/auth/LoginScreen.tsx +181 -0
- package/src/auth/OpenJoinScreen.tsx +131 -0
- package/src/auth/handoffExchange.ts +49 -0
- package/src/auth/inviteJoin.ts +44 -0
- package/src/auth/login.ts +57 -0
- package/src/auth/openJoin.ts +56 -0
- package/src/chat/MessageBubble.tsx +14 -1
- package/src/chat/QuestionChips.tsx +76 -0
- package/src/chat/UIActionsRow.tsx +7 -1
- package/src/index.ts +38 -1
- package/src/plugin/Plugin.tsx +14 -9
- package/src/providers.ts +44 -0
- package/src/voice/VoiceCallSheet.tsx +4 -32
- package/src/voice/VoiceMicIndicator.tsx +99 -0
- package/src/voice/VoiceSessionHost.tsx +77 -0
- package/src/voice/useVoiceCall.ts +40 -231
- package/src/voice/voiceSession.ts +628 -0
package/dist/index.mjs
CHANGED
|
@@ -3,18 +3,18 @@ import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMem
|
|
|
3
3
|
import {
|
|
4
4
|
FlatList,
|
|
5
5
|
KeyboardAvoidingView,
|
|
6
|
-
Platform as
|
|
6
|
+
Platform as Platform7,
|
|
7
7
|
RefreshControl,
|
|
8
|
-
StyleSheet as
|
|
9
|
-
View as
|
|
8
|
+
StyleSheet as StyleSheet11,
|
|
9
|
+
View as View12
|
|
10
10
|
} from "react-native";
|
|
11
|
-
import { ada as
|
|
11
|
+
import { ada as ada8, useChatStore as useChatStore2, pluginCommandEmitter as pluginCommandEmitter3 } from "@ateam-ai-mobile/core";
|
|
12
12
|
|
|
13
13
|
// src/chat/MessageBubble.tsx
|
|
14
14
|
import { useState as useState4, useCallback as useCallback3 } from "react";
|
|
15
|
-
import { View as
|
|
15
|
+
import { View as View8, Text as Text7, Pressable as Pressable4, StyleSheet as StyleSheet7, Image, Platform as Platform5 } from "react-native";
|
|
16
16
|
import Markdown from "react-native-markdown-display";
|
|
17
|
-
import { TABLE_BLOCK_OPEN, TABLE_BLOCK_CLOSE, getConfig as getConfig2, ada as
|
|
17
|
+
import { TABLE_BLOCK_OPEN, TABLE_BLOCK_CLOSE, getConfig as getConfig2, ada as ada7, borderRadius as borderRadius2, fontSize as fontSize5 } from "@ateam-ai-mobile/core";
|
|
18
18
|
import { AdaOrb, getHaptics as getHaptics2 } from "@ateam-ai-mobile/plugin-runtime";
|
|
19
19
|
|
|
20
20
|
// src/chat/JobProgressBar.tsx
|
|
@@ -208,6 +208,13 @@ import { ada as ada4, fontSize as fontSize2 } from "@ateam-ai-mobile/core";
|
|
|
208
208
|
import { useSurfaceStore as useSurfaceStore2, getHaptics } from "@ateam-ai-mobile/plugin-runtime";
|
|
209
209
|
|
|
210
210
|
// src/providers.ts
|
|
211
|
+
var _oauth = null;
|
|
212
|
+
function setOAuthProvider(oauth) {
|
|
213
|
+
_oauth = oauth;
|
|
214
|
+
}
|
|
215
|
+
function getOAuthProvider() {
|
|
216
|
+
return _oauth;
|
|
217
|
+
}
|
|
211
218
|
var _clipboard = null;
|
|
212
219
|
function setClipboardProvider(clipboard) {
|
|
213
220
|
_clipboard = clipboard;
|
|
@@ -254,8 +261,7 @@ import {
|
|
|
254
261
|
usePlugin,
|
|
255
262
|
useNativeBridge,
|
|
256
263
|
usePluginTheme,
|
|
257
|
-
|
|
258
|
-
gatePluginNative
|
|
264
|
+
resolvePluginRuntimeProps
|
|
259
265
|
} from "@ateam-ai-mobile/plugin-runtime";
|
|
260
266
|
|
|
261
267
|
// src/plugin/EmbeddedPluginWebView.tsx
|
|
@@ -749,8 +755,10 @@ function Plugin({ id, manifest, commandBufferRef, props: engineProps }) {
|
|
|
749
755
|
const { plugin, loading, error, bundleMissing } = usePlugin(id, manifest);
|
|
750
756
|
const connectorId = id.startsWith("mcp:") ? id.split(":")[1] : manifest._connectorId;
|
|
751
757
|
const bridge = useNativeBridge(id, connectorId, commandBufferRef);
|
|
752
|
-
const
|
|
753
|
-
|
|
758
|
+
const { device, native, deviceState, voice } = useMemo2(
|
|
759
|
+
() => resolvePluginRuntimeProps({ pluginId: id, manifest, plugin }),
|
|
760
|
+
[id, manifest, plugin]
|
|
761
|
+
);
|
|
754
762
|
const theme = usePluginTheme();
|
|
755
763
|
const user = getUser();
|
|
756
764
|
const context = useMemo2(() => ({
|
|
@@ -773,7 +781,7 @@ function Plugin({ id, manifest, commandBufferRef, props: engineProps }) {
|
|
|
773
781
|
return /* @__PURE__ */ jsx3(View3, { style: styles3.center, children: /* @__PURE__ */ jsx3(Text3, { style: styles3.errorMessage, children: error || "Plugin not found" }) });
|
|
774
782
|
}
|
|
775
783
|
const { Component } = plugin;
|
|
776
|
-
return /* @__PURE__ */ jsx3(PluginErrorBoundary, { pluginId: id, children: /* @__PURE__ */ jsx3(Component, { bridge, native, theme, context, props: engineProps }) });
|
|
784
|
+
return /* @__PURE__ */ jsx3(PluginErrorBoundary, { pluginId: id, children: /* @__PURE__ */ jsx3(Component, { bridge, device, native, deviceState, voice, theme, context, props: engineProps }) });
|
|
777
785
|
}
|
|
778
786
|
var styles3 = StyleSheet3.create({
|
|
779
787
|
center: {
|
|
@@ -923,7 +931,8 @@ function UIActionsRow({ actions }) {
|
|
|
923
931
|
const focus = a.payload?.id || a.payload?.entity_id || a.payload?.focusId;
|
|
924
932
|
const surface = useSurfaceStore2.getState().manifests[id];
|
|
925
933
|
if (surface) {
|
|
926
|
-
|
|
934
|
+
const props = { ...focus ? { focus } : {}, ...a.payload?.data || {} };
|
|
935
|
+
useSurfaceStore2.getState().show(id, Object.keys(props).length ? props : void 0);
|
|
927
936
|
return;
|
|
928
937
|
}
|
|
929
938
|
const params = {};
|
|
@@ -998,47 +1007,107 @@ var styles4 = StyleSheet4.create({
|
|
|
998
1007
|
}
|
|
999
1008
|
});
|
|
1000
1009
|
|
|
1001
|
-
// src/chat/
|
|
1002
|
-
import { View as View6, Text as Text5, StyleSheet as StyleSheet5, Platform as Platform3 } from "react-native";
|
|
1003
|
-
import { ada as ada5,
|
|
1004
|
-
import { jsx as jsx7
|
|
1010
|
+
// src/chat/QuestionChips.tsx
|
|
1011
|
+
import { View as View6, Text as Text5, Pressable as Pressable3, StyleSheet as StyleSheet5, Platform as Platform3 } from "react-native";
|
|
1012
|
+
import { ada as ada5, fontSize as fontSize3, useChatStore } from "@ateam-ai-mobile/core";
|
|
1013
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1005
1014
|
var fontFam2 = Platform3.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
1015
|
+
function resolveOptions(inputType, options) {
|
|
1016
|
+
if (Array.isArray(options) && options.length) return options.filter((o) => typeof o === "string" && o.trim());
|
|
1017
|
+
if (inputType === "confirm") return ["Yes", "No"];
|
|
1018
|
+
return [];
|
|
1019
|
+
}
|
|
1020
|
+
function QuestionChips({
|
|
1021
|
+
inputType,
|
|
1022
|
+
options
|
|
1023
|
+
}) {
|
|
1024
|
+
const opts = resolveOptions(inputType, options);
|
|
1025
|
+
if (!opts.length) return null;
|
|
1026
|
+
const answer = (label) => {
|
|
1027
|
+
try {
|
|
1028
|
+
useChatStore.getState().sendMessage(label);
|
|
1029
|
+
} catch {
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
return /* @__PURE__ */ jsx7(View6, { style: styles5.row, children: opts.map((label, i) => /* @__PURE__ */ jsx7(
|
|
1033
|
+
Pressable3,
|
|
1034
|
+
{
|
|
1035
|
+
accessibilityRole: "button",
|
|
1036
|
+
accessibilityLabel: label,
|
|
1037
|
+
onPress: () => answer(label),
|
|
1038
|
+
style: ({ pressed }) => [styles5.chip, pressed && styles5.chipPressed],
|
|
1039
|
+
children: /* @__PURE__ */ jsx7(Text5, { style: styles5.label, numberOfLines: 2, children: label })
|
|
1040
|
+
},
|
|
1041
|
+
`${label}-${i}`
|
|
1042
|
+
)) });
|
|
1043
|
+
}
|
|
1044
|
+
var styles5 = StyleSheet5.create({
|
|
1045
|
+
row: {
|
|
1046
|
+
flexDirection: "row",
|
|
1047
|
+
flexWrap: "wrap",
|
|
1048
|
+
gap: 6,
|
|
1049
|
+
marginTop: 10
|
|
1050
|
+
},
|
|
1051
|
+
chip: {
|
|
1052
|
+
paddingHorizontal: 12,
|
|
1053
|
+
paddingVertical: 8,
|
|
1054
|
+
backgroundColor: ada5.orangeSoft,
|
|
1055
|
+
borderColor: ada5.orange,
|
|
1056
|
+
borderWidth: 1,
|
|
1057
|
+
borderRadius: 14
|
|
1058
|
+
},
|
|
1059
|
+
chipPressed: {
|
|
1060
|
+
backgroundColor: ada5.orange
|
|
1061
|
+
},
|
|
1062
|
+
label: {
|
|
1063
|
+
color: ada5.orangeDeep,
|
|
1064
|
+
fontSize: fontSize3.xs,
|
|
1065
|
+
fontWeight: "600",
|
|
1066
|
+
fontFamily: fontFam2
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
|
|
1070
|
+
// src/chat/TableCardBlock.tsx
|
|
1071
|
+
import { View as View7, Text as Text6, StyleSheet as StyleSheet6, Platform as Platform4 } from "react-native";
|
|
1072
|
+
import { ada as ada6, borderRadius, fontSize as fontSize4, spacing } from "@ateam-ai-mobile/core";
|
|
1073
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1074
|
+
var fontFam3 = Platform4.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
1006
1075
|
function TableCardBlock({ columns, rows }) {
|
|
1007
1076
|
if (!columns?.length || !rows?.length) return null;
|
|
1008
1077
|
const [titleCol, ...detailCols] = columns;
|
|
1009
|
-
return /* @__PURE__ */
|
|
1078
|
+
return /* @__PURE__ */ jsx8(View7, { style: styles6.wrap, children: rows.map((row, i) => {
|
|
1010
1079
|
const cells = Array.isArray(row) ? row : [row];
|
|
1011
1080
|
const title = cells[0];
|
|
1012
|
-
return /* @__PURE__ */ jsxs5(
|
|
1013
|
-
/* @__PURE__ */
|
|
1014
|
-
detailCols.length > 0 && /* @__PURE__ */
|
|
1081
|
+
return /* @__PURE__ */ jsxs5(View7, { style: styles6.card, children: [
|
|
1082
|
+
/* @__PURE__ */ jsx8(Text6, { style: styles6.title, children: String(title ?? "") }),
|
|
1083
|
+
detailCols.length > 0 && /* @__PURE__ */ jsx8(View7, { style: styles6.details, children: detailCols.map((col, ci) => {
|
|
1015
1084
|
const value = cells[ci + 1];
|
|
1016
1085
|
if (value == null || value === "") return null;
|
|
1017
|
-
return /* @__PURE__ */ jsxs5(
|
|
1018
|
-
/* @__PURE__ */
|
|
1019
|
-
/* @__PURE__ */
|
|
1086
|
+
return /* @__PURE__ */ jsxs5(View7, { style: styles6.row, children: [
|
|
1087
|
+
/* @__PURE__ */ jsx8(Text6, { style: styles6.label, children: String(col) }),
|
|
1088
|
+
/* @__PURE__ */ jsx8(Text6, { style: styles6.value, children: String(value) })
|
|
1020
1089
|
] }, ci);
|
|
1021
1090
|
}) })
|
|
1022
1091
|
] }, i);
|
|
1023
1092
|
}) });
|
|
1024
1093
|
}
|
|
1025
|
-
var
|
|
1094
|
+
var styles6 = StyleSheet6.create({
|
|
1026
1095
|
wrap: {
|
|
1027
1096
|
marginVertical: 6,
|
|
1028
1097
|
gap: 8
|
|
1029
1098
|
},
|
|
1030
1099
|
card: {
|
|
1031
|
-
backgroundColor:
|
|
1100
|
+
backgroundColor: ada6.paper,
|
|
1032
1101
|
borderRadius: borderRadius.md,
|
|
1033
1102
|
borderWidth: 1,
|
|
1034
|
-
borderColor:
|
|
1103
|
+
borderColor: ada6.border,
|
|
1035
1104
|
padding: spacing.md
|
|
1036
1105
|
},
|
|
1037
1106
|
title: {
|
|
1038
|
-
color:
|
|
1039
|
-
fontSize:
|
|
1107
|
+
color: ada6.ink,
|
|
1108
|
+
fontSize: fontSize4.md,
|
|
1040
1109
|
fontWeight: "600",
|
|
1041
|
-
fontFamily:
|
|
1110
|
+
fontFamily: fontFam3,
|
|
1042
1111
|
letterSpacing: -0.2,
|
|
1043
1112
|
marginBottom: 6
|
|
1044
1113
|
},
|
|
@@ -1051,9 +1120,9 @@ var styles5 = StyleSheet5.create({
|
|
|
1051
1120
|
gap: 8
|
|
1052
1121
|
},
|
|
1053
1122
|
label: {
|
|
1054
|
-
color:
|
|
1055
|
-
fontSize:
|
|
1056
|
-
fontFamily:
|
|
1123
|
+
color: ada6.inkMuted,
|
|
1124
|
+
fontSize: fontSize4.xs,
|
|
1125
|
+
fontFamily: fontFam3,
|
|
1057
1126
|
fontWeight: "500",
|
|
1058
1127
|
width: 84,
|
|
1059
1128
|
textTransform: "uppercase",
|
|
@@ -1062,9 +1131,9 @@ var styles5 = StyleSheet5.create({
|
|
|
1062
1131
|
},
|
|
1063
1132
|
value: {
|
|
1064
1133
|
flex: 1,
|
|
1065
|
-
color:
|
|
1066
|
-
fontSize:
|
|
1067
|
-
fontFamily:
|
|
1134
|
+
color: ada6.inkSoft,
|
|
1135
|
+
fontSize: fontSize4.sm,
|
|
1136
|
+
fontFamily: fontFam3,
|
|
1068
1137
|
lineHeight: 18
|
|
1069
1138
|
}
|
|
1070
1139
|
});
|
|
@@ -1078,8 +1147,8 @@ var useLightboxStore = create2((set) => ({
|
|
|
1078
1147
|
}));
|
|
1079
1148
|
|
|
1080
1149
|
// src/chat/MessageBubble.tsx
|
|
1081
|
-
import { Fragment, jsx as
|
|
1082
|
-
var
|
|
1150
|
+
import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1151
|
+
var fontFam4 = Platform5.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
1083
1152
|
function formatTime(date) {
|
|
1084
1153
|
const h = date.getHours();
|
|
1085
1154
|
const m = date.getMinutes().toString().padStart(2, "0");
|
|
@@ -1097,18 +1166,18 @@ function DaySeparator({ date }) {
|
|
|
1097
1166
|
} else {
|
|
1098
1167
|
label = date.toLocaleDateString(void 0, { weekday: "long", month: "short", day: "numeric" });
|
|
1099
1168
|
}
|
|
1100
|
-
return /* @__PURE__ */
|
|
1169
|
+
return /* @__PURE__ */ jsx9(View8, { style: separatorStyles.container, children: /* @__PURE__ */ jsx9(View8, { style: separatorStyles.pill, children: /* @__PURE__ */ jsx9(Text7, { style: separatorStyles.text, children: label }) }) });
|
|
1101
1170
|
}
|
|
1102
1171
|
function isSameDay(a, b) {
|
|
1103
1172
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1104
1173
|
}
|
|
1105
|
-
var separatorStyles =
|
|
1174
|
+
var separatorStyles = StyleSheet7.create({
|
|
1106
1175
|
container: {
|
|
1107
1176
|
alignItems: "center",
|
|
1108
1177
|
marginVertical: 14
|
|
1109
1178
|
},
|
|
1110
1179
|
pill: {
|
|
1111
|
-
backgroundColor:
|
|
1180
|
+
backgroundColor: ada7.paperSoft,
|
|
1112
1181
|
paddingHorizontal: 14,
|
|
1113
1182
|
paddingVertical: 5,
|
|
1114
1183
|
borderRadius: 999
|
|
@@ -1116,9 +1185,9 @@ var separatorStyles = StyleSheet6.create({
|
|
|
1116
1185
|
text: {
|
|
1117
1186
|
fontSize: 12,
|
|
1118
1187
|
fontWeight: "600",
|
|
1119
|
-
color:
|
|
1188
|
+
color: ada7.inkMuted,
|
|
1120
1189
|
letterSpacing: 0.4,
|
|
1121
|
-
fontFamily:
|
|
1190
|
+
fontFamily: fontFam4
|
|
1122
1191
|
}
|
|
1123
1192
|
});
|
|
1124
1193
|
function MessageBubble({ message }) {
|
|
@@ -1126,6 +1195,7 @@ function MessageBubble({ message }) {
|
|
|
1126
1195
|
const isSystem = message.role === "system";
|
|
1127
1196
|
const isNotification = !isUser && message.kind === "notification";
|
|
1128
1197
|
const st = message.jobProgress?.status;
|
|
1198
|
+
const pq = !isUser ? message.jobProgress?.pendingQuestion : void 0;
|
|
1129
1199
|
const isProgressOnly = !isUser && (st === "running" || st === "paused") && (!message.content?.trim() || message.content === "Working on it...");
|
|
1130
1200
|
const [copied, setCopied] = useState4("");
|
|
1131
1201
|
const showCopied = useCallback3((label) => {
|
|
@@ -1142,41 +1212,41 @@ function MessageBubble({ message }) {
|
|
|
1142
1212
|
const handleLongPress = useCallback3(() => {
|
|
1143
1213
|
copyText(message.content);
|
|
1144
1214
|
}, [message.content, copyText]);
|
|
1145
|
-
return /* @__PURE__ */ jsxs6(
|
|
1146
|
-
!isUser && !isNotification && /* @__PURE__ */
|
|
1215
|
+
return /* @__PURE__ */ jsxs6(View8, { style: [styles7.row, isUser && styles7.rowUser], children: [
|
|
1216
|
+
!isUser && !isNotification && /* @__PURE__ */ jsx9(View8, { style: styles7.avatarOrb, children: /* @__PURE__ */ jsx9(
|
|
1147
1217
|
AdaOrb,
|
|
1148
1218
|
{
|
|
1149
1219
|
size: 28,
|
|
1150
1220
|
state: message.jobProgress?.status === "running" ? "thinking" : "idle"
|
|
1151
1221
|
}
|
|
1152
1222
|
) }),
|
|
1153
|
-
isNotification && /* @__PURE__ */
|
|
1223
|
+
isNotification && /* @__PURE__ */ jsx9(View8, { style: styles7.notificationLeftStripe }),
|
|
1154
1224
|
/* @__PURE__ */ jsxs6(
|
|
1155
|
-
|
|
1225
|
+
Pressable4,
|
|
1156
1226
|
{
|
|
1157
1227
|
accessibilityRole: "text",
|
|
1158
1228
|
accessibilityLabel: `${isUser ? "You" : isNotification ? "Notification" : "Ada"}: ${message.content}`,
|
|
1159
1229
|
accessibilityHint: "Long-press to copy",
|
|
1160
1230
|
onLongPress: handleLongPress,
|
|
1161
1231
|
style: [
|
|
1162
|
-
|
|
1163
|
-
isUser &&
|
|
1164
|
-
isSystem &&
|
|
1165
|
-
isNotification &&
|
|
1166
|
-
isProgressOnly &&
|
|
1232
|
+
styles7.bubble,
|
|
1233
|
+
isUser && styles7.bubbleUser,
|
|
1234
|
+
isSystem && styles7.bubbleSystem,
|
|
1235
|
+
isNotification && styles7.bubbleNotification,
|
|
1236
|
+
isProgressOnly && styles7.bubbleProgress
|
|
1167
1237
|
],
|
|
1168
1238
|
children: [
|
|
1169
|
-
isNotification && /* @__PURE__ */ jsxs6(
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1239
|
+
isNotification && /* @__PURE__ */ jsxs6(View8, { style: styles7.notificationHeader, children: [
|
|
1240
|
+
/* @__PURE__ */ jsx9(Text7, { style: styles7.notificationHeaderIcon, children: "\u{1F514}" }),
|
|
1241
|
+
/* @__PURE__ */ jsx9(Text7, { style: styles7.notificationHeaderText, children: "Notification" })
|
|
1172
1242
|
] }),
|
|
1173
|
-
message.attachments && message.attachments.length > 0 && /* @__PURE__ */
|
|
1174
|
-
|
|
1243
|
+
message.attachments && message.attachments.length > 0 && /* @__PURE__ */ jsx9(View8, { style: styles7.attachments, children: message.attachments.map((att, i) => att.previewUri ? /* @__PURE__ */ jsx9(
|
|
1244
|
+
Pressable4,
|
|
1175
1245
|
{
|
|
1176
1246
|
accessibilityRole: "imagebutton",
|
|
1177
1247
|
accessibilityLabel: `Photo${att.name ? `: ${att.name}` : ""}. Tap to enlarge.`,
|
|
1178
1248
|
onPress: () => useLightboxStore.getState().show(att.previewUri),
|
|
1179
|
-
children: /* @__PURE__ */
|
|
1249
|
+
children: /* @__PURE__ */ jsx9(
|
|
1180
1250
|
Image,
|
|
1181
1251
|
{
|
|
1182
1252
|
source: {
|
|
@@ -1185,36 +1255,44 @@ function MessageBubble({ message }) {
|
|
|
1185
1255
|
headers: { Authorization: `Bearer ${getConfig2().tokenProvider.getToken()}` }
|
|
1186
1256
|
} : {}
|
|
1187
1257
|
},
|
|
1188
|
-
style:
|
|
1258
|
+
style: styles7.attachmentImage,
|
|
1189
1259
|
resizeMode: "cover",
|
|
1190
1260
|
onError: (e) => console.warn("[Image] Failed to load:", att.previewUri?.slice(0, 100), e.nativeEvent.error)
|
|
1191
1261
|
}
|
|
1192
1262
|
)
|
|
1193
1263
|
},
|
|
1194
1264
|
i
|
|
1195
|
-
) : /* @__PURE__ */
|
|
1265
|
+
) : /* @__PURE__ */ jsx9(View8, { style: styles7.attachmentFile, children: /* @__PURE__ */ jsx9(Text7, { style: styles7.attachmentFileName, numberOfLines: 1, children: att.name }) }, i)) }),
|
|
1196
1266
|
isUser ? (
|
|
1197
1267
|
// Hide the "See attachment" placeholder when the bubble already shows the photo.
|
|
1198
|
-
message.content && !(message.content === "See attachment" && message.attachments?.length) ? /* @__PURE__ */
|
|
1268
|
+
message.content && !(message.content === "See attachment" && message.attachments?.length) ? /* @__PURE__ */ jsx9(Text7, { selectable: true, style: styles7.userText, children: message.content }) : null
|
|
1199
1269
|
) : isProgressOnly ? (
|
|
1200
1270
|
// No "Working on it…" text — the indicator below is the whole message.
|
|
1201
1271
|
null
|
|
1202
|
-
) :
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1272
|
+
) : (
|
|
1273
|
+
// When the turn asked a question, show its clean question string —
|
|
1274
|
+
// never message.content, which may carry the raw JSON payload.
|
|
1275
|
+
renderAssistantContent(pq?.question || message.content, copyText)
|
|
1276
|
+
),
|
|
1277
|
+
!!copied && /* @__PURE__ */ jsx9(View8, { style: styles7.copiedBadge, children: /* @__PURE__ */ jsx9(Text7, { style: styles7.copiedText, children: copied }) }),
|
|
1278
|
+
message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ jsx9(ToolCallsBadge, { calls: message.toolCalls }),
|
|
1279
|
+
message.jobProgress && /* @__PURE__ */ jsx9(JobProgressBar, { progress: message.jobProgress, standalone: isProgressOnly }),
|
|
1280
|
+
!isUser && message.actions && message.actions.length > 0 && /* @__PURE__ */ jsx9(UIActionsRow, { actions: message.actions }),
|
|
1281
|
+
pq && // Per-chain: this bubble's OWN chain has a pending question. Parallel
|
|
1282
|
+
// pending chains each render their own chips (jobProgress is per
|
|
1283
|
+
// bubble); answered questions have no jobProgress → no chips.
|
|
1284
|
+
/* @__PURE__ */ jsx9(QuestionChips, { inputType: pq.inputType, options: pq.options }),
|
|
1285
|
+
!isProgressOnly && /* @__PURE__ */ jsx9(Text7, { style: [styles7.timeText, isUser && styles7.timeTextUser], children: formatTime(message.timestamp) })
|
|
1208
1286
|
]
|
|
1209
1287
|
}
|
|
1210
1288
|
),
|
|
1211
|
-
isUser && /* @__PURE__ */
|
|
1289
|
+
isUser && /* @__PURE__ */ jsx9(View8, { style: styles7.avatarSpacer })
|
|
1212
1290
|
] });
|
|
1213
1291
|
}
|
|
1214
1292
|
function renderAssistantContent(content, copyText) {
|
|
1215
1293
|
if (!content) return null;
|
|
1216
1294
|
if (!content.includes(TABLE_BLOCK_OPEN)) {
|
|
1217
|
-
return /* @__PURE__ */
|
|
1295
|
+
return /* @__PURE__ */ jsx9(MarkdownBubble, { content, copyText });
|
|
1218
1296
|
}
|
|
1219
1297
|
const segments = [];
|
|
1220
1298
|
let cursor = 0;
|
|
@@ -1236,28 +1314,28 @@ function renderAssistantContent(content, copyText) {
|
|
|
1236
1314
|
segments.push({ kind: "table", content: payload });
|
|
1237
1315
|
cursor = close + TABLE_BLOCK_CLOSE.length;
|
|
1238
1316
|
}
|
|
1239
|
-
return /* @__PURE__ */
|
|
1317
|
+
return /* @__PURE__ */ jsx9(Fragment, { children: segments.map((seg, i) => {
|
|
1240
1318
|
if (seg.kind === "md") {
|
|
1241
1319
|
const trimmed = seg.content.trim();
|
|
1242
1320
|
if (!trimmed) return null;
|
|
1243
|
-
return /* @__PURE__ */
|
|
1321
|
+
return /* @__PURE__ */ jsx9(MarkdownBubble, { content: seg.content, copyText }, i);
|
|
1244
1322
|
}
|
|
1245
1323
|
try {
|
|
1246
1324
|
const data = JSON.parse(decodeURIComponent(seg.content));
|
|
1247
|
-
return /* @__PURE__ */
|
|
1325
|
+
return /* @__PURE__ */ jsx9(TableCardBlock, { columns: data.columns, rows: data.rows }, i);
|
|
1248
1326
|
} catch {
|
|
1249
1327
|
return null;
|
|
1250
1328
|
}
|
|
1251
1329
|
}) });
|
|
1252
1330
|
}
|
|
1253
1331
|
function MarkdownBubble({ content, copyText }) {
|
|
1254
|
-
return /* @__PURE__ */
|
|
1332
|
+
return /* @__PURE__ */ jsx9(
|
|
1255
1333
|
Markdown,
|
|
1256
1334
|
{
|
|
1257
1335
|
style: markdownStyles,
|
|
1258
1336
|
rules: {
|
|
1259
|
-
code_inline: (node) => /* @__PURE__ */
|
|
1260
|
-
|
|
1337
|
+
code_inline: (node) => /* @__PURE__ */ jsx9(
|
|
1338
|
+
Text7,
|
|
1261
1339
|
{
|
|
1262
1340
|
style: markdownStyles.code_inline,
|
|
1263
1341
|
onPress: () => copyText(node.content),
|
|
@@ -1265,12 +1343,12 @@ function MarkdownBubble({ content, copyText }) {
|
|
|
1265
1343
|
},
|
|
1266
1344
|
node.key
|
|
1267
1345
|
),
|
|
1268
|
-
fence: (node) => /* @__PURE__ */
|
|
1269
|
-
|
|
1346
|
+
fence: (node) => /* @__PURE__ */ jsx9(
|
|
1347
|
+
Pressable4,
|
|
1270
1348
|
{
|
|
1271
1349
|
onPress: () => copyText(node.content),
|
|
1272
1350
|
style: markdownStyles.fence,
|
|
1273
|
-
children: /* @__PURE__ */
|
|
1351
|
+
children: /* @__PURE__ */ jsx9(Text7, { style: markdownStyles.fenceText, children: node.content })
|
|
1274
1352
|
},
|
|
1275
1353
|
node.key
|
|
1276
1354
|
)
|
|
@@ -1282,18 +1360,18 @@ function MarkdownBubble({ content, copyText }) {
|
|
|
1282
1360
|
function ToolCallsBadge({ calls }) {
|
|
1283
1361
|
const [expanded, setExpanded] = useState4(false);
|
|
1284
1362
|
const label = calls.filter((c) => c.name === "send_message_to_skill").map((c) => c.args.skill_name || c.skill).filter(Boolean).join(", ") || "Tool call";
|
|
1285
|
-
return /* @__PURE__ */ jsxs6(
|
|
1286
|
-
/* @__PURE__ */ jsxs6(
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
/* @__PURE__ */
|
|
1363
|
+
return /* @__PURE__ */ jsxs6(View8, { style: styles7.toolCalls, children: [
|
|
1364
|
+
/* @__PURE__ */ jsxs6(Pressable4, { style: styles7.toolToggle, onPress: () => setExpanded(!expanded), children: [
|
|
1365
|
+
/* @__PURE__ */ jsx9(Text7, { style: styles7.toolLabel, children: label }),
|
|
1366
|
+
/* @__PURE__ */ jsx9(Text7, { style: styles7.toolChevron, children: expanded ? "\u25B2" : "\u25BC" })
|
|
1289
1367
|
] }),
|
|
1290
|
-
expanded && calls.map((tc, i) => /* @__PURE__ */ jsxs6(
|
|
1291
|
-
/* @__PURE__ */
|
|
1292
|
-
tc.skill && /* @__PURE__ */
|
|
1368
|
+
expanded && calls.map((tc, i) => /* @__PURE__ */ jsxs6(View8, { style: styles7.toolItem, children: [
|
|
1369
|
+
/* @__PURE__ */ jsx9(Text7, { style: styles7.toolName, children: tc.name }),
|
|
1370
|
+
tc.skill && /* @__PURE__ */ jsx9(Text7, { style: styles7.toolSkill, children: tc.skill })
|
|
1293
1371
|
] }, i))
|
|
1294
1372
|
] });
|
|
1295
1373
|
}
|
|
1296
|
-
var
|
|
1374
|
+
var styles7 = StyleSheet7.create({
|
|
1297
1375
|
row: {
|
|
1298
1376
|
flexDirection: "row",
|
|
1299
1377
|
alignItems: "flex-end",
|
|
@@ -1316,15 +1394,15 @@ var styles6 = StyleSheet6.create({
|
|
|
1316
1394
|
},
|
|
1317
1395
|
bubble: {
|
|
1318
1396
|
maxWidth: "78%",
|
|
1319
|
-
backgroundColor:
|
|
1397
|
+
backgroundColor: ada7.botBubble,
|
|
1320
1398
|
borderWidth: 1,
|
|
1321
|
-
borderColor:
|
|
1399
|
+
borderColor: ada7.botBubbleBorder,
|
|
1322
1400
|
borderRadius: borderRadius2.xl,
|
|
1323
1401
|
paddingHorizontal: 16,
|
|
1324
1402
|
paddingVertical: 12
|
|
1325
1403
|
},
|
|
1326
1404
|
bubbleUser: {
|
|
1327
|
-
backgroundColor:
|
|
1405
|
+
backgroundColor: ada7.userBubble,
|
|
1328
1406
|
borderColor: "transparent"
|
|
1329
1407
|
},
|
|
1330
1408
|
// Live-chain placeholder: no fill, no border, tighter padding — the
|
|
@@ -1336,12 +1414,12 @@ var styles6 = StyleSheet6.create({
|
|
|
1336
1414
|
paddingVertical: 2
|
|
1337
1415
|
},
|
|
1338
1416
|
bubbleSystem: {
|
|
1339
|
-
backgroundColor:
|
|
1340
|
-
borderColor:
|
|
1417
|
+
backgroundColor: ada7.orangeSoft,
|
|
1418
|
+
borderColor: ada7.orange,
|
|
1341
1419
|
maxWidth: "90%"
|
|
1342
1420
|
},
|
|
1343
1421
|
bubbleNotification: {
|
|
1344
|
-
backgroundColor:
|
|
1422
|
+
backgroundColor: ada7.orangeSoft,
|
|
1345
1423
|
borderColor: "rgba(255, 122, 40, 0.35)",
|
|
1346
1424
|
borderRadius: borderRadius2.lg,
|
|
1347
1425
|
maxWidth: "90%"
|
|
@@ -1349,7 +1427,7 @@ var styles6 = StyleSheet6.create({
|
|
|
1349
1427
|
notificationLeftStripe: {
|
|
1350
1428
|
width: 3,
|
|
1351
1429
|
alignSelf: "stretch",
|
|
1352
|
-
backgroundColor:
|
|
1430
|
+
backgroundColor: ada7.orange,
|
|
1353
1431
|
borderRadius: 2,
|
|
1354
1432
|
marginRight: 4
|
|
1355
1433
|
},
|
|
@@ -1363,25 +1441,25 @@ var styles6 = StyleSheet6.create({
|
|
|
1363
1441
|
fontSize: 12
|
|
1364
1442
|
},
|
|
1365
1443
|
notificationHeaderText: {
|
|
1366
|
-
color:
|
|
1444
|
+
color: ada7.orangeDeep,
|
|
1367
1445
|
fontSize: 11,
|
|
1368
1446
|
fontWeight: "700",
|
|
1369
1447
|
letterSpacing: 0.6,
|
|
1370
1448
|
textTransform: "uppercase",
|
|
1371
|
-
fontFamily:
|
|
1449
|
+
fontFamily: fontFam4
|
|
1372
1450
|
},
|
|
1373
1451
|
userText: {
|
|
1374
|
-
color:
|
|
1375
|
-
fontSize:
|
|
1452
|
+
color: ada7.userBubbleText,
|
|
1453
|
+
fontSize: fontSize5.md,
|
|
1376
1454
|
lineHeight: 22,
|
|
1377
|
-
fontFamily:
|
|
1455
|
+
fontFamily: fontFam4
|
|
1378
1456
|
},
|
|
1379
1457
|
timeText: {
|
|
1380
1458
|
fontSize: 11,
|
|
1381
|
-
color:
|
|
1459
|
+
color: ada7.inkMuted,
|
|
1382
1460
|
alignSelf: "flex-end",
|
|
1383
1461
|
marginTop: 4,
|
|
1384
|
-
fontFamily:
|
|
1462
|
+
fontFamily: fontFam4
|
|
1385
1463
|
},
|
|
1386
1464
|
timeTextUser: {
|
|
1387
1465
|
color: "rgba(250,246,238,0.55)"
|
|
@@ -1419,13 +1497,13 @@ var styles6 = StyleSheet6.create({
|
|
|
1419
1497
|
},
|
|
1420
1498
|
copiedText: {
|
|
1421
1499
|
color: "#fff",
|
|
1422
|
-
fontSize:
|
|
1500
|
+
fontSize: fontSize5.xs,
|
|
1423
1501
|
fontWeight: "600"
|
|
1424
1502
|
},
|
|
1425
1503
|
toolCalls: {
|
|
1426
1504
|
marginTop: 8,
|
|
1427
1505
|
borderTopWidth: 1,
|
|
1428
|
-
borderTopColor:
|
|
1506
|
+
borderTopColor: ada7.border,
|
|
1429
1507
|
paddingTop: 6
|
|
1430
1508
|
},
|
|
1431
1509
|
toolToggle: {
|
|
@@ -1434,12 +1512,12 @@ var styles6 = StyleSheet6.create({
|
|
|
1434
1512
|
gap: 6
|
|
1435
1513
|
},
|
|
1436
1514
|
toolLabel: {
|
|
1437
|
-
color:
|
|
1438
|
-
fontSize:
|
|
1515
|
+
color: ada7.inkSoft,
|
|
1516
|
+
fontSize: fontSize5.xs,
|
|
1439
1517
|
fontWeight: "500"
|
|
1440
1518
|
},
|
|
1441
1519
|
toolChevron: {
|
|
1442
|
-
color:
|
|
1520
|
+
color: ada7.inkMuted,
|
|
1443
1521
|
fontSize: 8
|
|
1444
1522
|
},
|
|
1445
1523
|
toolItem: {
|
|
@@ -1447,21 +1525,21 @@ var styles6 = StyleSheet6.create({
|
|
|
1447
1525
|
paddingLeft: 8
|
|
1448
1526
|
},
|
|
1449
1527
|
toolName: {
|
|
1450
|
-
color:
|
|
1451
|
-
fontSize:
|
|
1528
|
+
color: ada7.inkSoft,
|
|
1529
|
+
fontSize: fontSize5.xs,
|
|
1452
1530
|
fontFamily: "monospace"
|
|
1453
1531
|
},
|
|
1454
1532
|
toolSkill: {
|
|
1455
|
-
color:
|
|
1456
|
-
fontSize:
|
|
1533
|
+
color: ada7.orangeDeep,
|
|
1534
|
+
fontSize: fontSize5.xs
|
|
1457
1535
|
}
|
|
1458
1536
|
});
|
|
1459
|
-
var markdownStyles =
|
|
1537
|
+
var markdownStyles = StyleSheet7.create({
|
|
1460
1538
|
body: {
|
|
1461
|
-
color:
|
|
1462
|
-
fontSize:
|
|
1539
|
+
color: ada7.botBubbleText,
|
|
1540
|
+
fontSize: fontSize5.md,
|
|
1463
1541
|
lineHeight: 22,
|
|
1464
|
-
fontFamily:
|
|
1542
|
+
fontFamily: fontFam4
|
|
1465
1543
|
},
|
|
1466
1544
|
paragraph: {
|
|
1467
1545
|
marginTop: 0,
|
|
@@ -1469,35 +1547,35 @@ var markdownStyles = StyleSheet6.create({
|
|
|
1469
1547
|
},
|
|
1470
1548
|
strong: {
|
|
1471
1549
|
fontWeight: "700",
|
|
1472
|
-
color:
|
|
1550
|
+
color: ada7.botBubbleText
|
|
1473
1551
|
},
|
|
1474
1552
|
em: {
|
|
1475
1553
|
fontStyle: "italic"
|
|
1476
1554
|
},
|
|
1477
1555
|
code_inline: {
|
|
1478
|
-
backgroundColor:
|
|
1479
|
-
color:
|
|
1556
|
+
backgroundColor: ada7.paperDeep,
|
|
1557
|
+
color: ada7.orangeDeep,
|
|
1480
1558
|
paddingHorizontal: 5,
|
|
1481
1559
|
paddingVertical: 1,
|
|
1482
1560
|
borderRadius: 4,
|
|
1483
1561
|
fontFamily: "monospace",
|
|
1484
|
-
fontSize:
|
|
1562
|
+
fontSize: fontSize5.sm
|
|
1485
1563
|
},
|
|
1486
1564
|
fence: {
|
|
1487
|
-
backgroundColor:
|
|
1565
|
+
backgroundColor: ada7.paperDeep,
|
|
1488
1566
|
padding: 10,
|
|
1489
1567
|
borderRadius: 10
|
|
1490
1568
|
},
|
|
1491
1569
|
fenceText: {
|
|
1492
1570
|
fontFamily: "monospace",
|
|
1493
|
-
fontSize:
|
|
1494
|
-
color:
|
|
1571
|
+
fontSize: fontSize5.sm,
|
|
1572
|
+
color: ada7.ink
|
|
1495
1573
|
},
|
|
1496
1574
|
link: {
|
|
1497
|
-
color:
|
|
1575
|
+
color: ada7.orangeDeep
|
|
1498
1576
|
},
|
|
1499
1577
|
list_item: {
|
|
1500
|
-
color:
|
|
1578
|
+
color: ada7.botBubbleText
|
|
1501
1579
|
},
|
|
1502
1580
|
bullet_list: {
|
|
1503
1581
|
marginVertical: 4
|
|
@@ -1505,13 +1583,13 @@ var markdownStyles = StyleSheet6.create({
|
|
|
1505
1583
|
});
|
|
1506
1584
|
|
|
1507
1585
|
// src/chat/TypingIndicator.tsx
|
|
1508
|
-
import { View as
|
|
1586
|
+
import { View as View9, StyleSheet as StyleSheet8 } from "react-native";
|
|
1509
1587
|
import { AdaOrb as AdaOrb2 } from "@ateam-ai-mobile/plugin-runtime";
|
|
1510
|
-
import { jsx as
|
|
1588
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1511
1589
|
function TypingIndicator() {
|
|
1512
|
-
return /* @__PURE__ */
|
|
1590
|
+
return /* @__PURE__ */ jsx10(View9, { style: styles8.row, children: /* @__PURE__ */ jsx10(AdaOrb2, { size: 32, state: "thinking" }) });
|
|
1513
1591
|
}
|
|
1514
|
-
var
|
|
1592
|
+
var styles8 = StyleSheet8.create({
|
|
1515
1593
|
row: {
|
|
1516
1594
|
flexDirection: "row",
|
|
1517
1595
|
alignItems: "center",
|
|
@@ -1524,16 +1602,16 @@ var styles7 = StyleSheet7.create({
|
|
|
1524
1602
|
// src/chat/ChatInput.tsx
|
|
1525
1603
|
import { useState as useState5, useRef as useRef3, useCallback as useCallback4, useEffect as useEffect5 } from "react";
|
|
1526
1604
|
import {
|
|
1527
|
-
View as
|
|
1605
|
+
View as View10,
|
|
1528
1606
|
TextInput,
|
|
1529
|
-
Pressable as
|
|
1530
|
-
StyleSheet as
|
|
1531
|
-
Platform as
|
|
1607
|
+
Pressable as Pressable5,
|
|
1608
|
+
StyleSheet as StyleSheet9,
|
|
1609
|
+
Platform as Platform6
|
|
1532
1610
|
} from "react-native";
|
|
1533
1611
|
import Svg, { Path, Line, Polygon } from "react-native-svg";
|
|
1534
1612
|
import { colors as colors2, borderRadius as borderRadius3 } from "@ateam-ai-mobile/core";
|
|
1535
1613
|
import { getHaptics as getHaptics3 } from "@ateam-ai-mobile/plugin-runtime";
|
|
1536
|
-
import { jsx as
|
|
1614
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1537
1615
|
function ChatInput({ onSend, onCallStart, loading, prefill, placeholder }) {
|
|
1538
1616
|
const [text, setText] = useState5("");
|
|
1539
1617
|
const [height, setHeight] = useState5(40);
|
|
@@ -1553,13 +1631,13 @@ function ChatInput({ onSend, onCallStart, loading, prefill, placeholder }) {
|
|
|
1553
1631
|
setHeight(40);
|
|
1554
1632
|
}, [text, loading, onSend]);
|
|
1555
1633
|
const canSend = text.trim().length > 0;
|
|
1556
|
-
return /* @__PURE__ */
|
|
1557
|
-
onCallStart && /* @__PURE__ */
|
|
1558
|
-
/* @__PURE__ */
|
|
1634
|
+
return /* @__PURE__ */ jsx11(View10, { style: styles9.dock, children: /* @__PURE__ */ jsxs7(View10, { style: styles9.inputRow, children: [
|
|
1635
|
+
onCallStart && /* @__PURE__ */ jsx11(Pressable5, { style: styles9.callBtn, onPress: onCallStart, children: /* @__PURE__ */ jsx11(Svg, { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: colors2.light.accent, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx11(Path, { d: "M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.63A2 2 0 014.11 2h3a2 2 0 012 1.72 12.84 12.84 0 00.7 2.81 2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45 12.84 12.84 0 002.81.7A2 2 0 0122 16.92z" }) }) }),
|
|
1636
|
+
/* @__PURE__ */ jsx11(
|
|
1559
1637
|
TextInput,
|
|
1560
1638
|
{
|
|
1561
1639
|
ref: inputRef,
|
|
1562
|
-
style: [
|
|
1640
|
+
style: [styles9.input, { height: Math.min(Math.max(40, height), 120) }],
|
|
1563
1641
|
value: text,
|
|
1564
1642
|
onChangeText: setText,
|
|
1565
1643
|
onContentSizeChange: (e) => setHeight(e.nativeEvent.contentSize.height),
|
|
@@ -1569,25 +1647,25 @@ function ChatInput({ onSend, onCallStart, loading, prefill, placeholder }) {
|
|
|
1569
1647
|
returnKeyType: "default",
|
|
1570
1648
|
blurOnSubmit: false,
|
|
1571
1649
|
onSubmitEditing: () => {
|
|
1572
|
-
if (
|
|
1650
|
+
if (Platform6.OS === "web") handleSend();
|
|
1573
1651
|
}
|
|
1574
1652
|
}
|
|
1575
1653
|
),
|
|
1576
|
-
/* @__PURE__ */
|
|
1577
|
-
|
|
1654
|
+
/* @__PURE__ */ jsx11(
|
|
1655
|
+
Pressable5,
|
|
1578
1656
|
{
|
|
1579
|
-
style: [
|
|
1657
|
+
style: [styles9.sendBtn, canSend && styles9.sendBtnActive],
|
|
1580
1658
|
onPress: handleSend,
|
|
1581
1659
|
disabled: !canSend,
|
|
1582
1660
|
children: /* @__PURE__ */ jsxs7(Svg, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: canSend ? "#fff" : colors2.light.textMuted, strokeWidth: 2, children: [
|
|
1583
|
-
/* @__PURE__ */
|
|
1584
|
-
/* @__PURE__ */
|
|
1661
|
+
/* @__PURE__ */ jsx11(Line, { x1: "22", y1: "2", x2: "11", y2: "13" }),
|
|
1662
|
+
/* @__PURE__ */ jsx11(Polygon, { points: "22 2 15 22 11 13 2 9 22 2" })
|
|
1585
1663
|
] })
|
|
1586
1664
|
}
|
|
1587
1665
|
)
|
|
1588
1666
|
] }) });
|
|
1589
1667
|
}
|
|
1590
|
-
var
|
|
1668
|
+
var styles9 = StyleSheet9.create({
|
|
1591
1669
|
dock: {
|
|
1592
1670
|
paddingHorizontal: 12,
|
|
1593
1671
|
paddingVertical: 8,
|
|
@@ -1635,15 +1713,15 @@ var styles8 = StyleSheet8.create({
|
|
|
1635
1713
|
});
|
|
1636
1714
|
|
|
1637
1715
|
// src/Lightbox.tsx
|
|
1638
|
-
import { Modal, View as
|
|
1716
|
+
import { Modal, View as View11, Image as Image2, Pressable as Pressable6, Text as Text8, StyleSheet as StyleSheet10 } from "react-native";
|
|
1639
1717
|
import { getConfig as getConfig3 } from "@ateam-ai-mobile/core";
|
|
1640
|
-
import { jsx as
|
|
1718
|
+
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1641
1719
|
function Lightbox() {
|
|
1642
1720
|
const uri = useLightboxStore((s) => s.uri);
|
|
1643
1721
|
const hide = useLightboxStore((s) => s.hide);
|
|
1644
1722
|
if (!uri) return null;
|
|
1645
|
-
return /* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
1723
|
+
return /* @__PURE__ */ jsx12(Modal, { visible: true, transparent: true, animationType: "fade", onRequestClose: hide, children: /* @__PURE__ */ jsxs8(Pressable6, { style: styles10.backdrop, onPress: hide, children: [
|
|
1724
|
+
/* @__PURE__ */ jsx12(
|
|
1647
1725
|
Image2,
|
|
1648
1726
|
{
|
|
1649
1727
|
source: {
|
|
@@ -1652,14 +1730,14 @@ function Lightbox() {
|
|
|
1652
1730
|
headers: { Authorization: `Bearer ${getConfig3().tokenProvider.getToken()}` }
|
|
1653
1731
|
} : {}
|
|
1654
1732
|
},
|
|
1655
|
-
style:
|
|
1733
|
+
style: styles10.image,
|
|
1656
1734
|
resizeMode: "contain"
|
|
1657
1735
|
}
|
|
1658
1736
|
),
|
|
1659
|
-
/* @__PURE__ */
|
|
1737
|
+
/* @__PURE__ */ jsx12(View11, { style: styles10.closeHint, children: /* @__PURE__ */ jsx12(Text8, { style: styles10.closeHintText, children: "Tap to close" }) })
|
|
1660
1738
|
] }) });
|
|
1661
1739
|
}
|
|
1662
|
-
var
|
|
1740
|
+
var styles10 = StyleSheet10.create({
|
|
1663
1741
|
backdrop: {
|
|
1664
1742
|
flex: 1,
|
|
1665
1743
|
backgroundColor: "rgba(0,0,0,0.92)",
|
|
@@ -1681,7 +1759,7 @@ var styles9 = StyleSheet9.create({
|
|
|
1681
1759
|
});
|
|
1682
1760
|
|
|
1683
1761
|
// src/AdasChatScreen.tsx
|
|
1684
|
-
import { jsx as
|
|
1762
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1685
1763
|
function isSameDay2(a, b) {
|
|
1686
1764
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1687
1765
|
}
|
|
@@ -1691,11 +1769,11 @@ function AdasChatScreen({
|
|
|
1691
1769
|
footerAccessory,
|
|
1692
1770
|
withLightbox = true
|
|
1693
1771
|
}) {
|
|
1694
|
-
const messages =
|
|
1695
|
-
const loading =
|
|
1696
|
-
const conversationLoaded =
|
|
1697
|
-
const loadConversation =
|
|
1698
|
-
const sendMessage =
|
|
1772
|
+
const messages = useChatStore2((s) => s.messages);
|
|
1773
|
+
const loading = useChatStore2((s) => s.loading);
|
|
1774
|
+
const conversationLoaded = useChatStore2((s) => s.conversationLoaded);
|
|
1775
|
+
const loadConversation = useChatStore2((s) => s.loadConversation);
|
|
1776
|
+
const sendMessage = useChatStore2((s) => s.sendMessage);
|
|
1699
1777
|
const listRef = useRef4(null);
|
|
1700
1778
|
const [refreshing, setRefreshing] = useState6(false);
|
|
1701
1779
|
const [prefill, setPrefill] = useState6("");
|
|
@@ -1708,7 +1786,7 @@ function AdasChatScreen({
|
|
|
1708
1786
|
});
|
|
1709
1787
|
return unsub;
|
|
1710
1788
|
}, []);
|
|
1711
|
-
const useInverted =
|
|
1789
|
+
const useInverted = Platform7.OS !== "web";
|
|
1712
1790
|
const listData = useMemo3(
|
|
1713
1791
|
() => useInverted ? [...messages].reverse() : messages,
|
|
1714
1792
|
[messages, useInverted]
|
|
@@ -1733,23 +1811,23 @@ function AdasChatScreen({
|
|
|
1733
1811
|
const renderItem = useCallback5(({ item, index }) => {
|
|
1734
1812
|
const older = useInverted ? listData[index + 1] : listData[index - 1];
|
|
1735
1813
|
const showDaySep = !older || !isSameDay2(older.timestamp, item.timestamp);
|
|
1736
|
-
return /* @__PURE__ */ jsxs9(
|
|
1737
|
-
showDaySep && /* @__PURE__ */
|
|
1738
|
-
/* @__PURE__ */
|
|
1814
|
+
return /* @__PURE__ */ jsxs9(View12, { children: [
|
|
1815
|
+
showDaySep && /* @__PURE__ */ jsx13(DaySeparator, { date: item.timestamp }),
|
|
1816
|
+
/* @__PURE__ */ jsx13(MessageBubble, { message: item })
|
|
1739
1817
|
] });
|
|
1740
1818
|
}, [listData, useInverted]);
|
|
1741
|
-
const typingIndicator = loading && !(useInverted ? listData[0] : listData[listData.length - 1])?.jobProgress ? /* @__PURE__ */
|
|
1819
|
+
const typingIndicator = loading && !(useInverted ? listData[0] : listData[listData.length - 1])?.jobProgress ? /* @__PURE__ */ jsx13(TypingIndicator, {}) : null;
|
|
1742
1820
|
return /* @__PURE__ */ jsxs9(
|
|
1743
1821
|
KeyboardAvoidingView,
|
|
1744
1822
|
{
|
|
1745
|
-
style:
|
|
1746
|
-
behavior:
|
|
1823
|
+
style: styles11.root,
|
|
1824
|
+
behavior: Platform7.OS === "ios" ? "padding" : void 0,
|
|
1747
1825
|
children: [
|
|
1748
|
-
/* @__PURE__ */
|
|
1826
|
+
/* @__PURE__ */ jsx13(
|
|
1749
1827
|
FlatList,
|
|
1750
1828
|
{
|
|
1751
1829
|
ref: listRef,
|
|
1752
|
-
style:
|
|
1830
|
+
style: styles11.list,
|
|
1753
1831
|
data: listData,
|
|
1754
1832
|
inverted: useInverted,
|
|
1755
1833
|
keyExtractor: (m) => m.id,
|
|
@@ -1757,13 +1835,13 @@ function AdasChatScreen({
|
|
|
1757
1835
|
ListHeaderComponent: useInverted ? typingIndicator : null,
|
|
1758
1836
|
ListFooterComponent: useInverted ? null : typingIndicator,
|
|
1759
1837
|
onContentSizeChange: useInverted ? void 0 : () => scrollToLatest(false),
|
|
1760
|
-
refreshControl: /* @__PURE__ */
|
|
1838
|
+
refreshControl: /* @__PURE__ */ jsx13(RefreshControl, { refreshing, onRefresh: handleRefresh, tintColor: ada8.orange }),
|
|
1761
1839
|
keyboardShouldPersistTaps: "handled",
|
|
1762
|
-
contentContainerStyle:
|
|
1840
|
+
contentContainerStyle: styles11.listContent
|
|
1763
1841
|
}
|
|
1764
1842
|
),
|
|
1765
1843
|
footerAccessory,
|
|
1766
|
-
/* @__PURE__ */
|
|
1844
|
+
/* @__PURE__ */ jsx13(
|
|
1767
1845
|
ChatInput,
|
|
1768
1846
|
{
|
|
1769
1847
|
onSend: handleSend,
|
|
@@ -1773,16 +1851,16 @@ function AdasChatScreen({
|
|
|
1773
1851
|
placeholder
|
|
1774
1852
|
}
|
|
1775
1853
|
),
|
|
1776
|
-
withLightbox && /* @__PURE__ */
|
|
1777
|
-
/* @__PURE__ */
|
|
1854
|
+
withLightbox && /* @__PURE__ */ jsx13(Lightbox, {}),
|
|
1855
|
+
/* @__PURE__ */ jsx13(WidgetHost, {})
|
|
1778
1856
|
]
|
|
1779
1857
|
}
|
|
1780
1858
|
);
|
|
1781
1859
|
}
|
|
1782
|
-
var
|
|
1860
|
+
var styles11 = StyleSheet11.create({
|
|
1783
1861
|
root: {
|
|
1784
1862
|
flex: 1,
|
|
1785
|
-
backgroundColor:
|
|
1863
|
+
backgroundColor: ada8.paper
|
|
1786
1864
|
},
|
|
1787
1865
|
list: {
|
|
1788
1866
|
flex: 1
|
|
@@ -1796,18 +1874,18 @@ var styles10 = StyleSheet10.create({
|
|
|
1796
1874
|
import { useMemo as useMemo4, useState as useState7 } from "react";
|
|
1797
1875
|
import {
|
|
1798
1876
|
Modal as Modal2,
|
|
1799
|
-
View as
|
|
1800
|
-
Text as
|
|
1801
|
-
Pressable as
|
|
1802
|
-
StyleSheet as
|
|
1877
|
+
View as View13,
|
|
1878
|
+
Text as Text9,
|
|
1879
|
+
Pressable as Pressable7,
|
|
1880
|
+
StyleSheet as StyleSheet12,
|
|
1803
1881
|
ActivityIndicator as ActivityIndicator4,
|
|
1804
|
-
Platform as
|
|
1882
|
+
Platform as Platform8
|
|
1805
1883
|
} from "react-native";
|
|
1806
1884
|
import { WebView as WebView2 } from "react-native-webview";
|
|
1807
|
-
import { ada as
|
|
1885
|
+
import { ada as ada9 } from "@ateam-ai-mobile/core";
|
|
1808
1886
|
import { getCoreApiUrl as getCoreApiUrl2 } from "@ateam-ai-mobile/core";
|
|
1809
|
-
import { Fragment as Fragment2, jsx as
|
|
1810
|
-
var
|
|
1887
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1888
|
+
var fontFam5 = Platform8.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
1811
1889
|
function WidgetWebView({ visible, title, bundleUrl, onClose }) {
|
|
1812
1890
|
const [loading, setLoading] = useState7(true);
|
|
1813
1891
|
const [error, setError] = useState7(null);
|
|
@@ -1816,28 +1894,28 @@ function WidgetWebView({ visible, title, bundleUrl, onClose }) {
|
|
|
1816
1894
|
if (/^https?:\/\//i.test(bundleUrl)) return bundleUrl;
|
|
1817
1895
|
return `${getCoreApiUrl2()}${bundleUrl}`;
|
|
1818
1896
|
}, [bundleUrl]);
|
|
1819
|
-
return /* @__PURE__ */
|
|
1897
|
+
return /* @__PURE__ */ jsx14(
|
|
1820
1898
|
Modal2,
|
|
1821
1899
|
{
|
|
1822
1900
|
visible,
|
|
1823
1901
|
animationType: "slide",
|
|
1824
1902
|
presentationStyle: "pageSheet",
|
|
1825
1903
|
onRequestClose: onClose,
|
|
1826
|
-
children: /* @__PURE__ */ jsxs10(
|
|
1827
|
-
/* @__PURE__ */ jsxs10(
|
|
1828
|
-
/* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
1904
|
+
children: /* @__PURE__ */ jsxs10(View13, { style: styles12.root, children: [
|
|
1905
|
+
/* @__PURE__ */ jsxs10(View13, { style: styles12.bar, children: [
|
|
1906
|
+
/* @__PURE__ */ jsx14(Pressable7, { onPress: onClose, hitSlop: 12, style: styles12.closeBtn, children: /* @__PURE__ */ jsx14(Text9, { style: styles12.closeIcon, children: "\u2715" }) }),
|
|
1907
|
+
/* @__PURE__ */ jsx14(Text9, { style: styles12.title, numberOfLines: 1, children: title || "Widget" }),
|
|
1908
|
+
/* @__PURE__ */ jsx14(View13, { style: styles12.closeBtn })
|
|
1831
1909
|
] }),
|
|
1832
|
-
!uri ? /* @__PURE__ */
|
|
1833
|
-
/* @__PURE__ */
|
|
1834
|
-
/* @__PURE__ */
|
|
1910
|
+
!uri ? /* @__PURE__ */ jsx14(View13, { style: styles12.errorWrap, children: /* @__PURE__ */ jsx14(Text9, { style: styles12.errorText, children: "No bundle available for this widget." }) }) : error ? /* @__PURE__ */ jsxs10(View13, { style: styles12.errorWrap, children: [
|
|
1911
|
+
/* @__PURE__ */ jsx14(Text9, { style: styles12.errorText, children: "Couldn't load widget" }),
|
|
1912
|
+
/* @__PURE__ */ jsx14(Text9, { style: styles12.errorSub, children: error })
|
|
1835
1913
|
] }) : /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
1836
|
-
/* @__PURE__ */
|
|
1914
|
+
/* @__PURE__ */ jsx14(
|
|
1837
1915
|
WebView2,
|
|
1838
1916
|
{
|
|
1839
1917
|
source: { uri },
|
|
1840
|
-
style:
|
|
1918
|
+
style: styles12.web,
|
|
1841
1919
|
onLoadStart: () => {
|
|
1842
1920
|
setLoading(true);
|
|
1843
1921
|
setError(null);
|
|
@@ -1855,16 +1933,16 @@ function WidgetWebView({ visible, title, bundleUrl, onClose }) {
|
|
|
1855
1933
|
setSupportMultipleWindows: false
|
|
1856
1934
|
}
|
|
1857
1935
|
),
|
|
1858
|
-
loading && /* @__PURE__ */
|
|
1936
|
+
loading && /* @__PURE__ */ jsx14(View13, { pointerEvents: "none", style: styles12.spinner, children: /* @__PURE__ */ jsx14(ActivityIndicator4, { color: ada9.orange }) })
|
|
1859
1937
|
] })
|
|
1860
1938
|
] })
|
|
1861
1939
|
}
|
|
1862
1940
|
);
|
|
1863
1941
|
}
|
|
1864
|
-
var
|
|
1942
|
+
var styles12 = StyleSheet12.create({
|
|
1865
1943
|
root: {
|
|
1866
1944
|
flex: 1,
|
|
1867
|
-
backgroundColor:
|
|
1945
|
+
backgroundColor: ada9.paper
|
|
1868
1946
|
},
|
|
1869
1947
|
bar: {
|
|
1870
1948
|
flexDirection: "row",
|
|
@@ -1872,8 +1950,8 @@ var styles11 = StyleSheet11.create({
|
|
|
1872
1950
|
paddingHorizontal: 14,
|
|
1873
1951
|
paddingVertical: 12,
|
|
1874
1952
|
borderBottomWidth: 1,
|
|
1875
|
-
borderBottomColor:
|
|
1876
|
-
backgroundColor:
|
|
1953
|
+
borderBottomColor: ada9.border,
|
|
1954
|
+
backgroundColor: ada9.paperSoft
|
|
1877
1955
|
},
|
|
1878
1956
|
closeBtn: {
|
|
1879
1957
|
width: 32,
|
|
@@ -1883,7 +1961,7 @@ var styles11 = StyleSheet11.create({
|
|
|
1883
1961
|
},
|
|
1884
1962
|
closeIcon: {
|
|
1885
1963
|
fontSize: 18,
|
|
1886
|
-
color:
|
|
1964
|
+
color: ada9.ink,
|
|
1887
1965
|
fontWeight: "500"
|
|
1888
1966
|
},
|
|
1889
1967
|
title: {
|
|
@@ -1891,13 +1969,13 @@ var styles11 = StyleSheet11.create({
|
|
|
1891
1969
|
textAlign: "center",
|
|
1892
1970
|
fontSize: 16,
|
|
1893
1971
|
fontWeight: "600",
|
|
1894
|
-
color:
|
|
1895
|
-
fontFamily:
|
|
1972
|
+
color: ada9.ink,
|
|
1973
|
+
fontFamily: fontFam5,
|
|
1896
1974
|
letterSpacing: -0.2
|
|
1897
1975
|
},
|
|
1898
1976
|
web: {
|
|
1899
1977
|
flex: 1,
|
|
1900
|
-
backgroundColor:
|
|
1978
|
+
backgroundColor: ada9.paper
|
|
1901
1979
|
},
|
|
1902
1980
|
spinner: {
|
|
1903
1981
|
position: "absolute",
|
|
@@ -1914,23 +1992,23 @@ var styles11 = StyleSheet11.create({
|
|
|
1914
1992
|
},
|
|
1915
1993
|
errorText: {
|
|
1916
1994
|
fontSize: 15,
|
|
1917
|
-
color:
|
|
1995
|
+
color: ada9.ink,
|
|
1918
1996
|
fontWeight: "600",
|
|
1919
1997
|
marginBottom: 6
|
|
1920
1998
|
},
|
|
1921
1999
|
errorSub: {
|
|
1922
2000
|
fontSize: 13,
|
|
1923
|
-
color:
|
|
2001
|
+
color: ada9.inkMuted,
|
|
1924
2002
|
textAlign: "center"
|
|
1925
2003
|
}
|
|
1926
2004
|
});
|
|
1927
2005
|
|
|
1928
2006
|
// src/TenantPicker.tsx
|
|
1929
2007
|
import { useEffect as useEffect7, useState as useState8 } from "react";
|
|
1930
|
-
import { View as
|
|
1931
|
-
import { ada as
|
|
1932
|
-
import { jsx as
|
|
1933
|
-
var
|
|
2008
|
+
import { View as View14, Text as Text10, Pressable as Pressable8, ActivityIndicator as ActivityIndicator5, StyleSheet as StyleSheet13, Platform as Platform9 } from "react-native";
|
|
2009
|
+
import { ada as ada10, fontSize as fontSize6, borderRadius as borderRadius4, listMyTenants, switchTenant, getTenant as getTenant4 } from "@ateam-ai-mobile/core";
|
|
2010
|
+
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2011
|
+
var fontFam6 = Platform9.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
1934
2012
|
function TenantPicker({ onSwitched, onSelect, currentTenantId }) {
|
|
1935
2013
|
const [tenants, setTenants] = useState8(null);
|
|
1936
2014
|
const [error, setError] = useState8(null);
|
|
@@ -1964,36 +2042,36 @@ function TenantPicker({ onSwitched, onSelect, currentTenantId }) {
|
|
|
1964
2042
|
setSwitching(null);
|
|
1965
2043
|
}
|
|
1966
2044
|
};
|
|
1967
|
-
if (error) return /* @__PURE__ */
|
|
2045
|
+
if (error) return /* @__PURE__ */ jsx15(Text10, { style: styles13.error, children: error });
|
|
1968
2046
|
if (!tenants) {
|
|
1969
|
-
return /* @__PURE__ */
|
|
2047
|
+
return /* @__PURE__ */ jsx15(View14, { style: styles13.loading, children: /* @__PURE__ */ jsx15(ActivityIndicator5, { color: ada10.orange }) });
|
|
1970
2048
|
}
|
|
1971
|
-
if (tenants.length === 0) return /* @__PURE__ */
|
|
1972
|
-
return /* @__PURE__ */
|
|
2049
|
+
if (tenants.length === 0) return /* @__PURE__ */ jsx15(Text10, { style: styles13.empty, children: "No teams found for this account." });
|
|
2050
|
+
return /* @__PURE__ */ jsx15(View14, { style: styles13.list, children: tenants.map((t) => {
|
|
1973
2051
|
const isActive = t.id === active;
|
|
1974
2052
|
const isSwitching = switching === t.id;
|
|
1975
2053
|
return /* @__PURE__ */ jsxs11(
|
|
1976
|
-
|
|
2054
|
+
Pressable8,
|
|
1977
2055
|
{
|
|
1978
2056
|
accessibilityRole: "button",
|
|
1979
2057
|
accessibilityLabel: `Team ${t.name}${isActive ? ", current" : ""}`,
|
|
1980
2058
|
disabled: !!switching,
|
|
1981
2059
|
onPress: () => handlePress(t),
|
|
1982
|
-
style: [
|
|
2060
|
+
style: [styles13.row, isActive && styles13.rowActive],
|
|
1983
2061
|
children: [
|
|
1984
|
-
/* @__PURE__ */
|
|
1985
|
-
/* @__PURE__ */ jsxs11(
|
|
1986
|
-
/* @__PURE__ */
|
|
1987
|
-
/* @__PURE__ */
|
|
2062
|
+
/* @__PURE__ */ jsx15(View14, { style: styles13.dot }),
|
|
2063
|
+
/* @__PURE__ */ jsxs11(View14, { style: styles13.rowText, children: [
|
|
2064
|
+
/* @__PURE__ */ jsx15(Text10, { style: styles13.name, children: t.name }),
|
|
2065
|
+
/* @__PURE__ */ jsx15(Text10, { style: styles13.slug, children: t.id })
|
|
1988
2066
|
] }),
|
|
1989
|
-
isSwitching ? /* @__PURE__ */
|
|
2067
|
+
isSwitching ? /* @__PURE__ */ jsx15(ActivityIndicator5, { color: ada10.orange }) : isActive ? /* @__PURE__ */ jsx15(Text10, { style: styles13.check, children: "\u2713" }) : null
|
|
1990
2068
|
]
|
|
1991
2069
|
},
|
|
1992
2070
|
t.id
|
|
1993
2071
|
);
|
|
1994
2072
|
}) });
|
|
1995
2073
|
}
|
|
1996
|
-
var
|
|
2074
|
+
var styles13 = StyleSheet13.create({
|
|
1997
2075
|
list: {
|
|
1998
2076
|
gap: 10
|
|
1999
2077
|
},
|
|
@@ -2001,7 +2079,7 @@ var styles12 = StyleSheet12.create({
|
|
|
2001
2079
|
flexDirection: "row",
|
|
2002
2080
|
alignItems: "center",
|
|
2003
2081
|
gap: 12,
|
|
2004
|
-
backgroundColor:
|
|
2082
|
+
backgroundColor: ada10.paperSoft,
|
|
2005
2083
|
borderRadius: borderRadius4.lg,
|
|
2006
2084
|
borderWidth: 1,
|
|
2007
2085
|
borderColor: "transparent",
|
|
@@ -2009,32 +2087,32 @@ var styles12 = StyleSheet12.create({
|
|
|
2009
2087
|
paddingVertical: 14
|
|
2010
2088
|
},
|
|
2011
2089
|
rowActive: {
|
|
2012
|
-
backgroundColor:
|
|
2013
|
-
borderColor:
|
|
2090
|
+
backgroundColor: ada10.orangeSoft,
|
|
2091
|
+
borderColor: ada10.orange
|
|
2014
2092
|
},
|
|
2015
2093
|
dot: {
|
|
2016
2094
|
width: 10,
|
|
2017
2095
|
height: 10,
|
|
2018
2096
|
borderRadius: 5,
|
|
2019
|
-
backgroundColor:
|
|
2097
|
+
backgroundColor: ada10.orange
|
|
2020
2098
|
},
|
|
2021
2099
|
rowText: {
|
|
2022
2100
|
flex: 1
|
|
2023
2101
|
},
|
|
2024
2102
|
name: {
|
|
2025
|
-
color:
|
|
2026
|
-
fontSize:
|
|
2103
|
+
color: ada10.ink,
|
|
2104
|
+
fontSize: fontSize6.lg,
|
|
2027
2105
|
fontWeight: "600",
|
|
2028
|
-
fontFamily:
|
|
2106
|
+
fontFamily: fontFam6
|
|
2029
2107
|
},
|
|
2030
2108
|
slug: {
|
|
2031
|
-
color:
|
|
2032
|
-
fontSize:
|
|
2109
|
+
color: ada10.inkMuted,
|
|
2110
|
+
fontSize: fontSize6.sm,
|
|
2033
2111
|
fontFamily: "monospace"
|
|
2034
2112
|
},
|
|
2035
2113
|
check: {
|
|
2036
|
-
color:
|
|
2037
|
-
fontSize:
|
|
2114
|
+
color: ada10.orangeDeep,
|
|
2115
|
+
fontSize: fontSize6.lg,
|
|
2038
2116
|
fontWeight: "700"
|
|
2039
2117
|
},
|
|
2040
2118
|
loading: {
|
|
@@ -2042,37 +2120,553 @@ var styles12 = StyleSheet12.create({
|
|
|
2042
2120
|
alignItems: "center"
|
|
2043
2121
|
},
|
|
2044
2122
|
empty: {
|
|
2045
|
-
color:
|
|
2046
|
-
fontSize:
|
|
2123
|
+
color: ada10.inkMuted,
|
|
2124
|
+
fontSize: fontSize6.md,
|
|
2047
2125
|
textAlign: "center",
|
|
2048
2126
|
paddingVertical: 16
|
|
2049
2127
|
},
|
|
2050
2128
|
error: {
|
|
2051
2129
|
color: "#C15545",
|
|
2052
|
-
fontSize:
|
|
2130
|
+
fontSize: fontSize6.md,
|
|
2053
2131
|
textAlign: "center",
|
|
2054
2132
|
paddingVertical: 16
|
|
2055
2133
|
}
|
|
2056
2134
|
});
|
|
2057
2135
|
|
|
2136
|
+
// src/WorkspaceBanner.tsx
|
|
2137
|
+
import { View as View15, Text as Text11, StyleSheet as StyleSheet14 } from "react-native";
|
|
2138
|
+
import { ada as ada11, fontSize as fontSize7, spacing as spacing2, useWorkspaceStore } from "@ateam-ai-mobile/core";
|
|
2139
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2140
|
+
var WARM_AMBER2 = "#D49A4E";
|
|
2141
|
+
var WARM_AMBER_SOFT2 = "rgba(212, 154, 78, 0.16)";
|
|
2142
|
+
var WARM_AMBER_BORDER = "rgba(212, 154, 78, 0.4)";
|
|
2143
|
+
function WorkspaceBanner({ topInset = 0 }) {
|
|
2144
|
+
const snapshot = useWorkspaceStore((s) => s.snapshot);
|
|
2145
|
+
if (!snapshot) return null;
|
|
2146
|
+
if (snapshot.state === "active" || snapshot.state === "unknown") return null;
|
|
2147
|
+
if (!snapshot.message) return null;
|
|
2148
|
+
return /* @__PURE__ */ jsxs12(
|
|
2149
|
+
View15,
|
|
2150
|
+
{
|
|
2151
|
+
style: [styles14.container, { paddingTop: spacing2.sm + topInset }],
|
|
2152
|
+
accessibilityRole: "alert",
|
|
2153
|
+
accessibilityLabel: snapshot.message,
|
|
2154
|
+
children: [
|
|
2155
|
+
/* @__PURE__ */ jsx16(View15, { style: styles14.dot }),
|
|
2156
|
+
/* @__PURE__ */ jsx16(Text11, { style: styles14.message, children: snapshot.message })
|
|
2157
|
+
]
|
|
2158
|
+
}
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
var styles14 = StyleSheet14.create({
|
|
2162
|
+
container: {
|
|
2163
|
+
flexDirection: "row",
|
|
2164
|
+
alignItems: "flex-start",
|
|
2165
|
+
gap: spacing2.sm,
|
|
2166
|
+
paddingHorizontal: spacing2.md,
|
|
2167
|
+
paddingBottom: spacing2.sm,
|
|
2168
|
+
backgroundColor: WARM_AMBER_SOFT2,
|
|
2169
|
+
borderBottomWidth: StyleSheet14.hairlineWidth,
|
|
2170
|
+
borderBottomColor: WARM_AMBER_BORDER
|
|
2171
|
+
},
|
|
2172
|
+
dot: {
|
|
2173
|
+
width: 8,
|
|
2174
|
+
height: 8,
|
|
2175
|
+
borderRadius: 4,
|
|
2176
|
+
marginTop: 5,
|
|
2177
|
+
backgroundColor: WARM_AMBER2
|
|
2178
|
+
},
|
|
2179
|
+
message: {
|
|
2180
|
+
flex: 1,
|
|
2181
|
+
color: ada11.ink,
|
|
2182
|
+
fontSize: fontSize7.sm,
|
|
2183
|
+
lineHeight: fontSize7.sm * 1.35
|
|
2184
|
+
}
|
|
2185
|
+
});
|
|
2186
|
+
|
|
2187
|
+
// src/auth/HandoffScreen.tsx
|
|
2188
|
+
import { useEffect as useEffect8, useRef as useRef5, useState as useState9 } from "react";
|
|
2189
|
+
import { View as View16, Text as Text12, Pressable as Pressable9, StyleSheet as StyleSheet15, Platform as Platform10, ActivityIndicator as ActivityIndicator6 } from "react-native";
|
|
2190
|
+
import { exchangeHandoff, ada as ada12 } from "@ateam-ai-mobile/core";
|
|
2191
|
+
import { AdaOrb as AdaOrb3 } from "@ateam-ai-mobile/plugin-runtime";
|
|
2192
|
+
|
|
2193
|
+
// src/auth/handoffExchange.ts
|
|
2194
|
+
async function runHandoffExchange(code, deps) {
|
|
2195
|
+
const res = await deps.exchange(code);
|
|
2196
|
+
if (res.tenant) await deps.onAdoptTenant(res.tenant);
|
|
2197
|
+
await deps.onSignedIn(res.jwt);
|
|
2198
|
+
deps.onDone();
|
|
2199
|
+
}
|
|
2200
|
+
function handoffErrorMessage(msg) {
|
|
2201
|
+
const m = (msg || "").toLowerCase();
|
|
2202
|
+
if (m.includes("429") || m.includes("rate") || m.includes("too many")) {
|
|
2203
|
+
return "Too many attempts \u2014 wait a moment, then get a new sign-in link on the web.";
|
|
2204
|
+
}
|
|
2205
|
+
return "This sign-in link is no longer valid. Get a new one on the web and try again.";
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
// src/auth/HandoffScreen.tsx
|
|
2209
|
+
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2210
|
+
var fontFam7 = Platform10.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
2211
|
+
function HandoffScreen({ code, onAdoptTenant, onSignedIn, onDone, onCancel }) {
|
|
2212
|
+
const [err, setErr] = useState9(null);
|
|
2213
|
+
const startedForRef = useRef5(null);
|
|
2214
|
+
useEffect8(() => {
|
|
2215
|
+
if (!code || startedForRef.current === code) return;
|
|
2216
|
+
startedForRef.current = code;
|
|
2217
|
+
runHandoffExchange(code, { exchange: exchangeHandoff, onAdoptTenant, onSignedIn, onDone }).catch((e) => setErr(handoffErrorMessage(e?.message)));
|
|
2218
|
+
}, [code, onAdoptTenant, onSignedIn, onDone]);
|
|
2219
|
+
return /* @__PURE__ */ jsx17(View16, { style: styles15.container, children: /* @__PURE__ */ jsxs13(View16, { style: styles15.center, children: [
|
|
2220
|
+
/* @__PURE__ */ jsx17(AdaOrb3, { size: 72, state: err ? "idle" : "thinking" }),
|
|
2221
|
+
!err ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
2222
|
+
/* @__PURE__ */ jsx17(Text12, { style: styles15.title, children: "Signing you in\u2026" }),
|
|
2223
|
+
/* @__PURE__ */ jsx17(ActivityIndicator6, { color: ada12.ink, style: { marginTop: 6 } })
|
|
2224
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
2225
|
+
/* @__PURE__ */ jsx17(Text12, { style: styles15.title, children: "Couldn\u2019t finish sign-in" }),
|
|
2226
|
+
/* @__PURE__ */ jsx17(Text12, { style: styles15.sub, children: err }),
|
|
2227
|
+
/* @__PURE__ */ jsx17(Pressable9, { onPress: onCancel, hitSlop: 8, style: styles15.back, children: /* @__PURE__ */ jsx17(Text12, { style: styles15.backText, children: "Back to sign in" }) })
|
|
2228
|
+
] })
|
|
2229
|
+
] }) });
|
|
2230
|
+
}
|
|
2231
|
+
var styles15 = StyleSheet15.create({
|
|
2232
|
+
container: { flex: 1, backgroundColor: ada12.paper },
|
|
2233
|
+
center: { flex: 1, alignItems: "center", justifyContent: "center", gap: 14, paddingHorizontal: 32 },
|
|
2234
|
+
title: { fontSize: 20, fontWeight: "600", color: ada12.ink, fontFamily: fontFam7, marginTop: 8 },
|
|
2235
|
+
sub: { fontSize: 14, lineHeight: 20, color: ada12.inkSoft, textAlign: "center", fontFamily: fontFam7 },
|
|
2236
|
+
back: { marginTop: 10, paddingVertical: 10 },
|
|
2237
|
+
backText: { fontSize: 15, fontWeight: "600", color: ada12.orangeDeep, fontFamily: fontFam7 }
|
|
2238
|
+
});
|
|
2239
|
+
|
|
2240
|
+
// src/auth/OpenJoinScreen.tsx
|
|
2241
|
+
import { useEffect as useEffect9, useState as useState10 } from "react";
|
|
2242
|
+
import { View as View17, Text as Text13, Pressable as Pressable10, StyleSheet as StyleSheet16, ActivityIndicator as ActivityIndicator7, Platform as Platform11, TextInput as TextInput2 } from "react-native";
|
|
2243
|
+
import { openJoinWithGoogle, openJoinWithApple, ada as ada13, spacing as spacing3 } from "@ateam-ai-mobile/core";
|
|
2244
|
+
import { AdaOrb as AdaOrb4 } from "@ateam-ai-mobile/plugin-runtime";
|
|
2245
|
+
|
|
2246
|
+
// src/auth/openJoin.ts
|
|
2247
|
+
async function completeOpenJoin(slug, idToken, deps) {
|
|
2248
|
+
if (!idToken) return false;
|
|
2249
|
+
const consumer = await deps.join(slug, idToken);
|
|
2250
|
+
await deps.onAdoptTenant(slug);
|
|
2251
|
+
await deps.onSignedIn(consumer.jwt);
|
|
2252
|
+
return true;
|
|
2253
|
+
}
|
|
2254
|
+
function openJoinErrorMessage(msg) {
|
|
2255
|
+
const m = (msg || "").toLowerCase();
|
|
2256
|
+
if (m.includes("invite-only") || m.includes("invite only")) {
|
|
2257
|
+
return "This team is invite-only \u2014 ask an admin for an invite link.";
|
|
2258
|
+
}
|
|
2259
|
+
if (m.includes("not found") || m.includes("unknown tenant")) {
|
|
2260
|
+
return "No team with that handle.";
|
|
2261
|
+
}
|
|
2262
|
+
return msg || "Could not join";
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
// src/auth/OpenJoinScreen.tsx
|
|
2266
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2267
|
+
var fontFam8 = Platform11.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
2268
|
+
function OpenJoinScreen({ onAdoptTenant, onSignedIn, onBack }) {
|
|
2269
|
+
const [team, setTeam] = useState10("");
|
|
2270
|
+
const [busy, setBusy] = useState10(false);
|
|
2271
|
+
const [err, setErr] = useState10(null);
|
|
2272
|
+
const [appleAvailable, setAppleAvailable] = useState10(false);
|
|
2273
|
+
useEffect9(() => {
|
|
2274
|
+
getOAuthProvider()?.isAppleAvailable().then(setAppleAvailable).catch(() => setAppleAvailable(false));
|
|
2275
|
+
}, []);
|
|
2276
|
+
const slug = team.trim().toLowerCase();
|
|
2277
|
+
const canSubmit = slug.length > 0 && !busy;
|
|
2278
|
+
async function run(acquire, join) {
|
|
2279
|
+
if (!slug) return;
|
|
2280
|
+
const oauth = getOAuthProvider();
|
|
2281
|
+
if (!oauth) {
|
|
2282
|
+
setErr("Sign-in is unavailable on this device.");
|
|
2283
|
+
return;
|
|
2284
|
+
}
|
|
2285
|
+
setErr(null);
|
|
2286
|
+
setBusy(true);
|
|
2287
|
+
try {
|
|
2288
|
+
const idToken = await acquire(oauth);
|
|
2289
|
+
await completeOpenJoin(slug, idToken, { join, onAdoptTenant, onSignedIn });
|
|
2290
|
+
} catch (e) {
|
|
2291
|
+
setErr(openJoinErrorMessage(e?.message));
|
|
2292
|
+
} finally {
|
|
2293
|
+
setBusy(false);
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
const handleGoogle = () => run((oauth) => oauth.signInWithGoogle(), openJoinWithGoogle);
|
|
2297
|
+
const handleApple = () => run((oauth) => oauth.signInWithApple(), openJoinWithApple);
|
|
2298
|
+
return /* @__PURE__ */ jsxs14(View17, { style: styles16.container, children: [
|
|
2299
|
+
/* @__PURE__ */ jsxs14(View17, { style: styles16.hero, children: [
|
|
2300
|
+
/* @__PURE__ */ jsx18(AdaOrb4, { size: 110 }),
|
|
2301
|
+
/* @__PURE__ */ jsx18(Text13, { style: styles16.wordmark, children: "Join a team" }),
|
|
2302
|
+
/* @__PURE__ */ jsx18(Text13, { style: styles16.tagline, children: "Enter the team's handle. If it's open to join, you're in." })
|
|
2303
|
+
] }),
|
|
2304
|
+
/* @__PURE__ */ jsxs14(View17, { style: styles16.form, children: [
|
|
2305
|
+
/* @__PURE__ */ jsx18(
|
|
2306
|
+
TextInput2,
|
|
2307
|
+
{
|
|
2308
|
+
style: styles16.input,
|
|
2309
|
+
value: team,
|
|
2310
|
+
onChangeText: setTeam,
|
|
2311
|
+
placeholder: "team handle (e.g. acme)",
|
|
2312
|
+
placeholderTextColor: ada13.inkMuted,
|
|
2313
|
+
autoCapitalize: "none",
|
|
2314
|
+
autoCorrect: false,
|
|
2315
|
+
returnKeyType: "done"
|
|
2316
|
+
}
|
|
2317
|
+
),
|
|
2318
|
+
/* @__PURE__ */ jsxs14(
|
|
2319
|
+
Pressable10,
|
|
2320
|
+
{
|
|
2321
|
+
style: [styles16.googleBtn, !canSubmit && styles16.btnDisabled],
|
|
2322
|
+
onPress: handleGoogle,
|
|
2323
|
+
disabled: !canSubmit,
|
|
2324
|
+
children: [
|
|
2325
|
+
/* @__PURE__ */ jsx18(Text13, { style: styles16.googleGlyph, children: "G" }),
|
|
2326
|
+
/* @__PURE__ */ jsx18(Text13, { style: styles16.googleText, children: "Continue with Google" })
|
|
2327
|
+
]
|
|
2328
|
+
}
|
|
2329
|
+
),
|
|
2330
|
+
appleAvailable && /* @__PURE__ */ jsx18(View17, { style: { opacity: canSubmit ? 1 : 0.5 }, pointerEvents: canSubmit ? "auto" : "none", children: getOAuthProvider()?.renderAppleButton({ onPress: handleApple, disabled: !canSubmit, style: styles16.appleBtn }) }),
|
|
2331
|
+
busy && /* @__PURE__ */ jsx18(ActivityIndicator7, { color: ada13.ink, style: { marginTop: 10 } }),
|
|
2332
|
+
!!err && /* @__PURE__ */ jsx18(Text13, { style: styles16.err, children: err }),
|
|
2333
|
+
/* @__PURE__ */ jsx18(Pressable10, { onPress: onBack, hitSlop: 8, style: styles16.back, children: /* @__PURE__ */ jsx18(Text13, { style: styles16.backText, children: "Back to sign in" }) })
|
|
2334
|
+
] })
|
|
2335
|
+
] });
|
|
2336
|
+
}
|
|
2337
|
+
var styles16 = StyleSheet16.create({
|
|
2338
|
+
container: { flex: 1, backgroundColor: ada13.paper, justifyContent: "space-between" },
|
|
2339
|
+
hero: { alignItems: "center", marginTop: spacing3.xxl },
|
|
2340
|
+
wordmark: { fontSize: 26, fontWeight: "800", color: ada13.ink, marginTop: 14, fontFamily: fontFam8 },
|
|
2341
|
+
tagline: { fontSize: 15, color: ada13.inkSoft, marginTop: 8, textAlign: "center", paddingHorizontal: 28, fontFamily: fontFam8 },
|
|
2342
|
+
form: { paddingHorizontal: 24, paddingBottom: 40, gap: 12 },
|
|
2343
|
+
input: {
|
|
2344
|
+
backgroundColor: ada13.paperSoft,
|
|
2345
|
+
borderWidth: 1,
|
|
2346
|
+
borderColor: ada13.border,
|
|
2347
|
+
borderRadius: 14,
|
|
2348
|
+
paddingHorizontal: 16,
|
|
2349
|
+
paddingVertical: 14,
|
|
2350
|
+
fontSize: 16,
|
|
2351
|
+
color: ada13.ink
|
|
2352
|
+
},
|
|
2353
|
+
googleBtn: {
|
|
2354
|
+
flexDirection: "row",
|
|
2355
|
+
alignItems: "center",
|
|
2356
|
+
justifyContent: "center",
|
|
2357
|
+
gap: 10,
|
|
2358
|
+
backgroundColor: ada13.ink,
|
|
2359
|
+
paddingVertical: 15,
|
|
2360
|
+
borderRadius: 999
|
|
2361
|
+
},
|
|
2362
|
+
btnDisabled: { opacity: 0.5 },
|
|
2363
|
+
googleGlyph: { color: "#fff", fontSize: 18, fontWeight: "800" },
|
|
2364
|
+
googleText: { color: "#fff", fontSize: 16, fontWeight: "600", fontFamily: fontFam8 },
|
|
2365
|
+
appleBtn: { height: 52, width: "100%" },
|
|
2366
|
+
err: { color: "#C15545", fontSize: 13, textAlign: "center", paddingHorizontal: 16, marginTop: 4 },
|
|
2367
|
+
back: { alignItems: "center", paddingVertical: 10 },
|
|
2368
|
+
backText: { color: ada13.inkMuted, fontSize: 15, fontWeight: "500" }
|
|
2369
|
+
});
|
|
2370
|
+
|
|
2371
|
+
// src/auth/JoinScreen.tsx
|
|
2372
|
+
import { useEffect as useEffect10, useMemo as useMemo5, useState as useState11 } from "react";
|
|
2373
|
+
import { View as View18, Text as Text14, Pressable as Pressable11, StyleSheet as StyleSheet17, ActivityIndicator as ActivityIndicator8, Platform as Platform12 } from "react-native";
|
|
2374
|
+
import {
|
|
2375
|
+
previewInvite,
|
|
2376
|
+
joinWithGoogle,
|
|
2377
|
+
joinWithApple,
|
|
2378
|
+
ada as ada14,
|
|
2379
|
+
spacing as spacing4
|
|
2380
|
+
} from "@ateam-ai-mobile/core";
|
|
2381
|
+
import { AdaOrb as AdaOrb5 } from "@ateam-ai-mobile/plugin-runtime";
|
|
2382
|
+
|
|
2383
|
+
// src/auth/inviteJoin.ts
|
|
2384
|
+
async function completeInviteJoin(code, idToken, deps) {
|
|
2385
|
+
if (!idToken) return false;
|
|
2386
|
+
const consumer = await deps.join(code, idToken);
|
|
2387
|
+
deps.onDone();
|
|
2388
|
+
await deps.onSignedIn(consumer.jwt);
|
|
2389
|
+
return true;
|
|
2390
|
+
}
|
|
2391
|
+
function inviteHeadline(preview) {
|
|
2392
|
+
if (!preview) return "";
|
|
2393
|
+
return preview.role ? `Join ${preview.org} as ${preview.role}?` : `Join ${preview.org}?`;
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
// src/auth/JoinScreen.tsx
|
|
2397
|
+
import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2398
|
+
var fontFam9 = Platform12.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
2399
|
+
function JoinScreen({ code, onSignedIn, onDone, onCancel }) {
|
|
2400
|
+
const [preview, setPreview] = useState11(null);
|
|
2401
|
+
const [loadErr, setLoadErr] = useState11(null);
|
|
2402
|
+
const [busy, setBusy] = useState11(false);
|
|
2403
|
+
const [err, setErr] = useState11(null);
|
|
2404
|
+
const [appleAvailable, setAppleAvailable] = useState11(false);
|
|
2405
|
+
useEffect10(() => {
|
|
2406
|
+
if (!code) return;
|
|
2407
|
+
setPreview(null);
|
|
2408
|
+
setLoadErr(null);
|
|
2409
|
+
previewInvite(code).then(setPreview).catch((e) => setLoadErr(e?.message || "Could not load invite"));
|
|
2410
|
+
}, [code]);
|
|
2411
|
+
useEffect10(() => {
|
|
2412
|
+
getOAuthProvider()?.isAppleAvailable().then(setAppleAvailable).catch(() => setAppleAvailable(false));
|
|
2413
|
+
}, []);
|
|
2414
|
+
const orgLine = useMemo5(() => inviteHeadline(preview), [preview]);
|
|
2415
|
+
async function run(acquire, join) {
|
|
2416
|
+
if (!code) return;
|
|
2417
|
+
const oauth = getOAuthProvider();
|
|
2418
|
+
if (!oauth) {
|
|
2419
|
+
setErr("Sign-in is unavailable on this device.");
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
setErr(null);
|
|
2423
|
+
setBusy(true);
|
|
2424
|
+
try {
|
|
2425
|
+
const idToken = await acquire(oauth);
|
|
2426
|
+
await completeInviteJoin(code, idToken, { join, onDone, onSignedIn });
|
|
2427
|
+
} catch (e) {
|
|
2428
|
+
setErr(e?.message || "Sign-in failed");
|
|
2429
|
+
} finally {
|
|
2430
|
+
setBusy(false);
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
const handleGoogle = () => run((oauth) => oauth.signInWithGoogle(), joinWithGoogle);
|
|
2434
|
+
const handleApple = () => run((oauth) => oauth.signInWithApple(), joinWithApple);
|
|
2435
|
+
return /* @__PURE__ */ jsxs15(View18, { style: styles17.container, children: [
|
|
2436
|
+
/* @__PURE__ */ jsxs15(View18, { style: styles17.hero, children: [
|
|
2437
|
+
/* @__PURE__ */ jsx19(AdaOrb5, { size: 120 }),
|
|
2438
|
+
/* @__PURE__ */ jsx19(Text14, { style: styles17.wordmark, children: "ada" }),
|
|
2439
|
+
loadErr ? /* @__PURE__ */ jsx19(Text14, { style: styles17.err, children: loadErr }) : preview ? /* @__PURE__ */ jsx19(Text14, { style: styles17.tagline, children: orgLine }) : /* @__PURE__ */ jsx19(ActivityIndicator8, { color: ada14.ink, style: { marginTop: 12 } })
|
|
2440
|
+
] }),
|
|
2441
|
+
/* @__PURE__ */ jsxs15(View18, { style: styles17.buttons, children: [
|
|
2442
|
+
preview && !loadErr && /* @__PURE__ */ jsxs15(Fragment4, { children: [
|
|
2443
|
+
/* @__PURE__ */ jsxs15(
|
|
2444
|
+
Pressable11,
|
|
2445
|
+
{
|
|
2446
|
+
style: [styles17.googleBtn, busy && styles17.btnDisabled],
|
|
2447
|
+
onPress: handleGoogle,
|
|
2448
|
+
disabled: busy,
|
|
2449
|
+
children: [
|
|
2450
|
+
/* @__PURE__ */ jsx19(Text14, { style: styles17.googleGlyph, children: "G" }),
|
|
2451
|
+
/* @__PURE__ */ jsx19(Text14, { style: styles17.googleText, children: "Continue with Google" })
|
|
2452
|
+
]
|
|
2453
|
+
}
|
|
2454
|
+
),
|
|
2455
|
+
appleAvailable && getOAuthProvider()?.renderAppleButton({ onPress: handleApple, disabled: busy, style: styles17.appleBtn })
|
|
2456
|
+
] }),
|
|
2457
|
+
loadErr && /* @__PURE__ */ jsx19(Pressable11, { style: styles17.dismiss, onPress: onCancel, hitSlop: 8, children: /* @__PURE__ */ jsx19(Text14, { style: styles17.dismissText, children: "Back to sign in" }) }),
|
|
2458
|
+
!!err && /* @__PURE__ */ jsx19(Text14, { style: styles17.err, children: err }),
|
|
2459
|
+
busy && /* @__PURE__ */ jsx19(ActivityIndicator8, { color: ada14.ink, style: { marginTop: 12 } }),
|
|
2460
|
+
/* @__PURE__ */ jsx19(Text14, { style: styles17.disclaimer, children: "By continuing you agree to Ada's Terms and Privacy Policy." })
|
|
2461
|
+
] })
|
|
2462
|
+
] });
|
|
2463
|
+
}
|
|
2464
|
+
var styles17 = StyleSheet17.create({
|
|
2465
|
+
container: { flex: 1, backgroundColor: ada14.paper, justifyContent: "space-between" },
|
|
2466
|
+
hero: { alignItems: "center", marginTop: spacing4.xxl * 1.4 },
|
|
2467
|
+
wordmark: { fontSize: 34, fontWeight: "800", color: ada14.ink, letterSpacing: 4, marginTop: 12, fontFamily: fontFam9 },
|
|
2468
|
+
tagline: { fontSize: 17, color: ada14.inkSoft, marginTop: 10, textAlign: "center", paddingHorizontal: 24, fontFamily: fontFam9 },
|
|
2469
|
+
buttons: { paddingHorizontal: 24, paddingBottom: 40, gap: 12 },
|
|
2470
|
+
googleBtn: {
|
|
2471
|
+
flexDirection: "row",
|
|
2472
|
+
alignItems: "center",
|
|
2473
|
+
justifyContent: "center",
|
|
2474
|
+
gap: 10,
|
|
2475
|
+
backgroundColor: ada14.ink,
|
|
2476
|
+
paddingVertical: 15,
|
|
2477
|
+
borderRadius: 999
|
|
2478
|
+
},
|
|
2479
|
+
btnDisabled: { opacity: 0.5 },
|
|
2480
|
+
googleGlyph: { color: "#fff", fontSize: 18, fontWeight: "800" },
|
|
2481
|
+
googleText: { color: "#fff", fontSize: 16, fontWeight: "600", fontFamily: fontFam9 },
|
|
2482
|
+
appleBtn: { height: 52, width: "100%" },
|
|
2483
|
+
dismiss: { alignItems: "center", paddingVertical: 10 },
|
|
2484
|
+
dismissText: { color: ada14.inkMuted, fontSize: 15, fontWeight: "500" },
|
|
2485
|
+
err: { color: "#C15545", fontSize: 13, textAlign: "center", paddingHorizontal: 16, marginTop: 8 },
|
|
2486
|
+
disclaimer: { fontSize: 12, color: ada14.inkMuted, textAlign: "center", marginTop: 8 }
|
|
2487
|
+
});
|
|
2488
|
+
|
|
2489
|
+
// src/auth/LoginScreen.tsx
|
|
2490
|
+
import { useEffect as useEffect11, useMemo as useMemo6, useState as useState12 } from "react";
|
|
2491
|
+
import { View as View19, Text as Text15, Pressable as Pressable12, StyleSheet as StyleSheet18, Platform as Platform13, ActivityIndicator as ActivityIndicator9 } from "react-native";
|
|
2492
|
+
import { fetchConsumerConfig, signInWithGoogle, signInWithApple, ada as ada15 } from "@ateam-ai-mobile/core";
|
|
2493
|
+
import { AdaOrb as AdaOrb6 } from "@ateam-ai-mobile/plugin-runtime";
|
|
2494
|
+
|
|
2495
|
+
// src/auth/login.ts
|
|
2496
|
+
function googleClientIds(config) {
|
|
2497
|
+
const g = config.providers.google || {};
|
|
2498
|
+
return {
|
|
2499
|
+
webClientId: g.web_client_id || g.client_id || "",
|
|
2500
|
+
iosClientId: g.ios_client_id || ""
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
function shouldRecoverToDefaultTenant(errorMsg, currentTenant, defaultTenant) {
|
|
2504
|
+
return /capability not enabled/i.test(errorMsg || "") && currentTenant !== defaultTenant;
|
|
2505
|
+
}
|
|
2506
|
+
async function completeProviderSignIn(idToken, deps) {
|
|
2507
|
+
if (!idToken) return false;
|
|
2508
|
+
const consumer = await deps.exchange(idToken);
|
|
2509
|
+
await deps.onSignedIn(consumer.jwt);
|
|
2510
|
+
return true;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
// src/auth/LoginScreen.tsx
|
|
2514
|
+
import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2515
|
+
var fontFam10 = Platform13.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
2516
|
+
function LoginScreen({ activeTenant, defaultTenant, onConsumerDisabled, onSignedIn, onJoinTeam }) {
|
|
2517
|
+
const [config, setConfig] = useState12(null);
|
|
2518
|
+
const [error, setError] = useState12(null);
|
|
2519
|
+
useEffect11(() => {
|
|
2520
|
+
setConfig(null);
|
|
2521
|
+
setError(null);
|
|
2522
|
+
fetchConsumerConfig().then(setConfig).catch(async (err) => {
|
|
2523
|
+
const msg = err?.message || "Failed to load sign-in config";
|
|
2524
|
+
if (shouldRecoverToDefaultTenant(msg, activeTenant, defaultTenant)) {
|
|
2525
|
+
await onConsumerDisabled();
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
setError(msg);
|
|
2529
|
+
});
|
|
2530
|
+
}, [activeTenant, defaultTenant, onConsumerDisabled]);
|
|
2531
|
+
return /* @__PURE__ */ jsxs16(View19, { style: styles18.container, children: [
|
|
2532
|
+
/* @__PURE__ */ jsxs16(View19, { style: styles18.hero, children: [
|
|
2533
|
+
/* @__PURE__ */ jsx20(AdaOrb6, { size: 140 }),
|
|
2534
|
+
/* @__PURE__ */ jsx20(Text15, { style: styles18.wordmark, children: "ada" }),
|
|
2535
|
+
/* @__PURE__ */ jsx20(Text15, { style: styles18.tagline, children: "Your private personal AI-Team" })
|
|
2536
|
+
] }),
|
|
2537
|
+
/* @__PURE__ */ jsxs16(View19, { style: styles18.buttonSection, children: [
|
|
2538
|
+
!config && !error && /* @__PURE__ */ jsx20(ActivityIndicator9, { color: ada15.ink }),
|
|
2539
|
+
!!error && /* @__PURE__ */ jsx20(Text15, { style: styles18.errorText, children: error }),
|
|
2540
|
+
!!config && /* @__PURE__ */ jsx20(SignInButtons, { config, onSignedIn }),
|
|
2541
|
+
onJoinTeam && /* @__PURE__ */ jsx20(Pressable12, { onPress: onJoinTeam, hitSlop: 8, style: { paddingVertical: 8 }, children: /* @__PURE__ */ jsx20(Text15, { style: styles18.joinLink, children: "Join a team by name" }) }),
|
|
2542
|
+
/* @__PURE__ */ jsx20(Text15, { style: styles18.disclaimer, children: "By continuing you agree to Ada's Terms and Privacy Policy." })
|
|
2543
|
+
] })
|
|
2544
|
+
] });
|
|
2545
|
+
}
|
|
2546
|
+
function SignInButtons({ config, onSignedIn }) {
|
|
2547
|
+
const [busy, setBusy] = useState12(false);
|
|
2548
|
+
const [error, setError] = useState12(null);
|
|
2549
|
+
const [appleAvailable, setAppleAvailable] = useState12(false);
|
|
2550
|
+
const { webClientId, iosClientId } = useMemo6(() => googleClientIds(config), [config]);
|
|
2551
|
+
useEffect11(() => {
|
|
2552
|
+
getOAuthProvider()?.isAppleAvailable().then(setAppleAvailable).catch(() => setAppleAvailable(false));
|
|
2553
|
+
}, []);
|
|
2554
|
+
const handleGoogleLogin = async () => {
|
|
2555
|
+
setError(null);
|
|
2556
|
+
if (!webClientId) {
|
|
2557
|
+
setError("Google sign-in is not configured for this tenant");
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
const oauth = getOAuthProvider();
|
|
2561
|
+
if (!oauth) {
|
|
2562
|
+
setError("Sign-in is unavailable on this device.");
|
|
2563
|
+
return;
|
|
2564
|
+
}
|
|
2565
|
+
setBusy(true);
|
|
2566
|
+
try {
|
|
2567
|
+
const idToken = await oauth.signInWithGoogle({ webClientId, iosClientId });
|
|
2568
|
+
await completeProviderSignIn(idToken, { exchange: signInWithGoogle, onSignedIn });
|
|
2569
|
+
} catch (err) {
|
|
2570
|
+
setError(err?.message || "Sign-in failed");
|
|
2571
|
+
} finally {
|
|
2572
|
+
setBusy(false);
|
|
2573
|
+
}
|
|
2574
|
+
};
|
|
2575
|
+
const handleAppleLogin = async () => {
|
|
2576
|
+
setError(null);
|
|
2577
|
+
const oauth = getOAuthProvider();
|
|
2578
|
+
if (!oauth) {
|
|
2579
|
+
setError("Sign-in is unavailable on this device.");
|
|
2580
|
+
return;
|
|
2581
|
+
}
|
|
2582
|
+
setBusy(true);
|
|
2583
|
+
try {
|
|
2584
|
+
const idToken = await oauth.signInWithApple();
|
|
2585
|
+
await completeProviderSignIn(idToken, { exchange: signInWithApple, onSignedIn });
|
|
2586
|
+
} catch (err) {
|
|
2587
|
+
setError(err?.message || "Apple sign-in failed");
|
|
2588
|
+
} finally {
|
|
2589
|
+
setBusy(false);
|
|
2590
|
+
}
|
|
2591
|
+
};
|
|
2592
|
+
const googleEnabled = !!webClientId && !busy;
|
|
2593
|
+
const appleEnabled = appleAvailable && !!config.providers.apple?.service_id && !busy;
|
|
2594
|
+
return /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
2595
|
+
!!config.providers.google && /* @__PURE__ */ jsxs16(
|
|
2596
|
+
Pressable12,
|
|
2597
|
+
{
|
|
2598
|
+
style: [styles18.signInBtn, !googleEnabled && styles18.signInBtnDisabled],
|
|
2599
|
+
onPress: handleGoogleLogin,
|
|
2600
|
+
disabled: !googleEnabled,
|
|
2601
|
+
children: [
|
|
2602
|
+
/* @__PURE__ */ jsx20(Text15, { style: styles18.signInGlyph, children: "G" }),
|
|
2603
|
+
/* @__PURE__ */ jsx20(Text15, { style: styles18.signInText, children: "Continue with Google" })
|
|
2604
|
+
]
|
|
2605
|
+
}
|
|
2606
|
+
),
|
|
2607
|
+
appleEnabled && getOAuthProvider()?.renderAppleButton({ onPress: handleAppleLogin, disabled: busy, style: styles18.appleBtn }),
|
|
2608
|
+
!!error && /* @__PURE__ */ jsx20(Text15, { style: styles18.errorText, children: error }),
|
|
2609
|
+
busy && /* @__PURE__ */ jsx20(ActivityIndicator9, { color: ada15.ink })
|
|
2610
|
+
] });
|
|
2611
|
+
}
|
|
2612
|
+
var styles18 = StyleSheet18.create({
|
|
2613
|
+
container: {
|
|
2614
|
+
flex: 1,
|
|
2615
|
+
backgroundColor: ada15.paper,
|
|
2616
|
+
justifyContent: "space-between",
|
|
2617
|
+
paddingHorizontal: 32,
|
|
2618
|
+
paddingBottom: 24
|
|
2619
|
+
},
|
|
2620
|
+
hero: { flex: 1, alignItems: "center", justifyContent: "center", gap: 18 },
|
|
2621
|
+
wordmark: { fontSize: 32, fontWeight: "600", color: ada15.ink, letterSpacing: 4, fontFamily: fontFam10, marginTop: 8 },
|
|
2622
|
+
tagline: { fontSize: 16, fontWeight: "500", color: ada15.inkSoft, letterSpacing: -0.1, fontFamily: fontFam10 },
|
|
2623
|
+
buttonSection: { alignItems: "center", gap: 12 },
|
|
2624
|
+
signInBtn: {
|
|
2625
|
+
flexDirection: "row",
|
|
2626
|
+
alignItems: "center",
|
|
2627
|
+
justifyContent: "center",
|
|
2628
|
+
backgroundColor: ada15.ink,
|
|
2629
|
+
paddingVertical: 16,
|
|
2630
|
+
paddingHorizontal: 24,
|
|
2631
|
+
borderRadius: 999,
|
|
2632
|
+
width: "100%",
|
|
2633
|
+
gap: 12
|
|
2634
|
+
},
|
|
2635
|
+
signInBtnDisabled: { opacity: 0.5 },
|
|
2636
|
+
signInGlyph: { fontSize: 18, fontWeight: "700", color: ada15.paper, fontFamily: fontFam10 },
|
|
2637
|
+
signInText: { fontSize: 16, fontWeight: "600", color: ada15.paper, letterSpacing: -0.2, fontFamily: fontFam10 },
|
|
2638
|
+
appleBtn: { width: "100%", height: 52 },
|
|
2639
|
+
errorText: { fontSize: 13, color: "#c43d3d", textAlign: "center", paddingHorizontal: 16 },
|
|
2640
|
+
disclaimer: { fontSize: 12, color: ada15.inkMuted, textAlign: "center", marginTop: 8, lineHeight: 18, fontFamily: fontFam10 },
|
|
2641
|
+
joinLink: { fontSize: 14, fontWeight: "600", color: ada15.orangeDeep, textAlign: "center", fontFamily: fontFam10 }
|
|
2642
|
+
});
|
|
2643
|
+
|
|
2058
2644
|
// src/voice/VoiceCallSheet.tsx
|
|
2059
|
-
import { useEffect as
|
|
2645
|
+
import { useEffect as useEffect13, useRef as useRef6, useMemo as useMemo7 } from "react";
|
|
2060
2646
|
import {
|
|
2061
|
-
View as
|
|
2062
|
-
Text as
|
|
2063
|
-
StyleSheet as
|
|
2064
|
-
Platform as
|
|
2065
|
-
Pressable as
|
|
2647
|
+
View as View20,
|
|
2648
|
+
Text as Text16,
|
|
2649
|
+
StyleSheet as StyleSheet19,
|
|
2650
|
+
Platform as Platform14,
|
|
2651
|
+
Pressable as Pressable13,
|
|
2066
2652
|
ScrollView
|
|
2067
2653
|
} from "react-native";
|
|
2068
2654
|
import Svg2, { Path as Path2, Line as Line2 } from "react-native-svg";
|
|
2069
|
-
import {
|
|
2070
|
-
import {
|
|
2071
|
-
import { AdaOrb as AdaOrb3, SurfaceFullscreen as SurfaceFullscreen2 } from "@ateam-ai-mobile/plugin-runtime";
|
|
2655
|
+
import { ada as ada16 } from "@ateam-ai-mobile/core";
|
|
2656
|
+
import { AdaOrb as AdaOrb7, SurfaceFullscreen as SurfaceFullscreen2 } from "@ateam-ai-mobile/plugin-runtime";
|
|
2072
2657
|
|
|
2073
2658
|
// src/voice/useVoiceCall.ts
|
|
2074
|
-
import {
|
|
2659
|
+
import { useCallback as useCallback6, useEffect as useEffect12, useReducer } from "react";
|
|
2660
|
+
|
|
2661
|
+
// src/voice/voiceSession.ts
|
|
2075
2662
|
import { getVoiceApiUrl as getVoiceApiUrl2, getToken as getToken2, getTenant as getTenant5, getUser as getUser2, refreshToken } from "@ateam-ai-mobile/core";
|
|
2663
|
+
import {
|
|
2664
|
+
callDeviceTool,
|
|
2665
|
+
ensureDeviceToolsLoaded,
|
|
2666
|
+
listDeviceTools,
|
|
2667
|
+
PLATFORM_VOICE_CALLER
|
|
2668
|
+
} from "@ateam-ai-mobile/plugin-runtime";
|
|
2669
|
+
var CONNECT_TIMEOUT_MS = 3e4;
|
|
2076
2670
|
var TOKEN_REFRESH_SKEW_MS = 9e4;
|
|
2077
2671
|
function tokenNeedsRefresh(token) {
|
|
2078
2672
|
if (!token) return true;
|
|
@@ -2100,7 +2694,6 @@ var INJECT_TRACK_HOOK = `
|
|
|
2100
2694
|
}
|
|
2101
2695
|
}
|
|
2102
2696
|
|
|
2103
|
-
// 1) Hook getUserMedia \u2014 captures mic streams at request time.
|
|
2104
2697
|
try {
|
|
2105
2698
|
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
|
2106
2699
|
const origGUM = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
|
|
@@ -2114,7 +2707,6 @@ var INJECT_TRACK_HOOK = `
|
|
|
2114
2707
|
}
|
|
2115
2708
|
} catch (e) {}
|
|
2116
2709
|
|
|
2117
|
-
// 2) Hook RTCPeerConnection.addTrack \u2014 catches whatever the app sends.
|
|
2118
2710
|
try {
|
|
2119
2711
|
if (window.RTCPeerConnection) {
|
|
2120
2712
|
const origPC = window.RTCPeerConnection;
|
|
@@ -2134,9 +2726,7 @@ var INJECT_TRACK_HOOK = `
|
|
|
2134
2726
|
}
|
|
2135
2727
|
if (origAddTransceiver) {
|
|
2136
2728
|
origPC.prototype.addTransceiver = function(arg) {
|
|
2137
|
-
if (arg && arg.kind === 'audio') {
|
|
2138
|
-
// Transceiver created with kind 'audio' \u2014 sender track set later.
|
|
2139
|
-
} else if (arg && arg.kind === undefined && arg.track && arg.track.kind === 'audio') {
|
|
2729
|
+
if (arg && arg.kind === undefined && arg.track && arg.track.kind === 'audio') {
|
|
2140
2730
|
track(arg.track);
|
|
2141
2731
|
}
|
|
2142
2732
|
const tx = origAddTransceiver.apply(this, arguments);
|
|
@@ -2149,7 +2739,6 @@ var INJECT_TRACK_HOOK = `
|
|
|
2149
2739
|
}
|
|
2150
2740
|
} catch (e) {}
|
|
2151
2741
|
|
|
2152
|
-
// 3) Helper exposed for direct calls.
|
|
2153
2742
|
window._adaSetMuted = function(muted) {
|
|
2154
2743
|
let n = 0;
|
|
2155
2744
|
if (Array.isArray(window._allAudioTracks)) {
|
|
@@ -2168,7 +2757,6 @@ var buildMuteScript = (muted) => `
|
|
|
2168
2757
|
if (typeof window._adaSetMuted === 'function') {
|
|
2169
2758
|
n = window._adaSetMuted(muted);
|
|
2170
2759
|
}
|
|
2171
|
-
// Last-resort scan if hook somehow missed.
|
|
2172
2760
|
if (n === 0 && Array.isArray(window._allAudioTracks)) {
|
|
2173
2761
|
window._allAudioTracks.forEach(function(t) {
|
|
2174
2762
|
try { t.enabled = !muted; n++; } catch (e) {}
|
|
@@ -2177,104 +2765,413 @@ var buildMuteScript = (muted) => `
|
|
|
2177
2765
|
console.log('[ada-mute]', muted ? 'MUTED' : 'UNMUTED', 'tracks=', n);
|
|
2178
2766
|
})(${muted}); true;
|
|
2179
2767
|
`;
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2768
|
+
var buildAgentTurnScript = (input) => `
|
|
2769
|
+
(function(input) {
|
|
2770
|
+
if (typeof window.__adasAgentTurn === 'function') {
|
|
2771
|
+
try { window.__adasAgentTurn(input); }
|
|
2772
|
+
catch (e) {
|
|
2773
|
+
window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
2774
|
+
type: 'agentTurnFailed', message: String(e && e.message || e),
|
|
2775
|
+
}));
|
|
2776
|
+
}
|
|
2777
|
+
} else if (window.ReactNativeWebView) {
|
|
2778
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
2779
|
+
type: 'agentTurnUnsupported',
|
|
2780
|
+
message: 'voice app does not support agent turns (__adasAgentTurn missing) \u2014 update the voice page',
|
|
2781
|
+
}));
|
|
2782
|
+
}
|
|
2783
|
+
})(${JSON.stringify(input)}); true;
|
|
2784
|
+
`;
|
|
2785
|
+
var buildObserveScript = (text) => `
|
|
2786
|
+
(function(text) {
|
|
2787
|
+
if (typeof window.__adasObserve === 'function') {
|
|
2788
|
+
try { window.__adasObserve(text); }
|
|
2789
|
+
catch (e) {
|
|
2790
|
+
window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
2791
|
+
type: 'observeFailed', message: String(e && e.message || e),
|
|
2792
|
+
}));
|
|
2793
|
+
}
|
|
2794
|
+
} else if (window.ReactNativeWebView) {
|
|
2795
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
2796
|
+
type: 'observeUnsupported',
|
|
2797
|
+
message: 'voice app does not support observe (__adasObserve missing) \u2014 update the voice page',
|
|
2798
|
+
}));
|
|
2799
|
+
}
|
|
2800
|
+
})(${JSON.stringify(text)}); true;
|
|
2801
|
+
`;
|
|
2802
|
+
function originOf(url) {
|
|
2803
|
+
if (!url) return null;
|
|
2804
|
+
const m = /^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(url);
|
|
2805
|
+
return m ? m[1].toLowerCase() : null;
|
|
2806
|
+
}
|
|
2807
|
+
var IDLE = {
|
|
2808
|
+
callState: "idle",
|
|
2809
|
+
sessionId: null,
|
|
2810
|
+
error: null,
|
|
2811
|
+
transcript: [],
|
|
2812
|
+
aiPartial: "",
|
|
2813
|
+
userPartial: "",
|
|
2814
|
+
muted: false,
|
|
2815
|
+
userSpeaking: false,
|
|
2816
|
+
lastUserSpeechEndedAt: null,
|
|
2817
|
+
mounted: false,
|
|
2818
|
+
webViewSource: null,
|
|
2819
|
+
skillSlug: void 0
|
|
2820
|
+
};
|
|
2821
|
+
var VoiceSessionManager = class {
|
|
2822
|
+
constructor() {
|
|
2823
|
+
this.state = { ...IDLE };
|
|
2824
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
2825
|
+
this.webView = null;
|
|
2826
|
+
this.pending = [];
|
|
2827
|
+
/**
|
|
2828
|
+
* WHO owns the one physical session. Set to the caller that started it from
|
|
2829
|
+
* idle (a plugin's pluginId, or the PLATFORM symbol for the built-in sheet),
|
|
2830
|
+
* and kept after stop until the next start reassigns it — so a plugin can read
|
|
2831
|
+
* its own just-ended transcript but another plugin never can.
|
|
2832
|
+
*
|
|
2833
|
+
* ISOLATION (GPT blocker on 8881225): every access is scoped through this. A
|
|
2834
|
+
* different plugin must not read, control, or attach to another plugin's live
|
|
2835
|
+
* conversation just because it declared voice.
|
|
2836
|
+
*/
|
|
2837
|
+
this.owner = null;
|
|
2838
|
+
this.injectedTrackHook = INJECT_TRACK_HOOK;
|
|
2839
|
+
}
|
|
2840
|
+
/** The platform (built-in sheet, mic indicator, session host) sees and
|
|
2841
|
+
* controls any session — it is the user's own surface. A plugin caller may
|
|
2842
|
+
* only touch a session it owns. */
|
|
2843
|
+
canAccess(caller) {
|
|
2844
|
+
return caller === PLATFORM_VOICE_CALLER || this.owner === caller;
|
|
2845
|
+
}
|
|
2846
|
+
foreignError() {
|
|
2847
|
+
const err = new Error(
|
|
2848
|
+
"voice: another solution is using the microphone \u2014 one live session per device."
|
|
2849
|
+
);
|
|
2850
|
+
err.code = "RESTRICTED";
|
|
2851
|
+
return err;
|
|
2852
|
+
}
|
|
2853
|
+
// ── Host wiring (used only by VoiceSessionHost) ──────────────
|
|
2854
|
+
/** The offscreen WebView sets its ref here so the session can inject into it. */
|
|
2855
|
+
setWebView(ref) {
|
|
2856
|
+
this.webView = ref;
|
|
2857
|
+
}
|
|
2858
|
+
/** Whole state — the host reads `mounted` + `webViewSource` to decide what to
|
|
2859
|
+
* render, and every reader derives its snapshot from this. */
|
|
2860
|
+
getInternal() {
|
|
2861
|
+
return this.state;
|
|
2862
|
+
}
|
|
2863
|
+
// ── VoiceAPI (what props.voice and useVoiceCall call) ────────
|
|
2864
|
+
async start(opts, caller = PLATFORM_VOICE_CALLER) {
|
|
2865
|
+
if (this.state.callState === "connected") {
|
|
2866
|
+
if (!this.canAccess(caller)) throw this.foreignError();
|
|
2867
|
+
return this.realSnapshot();
|
|
2868
|
+
}
|
|
2869
|
+
if (this.state.callState === "connecting") {
|
|
2870
|
+
if (!this.canAccess(caller)) throw this.foreignError();
|
|
2871
|
+
return this.waitForConnect();
|
|
2872
|
+
}
|
|
2190
2873
|
try {
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
case "callState":
|
|
2195
|
-
case "call-state":
|
|
2196
|
-
setCallState(data.state);
|
|
2197
|
-
if (data.sessionId) setSessionId(data.sessionId);
|
|
2198
|
-
if (data.error) setError(data.error);
|
|
2199
|
-
break;
|
|
2200
|
-
case "transcript":
|
|
2201
|
-
setTranscript((prev) => [...prev, { role: data.role, text: data.text, ts: Date.now() }]);
|
|
2202
|
-
break;
|
|
2203
|
-
case "aiPartial":
|
|
2204
|
-
setAiPartial(data.text);
|
|
2205
|
-
break;
|
|
2206
|
-
case "userPartial":
|
|
2207
|
-
setUserPartial(data.text);
|
|
2208
|
-
break;
|
|
2209
|
-
case "clearPartials":
|
|
2210
|
-
setAiPartial("");
|
|
2211
|
-
setUserPartial("");
|
|
2212
|
-
break;
|
|
2213
|
-
case "error":
|
|
2214
|
-
setError(data.message);
|
|
2215
|
-
setCallState("error");
|
|
2216
|
-
break;
|
|
2217
|
-
}
|
|
2218
|
-
} catch {
|
|
2874
|
+
await ensureDeviceToolsLoaded();
|
|
2875
|
+
} catch (e) {
|
|
2876
|
+
console.warn("[voiceSession] device tool preload failed:", e?.message || String(e));
|
|
2219
2877
|
}
|
|
2220
|
-
}, []);
|
|
2221
|
-
const startCall = useCallback6(async () => {
|
|
2222
|
-
setError(null);
|
|
2223
|
-
setTranscript([]);
|
|
2224
|
-
setAiPartial("");
|
|
2225
|
-
setUserPartial("");
|
|
2226
2878
|
try {
|
|
2227
|
-
if (tokenNeedsRefresh(getToken2()))
|
|
2228
|
-
await refreshToken();
|
|
2229
|
-
}
|
|
2879
|
+
if (tokenNeedsRefresh(getToken2())) await refreshToken();
|
|
2230
2880
|
} catch {
|
|
2231
2881
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
webViewRef.current?.injectJavaScript?.(buildMuteScript(next));
|
|
2245
|
-
return next;
|
|
2882
|
+
this.owner = caller;
|
|
2883
|
+
const skillSlug = opts?.skillSlug;
|
|
2884
|
+
this.setState({
|
|
2885
|
+
callState: "connecting",
|
|
2886
|
+
error: null,
|
|
2887
|
+
transcript: [],
|
|
2888
|
+
aiPartial: "",
|
|
2889
|
+
userPartial: "",
|
|
2890
|
+
muted: false,
|
|
2891
|
+
mounted: true,
|
|
2892
|
+
skillSlug,
|
|
2893
|
+
webViewSource: { uri: this.buildUri(skillSlug) }
|
|
2246
2894
|
});
|
|
2247
|
-
|
|
2248
|
-
|
|
2895
|
+
return this.waitForConnect();
|
|
2896
|
+
}
|
|
2897
|
+
stop(caller = PLATFORM_VOICE_CALLER) {
|
|
2898
|
+
if (this.state.callState !== "idle" && !this.canAccess(caller)) throw this.foreignError();
|
|
2899
|
+
this.webView?.injectJavaScript?.("window.hangUp && window.hangUp(); true;");
|
|
2900
|
+
this.rejectPending(new Error("voice: session stopped before it connected"));
|
|
2901
|
+
this.setState({
|
|
2902
|
+
...IDLE,
|
|
2903
|
+
// keep the transcript of the call that just ended for any reader still up
|
|
2904
|
+
transcript: this.state.transcript
|
|
2905
|
+
});
|
|
2906
|
+
}
|
|
2907
|
+
setMuted(muted, caller = PLATFORM_VOICE_CALLER) {
|
|
2908
|
+
if (this.state.callState !== "idle" && !this.canAccess(caller)) throw this.foreignError();
|
|
2909
|
+
this.webView?.injectJavaScript?.(buildMuteScript(muted));
|
|
2910
|
+
this.setState({ muted });
|
|
2911
|
+
}
|
|
2912
|
+
prompt(input, caller = PLATFORM_VOICE_CALLER) {
|
|
2913
|
+
if (this.state.callState !== "connected") {
|
|
2914
|
+
throw new Error("voice: session is not connected \u2014 call start() and await it before prompt().");
|
|
2915
|
+
}
|
|
2916
|
+
if (!this.canAccess(caller)) throw this.foreignError();
|
|
2917
|
+
this.webView?.injectJavaScript?.(buildAgentTurnScript(input));
|
|
2918
|
+
}
|
|
2919
|
+
/**
|
|
2920
|
+
* Stream a silent observation into the live session — tell the model without
|
|
2921
|
+
* asking it to speak. The cheap, high-frequency channel (safe once or twice a
|
|
2922
|
+
* second) behind a future props.voice.observe(); today the host uses it to run
|
|
2923
|
+
* the real-device stream proof (VOICE_RT_STREAM_DEVICE_PROOF) before the gated
|
|
2924
|
+
* plugin API is added. Owner-scoped like every other control.
|
|
2925
|
+
*/
|
|
2926
|
+
observe(text, caller = PLATFORM_VOICE_CALLER) {
|
|
2927
|
+
if (this.state.callState !== "connected") {
|
|
2928
|
+
throw new Error("voice: session is not connected \u2014 observe() needs a live session.");
|
|
2929
|
+
}
|
|
2930
|
+
if (!this.canAccess(caller)) throw this.foreignError();
|
|
2931
|
+
this.webView?.injectJavaScript?.(buildObserveScript(text));
|
|
2932
|
+
}
|
|
2933
|
+
getSnapshot(caller = PLATFORM_VOICE_CALLER) {
|
|
2934
|
+
return this.canAccess(caller) ? this.realSnapshot() : this.foreignSnapshot();
|
|
2935
|
+
}
|
|
2936
|
+
realSnapshot() {
|
|
2937
|
+
const s = this.state;
|
|
2938
|
+
return {
|
|
2939
|
+
state: s.callState,
|
|
2940
|
+
sessionId: s.sessionId,
|
|
2941
|
+
muted: s.muted,
|
|
2942
|
+
speaking: !!s.aiPartial,
|
|
2943
|
+
listening: !!s.userPartial,
|
|
2944
|
+
userSpeaking: s.userSpeaking,
|
|
2945
|
+
lastUserSpeechEndedAt: s.lastUserSpeechEndedAt,
|
|
2946
|
+
lastError: s.error
|
|
2947
|
+
};
|
|
2948
|
+
}
|
|
2949
|
+
foreignSnapshot() {
|
|
2950
|
+
return {
|
|
2951
|
+
state: "idle",
|
|
2952
|
+
sessionId: null,
|
|
2953
|
+
muted: false,
|
|
2954
|
+
speaking: false,
|
|
2955
|
+
listening: false,
|
|
2956
|
+
userSpeaking: false,
|
|
2957
|
+
lastUserSpeechEndedAt: null,
|
|
2958
|
+
lastError: null
|
|
2959
|
+
};
|
|
2960
|
+
}
|
|
2961
|
+
subscribe(cb, caller = PLATFORM_VOICE_CALLER) {
|
|
2962
|
+
const wrapped = (event) => {
|
|
2963
|
+
if (this.canAccess(caller)) cb(event);
|
|
2964
|
+
};
|
|
2965
|
+
this.listeners.add(wrapped);
|
|
2966
|
+
return { unsubscribe: () => {
|
|
2967
|
+
this.listeners.delete(wrapped);
|
|
2968
|
+
} };
|
|
2969
|
+
}
|
|
2970
|
+
transcript(caller = PLATFORM_VOICE_CALLER) {
|
|
2971
|
+
return this.canAccess(caller) ? this.state.transcript.slice() : [];
|
|
2972
|
+
}
|
|
2973
|
+
// ── WebView plumbing ─────────────────────────────────────────
|
|
2974
|
+
buildUri(skillSlug) {
|
|
2249
2975
|
const token = getToken2();
|
|
2250
2976
|
const tenant = getTenant5();
|
|
2251
2977
|
const actorId = getUser2()?.actorId || "";
|
|
2252
2978
|
const skillParam = skillSlug ? `&skillSlug=${encodeURIComponent(skillSlug)}` : "";
|
|
2253
|
-
return {
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2979
|
+
return `${getVoiceApiUrl2()}/app?mode=mini&embedded=rn&authToken=${encodeURIComponent(token || "")}&tenant=${encodeURIComponent(tenant)}&actorId=${encodeURIComponent(actorId)}${skillParam}`;
|
|
2980
|
+
}
|
|
2981
|
+
/** Handle a postMessage from the WebView. `event` is the RN WebView event. */
|
|
2982
|
+
handleMessage(event) {
|
|
2983
|
+
let data;
|
|
2984
|
+
try {
|
|
2985
|
+
data = JSON.parse(event.nativeEvent.data);
|
|
2986
|
+
} catch {
|
|
2987
|
+
return;
|
|
2988
|
+
}
|
|
2989
|
+
switch (data.type) {
|
|
2990
|
+
case "callState":
|
|
2991
|
+
case "call-state":
|
|
2992
|
+
if (data.state) this.setState({ callState: data.state });
|
|
2993
|
+
if (data.sessionId) this.setState({ sessionId: data.sessionId });
|
|
2994
|
+
if (data.error) this.setState({ error: data.error });
|
|
2995
|
+
if (data.state === "connected") this.resolvePending();
|
|
2996
|
+
if (data.state === "error") this.rejectPending(new Error(data.error || "voice: connection error"));
|
|
2997
|
+
break;
|
|
2998
|
+
case "transcript":
|
|
2999
|
+
this.appendTranscript({ role: data.role, text: data.text, ts: Date.now() });
|
|
3000
|
+
break;
|
|
3001
|
+
case "aiPartial":
|
|
3002
|
+
this.setState({ aiPartial: data.text });
|
|
3003
|
+
break;
|
|
3004
|
+
case "userPartial":
|
|
3005
|
+
this.setState({ userPartial: data.text });
|
|
3006
|
+
break;
|
|
3007
|
+
case "clearPartials":
|
|
3008
|
+
this.setState({ aiPartial: "", userPartial: "" });
|
|
3009
|
+
break;
|
|
3010
|
+
// User VAD from the mini-app. `at` is when it happened; on speaking:false
|
|
3011
|
+
// we stamp lastUserSpeechEndedAt so a solution can gate "speak after N s of
|
|
3012
|
+
// silence" on the first real stop, never before the user has spoken.
|
|
3013
|
+
case "speechActivity": {
|
|
3014
|
+
const speaking = !!data.speaking;
|
|
3015
|
+
const at = typeof data.at === "number" ? data.at : Date.now();
|
|
3016
|
+
this.setState(
|
|
3017
|
+
speaking ? { userSpeaking: true } : { userSpeaking: false, lastUserSpeechEndedAt: at }
|
|
3018
|
+
);
|
|
3019
|
+
break;
|
|
3020
|
+
}
|
|
3021
|
+
case "error":
|
|
3022
|
+
this.setState({ error: data.message, callState: "error" });
|
|
3023
|
+
this.rejectPending(new Error(data.message || "voice: error"));
|
|
3024
|
+
break;
|
|
3025
|
+
// A proactive turn couldn't run (older voice page / hook threw). NON-FATAL:
|
|
3026
|
+
// the session stays live; we only surface why the guide didn't speak.
|
|
3027
|
+
case "agentTurnUnsupported":
|
|
3028
|
+
case "agentTurnFailed":
|
|
3029
|
+
case "observeUnsupported":
|
|
3030
|
+
case "observeFailed":
|
|
3031
|
+
this.setState({ error: data.message || "voice: channel notice" });
|
|
3032
|
+
break;
|
|
3033
|
+
// Device tools — executed locally, origin-checked. The model's function
|
|
3034
|
+
// call already arrived on this phone; only the voice app's own origin may
|
|
3035
|
+
// drive the camera/GPS.
|
|
3036
|
+
case "device-tool-list": {
|
|
3037
|
+
const listSender = originOf(event?.nativeEvent?.url);
|
|
3038
|
+
const listExpected = originOf(getVoiceApiUrl2());
|
|
3039
|
+
if (!listSender || !listExpected || listSender !== listExpected) break;
|
|
3040
|
+
this.sendDeviceToolList(data.correlationId);
|
|
3041
|
+
break;
|
|
3042
|
+
}
|
|
3043
|
+
case "device-tool-call": {
|
|
3044
|
+
const sender = originOf(event?.nativeEvent?.url);
|
|
3045
|
+
const expected = originOf(getVoiceApiUrl2());
|
|
3046
|
+
if (!sender || !expected || sender !== expected) {
|
|
3047
|
+
console.warn(`[voiceSession] REFUSED device tool call from "${sender || "unknown origin"}" (expected "${expected}")`);
|
|
3048
|
+
break;
|
|
3049
|
+
}
|
|
3050
|
+
void this.runDeviceTool(data);
|
|
3051
|
+
break;
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
/** Answer "what device tools do you have?" — the client is the authority. */
|
|
3056
|
+
sendDeviceToolList(correlationId) {
|
|
3057
|
+
const tools = listDeviceTools().map((t) => ({
|
|
3058
|
+
name: t.name,
|
|
3059
|
+
description: t.description,
|
|
3060
|
+
input_schema: t.input_schema
|
|
3061
|
+
}));
|
|
3062
|
+
this.webView?.injectJavaScript?.(
|
|
3063
|
+
`window.__adasDeviceToolResult && window.__adasDeviceToolResult(${JSON.stringify(
|
|
3064
|
+
JSON.stringify({ correlationId, ok: true, tools })
|
|
3065
|
+
)}); true;`
|
|
3066
|
+
);
|
|
3067
|
+
}
|
|
3068
|
+
/** Run a device tool and post the outcome back into the WebView. */
|
|
3069
|
+
async runDeviceTool(data) {
|
|
3070
|
+
const { correlationId, name, args, timeoutMs } = data || {};
|
|
3071
|
+
if (!correlationId || typeof name !== "string") return;
|
|
3072
|
+
let payload;
|
|
3073
|
+
try {
|
|
3074
|
+
const outcome = await callDeviceTool(name, args || {}, { timeoutMs });
|
|
3075
|
+
payload = outcome.ok ? { correlationId, ok: true, result: outcome.result } : { correlationId, ok: false, error: outcome.error, reason: outcome.reason };
|
|
3076
|
+
} catch (err) {
|
|
3077
|
+
payload = { correlationId, ok: false, reason: "failed", error: err?.message || String(err) };
|
|
3078
|
+
}
|
|
3079
|
+
this.webView?.injectJavaScript?.(
|
|
3080
|
+
`window.__adasDeviceToolResult && window.__adasDeviceToolResult(${JSON.stringify(
|
|
3081
|
+
JSON.stringify(payload)
|
|
3082
|
+
)}); true;`
|
|
3083
|
+
);
|
|
3084
|
+
}
|
|
3085
|
+
// ── internals ────────────────────────────────────────────────
|
|
3086
|
+
setState(partial) {
|
|
3087
|
+
this.state = { ...this.state, ...partial };
|
|
3088
|
+
this.emit({ type: "state" });
|
|
3089
|
+
}
|
|
3090
|
+
appendTranscript(entry) {
|
|
3091
|
+
this.state = { ...this.state, transcript: [...this.state.transcript, entry] };
|
|
3092
|
+
this.emit({ type: "transcript" });
|
|
3093
|
+
}
|
|
3094
|
+
emit(event) {
|
|
3095
|
+
for (const cb of this.listeners) {
|
|
3096
|
+
try {
|
|
3097
|
+
cb(event);
|
|
3098
|
+
} catch (e) {
|
|
3099
|
+
console.warn("[voiceSession] listener threw", e);
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
waitForConnect() {
|
|
3104
|
+
return new Promise((resolve, reject) => {
|
|
3105
|
+
const timer = setTimeout(() => {
|
|
3106
|
+
this.pending = this.pending.filter((p) => p.timer !== timer);
|
|
3107
|
+
reject(new Error("voice: timed out waiting to connect (is VoiceSessionHost mounted?)"));
|
|
3108
|
+
}, CONNECT_TIMEOUT_MS);
|
|
3109
|
+
this.pending.push({ resolve, reject, timer });
|
|
3110
|
+
});
|
|
3111
|
+
}
|
|
3112
|
+
resolvePending() {
|
|
3113
|
+
const snap = this.realSnapshot();
|
|
3114
|
+
const waiting = this.pending;
|
|
3115
|
+
this.pending = [];
|
|
3116
|
+
for (const p of waiting) {
|
|
3117
|
+
clearTimeout(p.timer);
|
|
3118
|
+
p.resolve(snap);
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
rejectPending(err) {
|
|
3122
|
+
const waiting = this.pending;
|
|
3123
|
+
this.pending = [];
|
|
3124
|
+
for (const p of waiting) {
|
|
3125
|
+
clearTimeout(p.timer);
|
|
3126
|
+
p.reject(err);
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
/** TEST ONLY: reset the singleton to a clean idle state (mirrors the
|
|
3130
|
+
* __resetSessionSyncForTest precedent). Not part of any surface. */
|
|
3131
|
+
__resetForTest() {
|
|
3132
|
+
this.rejectPending(new Error("voice: reset"));
|
|
3133
|
+
this.state = { ...IDLE };
|
|
3134
|
+
this.owner = null;
|
|
3135
|
+
this.listeners.clear();
|
|
3136
|
+
this.webView = null;
|
|
3137
|
+
}
|
|
3138
|
+
};
|
|
3139
|
+
var voiceSession = new VoiceSessionManager();
|
|
3140
|
+
|
|
3141
|
+
// src/voice/useVoiceCall.ts
|
|
3142
|
+
function useVoiceCall({ skillSlug } = {}) {
|
|
3143
|
+
const [, force] = useReducer((x) => x + 1, 0);
|
|
3144
|
+
useEffect12(() => {
|
|
3145
|
+
const sub = voiceSession.subscribe(() => force());
|
|
3146
|
+
return () => sub.unsubscribe();
|
|
3147
|
+
}, []);
|
|
3148
|
+
const s = voiceSession.getInternal();
|
|
3149
|
+
const startCall = useCallback6(
|
|
3150
|
+
(opts) => voiceSession.start(opts ?? { skillSlug }),
|
|
3151
|
+
[skillSlug]
|
|
3152
|
+
);
|
|
3153
|
+
const stopCall = useCallback6(() => voiceSession.stop(), []);
|
|
3154
|
+
const toggleMute = useCallback6(
|
|
3155
|
+
() => voiceSession.setMuted(!voiceSession.getSnapshot().muted),
|
|
3156
|
+
[]
|
|
3157
|
+
);
|
|
2257
3158
|
return {
|
|
2258
|
-
callState,
|
|
2259
|
-
sessionId,
|
|
2260
|
-
error,
|
|
2261
|
-
transcript,
|
|
2262
|
-
aiPartial,
|
|
2263
|
-
userPartial,
|
|
2264
|
-
muted,
|
|
3159
|
+
callState: s.callState,
|
|
3160
|
+
sessionId: s.sessionId,
|
|
3161
|
+
error: s.error,
|
|
3162
|
+
transcript: s.transcript,
|
|
3163
|
+
aiPartial: s.aiPartial,
|
|
3164
|
+
userPartial: s.userPartial,
|
|
3165
|
+
muted: s.muted,
|
|
2265
3166
|
startCall,
|
|
2266
3167
|
stopCall,
|
|
2267
|
-
toggleMute
|
|
2268
|
-
handleWebViewMessage,
|
|
2269
|
-
getWebViewSource,
|
|
2270
|
-
webViewRef,
|
|
2271
|
-
injectedTrackHook: INJECT_TRACK_HOOK
|
|
3168
|
+
toggleMute
|
|
2272
3169
|
};
|
|
2273
3170
|
}
|
|
2274
3171
|
|
|
2275
3172
|
// src/voice/VoiceCallSheet.tsx
|
|
2276
|
-
import { jsx as
|
|
2277
|
-
var
|
|
3173
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3174
|
+
var fontFam11 = Platform14.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
2278
3175
|
var HIGHLIGHT_PATTERNS = [
|
|
2279
3176
|
/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,
|
|
2280
3177
|
/(?:\+?\d[\s\-().]?){7,}\d/g,
|
|
@@ -2317,8 +3214,8 @@ function HighlightedText({
|
|
|
2317
3214
|
baseStyle,
|
|
2318
3215
|
importantStyle
|
|
2319
3216
|
}) {
|
|
2320
|
-
const segments =
|
|
2321
|
-
return /* @__PURE__ */
|
|
3217
|
+
const segments = useMemo7(() => highlightSegments(text), [text]);
|
|
3218
|
+
return /* @__PURE__ */ jsx21(Text16, { style: baseStyle, children: segments.map((seg, i) => /* @__PURE__ */ jsx21(Text16, { style: seg.important ? importantStyle : void 0, children: seg.text }, i)) });
|
|
2322
3219
|
}
|
|
2323
3220
|
function VoiceCallSheet({ visible, onClose, skillSlug }) {
|
|
2324
3221
|
const {
|
|
@@ -2330,31 +3227,27 @@ function VoiceCallSheet({ visible, onClose, skillSlug }) {
|
|
|
2330
3227
|
muted,
|
|
2331
3228
|
startCall,
|
|
2332
3229
|
stopCall,
|
|
2333
|
-
toggleMute
|
|
2334
|
-
handleWebViewMessage,
|
|
2335
|
-
getWebViewSource,
|
|
2336
|
-
webViewRef,
|
|
2337
|
-
injectedTrackHook
|
|
3230
|
+
toggleMute
|
|
2338
3231
|
} = useVoiceCall({ skillSlug });
|
|
2339
3232
|
const scrollRef = useRef6(null);
|
|
2340
|
-
|
|
3233
|
+
useEffect13(() => {
|
|
2341
3234
|
if (visible && callState === "idle") startCall();
|
|
2342
3235
|
}, [visible]);
|
|
2343
|
-
|
|
3236
|
+
useEffect13(() => {
|
|
2344
3237
|
scrollRef.current?.scrollToEnd?.({ animated: true });
|
|
2345
3238
|
}, [transcript.length, aiPartial, userPartial]);
|
|
2346
3239
|
const handleHangUp = () => {
|
|
2347
3240
|
stopCall();
|
|
2348
3241
|
onClose();
|
|
2349
3242
|
};
|
|
2350
|
-
const orbState =
|
|
3243
|
+
const orbState = useMemo7(() => {
|
|
2351
3244
|
if (callState === "connecting") return "thinking";
|
|
2352
3245
|
if (callState === "error") return "idle";
|
|
2353
3246
|
if (aiPartial) return "speaking";
|
|
2354
3247
|
if (userPartial) return "listening";
|
|
2355
3248
|
return "idle";
|
|
2356
3249
|
}, [callState, aiPartial, userPartial]);
|
|
2357
|
-
const statusLabel =
|
|
3250
|
+
const statusLabel = useMemo7(() => {
|
|
2358
3251
|
if (callState === "connecting") return "Connecting\u2026";
|
|
2359
3252
|
if (callState === "error") return error || "Couldn\u2019t connect";
|
|
2360
3253
|
if (aiPartial) return "Ada is speaking";
|
|
@@ -2364,92 +3257,76 @@ function VoiceCallSheet({ visible, onClose, skillSlug }) {
|
|
|
2364
3257
|
}, [callState, aiPartial, userPartial, error]);
|
|
2365
3258
|
if (!visible) return null;
|
|
2366
3259
|
const visibleEntries = transcript.filter((e) => e.role === "user" || e.role === "ai");
|
|
2367
|
-
return /* @__PURE__ */
|
|
3260
|
+
return /* @__PURE__ */ jsxs17(
|
|
2368
3261
|
SurfaceFullscreen2,
|
|
2369
3262
|
{
|
|
2370
3263
|
visible,
|
|
2371
3264
|
onClose: handleHangUp,
|
|
2372
3265
|
status: statusLabel,
|
|
2373
|
-
hero: /* @__PURE__ */
|
|
3266
|
+
hero: /* @__PURE__ */ jsx21(AdaOrb7, { size: 180, state: orbState }),
|
|
2374
3267
|
closeIcon: "hangup",
|
|
2375
3268
|
closeLabel: "End",
|
|
2376
3269
|
children: [
|
|
2377
|
-
/* @__PURE__ */
|
|
3270
|
+
/* @__PURE__ */ jsxs17(
|
|
2378
3271
|
ScrollView,
|
|
2379
3272
|
{
|
|
2380
3273
|
ref: scrollRef,
|
|
2381
|
-
style:
|
|
2382
|
-
contentContainerStyle:
|
|
3274
|
+
style: styles19.transcript,
|
|
3275
|
+
contentContainerStyle: styles19.transcriptContent,
|
|
2383
3276
|
showsVerticalScrollIndicator: false,
|
|
2384
3277
|
children: [
|
|
2385
|
-
callState === "error" && error ? /* @__PURE__ */
|
|
2386
|
-
visibleEntries.map((entry, i) => /* @__PURE__ */
|
|
2387
|
-
/* @__PURE__ */
|
|
2388
|
-
/* @__PURE__ */
|
|
3278
|
+
callState === "error" && error ? /* @__PURE__ */ jsx21(View20, { style: styles19.errorBox, children: /* @__PURE__ */ jsx21(Text16, { style: styles19.errorText, children: error }) }) : null,
|
|
3279
|
+
visibleEntries.map((entry, i) => /* @__PURE__ */ jsxs17(View20, { style: styles19.entry, children: [
|
|
3280
|
+
/* @__PURE__ */ jsx21(Text16, { style: styles19.role, children: entry.role === "user" ? "YOU" : "ADA" }),
|
|
3281
|
+
/* @__PURE__ */ jsx21(
|
|
2389
3282
|
HighlightedText,
|
|
2390
3283
|
{
|
|
2391
3284
|
text: entry.text,
|
|
2392
|
-
baseStyle:
|
|
2393
|
-
importantStyle:
|
|
3285
|
+
baseStyle: styles19.entryText,
|
|
3286
|
+
importantStyle: styles19.important
|
|
2394
3287
|
}
|
|
2395
3288
|
)
|
|
2396
3289
|
] }, `${entry.ts}-${i}`)),
|
|
2397
|
-
userPartial || aiPartial ? /* @__PURE__ */
|
|
2398
|
-
/* @__PURE__ */
|
|
2399
|
-
/* @__PURE__ */
|
|
3290
|
+
userPartial || aiPartial ? /* @__PURE__ */ jsxs17(View20, { style: styles19.entry, children: [
|
|
3291
|
+
/* @__PURE__ */ jsx21(Text16, { style: styles19.role, children: userPartial ? "YOU" : "ADA" }),
|
|
3292
|
+
/* @__PURE__ */ jsx21(
|
|
2400
3293
|
HighlightedText,
|
|
2401
3294
|
{
|
|
2402
3295
|
text: userPartial || aiPartial,
|
|
2403
|
-
baseStyle:
|
|
2404
|
-
importantStyle:
|
|
3296
|
+
baseStyle: styles19.entryTextLive,
|
|
3297
|
+
importantStyle: styles19.important
|
|
2405
3298
|
}
|
|
2406
3299
|
)
|
|
2407
3300
|
] }) : null
|
|
2408
3301
|
]
|
|
2409
3302
|
}
|
|
2410
3303
|
),
|
|
2411
|
-
callState === "connected" || callState === "connecting" ? /* @__PURE__ */
|
|
2412
|
-
/* @__PURE__ */
|
|
2413
|
-
|
|
3304
|
+
callState === "connected" || callState === "connecting" ? /* @__PURE__ */ jsxs17(View20, { style: styles19.muteWrap, pointerEvents: "box-none", children: [
|
|
3305
|
+
/* @__PURE__ */ jsx21(
|
|
3306
|
+
Pressable13,
|
|
2414
3307
|
{
|
|
2415
3308
|
onPress: toggleMute,
|
|
2416
3309
|
accessibilityRole: "button",
|
|
2417
3310
|
accessibilityLabel: muted ? "Unmute microphone" : "Mute microphone",
|
|
2418
3311
|
accessibilityState: { selected: muted },
|
|
2419
|
-
style: [
|
|
3312
|
+
style: [styles19.muteBtn, muted && styles19.muteBtnActive],
|
|
2420
3313
|
hitSlop: 12,
|
|
2421
|
-
children: /* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2423
|
-
/* @__PURE__ */
|
|
2424
|
-
/* @__PURE__ */
|
|
2425
|
-
/* @__PURE__ */
|
|
2426
|
-
muted ? /* @__PURE__ */
|
|
3314
|
+
children: /* @__PURE__ */ jsxs17(Svg2, { width: 22, height: 22, viewBox: "0 0 24 24", fill: "none", stroke: muted ? ada16.paper : ada16.ink, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3315
|
+
/* @__PURE__ */ jsx21(Path2, { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
|
|
3316
|
+
/* @__PURE__ */ jsx21(Path2, { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
3317
|
+
/* @__PURE__ */ jsx21(Line2, { x1: "12", y1: "19", x2: "12", y2: "23" }),
|
|
3318
|
+
/* @__PURE__ */ jsx21(Line2, { x1: "8", y1: "23", x2: "16", y2: "23" }),
|
|
3319
|
+
muted ? /* @__PURE__ */ jsx21(Line2, { x1: "3", y1: "3", x2: "21", y2: "21", stroke: ada16.paper, strokeWidth: 2.4 }) : null
|
|
2427
3320
|
] })
|
|
2428
3321
|
}
|
|
2429
3322
|
),
|
|
2430
|
-
/* @__PURE__ */
|
|
2431
|
-
] }) : null
|
|
2432
|
-
callState !== "idle" && /* @__PURE__ */ jsx15(View14, { style: styles13.hiddenWebView, pointerEvents: "none", children: /* @__PURE__ */ jsx15(
|
|
2433
|
-
WebView3,
|
|
2434
|
-
{
|
|
2435
|
-
ref: webViewRef,
|
|
2436
|
-
source: getWebViewSource(),
|
|
2437
|
-
style: { flex: 1, backgroundColor: "transparent" },
|
|
2438
|
-
onMessage: handleWebViewMessage,
|
|
2439
|
-
onError: (e) => console.log("[VoiceWebView] error:", e.nativeEvent?.description),
|
|
2440
|
-
injectedJavaScriptBeforeContentLoaded: injectedTrackHook,
|
|
2441
|
-
mediaPlaybackRequiresUserAction: false,
|
|
2442
|
-
allowsInlineMediaPlayback: true,
|
|
2443
|
-
mediaCapturePermissionGrantType: "grant",
|
|
2444
|
-
javaScriptEnabled: true,
|
|
2445
|
-
originWhitelist: ["*"]
|
|
2446
|
-
}
|
|
2447
|
-
) })
|
|
3323
|
+
/* @__PURE__ */ jsx21(Text16, { style: styles19.muteLabel, children: muted ? "Muted" : "Mute" })
|
|
3324
|
+
] }) : null
|
|
2448
3325
|
]
|
|
2449
3326
|
}
|
|
2450
3327
|
);
|
|
2451
3328
|
}
|
|
2452
|
-
var
|
|
3329
|
+
var styles19 = StyleSheet19.create({
|
|
2453
3330
|
transcript: {
|
|
2454
3331
|
flex: 1,
|
|
2455
3332
|
paddingHorizontal: 28
|
|
@@ -2466,9 +3343,9 @@ var styles13 = StyleSheet13.create({
|
|
|
2466
3343
|
},
|
|
2467
3344
|
role: {
|
|
2468
3345
|
fontSize: 10,
|
|
2469
|
-
fontFamily:
|
|
3346
|
+
fontFamily: fontFam11,
|
|
2470
3347
|
fontWeight: "700",
|
|
2471
|
-
color:
|
|
3348
|
+
color: ada16.inkMuted,
|
|
2472
3349
|
letterSpacing: 1.4,
|
|
2473
3350
|
minWidth: 32,
|
|
2474
3351
|
paddingTop: 3,
|
|
@@ -2477,9 +3354,9 @@ var styles13 = StyleSheet13.create({
|
|
|
2477
3354
|
entryText: {
|
|
2478
3355
|
flex: 1,
|
|
2479
3356
|
fontSize: 14,
|
|
2480
|
-
fontFamily:
|
|
3357
|
+
fontFamily: fontFam11,
|
|
2481
3358
|
fontWeight: "400",
|
|
2482
|
-
color:
|
|
3359
|
+
color: ada16.inkSoft,
|
|
2483
3360
|
lineHeight: 20,
|
|
2484
3361
|
letterSpacing: -0.1,
|
|
2485
3362
|
opacity: 0.42
|
|
@@ -2487,18 +3364,18 @@ var styles13 = StyleSheet13.create({
|
|
|
2487
3364
|
entryTextLive: {
|
|
2488
3365
|
flex: 1,
|
|
2489
3366
|
fontSize: 14,
|
|
2490
|
-
fontFamily:
|
|
3367
|
+
fontFamily: fontFam11,
|
|
2491
3368
|
fontWeight: "400",
|
|
2492
|
-
color:
|
|
3369
|
+
color: ada16.inkSoft,
|
|
2493
3370
|
lineHeight: 20,
|
|
2494
3371
|
letterSpacing: -0.1,
|
|
2495
3372
|
opacity: 0.7
|
|
2496
3373
|
},
|
|
2497
3374
|
important: {
|
|
2498
3375
|
fontSize: 17,
|
|
2499
|
-
fontFamily:
|
|
3376
|
+
fontFamily: fontFam11,
|
|
2500
3377
|
fontWeight: "700",
|
|
2501
|
-
color:
|
|
3378
|
+
color: ada16.ink,
|
|
2502
3379
|
letterSpacing: -0.1,
|
|
2503
3380
|
opacity: 1
|
|
2504
3381
|
},
|
|
@@ -2513,14 +3390,14 @@ var styles13 = StyleSheet13.create({
|
|
|
2513
3390
|
},
|
|
2514
3391
|
errorText: {
|
|
2515
3392
|
fontSize: 13,
|
|
2516
|
-
fontFamily:
|
|
3393
|
+
fontFamily: fontFam11,
|
|
2517
3394
|
fontWeight: "500",
|
|
2518
3395
|
color: "#fca5a5",
|
|
2519
3396
|
lineHeight: 18
|
|
2520
3397
|
},
|
|
2521
3398
|
muteWrap: {
|
|
2522
3399
|
position: "absolute",
|
|
2523
|
-
bottom:
|
|
3400
|
+
bottom: Platform14.OS === "ios" ? 56 : 40,
|
|
2524
3401
|
left: 28,
|
|
2525
3402
|
alignItems: "center",
|
|
2526
3403
|
gap: 6
|
|
@@ -2529,9 +3406,9 @@ var styles13 = StyleSheet13.create({
|
|
|
2529
3406
|
width: 56,
|
|
2530
3407
|
height: 56,
|
|
2531
3408
|
borderRadius: 28,
|
|
2532
|
-
backgroundColor:
|
|
3409
|
+
backgroundColor: ada16.paperSoft,
|
|
2533
3410
|
borderWidth: 1,
|
|
2534
|
-
borderColor:
|
|
3411
|
+
borderColor: ada16.border,
|
|
2535
3412
|
justifyContent: "center",
|
|
2536
3413
|
alignItems: "center"
|
|
2537
3414
|
},
|
|
@@ -2541,18 +3418,133 @@ var styles13 = StyleSheet13.create({
|
|
|
2541
3418
|
},
|
|
2542
3419
|
muteLabel: {
|
|
2543
3420
|
fontSize: 12,
|
|
2544
|
-
fontFamily:
|
|
3421
|
+
fontFamily: fontFam11,
|
|
2545
3422
|
fontWeight: "500",
|
|
2546
|
-
color:
|
|
3423
|
+
color: ada16.inkMuted,
|
|
2547
3424
|
letterSpacing: 0.3
|
|
2548
|
-
}
|
|
2549
|
-
|
|
3425
|
+
}
|
|
3426
|
+
});
|
|
3427
|
+
|
|
3428
|
+
// src/voice/VoiceSessionHost.tsx
|
|
3429
|
+
import { useCallback as useCallback7, useEffect as useEffect14, useReducer as useReducer2, useRef as useRef7 } from "react";
|
|
3430
|
+
import { View as View21, StyleSheet as StyleSheet20 } from "react-native";
|
|
3431
|
+
import { WebView as WebView3 } from "react-native-webview";
|
|
3432
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
3433
|
+
function VoiceSessionHost() {
|
|
3434
|
+
const [, force] = useReducer2((x) => x + 1, 0);
|
|
3435
|
+
const lastSig = useRef7("");
|
|
3436
|
+
useEffect14(() => {
|
|
3437
|
+
const sub = voiceSession.subscribe(() => {
|
|
3438
|
+
const s2 = voiceSession.getInternal();
|
|
3439
|
+
const sig = `${s2.mounted}|${s2.webViewSource?.uri || ""}`;
|
|
3440
|
+
if (sig !== lastSig.current) {
|
|
3441
|
+
lastSig.current = sig;
|
|
3442
|
+
force();
|
|
3443
|
+
}
|
|
3444
|
+
});
|
|
3445
|
+
return () => sub.unsubscribe();
|
|
3446
|
+
}, []);
|
|
3447
|
+
const setRef = useCallback7((r) => {
|
|
3448
|
+
voiceSession.setWebView(r);
|
|
3449
|
+
}, []);
|
|
3450
|
+
const s = voiceSession.getInternal();
|
|
3451
|
+
if (!s.mounted || !s.webViewSource) return null;
|
|
3452
|
+
return /* @__PURE__ */ jsx22(View21, { style: styles20.hidden, pointerEvents: "none", children: /* @__PURE__ */ jsx22(
|
|
3453
|
+
WebView3,
|
|
3454
|
+
{
|
|
3455
|
+
ref: setRef,
|
|
3456
|
+
source: s.webViewSource,
|
|
3457
|
+
style: styles20.web,
|
|
3458
|
+
onMessage: (e) => voiceSession.handleMessage(e),
|
|
3459
|
+
onError: (e) => console.log("[VoiceSessionHost] error:", e.nativeEvent?.description),
|
|
3460
|
+
injectedJavaScriptBeforeContentLoaded: voiceSession.injectedTrackHook,
|
|
3461
|
+
mediaPlaybackRequiresUserAction: false,
|
|
3462
|
+
allowsInlineMediaPlayback: true,
|
|
3463
|
+
mediaCapturePermissionGrantType: "grant",
|
|
3464
|
+
javaScriptEnabled: true,
|
|
3465
|
+
originWhitelist: ["*"]
|
|
3466
|
+
}
|
|
3467
|
+
) });
|
|
3468
|
+
}
|
|
3469
|
+
var styles20 = StyleSheet20.create({
|
|
3470
|
+
hidden: {
|
|
2550
3471
|
position: "absolute",
|
|
2551
3472
|
width: 1,
|
|
2552
3473
|
height: 1,
|
|
2553
3474
|
top: -100,
|
|
2554
3475
|
left: -100,
|
|
2555
3476
|
opacity: 0
|
|
3477
|
+
},
|
|
3478
|
+
web: { flex: 1, backgroundColor: "transparent" }
|
|
3479
|
+
});
|
|
3480
|
+
|
|
3481
|
+
// src/voice/VoiceMicIndicator.tsx
|
|
3482
|
+
import { useEffect as useEffect15, useReducer as useReducer3, useRef as useRef8 } from "react";
|
|
3483
|
+
import { View as View22, Text as Text17, Animated as Animated2, StyleSheet as StyleSheet21, Platform as Platform15 } from "react-native";
|
|
3484
|
+
import { ada as ada17 } from "@ateam-ai-mobile/core";
|
|
3485
|
+
import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3486
|
+
var fontFam12 = Platform15.OS === "ios" ? "SF Pro Rounded" : void 0;
|
|
3487
|
+
function VoiceMicIndicator({ topInset = 8 }) {
|
|
3488
|
+
const [, force] = useReducer3((x) => x + 1, 0);
|
|
3489
|
+
const pulse = useRef8(new Animated2.Value(0.4)).current;
|
|
3490
|
+
useEffect15(() => {
|
|
3491
|
+
const sub = voiceSession.subscribe(() => force());
|
|
3492
|
+
return () => sub.unsubscribe();
|
|
3493
|
+
}, []);
|
|
3494
|
+
const snap = voiceSession.getSnapshot();
|
|
3495
|
+
const live = snap.state === "connecting" || snap.state === "connected";
|
|
3496
|
+
useEffect15(() => {
|
|
3497
|
+
if (!live) return;
|
|
3498
|
+
const loop = Animated2.loop(
|
|
3499
|
+
Animated2.sequence([
|
|
3500
|
+
Animated2.timing(pulse, { toValue: 1, duration: 700, useNativeDriver: true }),
|
|
3501
|
+
Animated2.timing(pulse, { toValue: 0.4, duration: 700, useNativeDriver: true })
|
|
3502
|
+
])
|
|
3503
|
+
);
|
|
3504
|
+
loop.start();
|
|
3505
|
+
return () => loop.stop();
|
|
3506
|
+
}, [live, pulse]);
|
|
3507
|
+
if (!live) return null;
|
|
3508
|
+
const label = snap.state === "connecting" ? "Connecting\u2026" : snap.muted ? "Mic muted" : "Ada is listening";
|
|
3509
|
+
const dotColor = snap.muted ? ada17.inkMuted : "#E5484D";
|
|
3510
|
+
return /* @__PURE__ */ jsx23(View22, { style: [styles21.wrap, { top: topInset }], pointerEvents: "none", children: /* @__PURE__ */ jsxs18(View22, { style: styles21.pill, children: [
|
|
3511
|
+
/* @__PURE__ */ jsx23(Animated2.View, { style: [styles21.dot, { backgroundColor: dotColor, opacity: snap.muted ? 1 : pulse }] }),
|
|
3512
|
+
/* @__PURE__ */ jsx23(Text17, { style: styles21.label, children: label })
|
|
3513
|
+
] }) });
|
|
3514
|
+
}
|
|
3515
|
+
var styles21 = StyleSheet21.create({
|
|
3516
|
+
wrap: {
|
|
3517
|
+
position: "absolute",
|
|
3518
|
+
left: 0,
|
|
3519
|
+
right: 0,
|
|
3520
|
+
alignItems: "center",
|
|
3521
|
+
zIndex: 9999,
|
|
3522
|
+
elevation: 9999
|
|
3523
|
+
},
|
|
3524
|
+
pill: {
|
|
3525
|
+
flexDirection: "row",
|
|
3526
|
+
alignItems: "center",
|
|
3527
|
+
gap: 7,
|
|
3528
|
+
paddingHorizontal: 12,
|
|
3529
|
+
paddingVertical: 6,
|
|
3530
|
+
borderRadius: 999,
|
|
3531
|
+
backgroundColor: ada17.ink,
|
|
3532
|
+
shadowColor: "#000",
|
|
3533
|
+
shadowOpacity: 0.2,
|
|
3534
|
+
shadowRadius: 8,
|
|
3535
|
+
shadowOffset: { width: 0, height: 2 }
|
|
3536
|
+
},
|
|
3537
|
+
dot: {
|
|
3538
|
+
width: 8,
|
|
3539
|
+
height: 8,
|
|
3540
|
+
borderRadius: 4
|
|
3541
|
+
},
|
|
3542
|
+
label: {
|
|
3543
|
+
fontSize: 12,
|
|
3544
|
+
fontFamily: fontFam12,
|
|
3545
|
+
fontWeight: "600",
|
|
3546
|
+
color: ada17.paper,
|
|
3547
|
+
letterSpacing: 0.2
|
|
2556
3548
|
}
|
|
2557
3549
|
});
|
|
2558
3550
|
export {
|
|
@@ -2560,9 +3552,13 @@ export {
|
|
|
2560
3552
|
ChatInput,
|
|
2561
3553
|
DaySeparator,
|
|
2562
3554
|
EmbeddedPluginWebView,
|
|
3555
|
+
HandoffScreen,
|
|
2563
3556
|
JobProgressBar,
|
|
3557
|
+
JoinScreen,
|
|
2564
3558
|
Lightbox,
|
|
3559
|
+
LoginScreen,
|
|
2565
3560
|
MessageBubble,
|
|
3561
|
+
OpenJoinScreen,
|
|
2566
3562
|
Plugin,
|
|
2567
3563
|
PluginSurface,
|
|
2568
3564
|
TableCardBlock,
|
|
@@ -2570,16 +3566,30 @@ export {
|
|
|
2570
3566
|
TypingIndicator,
|
|
2571
3567
|
UIActionsRow,
|
|
2572
3568
|
VoiceCallSheet,
|
|
3569
|
+
VoiceMicIndicator,
|
|
3570
|
+
VoiceSessionHost,
|
|
2573
3571
|
WidgetHost,
|
|
2574
3572
|
WidgetWebView,
|
|
3573
|
+
WorkspaceBanner,
|
|
2575
3574
|
buildPluginBridgeJS,
|
|
3575
|
+
completeInviteJoin,
|
|
3576
|
+
completeOpenJoin,
|
|
3577
|
+
completeProviderSignIn,
|
|
3578
|
+
googleClientIds,
|
|
3579
|
+
handoffErrorMessage,
|
|
3580
|
+
inviteHeadline,
|
|
3581
|
+
openJoinErrorMessage,
|
|
2576
3582
|
openWidget,
|
|
3583
|
+
runHandoffExchange,
|
|
2577
3584
|
setClipboardProvider,
|
|
3585
|
+
setOAuthProvider,
|
|
2578
3586
|
setPluginWebViewExtraHosts,
|
|
2579
3587
|
setUIActionNavigator,
|
|
3588
|
+
shouldRecoverToDefaultTenant,
|
|
2580
3589
|
useLightboxStore,
|
|
2581
3590
|
usePluginBridge,
|
|
2582
3591
|
useVoiceCall,
|
|
2583
|
-
useWidgetHostStore
|
|
3592
|
+
useWidgetHostStore,
|
|
3593
|
+
voiceSession
|
|
2584
3594
|
};
|
|
2585
3595
|
//# sourceMappingURL=index.mjs.map
|