@adminide-stack/yantra-mobile 12.0.54-alpha.1 → 12.0.54-alpha.3
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/lib/components/NavigationHeader/NavigationHeader.js +5 -2
- package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -1
- package/lib/features/agent-chat/NativeAgentChat.js +354 -0
- package/lib/features/agent-chat/NativeAgentChat.js.map +1 -0
- package/lib/features/attachments/displayUserMessageText.js +3 -2
- package/lib/features/attachments/displayUserMessageText.js.map +1 -1
- package/lib/features/attachments/useImageAttachments.js +9 -7
- package/lib/features/attachments/useImageAttachments.js.map +1 -1
- package/lib/features/canvas/withRemoteSafeArea.js +46 -0
- package/lib/features/canvas/withRemoteSafeArea.js.map +1 -0
- package/lib/features/chat/ChatTranscript.js +23 -15
- package/lib/features/chat/ChatTranscript.js.map +1 -1
- package/lib/features/chat/toolActivity.js +42 -6
- package/lib/features/chat/toolActivity.js.map +1 -1
- package/lib/features/chat/transcriptGroups.js +11 -2
- package/lib/features/chat/transcriptGroups.js.map +1 -1
- package/lib/features/shopping/chat/homeShoppingIntent.js +58 -0
- package/lib/features/shopping/chat/homeShoppingIntent.js.map +1 -0
- package/lib/features/shopping/chat/openShopNative.js +60 -0
- package/lib/features/shopping/chat/openShopNative.js.map +1 -0
- package/lib/hooks/useCdecliChannel.js +10 -8
- package/lib/hooks/useCdecliChannel.js.map +1 -1
- package/lib/hooks/useChatStream.js +13 -6
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/screens/Chat/index.js +44 -5
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js +23 -3
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/ShoppingNative/index.js +21 -2
- package/lib/screens/ShoppingNative/index.js.map +1 -1
- package/lib/screens/ShoppingNative/useShoppingHostChat.js +66 -0
- package/lib/screens/ShoppingNative/useShoppingHostChat.js.map +1 -0
- package/lib/services/brainQuickReply.js +72 -2
- package/lib/services/brainQuickReply.js.map +1 -1
- package/package.json +2 -2
|
@@ -19,7 +19,7 @@ function resolveTitle(options, route) {
|
|
|
19
19
|
return typeof fallback === "string" && fallback.trim() ? fallback : "Yantra";
|
|
20
20
|
}
|
|
21
21
|
const NavigationHeader = (props) => {
|
|
22
|
-
var _a, _b, _c, _d, _e;
|
|
22
|
+
var _a, _b, _c, _d, _e, _f;
|
|
23
23
|
const {
|
|
24
24
|
navigation: navProp,
|
|
25
25
|
route,
|
|
@@ -87,6 +87,9 @@ const NavigationHeader = (props) => {
|
|
|
87
87
|
}) => [styles.iconButton, pressed && styles.iconButtonPressed], hitSlop: 8, children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "chevron-left", size: ICON_SIZE + 4, color: iconColor }) }) : showToggle ? /* @__PURE__ */ jsx(Pressable, { onPress: handleToggleDrawer, accessibilityLabel: "Open menu", accessibilityRole: "button", style: ({
|
|
88
88
|
pressed
|
|
89
89
|
}) => [styles.iconButton, pressed && styles.iconButtonPressed], hitSlop: 8, children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "menu", size: ICON_SIZE, color: iconColor }) }) : null;
|
|
90
|
+
if ((_e = route == null ? void 0 : route.params) == null ? void 0 : _e.hideNavigationHeader) {
|
|
91
|
+
return /* @__PURE__ */ jsx(StatusBar, { style: isDark ? "light" : "dark" });
|
|
92
|
+
}
|
|
90
93
|
const hideBrandTitle = showChatToolbar && title === "Yantra";
|
|
91
94
|
const titleSlot = showTitle && !hideBrandTitle ? /* @__PURE__ */ jsx(Text, { style: [styles.title, titleAlignLeft ? styles.titleAlignLeft : styles.titleAlignCenter, {
|
|
92
95
|
color: titleColor
|
|
@@ -102,7 +105,7 @@ const NavigationHeader = (props) => {
|
|
|
102
105
|
backgroundColor: surfaceColor,
|
|
103
106
|
borderBottomColor: dividerColor,
|
|
104
107
|
paddingTop: insets.top > 0 ? 0 : 6
|
|
105
|
-
}, (
|
|
108
|
+
}, (_f = options == null ? void 0 : options.headerStyle) != null ? _f : null], children: [
|
|
106
109
|
/* @__PURE__ */ jsx(View, { style: styles.leftSlot, children: leftSlot }),
|
|
107
110
|
showChatToolbar ? /* @__PURE__ */ jsxs(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles.toolsScroll, contentContainerStyle: styles.toolsContent, keyboardShouldPersistTaps: "handled", children: [
|
|
108
111
|
/* @__PURE__ */ jsx(HeaderTasksButton, { isDark }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationHeader.js","sources":["../../../src/components/NavigationHeader/NavigationHeader.tsx"],"sourcesContent":["/**\n * Universal navigation header for the Yantra mobile app.\n *\n * Home and Chat keep Tasks · Skills in the top bar. Apps and History live in\n * the sidebar drawer (Manus-style rows); Apps opens a full screen, not a popup.\n *\n * Wired via `customHeader` in `compute.ts`. Screens never call `setOptions`.\n */\nimport React, { useCallback, useMemo } from 'react';\nimport { Pressable, ScrollView, StyleSheet, View, useColorScheme } from 'react-native';\nimport { dismissKeyboard } from '../../utils/keyboardController';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { StatusBar } from 'expo-status-bar';\nimport { CommonActions, DrawerActions, useNavigation } from '@react-navigation/native';\nimport { getHeaderTitle } from '@react-navigation/elements';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { Text } from '@admin-layout/gluestack-ui-mobile';\nimport { GatewayConnector } from '../GatewayConnector';\nimport { tryWebBuilderBack } from '../../screens/WebBuilder/webbuilderBackHandler';\nimport { config } from '../../config/env-config';\nimport { resolveAppTitleFromSurfaceUrl } from '../../features/apps/resolveSurfaceUrl';\nimport { navigateToNewChatHome } from '../../utils/navigateToNewChatHome';\nimport { HeaderMoreMenu } from './HeaderMoreMenu';\nimport { HeaderSkillsButton } from './HeaderSkillsButton';\nimport { HeaderTasksButton } from './HeaderTasksButton';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ninterface NavigationHeaderProps {\n navigation?: any;\n route?: any;\n options?: any;\n back?: { title?: string };\n\n showTitle?: boolean;\n showToggle?: boolean;\n showBack?: boolean;\n showFilter?: boolean;\n isSearchBack?: boolean;\n showGateway?: boolean;\n showApps?: boolean;\n showHistory?: boolean;\n showNewChat?: boolean;\n headerBgColor?: string;\n}\n\nconst ICON_SIZE = 22;\n\nfunction resolveTitle(options: any, route: any): string {\n const paramTitle = route?.params?.appTitle;\n const routeName = typeof route?.name === 'string' ? route.name : '';\n if (/CanvasNative/i.test(routeName)) return 'Canvas';\n if (typeof paramTitle === 'string' && paramTitle.trim()) {\n return paramTitle.trim();\n }\n const fromUrl = resolveAppTitleFromSurfaceUrl(route?.params?.url, config);\n if (fromUrl) return fromUrl;\n\n if (typeof options?.title === 'string' && options.title.trim()) {\n return options.title.trim();\n }\n if (typeof options?.headerTitle === 'string' && options.headerTitle.trim()) {\n return options.headerTitle.trim();\n }\n const fallback = getHeaderTitle?.(options ?? {}, route?.name ?? 'Yantra');\n return typeof fallback === 'string' && fallback.trim() ? fallback : 'Yantra';\n}\n\nconst NavigationHeader: React.FC<NavigationHeaderProps> = (props) => {\n const {\n navigation: navProp,\n route,\n options,\n back,\n showTitle = true,\n showToggle = false,\n showBack = false,\n showGateway = false,\n showNewChat = false,\n headerBgColor,\n } = props;\n\n const showChatToolbar = showGateway;\n\n const fallbackNav = useNavigation<any>();\n const navigation = navProp ?? fallbackNav;\n\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const insets = useSafeAreaInsets();\n\n const themeTitleColor = isDark ? '#f1f5f9' : '#0f172a';\n const optionTint = typeof options?.headerTintColor === 'string' ? options.headerTintColor : null;\n const tintLooksDark = optionTint && /^(#?000(000)?|black)$/i.test(optionTint.trim());\n const effectiveTint = optionTint && !(isDark && tintLooksDark) ? optionTint : null;\n const titleColor = effectiveTint ?? themeTitleColor;\n const iconColor = effectiveTint ?? themeTitleColor;\n\n const surfaceColor = headerBgColor ?? (isDark ? '#0f172a' : '#ffffff');\n const dividerColor = isDark ? 'rgba(148, 163, 184, 0.18)' : 'rgba(15, 23, 42, 0.06)';\n\n const titleAlignLeft = options?.headerTitleAlign === 'left';\n const title = useMemo(\n () => resolveTitle(options, route),\n [options, route, route?.params?.appTitle, route?.params?.url],\n );\n const optionTitleStyle = options?.headerTitleStyle ?? null;\n\n const orgName = useMemo(() => {\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [route?.params?.orgName]);\n\n const handleBack = useCallback(() => {\n const routeName = typeof route?.name === 'string' ? route.name : '';\n if (/webbuilder/i.test(routeName) && tryWebBuilderBack()) {\n return;\n }\n if (navigation?.canGoBack?.()) {\n navigation.goBack();\n return;\n }\n navigation?.dispatch?.(\n CommonActions.navigate({\n name: 'MainStack.Layout.Home',\n params: orgName ? { orgName } : undefined,\n }),\n );\n }, [navigation, orgName, route?.name]);\n\n const handleToggleDrawer = useCallback(() => {\n try {\n navigation?.dispatch?.(DrawerActions.openDrawer());\n } catch {\n /* Current navigator may not be a drawer — ignore. */\n }\n }, [navigation]);\n\n const handleNewChat = useCallback(() => {\n navigateToNewChatHome(navigation, orgName);\n }, [navigation, orgName]);\n\n const wantsBack = Boolean(back) || showBack;\n\n const leftSlot = wantsBack ? (\n <Pressable\n onPress={handleBack}\n accessibilityLabel=\"Go back\"\n accessibilityRole=\"button\"\n style={({ pressed }) => [styles.iconButton, pressed && styles.iconButtonPressed]}\n hitSlop={8}\n >\n <MaterialCommunityIcons name=\"chevron-left\" size={ICON_SIZE + 4} color={iconColor} />\n </Pressable>\n ) : showToggle ? (\n <Pressable\n onPress={handleToggleDrawer}\n accessibilityLabel=\"Open menu\"\n accessibilityRole=\"button\"\n style={({ pressed }) => [styles.iconButton, pressed && styles.iconButtonPressed]}\n hitSlop={8}\n >\n <MaterialCommunityIcons name=\"menu\" size={ICON_SIZE} color={iconColor} />\n </Pressable>\n ) : null;\n\n const hideBrandTitle = showChatToolbar && title === 'Yantra';\n const titleSlot =\n showTitle && !hideBrandTitle ? (\n <Text\n style={[\n styles.title,\n titleAlignLeft ? styles.titleAlignLeft : styles.titleAlignCenter,\n { color: titleColor },\n optionTitleStyle,\n ]}\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n >\n {title}\n </Text>\n ) : null;\n\n return (\n <>\n <StatusBar style={isDark ? 'light' : 'dark'} />\n <SafeAreaView edges={['top']} style={{ backgroundColor: surfaceColor }}>\n <View\n onStartShouldSetResponderCapture={() => {\n dismissKeyboard();\n return false;\n }}\n style={[\n styles.row,\n {\n backgroundColor: surfaceColor,\n borderBottomColor: dividerColor,\n paddingTop: insets.top > 0 ? 0 : 6,\n },\n options?.headerStyle ?? null,\n ]}\n >\n <View style={styles.leftSlot}>{leftSlot}</View>\n\n {showChatToolbar ? (\n <ScrollView\n horizontal\n showsHorizontalScrollIndicator={false}\n style={styles.toolsScroll}\n contentContainerStyle={styles.toolsContent}\n keyboardShouldPersistTaps=\"handled\"\n >\n <HeaderTasksButton isDark={isDark} />\n <HeaderSkillsButton isDark={isDark} />\n </ScrollView>\n ) : (\n <View style={[styles.titleSlot, titleAlignLeft && styles.titleSlotLeft]}>{titleSlot}</View>\n )}\n\n <View style={styles.rightSlot}>\n {showChatToolbar ? (\n <View style={styles.rightActions}>\n {showGateway ? <GatewayConnector /> : null}\n <HeaderMoreMenu isDark={isDark} onNewChat={showNewChat ? handleNewChat : undefined} />\n </View>\n ) : showNewChat ? (\n <HeaderToolbarButton\n icon=\"chat-plus-outline\"\n onPress={handleNewChat}\n accessibilityLabel=\"New chat\"\n isDark={isDark}\n />\n ) : null}\n </View>\n </View>\n </SafeAreaView>\n </>\n );\n};\n\nconst styles = StyleSheet.create({\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingLeft: 4,\n paddingRight: 6,\n paddingVertical: 4,\n minHeight: 48,\n borderBottomWidth: StyleSheet.hairlineWidth,\n overflow: 'visible',\n },\n leftSlot: {\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n },\n toolsScroll: {\n flex: 1,\n minWidth: 0,\n },\n toolsContent: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingLeft: 2,\n paddingRight: 8,\n gap: 2,\n },\n titleSlot: {\n flex: 1,\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 8,\n minWidth: 0,\n },\n titleSlotLeft: {\n alignItems: 'flex-start',\n },\n rightSlot: {\n flexShrink: 0,\n alignItems: 'flex-end',\n justifyContent: 'center',\n paddingLeft: 4,\n },\n rightActions: {\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n },\n title: {\n fontSize: 17,\n fontWeight: '700',\n letterSpacing: -0.2,\n flexShrink: 1,\n },\n titleAlignCenter: {\n textAlign: 'center',\n },\n titleAlignLeft: {\n textAlign: 'left',\n },\n iconButton: {\n width: 36,\n height: 36,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 10,\n },\n iconButtonPressed: {\n opacity: 0.6,\n },\n});\n\nexport default React.memo(NavigationHeader);\n"],"names":["_a","_b"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NavigationHeader.js","sources":["../../../src/components/NavigationHeader/NavigationHeader.tsx"],"sourcesContent":["/**\n * Universal navigation header for the Yantra mobile app.\n *\n * Home and Chat keep Tasks · Skills in the top bar. Apps and History live in\n * the sidebar drawer (Manus-style rows); Apps opens a full screen, not a popup.\n *\n * Wired via `customHeader` in `compute.ts`. Screens never call `setOptions`.\n */\nimport React, { useCallback, useMemo } from 'react';\nimport { Pressable, ScrollView, StyleSheet, View, useColorScheme } from 'react-native';\nimport { dismissKeyboard } from '../../utils/keyboardController';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { StatusBar } from 'expo-status-bar';\nimport { CommonActions, DrawerActions, useNavigation } from '@react-navigation/native';\nimport { getHeaderTitle } from '@react-navigation/elements';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { Text } from '@admin-layout/gluestack-ui-mobile';\nimport { GatewayConnector } from '../GatewayConnector';\nimport { tryWebBuilderBack } from '../../screens/WebBuilder/webbuilderBackHandler';\nimport { config } from '../../config/env-config';\nimport { resolveAppTitleFromSurfaceUrl } from '../../features/apps/resolveSurfaceUrl';\nimport { navigateToNewChatHome } from '../../utils/navigateToNewChatHome';\nimport { HeaderMoreMenu } from './HeaderMoreMenu';\nimport { HeaderSkillsButton } from './HeaderSkillsButton';\nimport { HeaderTasksButton } from './HeaderTasksButton';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ninterface NavigationHeaderProps {\n navigation?: any;\n route?: any;\n options?: any;\n back?: { title?: string };\n\n showTitle?: boolean;\n showToggle?: boolean;\n showBack?: boolean;\n showFilter?: boolean;\n isSearchBack?: boolean;\n showGateway?: boolean;\n showApps?: boolean;\n showHistory?: boolean;\n showNewChat?: boolean;\n headerBgColor?: string;\n}\n\nconst ICON_SIZE = 22;\n\nfunction resolveTitle(options: any, route: any): string {\n const paramTitle = route?.params?.appTitle;\n const routeName = typeof route?.name === 'string' ? route.name : '';\n if (/CanvasNative/i.test(routeName)) return 'Canvas';\n if (typeof paramTitle === 'string' && paramTitle.trim()) {\n return paramTitle.trim();\n }\n const fromUrl = resolveAppTitleFromSurfaceUrl(route?.params?.url, config);\n if (fromUrl) return fromUrl;\n\n if (typeof options?.title === 'string' && options.title.trim()) {\n return options.title.trim();\n }\n if (typeof options?.headerTitle === 'string' && options.headerTitle.trim()) {\n return options.headerTitle.trim();\n }\n const fallback = getHeaderTitle?.(options ?? {}, route?.name ?? 'Yantra');\n return typeof fallback === 'string' && fallback.trim() ? fallback : 'Yantra';\n}\n\nconst NavigationHeader: React.FC<NavigationHeaderProps> = (props) => {\n const {\n navigation: navProp,\n route,\n options,\n back,\n showTitle = true,\n showToggle = false,\n showBack = false,\n showGateway = false,\n showNewChat = false,\n headerBgColor,\n } = props;\n\n const showChatToolbar = showGateway;\n\n const fallbackNav = useNavigation<any>();\n const navigation = navProp ?? fallbackNav;\n\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const insets = useSafeAreaInsets();\n\n const themeTitleColor = isDark ? '#f1f5f9' : '#0f172a';\n const optionTint = typeof options?.headerTintColor === 'string' ? options.headerTintColor : null;\n const tintLooksDark = optionTint && /^(#?000(000)?|black)$/i.test(optionTint.trim());\n const effectiveTint = optionTint && !(isDark && tintLooksDark) ? optionTint : null;\n const titleColor = effectiveTint ?? themeTitleColor;\n const iconColor = effectiveTint ?? themeTitleColor;\n\n const surfaceColor = headerBgColor ?? (isDark ? '#0f172a' : '#ffffff');\n const dividerColor = isDark ? 'rgba(148, 163, 184, 0.18)' : 'rgba(15, 23, 42, 0.06)';\n\n const titleAlignLeft = options?.headerTitleAlign === 'left';\n const title = useMemo(\n () => resolveTitle(options, route),\n [options, route, route?.params?.appTitle, route?.params?.url],\n );\n const optionTitleStyle = options?.headerTitleStyle ?? null;\n\n const orgName = useMemo(() => {\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [route?.params?.orgName]);\n\n const handleBack = useCallback(() => {\n const routeName = typeof route?.name === 'string' ? route.name : '';\n if (/webbuilder/i.test(routeName) && tryWebBuilderBack()) {\n return;\n }\n if (navigation?.canGoBack?.()) {\n navigation.goBack();\n return;\n }\n navigation?.dispatch?.(\n CommonActions.navigate({\n name: 'MainStack.Layout.Home',\n params: orgName ? { orgName } : undefined,\n }),\n );\n }, [navigation, orgName, route?.name]);\n\n const handleToggleDrawer = useCallback(() => {\n try {\n navigation?.dispatch?.(DrawerActions.openDrawer());\n } catch {\n /* Current navigator may not be a drawer — ignore. */\n }\n }, [navigation]);\n\n const handleNewChat = useCallback(() => {\n navigateToNewChatHome(navigation, orgName);\n }, [navigation, orgName]);\n\n const wantsBack = Boolean(back) || showBack;\n\n const leftSlot = wantsBack ? (\n <Pressable\n onPress={handleBack}\n accessibilityLabel=\"Go back\"\n accessibilityRole=\"button\"\n style={({ pressed }) => [styles.iconButton, pressed && styles.iconButtonPressed]}\n hitSlop={8}\n >\n <MaterialCommunityIcons name=\"chevron-left\" size={ICON_SIZE + 4} color={iconColor} />\n </Pressable>\n ) : showToggle ? (\n <Pressable\n onPress={handleToggleDrawer}\n accessibilityLabel=\"Open menu\"\n accessibilityRole=\"button\"\n style={({ pressed }) => [styles.iconButton, pressed && styles.iconButtonPressed]}\n hitSlop={8}\n >\n <MaterialCommunityIcons name=\"menu\" size={ICON_SIZE} color={iconColor} />\n </Pressable>\n ) : null;\n\n if (route?.params?.hideNavigationHeader) {\n return <StatusBar style={isDark ? 'light' : 'dark'} />;\n }\n\n const hideBrandTitle = showChatToolbar && title === 'Yantra';\n const titleSlot =\n showTitle && !hideBrandTitle ? (\n <Text\n style={[\n styles.title,\n titleAlignLeft ? styles.titleAlignLeft : styles.titleAlignCenter,\n { color: titleColor },\n optionTitleStyle,\n ]}\n numberOfLines={1}\n ellipsizeMode=\"tail\"\n >\n {title}\n </Text>\n ) : null;\n\n return (\n <>\n <StatusBar style={isDark ? 'light' : 'dark'} />\n <SafeAreaView edges={['top']} style={{ backgroundColor: surfaceColor }}>\n <View\n onStartShouldSetResponderCapture={() => {\n dismissKeyboard();\n return false;\n }}\n style={[\n styles.row,\n {\n backgroundColor: surfaceColor,\n borderBottomColor: dividerColor,\n paddingTop: insets.top > 0 ? 0 : 6,\n },\n options?.headerStyle ?? null,\n ]}\n >\n <View style={styles.leftSlot}>{leftSlot}</View>\n\n {showChatToolbar ? (\n <ScrollView\n horizontal\n showsHorizontalScrollIndicator={false}\n style={styles.toolsScroll}\n contentContainerStyle={styles.toolsContent}\n keyboardShouldPersistTaps=\"handled\"\n >\n <HeaderTasksButton isDark={isDark} />\n <HeaderSkillsButton isDark={isDark} />\n </ScrollView>\n ) : (\n <View style={[styles.titleSlot, titleAlignLeft && styles.titleSlotLeft]}>{titleSlot}</View>\n )}\n\n <View style={styles.rightSlot}>\n {showChatToolbar ? (\n <View style={styles.rightActions}>\n {showGateway ? <GatewayConnector /> : null}\n <HeaderMoreMenu isDark={isDark} onNewChat={showNewChat ? handleNewChat : undefined} />\n </View>\n ) : showNewChat ? (\n <HeaderToolbarButton\n icon=\"chat-plus-outline\"\n onPress={handleNewChat}\n accessibilityLabel=\"New chat\"\n isDark={isDark}\n />\n ) : null}\n </View>\n </View>\n </SafeAreaView>\n </>\n );\n};\n\nconst styles = StyleSheet.create({\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingLeft: 4,\n paddingRight: 6,\n paddingVertical: 4,\n minHeight: 48,\n borderBottomWidth: StyleSheet.hairlineWidth,\n overflow: 'visible',\n },\n leftSlot: {\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n },\n toolsScroll: {\n flex: 1,\n minWidth: 0,\n },\n toolsContent: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingLeft: 2,\n paddingRight: 8,\n gap: 2,\n },\n titleSlot: {\n flex: 1,\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 8,\n minWidth: 0,\n },\n titleSlotLeft: {\n alignItems: 'flex-start',\n },\n rightSlot: {\n flexShrink: 0,\n alignItems: 'flex-end',\n justifyContent: 'center',\n paddingLeft: 4,\n },\n rightActions: {\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n },\n title: {\n fontSize: 17,\n fontWeight: '700',\n letterSpacing: -0.2,\n flexShrink: 1,\n },\n titleAlignCenter: {\n textAlign: 'center',\n },\n titleAlignLeft: {\n textAlign: 'left',\n },\n iconButton: {\n width: 36,\n height: 36,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 10,\n },\n iconButtonPressed: {\n opacity: 0.6,\n },\n});\n\nexport default React.memo(NavigationHeader);\n"],"names":["_a","_b"],"mappings":"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"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {useState,useRef,useEffect,useCallback}from'react';import {StyleSheet,Keyboard,InteractionManager,View,KeyboardAvoidingView,Text,Pressable,TextInput,ActivityIndicator,Platform}from'react-native';import {MaterialCommunityIcons,Feather}from'@expo/vector-icons';import {useSafeInsets}from'../canvas/withRemoteSafeArea.js';import {useImageAttachments}from'../attachments/useImageAttachments.js';import {ComposerAttachmentBar}from'../attachments/ComposerAttachmentBar.js';import {NativeDictationBar}from'../audio-input/NativeDictationBar.js';import {AudioRecorderPanel}from'../audio-input/AudioRecorderPanel.js';import {MicErrorBoundary}from'../audio-input/MicErrorBoundary.js';import {isNativeDictationAvailable}from'../audio-input/nativeDictation.js';import {requestMicPermission}from'../audio-input/useAudioPermission.js';import {ChatTranscript}from'../chat/ChatTranscript.js';import ThinkingIndicator from'../../components/ThinkingIndicator.js';function NativeAgentChat({
|
|
2
|
+
title,
|
|
3
|
+
visible,
|
|
4
|
+
onClose,
|
|
5
|
+
messages,
|
|
6
|
+
onSend,
|
|
7
|
+
onClear,
|
|
8
|
+
busy = false,
|
|
9
|
+
streamingContent = null,
|
|
10
|
+
error = null,
|
|
11
|
+
placeholder = "Ask anything\u2026",
|
|
12
|
+
emptyTitle,
|
|
13
|
+
emptyBody,
|
|
14
|
+
suggestions = [],
|
|
15
|
+
beforeComposer,
|
|
16
|
+
composerAccessory,
|
|
17
|
+
paneOverlay,
|
|
18
|
+
headerTrailing,
|
|
19
|
+
belowHeader,
|
|
20
|
+
composerLead,
|
|
21
|
+
draft: draftProp,
|
|
22
|
+
onDraftChange,
|
|
23
|
+
composerSeed,
|
|
24
|
+
composerSeedKey,
|
|
25
|
+
onComposerSeedConsumed,
|
|
26
|
+
embedded = false,
|
|
27
|
+
enableVoice = true,
|
|
28
|
+
enableAttachments = true,
|
|
29
|
+
isDark = false,
|
|
30
|
+
ink = "#0f172a",
|
|
31
|
+
muted = "#64748b",
|
|
32
|
+
screen = "#f8fafc",
|
|
33
|
+
border = "#e8ecf1"
|
|
34
|
+
}) {
|
|
35
|
+
const insets = useSafeInsets();
|
|
36
|
+
const draftControlled = onDraftChange !== void 0;
|
|
37
|
+
const [internalDraft, setInternalDraft] = useState("");
|
|
38
|
+
const draft = draftControlled ? draftProp != null ? draftProp : "" : internalDraft;
|
|
39
|
+
const draftRef = useRef(draft);
|
|
40
|
+
draftRef.current = draft;
|
|
41
|
+
const setDraft = (next) => {
|
|
42
|
+
const value = typeof next === "function" ? next(draftRef.current) : next;
|
|
43
|
+
if (draftControlled) onDraftChange == null ? void 0 : onDraftChange(value);
|
|
44
|
+
else setInternalDraft(value);
|
|
45
|
+
};
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (composerSeed == null) return;
|
|
48
|
+
setDraft((prev) => prev.trim() ? `${composerSeed}
|
|
49
|
+
|
|
50
|
+
${prev}` : composerSeed);
|
|
51
|
+
onComposerSeedConsumed == null ? void 0 : onComposerSeedConsumed();
|
|
52
|
+
}, [composerSeed, composerSeedKey]);
|
|
53
|
+
const attachments = useImageAttachments();
|
|
54
|
+
const [showNativeDictation, setShowNativeDictation] = useState(false);
|
|
55
|
+
const [showAudioRecorder, setShowAudioRecorder] = useState(false);
|
|
56
|
+
const [voiceError, setVoiceError] = useState(null);
|
|
57
|
+
const canSend = draft.trim().length > 0 || attachments.pending.length > 0;
|
|
58
|
+
const listening = showNativeDictation || showAudioRecorder;
|
|
59
|
+
const submit = (text = draft, files) => {
|
|
60
|
+
const trimmed = text.trim();
|
|
61
|
+
const pending = attachments.forSend();
|
|
62
|
+
if (!trimmed && !(pending == null ? void 0 : pending.length)) return;
|
|
63
|
+
setDraft("");
|
|
64
|
+
attachments.clear();
|
|
65
|
+
onSend(trimmed, pending);
|
|
66
|
+
};
|
|
67
|
+
const openWhisperRecorder = useCallback(() => {
|
|
68
|
+
setVoiceError(null);
|
|
69
|
+
void (async () => {
|
|
70
|
+
const {
|
|
71
|
+
granted,
|
|
72
|
+
error: error2
|
|
73
|
+
} = await requestMicPermission();
|
|
74
|
+
if (!granted) {
|
|
75
|
+
setVoiceError(error2 || "Microphone is not available.");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
setShowAudioRecorder(true);
|
|
79
|
+
})();
|
|
80
|
+
}, []);
|
|
81
|
+
const handleMicPress = useCallback(() => {
|
|
82
|
+
if (listening) {
|
|
83
|
+
setShowNativeDictation(false);
|
|
84
|
+
setShowAudioRecorder(false);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
setVoiceError(null);
|
|
88
|
+
Keyboard.dismiss();
|
|
89
|
+
if (isNativeDictationAvailable()) {
|
|
90
|
+
setShowNativeDictation(true);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
openWhisperRecorder();
|
|
94
|
+
}, [listening, openWhisperRecorder]);
|
|
95
|
+
const pasteTranscript = useCallback((text) => {
|
|
96
|
+
const cleaned = (text != null ? text : "").trim();
|
|
97
|
+
if (!cleaned) return;
|
|
98
|
+
setDraft((prev) => prev.trim() ? `${prev.trim()} ${cleaned}` : cleaned);
|
|
99
|
+
}, []);
|
|
100
|
+
const openPicker = useCallback((fn) => {
|
|
101
|
+
Keyboard.dismiss();
|
|
102
|
+
InteractionManager.runAfterInteractions(() => {
|
|
103
|
+
setTimeout(() => {
|
|
104
|
+
void fn();
|
|
105
|
+
}, 350);
|
|
106
|
+
});
|
|
107
|
+
}, []);
|
|
108
|
+
const banner = voiceError || attachments.error || error;
|
|
109
|
+
if (!visible) return null;
|
|
110
|
+
return /* @__PURE__ */ jsxs(View, { style: [StyleSheet.absoluteFill, styles.overlay, {
|
|
111
|
+
backgroundColor: screen
|
|
112
|
+
}], pointerEvents: "auto", children: [
|
|
113
|
+
/* @__PURE__ */ jsxs(KeyboardAvoidingView, { style: [styles.fill, {
|
|
114
|
+
backgroundColor: screen,
|
|
115
|
+
paddingTop: embedded ? 8 : Math.max(insets.top, 8)
|
|
116
|
+
}], behavior: Platform.OS === "ios" ? "padding" : void 0, children: [
|
|
117
|
+
/* @__PURE__ */ jsxs(View, { style: [styles.head, {
|
|
118
|
+
borderColor: border
|
|
119
|
+
}], children: [
|
|
120
|
+
/* @__PURE__ */ jsxs(View, { style: styles.headTitle, children: [
|
|
121
|
+
/* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "creation", size: 16, color: ink }),
|
|
122
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.title, {
|
|
123
|
+
color: ink
|
|
124
|
+
}], children: title })
|
|
125
|
+
] }),
|
|
126
|
+
/* @__PURE__ */ jsxs(View, { style: styles.headActions, children: [
|
|
127
|
+
onClear && messages.length > 0 ? /* @__PURE__ */ jsx(Pressable, { onPress: onClear, hitSlop: 10, accessibilityRole: "button", accessibilityLabel: "Clear chat", children: /* @__PURE__ */ jsx(Feather, { name: "trash-2", size: 18, color: muted }) }) : null,
|
|
128
|
+
headerTrailing,
|
|
129
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: onClose, hitSlop: 10, accessibilityLabel: `Close ${title}`, children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "close", size: 22, color: muted }) })
|
|
130
|
+
] })
|
|
131
|
+
] }),
|
|
132
|
+
belowHeader,
|
|
133
|
+
messages.length === 0 && !streamingContent ? /* @__PURE__ */ jsxs(View, { style: styles.empty, children: [
|
|
134
|
+
emptyTitle ? /* @__PURE__ */ jsx(Text, { style: [styles.emptyTitle, {
|
|
135
|
+
color: ink
|
|
136
|
+
}], children: emptyTitle }) : null,
|
|
137
|
+
emptyBody ? /* @__PURE__ */ jsx(Text, { style: [styles.emptyBody, {
|
|
138
|
+
color: muted
|
|
139
|
+
}], children: emptyBody }) : null,
|
|
140
|
+
suggestions.length > 0 ? /* @__PURE__ */ jsx(View, { style: styles.chips, children: suggestions.map((chip) => /* @__PURE__ */ jsx(Pressable, { onPress: () => {
|
|
141
|
+
var _a;
|
|
142
|
+
return submit((_a = chip.prompt) != null ? _a : chip.label);
|
|
143
|
+
}, style: [styles.chip, {
|
|
144
|
+
borderColor: border,
|
|
145
|
+
backgroundColor: isDark ? "#1e293b" : "#fff"
|
|
146
|
+
}], children: /* @__PURE__ */ jsx(Text, { style: [styles.chipText, {
|
|
147
|
+
color: ink
|
|
148
|
+
}], children: chip.label }) }, chip.id)) }) : null
|
|
149
|
+
] }) : /* @__PURE__ */ jsxs(View, { style: styles.fill, children: [
|
|
150
|
+
/* @__PURE__ */ jsx(ChatTranscript, { messages, streamingContent: streamingContent != null ? streamingContent : void 0, isDark, listFooter: beforeComposer }),
|
|
151
|
+
busy && !(streamingContent == null ? void 0 : streamingContent.trim()) ? /* @__PURE__ */ jsx(View, { style: styles.thinking, children: /* @__PURE__ */ jsx(ThinkingIndicator, { color: muted }) }) : null
|
|
152
|
+
] }),
|
|
153
|
+
/* @__PURE__ */ jsxs(View, { style: [styles.composerWrap, {
|
|
154
|
+
borderColor: border,
|
|
155
|
+
paddingBottom: Math.max(insets.bottom, 10)
|
|
156
|
+
}], children: [
|
|
157
|
+
composerLead,
|
|
158
|
+
banner ? /* @__PURE__ */ jsx(View, { style: [styles.errorBanner, {
|
|
159
|
+
backgroundColor: isDark ? "#2b1a1d" : "#fef2f2"
|
|
160
|
+
}], children: /* @__PURE__ */ jsx(Text, { style: styles.errorText, children: banner }) }) : null,
|
|
161
|
+
showNativeDictation ? /* @__PURE__ */ jsx(MicErrorBoundary, { onCancel: () => setShowNativeDictation(false), onError: () => {
|
|
162
|
+
setShowNativeDictation(false);
|
|
163
|
+
openWhisperRecorder();
|
|
164
|
+
}, children: /* @__PURE__ */ jsx(NativeDictationBar, { isDark, onInterim: () => void 0, onTranscriptionComplete: (text) => {
|
|
165
|
+
setShowNativeDictation(false);
|
|
166
|
+
pasteTranscript(text);
|
|
167
|
+
}, onCancel: () => setShowNativeDictation(false), onFallback: () => {
|
|
168
|
+
setShowNativeDictation(false);
|
|
169
|
+
openWhisperRecorder();
|
|
170
|
+
} }) }) : showAudioRecorder ? /* @__PURE__ */ jsx(MicErrorBoundary, { onCancel: () => setShowAudioRecorder(false), onError: (err) => {
|
|
171
|
+
setShowAudioRecorder(false);
|
|
172
|
+
setVoiceError(err);
|
|
173
|
+
}, children: /* @__PURE__ */ jsx(AudioRecorderPanel, { isDark, onTranscriptionComplete: (text) => {
|
|
174
|
+
setShowAudioRecorder(false);
|
|
175
|
+
pasteTranscript(text);
|
|
176
|
+
}, onCancel: () => setShowAudioRecorder(false), onError: (err) => {
|
|
177
|
+
setShowAudioRecorder(false);
|
|
178
|
+
setVoiceError(err);
|
|
179
|
+
} }) }) : /* @__PURE__ */ jsxs(View, { style: [styles.composerCard, {
|
|
180
|
+
borderColor: border,
|
|
181
|
+
backgroundColor: isDark ? "#111827" : "#fff"
|
|
182
|
+
}], children: [
|
|
183
|
+
enableAttachments ? /* @__PURE__ */ jsx(ComposerAttachmentBar, { attachments: attachments.pending, onRemove: attachments.remove, isDark }) : null,
|
|
184
|
+
/* @__PURE__ */ jsxs(View, { style: styles.inputRow, children: [
|
|
185
|
+
/* @__PURE__ */ jsx(TextInput, { value: draft, onChangeText: (next) => {
|
|
186
|
+
setDraft(next);
|
|
187
|
+
if (voiceError) setVoiceError(null);
|
|
188
|
+
}, placeholder: listening ? "Listening\u2026 speak your request" : placeholder, placeholderTextColor: muted, multiline: true, textAlignVertical: "top", editable: !busy, onSubmitEditing: () => submit(), style: [styles.input, {
|
|
189
|
+
color: ink
|
|
190
|
+
}], accessibilityLabel: placeholder }),
|
|
191
|
+
enableVoice ? /* @__PURE__ */ jsx(Pressable, { onPress: handleMicPress, disabled: busy && !listening, style: [styles.mic, listening && styles.micLive], accessibilityRole: "button", accessibilityLabel: listening ? "Stop listening" : "Start voice input", children: /* @__PURE__ */ jsx(Feather, { name: listening ? "square" : "mic", size: 16, color: listening ? "#b91c1c" : muted }) }) : null,
|
|
192
|
+
canSend ? /* @__PURE__ */ jsx(Pressable, { onPress: () => submit(), style: [styles.send, busy && {
|
|
193
|
+
opacity: 0.85
|
|
194
|
+
}], accessibilityRole: "button", accessibilityLabel: "Send", children: /* @__PURE__ */ jsx(Feather, { name: "send", size: 14, color: "#fff", style: styles.sendIcon }) }) : null
|
|
195
|
+
] }),
|
|
196
|
+
enableAttachments || composerAccessory ? /* @__PURE__ */ jsxs(View, { style: styles.tools, children: [
|
|
197
|
+
enableAttachments ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
198
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: () => openPicker(attachments.pickFromLibrary), onLongPress: () => openPicker(attachments.captureFromCamera), disabled: attachments.busy, style: styles.toolBtn, accessibilityRole: "button", accessibilityLabel: "Add image or screenshot", children: attachments.busyKind === "library" || attachments.busyKind === "camera" ? /* @__PURE__ */ jsx(ActivityIndicator, { size: "small" }) : /* @__PURE__ */ jsx(Feather, { name: "image", size: 18, color: muted }) }),
|
|
199
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: () => openPicker(attachments.pickDocuments), disabled: attachments.busy, style: styles.toolBtn, accessibilityRole: "button", accessibilityLabel: "Attach files", children: attachments.busyKind === "documents" ? /* @__PURE__ */ jsx(ActivityIndicator, { size: "small" }) : /* @__PURE__ */ jsx(Feather, { name: "paperclip", size: 18, color: muted }) })
|
|
200
|
+
] }) : null,
|
|
201
|
+
composerAccessory ? /* @__PURE__ */ jsx(View, { style: styles.toolsAccessory, children: composerAccessory }) : null
|
|
202
|
+
] }) : null
|
|
203
|
+
] })
|
|
204
|
+
] })
|
|
205
|
+
] }),
|
|
206
|
+
paneOverlay
|
|
207
|
+
] });
|
|
208
|
+
}
|
|
209
|
+
const styles = StyleSheet.create({
|
|
210
|
+
overlay: {
|
|
211
|
+
zIndex: 200,
|
|
212
|
+
elevation: 200
|
|
213
|
+
},
|
|
214
|
+
fill: {
|
|
215
|
+
flex: 1,
|
|
216
|
+
overflow: "hidden"
|
|
217
|
+
},
|
|
218
|
+
head: {
|
|
219
|
+
flexDirection: "row",
|
|
220
|
+
alignItems: "center",
|
|
221
|
+
justifyContent: "space-between",
|
|
222
|
+
paddingHorizontal: 16,
|
|
223
|
+
paddingBottom: 10,
|
|
224
|
+
borderBottomWidth: StyleSheet.hairlineWidth
|
|
225
|
+
},
|
|
226
|
+
headTitle: {
|
|
227
|
+
flexDirection: "row",
|
|
228
|
+
alignItems: "center",
|
|
229
|
+
gap: 8
|
|
230
|
+
},
|
|
231
|
+
headActions: {
|
|
232
|
+
flexDirection: "row",
|
|
233
|
+
alignItems: "center",
|
|
234
|
+
gap: 12
|
|
235
|
+
},
|
|
236
|
+
title: {
|
|
237
|
+
fontSize: 16,
|
|
238
|
+
fontWeight: "700"
|
|
239
|
+
},
|
|
240
|
+
empty: {
|
|
241
|
+
flex: 1,
|
|
242
|
+
gap: 10,
|
|
243
|
+
paddingTop: 20,
|
|
244
|
+
paddingHorizontal: 16
|
|
245
|
+
},
|
|
246
|
+
thinking: {
|
|
247
|
+
paddingHorizontal: 16,
|
|
248
|
+
paddingBottom: 8
|
|
249
|
+
},
|
|
250
|
+
emptyTitle: {
|
|
251
|
+
fontSize: 18,
|
|
252
|
+
fontWeight: "700",
|
|
253
|
+
letterSpacing: -0.3
|
|
254
|
+
},
|
|
255
|
+
emptyBody: {
|
|
256
|
+
fontSize: 14,
|
|
257
|
+
lineHeight: 20
|
|
258
|
+
},
|
|
259
|
+
chips: {
|
|
260
|
+
flexDirection: "row",
|
|
261
|
+
flexWrap: "wrap",
|
|
262
|
+
gap: 8,
|
|
263
|
+
marginTop: 4
|
|
264
|
+
},
|
|
265
|
+
chip: {
|
|
266
|
+
borderWidth: 1,
|
|
267
|
+
borderRadius: 999,
|
|
268
|
+
paddingHorizontal: 12,
|
|
269
|
+
paddingVertical: 8
|
|
270
|
+
},
|
|
271
|
+
chipText: {
|
|
272
|
+
fontSize: 13,
|
|
273
|
+
fontWeight: "600"
|
|
274
|
+
},
|
|
275
|
+
composerWrap: {
|
|
276
|
+
paddingHorizontal: 12,
|
|
277
|
+
paddingTop: 8,
|
|
278
|
+
gap: 8
|
|
279
|
+
},
|
|
280
|
+
errorBanner: {
|
|
281
|
+
borderRadius: 10,
|
|
282
|
+
padding: 8
|
|
283
|
+
},
|
|
284
|
+
errorText: {
|
|
285
|
+
color: "#991b1b",
|
|
286
|
+
fontSize: 12
|
|
287
|
+
},
|
|
288
|
+
composerCard: {
|
|
289
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
290
|
+
borderRadius: 18,
|
|
291
|
+
paddingHorizontal: 12,
|
|
292
|
+
paddingTop: 10,
|
|
293
|
+
paddingBottom: 8,
|
|
294
|
+
gap: 4,
|
|
295
|
+
overflow: "visible"
|
|
296
|
+
},
|
|
297
|
+
inputRow: {
|
|
298
|
+
flexDirection: "row",
|
|
299
|
+
alignItems: "flex-end",
|
|
300
|
+
gap: 4,
|
|
301
|
+
minHeight: 44
|
|
302
|
+
},
|
|
303
|
+
input: {
|
|
304
|
+
flex: 1,
|
|
305
|
+
fontSize: 15,
|
|
306
|
+
maxHeight: 120,
|
|
307
|
+
minHeight: 40,
|
|
308
|
+
paddingVertical: 8,
|
|
309
|
+
paddingHorizontal: 2
|
|
310
|
+
},
|
|
311
|
+
tools: {
|
|
312
|
+
flexDirection: "row",
|
|
313
|
+
alignItems: "center",
|
|
314
|
+
gap: 2,
|
|
315
|
+
paddingTop: 2,
|
|
316
|
+
overflow: "visible"
|
|
317
|
+
},
|
|
318
|
+
toolsAccessory: {
|
|
319
|
+
marginLeft: "auto",
|
|
320
|
+
flexShrink: 1
|
|
321
|
+
},
|
|
322
|
+
mic: {
|
|
323
|
+
width: 32,
|
|
324
|
+
height: 32,
|
|
325
|
+
borderRadius: 8,
|
|
326
|
+
alignItems: "center",
|
|
327
|
+
justifyContent: "center",
|
|
328
|
+
marginBottom: 2
|
|
329
|
+
},
|
|
330
|
+
micLive: {
|
|
331
|
+
backgroundColor: "rgba(185,28,28,0.12)"
|
|
332
|
+
},
|
|
333
|
+
send: {
|
|
334
|
+
width: 32,
|
|
335
|
+
height: 32,
|
|
336
|
+
borderRadius: 16,
|
|
337
|
+
backgroundColor: "#ea580c",
|
|
338
|
+
alignItems: "center",
|
|
339
|
+
justifyContent: "center",
|
|
340
|
+
marginBottom: 2
|
|
341
|
+
},
|
|
342
|
+
sendIcon: {
|
|
343
|
+
transform: [{
|
|
344
|
+
rotate: "45deg"
|
|
345
|
+
}]
|
|
346
|
+
},
|
|
347
|
+
toolBtn: {
|
|
348
|
+
width: 36,
|
|
349
|
+
height: 36,
|
|
350
|
+
borderRadius: 8,
|
|
351
|
+
alignItems: "center",
|
|
352
|
+
justifyContent: "center"
|
|
353
|
+
}
|
|
354
|
+
});export{NativeAgentChat};//# sourceMappingURL=NativeAgentChat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeAgentChat.js","sources":["../../../src/features/agent-chat/NativeAgentChat.tsx"],"sourcesContent":["/**\n * Reusable native Agent panel (header + transcript + composer).\n * Composer matches web Shopping Agent: text + mic/send on the first row,\n * image + paperclip under the field. Surface cards (`beforeComposer`) scroll\n * with the thread as the list footer.\n */\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n ActivityIndicator,\n InteractionManager,\n Keyboard,\n KeyboardAvoidingView,\n Platform,\n Pressable,\n StyleSheet,\n Text,\n TextInput,\n View,\n} from 'react-native';\nimport { Feather, MaterialCommunityIcons } from '@expo/vector-icons';\nimport { useSafeInsets } from '../canvas/withRemoteSafeArea';\nimport type { NativeAgentChatProps } from './types';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { useImageAttachments } from '../attachments/useImageAttachments';\nimport { ComposerAttachmentBar } from '../attachments/ComposerAttachmentBar';\nimport { NativeDictationBar } from '../audio-input/NativeDictationBar';\nimport { AudioRecorderPanel } from '../audio-input/AudioRecorderPanel';\nimport { MicErrorBoundary } from '../audio-input/MicErrorBoundary';\nimport { isNativeDictationAvailable } from '../audio-input/nativeDictation';\nimport { requestMicPermission } from '../audio-input/useAudioPermission';\nimport { ChatTranscript } from '../chat/ChatTranscript';\nimport ThinkingIndicator from '../../components/ThinkingIndicator';\n\nexport function NativeAgentChat({\n title,\n visible,\n onClose,\n messages,\n onSend,\n onClear,\n busy = false,\n streamingContent = null,\n error = null,\n placeholder = 'Ask anything…',\n emptyTitle,\n emptyBody,\n suggestions = [],\n beforeComposer,\n composerAccessory,\n paneOverlay,\n headerTrailing,\n belowHeader,\n composerLead,\n draft: draftProp,\n onDraftChange,\n composerSeed,\n composerSeedKey,\n onComposerSeedConsumed,\n embedded = false,\n enableVoice = true,\n enableAttachments = true,\n isDark = false,\n ink = '#0f172a',\n muted = '#64748b',\n screen = '#f8fafc',\n border = '#e8ecf1',\n}: NativeAgentChatProps) {\n const insets = useSafeInsets();\n const draftControlled = onDraftChange !== undefined;\n const [internalDraft, setInternalDraft] = useState('');\n const draft = draftControlled ? (draftProp ?? '') : internalDraft;\n const draftRef = useRef(draft);\n draftRef.current = draft;\n const setDraft = (next: string | ((prev: string) => string)) => {\n const value = typeof next === 'function' ? next(draftRef.current) : next;\n if (draftControlled) onDraftChange?.(value);\n else setInternalDraft(value);\n };\n useEffect(() => {\n if (composerSeed == null) return;\n setDraft((prev) => (prev.trim() ? `${composerSeed}\\n\\n${prev}` : composerSeed));\n onComposerSeedConsumed?.();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [composerSeed, composerSeedKey]);\n const attachments = useImageAttachments();\n const [showNativeDictation, setShowNativeDictation] = useState(false);\n const [showAudioRecorder, setShowAudioRecorder] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n\n const canSend = draft.trim().length > 0 || attachments.pending.length > 0;\n const listening = showNativeDictation || showAudioRecorder;\n\n const submit = (text = draft, files?: MessageAttachment[]) => {\n const trimmed = text.trim();\n const pending = files ?? attachments.forSend();\n if (!trimmed && !pending?.length) return;\n setDraft('');\n attachments.clear();\n onSend(trimmed, pending);\n };\n\n const openWhisperRecorder = useCallback(() => {\n setVoiceError(null);\n void (async () => {\n const { granted, error } = await requestMicPermission();\n if (!granted) {\n setVoiceError(error || 'Microphone is not available.');\n return;\n }\n setShowAudioRecorder(true);\n })();\n }, []);\n\n const handleMicPress = useCallback(() => {\n if (listening) {\n setShowNativeDictation(false);\n setShowAudioRecorder(false);\n return;\n }\n setVoiceError(null);\n Keyboard.dismiss();\n if (isNativeDictationAvailable()) {\n setShowNativeDictation(true);\n return;\n }\n openWhisperRecorder();\n }, [listening, openWhisperRecorder]);\n\n const pasteTranscript = useCallback((text: string) => {\n const cleaned = (text ?? '').trim();\n if (!cleaned) return;\n setDraft((prev) => (prev.trim() ? `${prev.trim()} ${cleaned}` : cleaned));\n }, []);\n\n const openPicker = useCallback((fn: () => Promise<void>) => {\n Keyboard.dismiss();\n InteractionManager.runAfterInteractions(() => {\n setTimeout(() => {\n void fn();\n }, 350);\n });\n }, []);\n\n const banner = voiceError || attachments.error || error;\n\n if (!visible) return null;\n\n return (\n <View style={[StyleSheet.absoluteFill, styles.overlay, { backgroundColor: screen }]} pointerEvents=\"auto\">\n <KeyboardAvoidingView\n style={[styles.fill, { backgroundColor: screen, paddingTop: embedded ? 8 : Math.max(insets.top, 8) }]}\n behavior={Platform.OS === 'ios' ? 'padding' : undefined}\n >\n <View style={[styles.head, { borderColor: border }]}>\n <View style={styles.headTitle}>\n <MaterialCommunityIcons name=\"creation\" size={16} color={ink} />\n <Text style={[styles.title, { color: ink }]}>{title}</Text>\n </View>\n <View style={styles.headActions}>\n {onClear && messages.length > 0 ? (\n <Pressable\n onPress={onClear}\n hitSlop={10}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Clear chat\"\n >\n <Feather name=\"trash-2\" size={18} color={muted} />\n </Pressable>\n ) : null}\n {headerTrailing}\n <Pressable onPress={onClose} hitSlop={10} accessibilityLabel={`Close ${title}`}>\n <MaterialCommunityIcons name=\"close\" size={22} color={muted} />\n </Pressable>\n </View>\n </View>\n {belowHeader}\n\n {messages.length === 0 && !streamingContent ? (\n <View style={styles.empty}>\n {emptyTitle ? <Text style={[styles.emptyTitle, { color: ink }]}>{emptyTitle}</Text> : null}\n {emptyBody ? <Text style={[styles.emptyBody, { color: muted }]}>{emptyBody}</Text> : null}\n {suggestions.length > 0 ? (\n <View style={styles.chips}>\n {suggestions.map((chip) => (\n <Pressable\n key={chip.id}\n onPress={() => submit(chip.prompt ?? chip.label)}\n style={[\n styles.chip,\n { borderColor: border, backgroundColor: isDark ? '#1e293b' : '#fff' },\n ]}\n >\n <Text style={[styles.chipText, { color: ink }]}>{chip.label}</Text>\n </Pressable>\n ))}\n </View>\n ) : null}\n </View>\n ) : (\n <View style={styles.fill}>\n <ChatTranscript\n messages={messages}\n streamingContent={streamingContent ?? undefined}\n isDark={isDark}\n listFooter={beforeComposer}\n />\n {busy && !streamingContent?.trim() ? (\n <View style={styles.thinking}>\n <ThinkingIndicator color={muted} />\n </View>\n ) : null}\n </View>\n )}\n\n <View\n style={[styles.composerWrap, { borderColor: border, paddingBottom: Math.max(insets.bottom, 10) }]}\n >\n {composerLead}\n {banner ? (\n <View style={[styles.errorBanner, { backgroundColor: isDark ? '#2b1a1d' : '#fef2f2' }]}>\n <Text style={styles.errorText}>{banner}</Text>\n </View>\n ) : null}\n\n {showNativeDictation ? (\n <MicErrorBoundary\n onCancel={() => setShowNativeDictation(false)}\n onError={() => {\n setShowNativeDictation(false);\n openWhisperRecorder();\n }}\n >\n <NativeDictationBar\n isDark={isDark}\n onInterim={() => undefined}\n onTranscriptionComplete={(text) => {\n setShowNativeDictation(false);\n pasteTranscript(text);\n }}\n onCancel={() => setShowNativeDictation(false)}\n onFallback={() => {\n setShowNativeDictation(false);\n openWhisperRecorder();\n }}\n />\n </MicErrorBoundary>\n ) : showAudioRecorder ? (\n <MicErrorBoundary\n onCancel={() => setShowAudioRecorder(false)}\n onError={(err) => {\n setShowAudioRecorder(false);\n setVoiceError(err);\n }}\n >\n <AudioRecorderPanel\n isDark={isDark}\n onTranscriptionComplete={(text) => {\n setShowAudioRecorder(false);\n pasteTranscript(text);\n }}\n onCancel={() => setShowAudioRecorder(false)}\n onError={(err) => {\n setShowAudioRecorder(false);\n setVoiceError(err);\n }}\n />\n </MicErrorBoundary>\n ) : (\n <View\n style={[\n styles.composerCard,\n { borderColor: border, backgroundColor: isDark ? '#111827' : '#fff' },\n ]}\n >\n {enableAttachments ? (\n <ComposerAttachmentBar\n attachments={attachments.pending}\n onRemove={attachments.remove}\n isDark={isDark}\n />\n ) : null}\n <View style={styles.inputRow}>\n <TextInput\n value={draft}\n onChangeText={(next) => {\n setDraft(next);\n if (voiceError) setVoiceError(null);\n }}\n placeholder={listening ? 'Listening… speak your request' : placeholder}\n placeholderTextColor={muted}\n multiline\n textAlignVertical=\"top\"\n editable={!busy}\n onSubmitEditing={() => submit()}\n style={[styles.input, { color: ink }]}\n accessibilityLabel={placeholder}\n />\n {enableVoice ? (\n <Pressable\n onPress={handleMicPress}\n disabled={busy && !listening}\n style={[styles.mic, listening && styles.micLive]}\n accessibilityRole=\"button\"\n accessibilityLabel={listening ? 'Stop listening' : 'Start voice input'}\n >\n <Feather\n name={listening ? 'square' : 'mic'}\n size={16}\n color={listening ? '#b91c1c' : muted}\n />\n </Pressable>\n ) : null}\n {canSend ? (\n <Pressable\n onPress={() => submit()}\n style={[styles.send, busy && { opacity: 0.85 }]}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Send\"\n >\n <Feather name=\"send\" size={14} color=\"#fff\" style={styles.sendIcon} />\n </Pressable>\n ) : null}\n </View>\n {enableAttachments || composerAccessory ? (\n <View style={styles.tools}>\n {enableAttachments ? (\n <>\n <Pressable\n onPress={() => openPicker(attachments.pickFromLibrary)}\n onLongPress={() => openPicker(attachments.captureFromCamera)}\n disabled={attachments.busy}\n style={styles.toolBtn}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Add image or screenshot\"\n >\n {attachments.busyKind === 'library' ||\n attachments.busyKind === 'camera' ? (\n <ActivityIndicator size=\"small\" />\n ) : (\n <Feather name=\"image\" size={18} color={muted} />\n )}\n </Pressable>\n <Pressable\n onPress={() => openPicker(attachments.pickDocuments)}\n disabled={attachments.busy}\n style={styles.toolBtn}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Attach files\"\n >\n {attachments.busyKind === 'documents' ? (\n <ActivityIndicator size=\"small\" />\n ) : (\n <Feather name=\"paperclip\" size={18} color={muted} />\n )}\n </Pressable>\n </>\n ) : null}\n {composerAccessory ? (\n <View style={styles.toolsAccessory}>{composerAccessory}</View>\n ) : null}\n </View>\n ) : null}\n </View>\n )}\n </View>\n </KeyboardAvoidingView>\n {paneOverlay}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: { zIndex: 200, elevation: 200 },\n fill: { flex: 1, overflow: 'hidden' },\n head: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingBottom: 10,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n headTitle: { flexDirection: 'row', alignItems: 'center', gap: 8 },\n headActions: { flexDirection: 'row', alignItems: 'center', gap: 12 },\n title: { fontSize: 16, fontWeight: '700' },\n empty: { flex: 1, gap: 10, paddingTop: 20, paddingHorizontal: 16 },\n thinking: { paddingHorizontal: 16, paddingBottom: 8 },\n emptyTitle: { fontSize: 18, fontWeight: '700', letterSpacing: -0.3 },\n emptyBody: { fontSize: 14, lineHeight: 20 },\n chips: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, marginTop: 4 },\n chip: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 12, paddingVertical: 8 },\n chipText: { fontSize: 13, fontWeight: '600' },\n composerWrap: { paddingHorizontal: 12, paddingTop: 8, gap: 8 },\n errorBanner: { borderRadius: 10, padding: 8 },\n errorText: { color: '#991b1b', fontSize: 12 },\n composerCard: {\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: 18,\n paddingHorizontal: 12,\n paddingTop: 10,\n paddingBottom: 8,\n gap: 4,\n overflow: 'visible',\n },\n inputRow: {\n flexDirection: 'row',\n alignItems: 'flex-end',\n gap: 4,\n minHeight: 44,\n },\n input: { flex: 1, fontSize: 15, maxHeight: 120, minHeight: 40, paddingVertical: 8, paddingHorizontal: 2 },\n tools: { flexDirection: 'row', alignItems: 'center', gap: 2, paddingTop: 2, overflow: 'visible' },\n toolsAccessory: { marginLeft: 'auto', flexShrink: 1 },\n mic: {\n width: 32,\n height: 32,\n borderRadius: 8,\n alignItems: 'center',\n justifyContent: 'center',\n marginBottom: 2,\n },\n micLive: { backgroundColor: 'rgba(185,28,28,0.12)' },\n send: {\n width: 32,\n height: 32,\n borderRadius: 16,\n backgroundColor: '#ea580c',\n alignItems: 'center',\n justifyContent: 'center',\n marginBottom: 2,\n },\n sendIcon: { transform: [{ rotate: '45deg' }] },\n toolBtn: {\n width: 36,\n height: 36,\n borderRadius: 8,\n alignItems: 'center',\n justifyContent: 'center',\n },\n});\n"],"names":["error"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {isAttachedCaption}from'./historyAttachmentLabel.js';
|
|
2
|
-
|
|
1
|
+
import {isAttachedCaption}from'./historyAttachmentLabel.js';const VISION_HINT_RE = /\n\nLook at the attached images? before answering\.?\s*$/i;
|
|
2
|
+
function displayUserMessageText(content, _attachments) {
|
|
3
|
+
const trimmed = (content != null ? content : "").replace(VISION_HINT_RE, "").trim();
|
|
3
4
|
if (!trimmed) return "";
|
|
4
5
|
if (isAttachedCaption(trimmed)) return "";
|
|
5
6
|
return trimmed;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"displayUserMessageText.js","sources":["../../../src/features/attachments/displayUserMessageText.ts"],"sourcesContent":["/**\n * Text that belongs in the user bubble after attachments are drawn visually.\n *\n * Attachment-only sends still go to the gateway as `Attached: filename` so the\n * agent has a caption — that string must not appear in the bubble (web hides\n * this turn entirely when there is no live preview).\n */\nimport { isAttachedCaption } from './historyAttachmentLabel';\n\nexport function displayUserMessageText(\n content: string | undefined,\n _attachments?: Array<{ name?: string }> | null,\n): string {\n const trimmed = (content ?? '').trim();\n if (!trimmed) return '';\n if (isAttachedCaption(trimmed)) return '';\n return trimmed;\n}\n\nfunction hasLiveLocalPreview(attachments?: Array<{ url?: string; dataUrl?: string }> | null): boolean {\n return (attachments ?? []).some((attachment) => {\n if (attachment.dataUrl?.startsWith('data:')) return true;\n const url = attachment.url?.trim();\n return Boolean(url && /^(file:|content:|ph:|assets-library:)/i.test(url));\n });\n}\n\n/**\n * Web omits the user bubble for attachment-only turns (empty query + files).\n * Mobile still shows a live thumbnail while sending; from history, skip the\n * `Attached: filename` row and keep the assistant reply.\n */\nexport function shouldRenderUserTranscriptTurn(\n content: string | undefined,\n attachments?: Array<{ url?: string; dataUrl?: string; name?: string }> | null,\n): boolean {\n if (displayUserMessageText(content, attachments)) return true;\n if (hasLiveLocalPreview(attachments)) return true;\n return false;\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"displayUserMessageText.js","sources":["../../../src/features/attachments/displayUserMessageText.ts"],"sourcesContent":["/**\n * Text that belongs in the user bubble after attachments are drawn visually.\n *\n * Attachment-only sends still go to the gateway as `Attached: filename` so the\n * agent has a caption — that string must not appear in the bubble (web hides\n * this turn entirely when there is no live preview).\n */\nimport { isAttachedCaption } from './historyAttachmentLabel';\n\nconst VISION_HINT_RE = /\\n\\nLook at the attached images? before answering\\.?\\s*$/i;\n\nexport function displayUserMessageText(\n content: string | undefined,\n _attachments?: Array<{ name?: string }> | null,\n): string {\n const trimmed = (content ?? '').replace(VISION_HINT_RE, '').trim();\n if (!trimmed) return '';\n if (isAttachedCaption(trimmed)) return '';\n return trimmed;\n}\n\nfunction hasLiveLocalPreview(attachments?: Array<{ url?: string; dataUrl?: string }> | null): boolean {\n return (attachments ?? []).some((attachment) => {\n if (attachment.dataUrl?.startsWith('data:')) return true;\n const url = attachment.url?.trim();\n return Boolean(url && /^(file:|content:|ph:|assets-library:)/i.test(url));\n });\n}\n\n/**\n * Web omits the user bubble for attachment-only turns (empty query + files).\n * Mobile still shows a live thumbnail while sending; from history, skip the\n * `Attached: filename` row and keep the assistant reply.\n */\nexport function shouldRenderUserTranscriptTurn(\n content: string | undefined,\n attachments?: Array<{ url?: string; dataUrl?: string; name?: string }> | null,\n): boolean {\n if (displayUserMessageText(content, attachments)) return true;\n if (hasLiveLocalPreview(attachments)) return true;\n return false;\n}\n"],"names":[],"mappings":"4DAQA,MAAM,cAAiB,GAAA,2DAAA;AACP,SAAA,sBAAA,CAAuB,SAA6B,YAEjD,EAAA;AACjB,EAAA,MAAM,WAAW,OAAW,IAAA,IAAA,GAAA,OAAA,GAAA,EAAA,EAAI,QAAQ,cAAgB,EAAA,EAAE,EAAE,IAAK,EAAA;AACjE,EAAI,IAAA,CAAC,SAAgB,OAAA,EAAA;AACrB,EAAI,IAAA,iBAAA,CAAkB,OAAO,CAAA,EAAU,OAAA,EAAA;AACvC,EAAO,OAAA,OAAA;AACT;AACA,SAAS,oBAAoB,WAGT,EAAA;AAClB,EAAA,OAAA,CAAQ,WAAe,IAAA,IAAA,GAAA,WAAA,GAAA,EAAI,EAAA,IAAA,CAAK,CAAc,UAAA,KAAA;AArBhD,IAAA,IAAA,EAAA,EAAA,EAAA;AAsBI,IAAA,IAAA,CAAI,EAAW,GAAA,UAAA,CAAA,OAAA,KAAX,IAAoB,GAAA,MAAA,GAAA,EAAA,CAAA,UAAA,CAAW,UAAiB,OAAA,IAAA;AACpD,IAAM,MAAA,GAAA,GAAA,CAAM,EAAW,GAAA,UAAA,CAAA,GAAA,KAAX,IAAgB,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,EAAA;AAC5B,IAAA,OAAO,OAAQ,CAAA,GAAA,IAAO,wCAAyC,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,GACzE,CAAA;AACH;AAOgB,SAAA,8BAAA,CAA+B,SAA6B,WAIxD,EAAA;AAClB,EAAA,IAAI,sBAAuB,CAAA,OAAoB,CAAA,EAAU,OAAA,IAAA;AACzD,EAAI,IAAA,mBAAA,CAAoB,WAAW,CAAA,EAAU,OAAA,IAAA;AAC7C,EAAO,OAAA,KAAA;AACT"}
|