@adminide-stack/yantra-mobile 12.0.50 → 12.0.51-alpha.0
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/KeyboardComposerDock.js +74 -29
- package/lib/components/KeyboardComposerDock.js.map +1 -1
- package/lib/components/NavigationHeader/NavigationHeader.js +5 -2
- package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -1
- package/lib/config/env-config.js +14 -2
- package/lib/config/env-config.js.map +1 -1
- package/lib/features/audio-input/NativeDictationBar.js +162 -0
- package/lib/features/audio-input/NativeDictationBar.js.map +1 -0
- package/lib/features/audio-input/nativeDictation.js +9 -0
- package/lib/features/audio-input/nativeDictation.js.map +1 -0
- package/lib/features/canvas/canvasCore.js +51 -0
- package/lib/features/canvas/canvasCore.js.map +1 -0
- package/lib/features/canvas/sessionIdentity.js +21 -0
- package/lib/features/canvas/sessionIdentity.js.map +1 -0
- package/lib/features/canvas/surfaceIndex.js +122 -1
- package/lib/features/canvas/surfaceIndex.js.map +1 -1
- package/lib/features/canvas/useCanvasSession.js +75 -29
- package/lib/features/canvas/useCanvasSession.js.map +1 -1
- package/lib/features/chat/ChatTranscript.js +35 -13
- package/lib/features/chat/ChatTranscript.js.map +1 -1
- package/lib/hooks/useChatApi.js +123 -41
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +4 -2
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/hooks/useKeyboardBottomOffset.js +22 -0
- package/lib/hooks/useKeyboardBottomOffset.js.map +1 -0
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/screens/Chat/index.js +39 -10
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/ChatHistory/index.js +1 -1
- package/lib/screens/ChatHistory/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js +27 -4
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/CanvasPrewarm.js +58 -0
- package/lib/screens/Home/components/CanvasPrewarm.js.map +1 -0
- package/lib/screens/Home/components/ChatHistoryLanding.js +30 -38
- package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
- package/lib/utils/keyboardController.js +21 -0
- package/lib/utils/keyboardController.js.map +1 -0
- package/package.json +5 -4
|
@@ -1,38 +1,87 @@
|
|
|
1
|
-
import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {
|
|
1
|
+
import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {useRef,useState,useEffect}from'react';import {StyleSheet,View,PanResponder,Platform,Keyboard,LayoutAnimation}from'react-native';import {isKeyboardControllerAvailable,dismissKeyboard}from'../utils/keyboardController.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
const COMPOSER_INPUT_NATIVE_ID = "yantra-composer";
|
|
2
21
|
function KeyboardAwareScreen({
|
|
3
22
|
children,
|
|
4
23
|
style
|
|
5
24
|
}) {
|
|
25
|
+
if (isKeyboardControllerAvailable()) {
|
|
26
|
+
const KeyboardGestureArea = require("react-native-keyboard-controller").KeyboardGestureArea;
|
|
27
|
+
return /* @__PURE__ */ jsx(KeyboardGestureArea, { style: [styles.flex, style], interpolator: "ios", showOnSwipeUp: true, enableSwipeToDismiss: true, textInputNativeID: COMPOSER_INPUT_NATIVE_ID, children });
|
|
28
|
+
}
|
|
6
29
|
return /* @__PURE__ */ jsx(View, { style: [styles.flex, style], children });
|
|
7
30
|
}
|
|
8
|
-
function
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
31
|
+
function configureKeyboardLayout(duration) {
|
|
32
|
+
if (Platform.OS !== "ios") return;
|
|
33
|
+
LayoutAnimation.configureNext({
|
|
34
|
+
duration: duration && duration > 0 ? duration : 250,
|
|
35
|
+
update: {
|
|
36
|
+
type: LayoutAnimation.Types.keyboard
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function useKeyboardLiftHeight() {
|
|
41
|
+
const [height, setHeight] = useState(0);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const show = Keyboard.addListener(Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow", (e) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
const next = (_b = (_a = e.endCoordinates) == null ? void 0 : _a.height) != null ? _b : 0;
|
|
46
|
+
configureKeyboardLayout(e.duration);
|
|
47
|
+
setHeight(next);
|
|
48
|
+
});
|
|
49
|
+
const hide = Keyboard.addListener(Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide", (e) => {
|
|
50
|
+
configureKeyboardLayout(e.duration);
|
|
51
|
+
setHeight(0);
|
|
52
|
+
});
|
|
53
|
+
return () => {
|
|
54
|
+
show.remove();
|
|
55
|
+
hide.remove();
|
|
56
|
+
};
|
|
57
|
+
}, []);
|
|
58
|
+
return Platform.OS === "android" ? 0 : height;
|
|
13
59
|
}
|
|
14
60
|
function KeyboardComposerDock({
|
|
15
61
|
children,
|
|
16
|
-
closedInset
|
|
62
|
+
closedInset,
|
|
63
|
+
onSwipeUp
|
|
17
64
|
}) {
|
|
18
|
-
const
|
|
19
|
-
const closedPadding = Math.max(closedInset,
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
65
|
+
const keyboardHeight = useKeyboardLiftHeight();
|
|
66
|
+
const closedPadding = Math.max(closedInset, 0);
|
|
67
|
+
const useNativeSwipe = isKeyboardControllerAvailable();
|
|
68
|
+
const onSwipeUpRef = useRef(onSwipeUp);
|
|
69
|
+
onSwipeUpRef.current = onSwipeUp;
|
|
70
|
+
const fallbackGestures = useRef(PanResponder.create({
|
|
71
|
+
onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dy) > 12 && Math.abs(g.dy) > Math.abs(g.dx) * 1.2,
|
|
72
|
+
onPanResponderRelease: (_, g) => {
|
|
73
|
+
var _a;
|
|
74
|
+
if (g.dy < -28 || g.vy < -0.55) (_a = onSwipeUpRef.current) == null ? void 0 : _a.call(onSwipeUpRef);
|
|
75
|
+
else if (g.dy > 28 || g.vy > 0.55) dismissKeyboard();
|
|
76
|
+
}
|
|
77
|
+
})).current;
|
|
29
78
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
30
|
-
/* @__PURE__ */ jsx(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
79
|
+
/* @__PURE__ */ jsx(View, __spreadProps(__spreadValues({ style: [styles.dock, {
|
|
80
|
+
paddingBottom: Math.max(0, closedPadding - keyboardHeight)
|
|
81
|
+
}] }, useNativeSwipe ? null : fallbackGestures.panHandlers), { children })),
|
|
82
|
+
Platform.OS === "ios" ? /* @__PURE__ */ jsx(View, { style: {
|
|
83
|
+
height: keyboardHeight
|
|
84
|
+
}, pointerEvents: "none" }) : null
|
|
36
85
|
] });
|
|
37
86
|
}
|
|
38
87
|
const styles = StyleSheet.create({
|
|
@@ -40,13 +89,9 @@ const styles = StyleSheet.create({
|
|
|
40
89
|
flex: 1
|
|
41
90
|
},
|
|
42
91
|
dock: {
|
|
43
|
-
position: "absolute",
|
|
44
|
-
left: 0,
|
|
45
|
-
right: 0,
|
|
46
|
-
bottom: 0,
|
|
47
92
|
width: "100%",
|
|
48
93
|
alignItems: "center",
|
|
49
94
|
zIndex: 20,
|
|
50
95
|
elevation: 20
|
|
51
96
|
}
|
|
52
|
-
});export{KeyboardAwareScreen,KeyboardComposerDock};//# sourceMappingURL=KeyboardComposerDock.js.map
|
|
97
|
+
});export{COMPOSER_INPUT_NATIVE_ID,KeyboardAwareScreen,KeyboardComposerDock,useKeyboardLiftHeight};//# sourceMappingURL=KeyboardComposerDock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyboardComposerDock.js","sources":["../../src/components/KeyboardComposerDock.tsx"],"sourcesContent":["import React from 'react';\nimport {
|
|
1
|
+
{"version":3,"file":"KeyboardComposerDock.js","sources":["../../src/components/KeyboardComposerDock.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport {\n Keyboard,\n LayoutAnimation,\n PanResponder,\n Platform,\n StyleSheet,\n View,\n type StyleProp,\n type ViewStyle,\n} from 'react-native';\nimport { dismissKeyboard, isKeyboardControllerAvailable } from '../utils/keyboardController';\n\nexport const COMPOSER_INPUT_NATIVE_ID = 'yantra-composer';\n\nexport type KeyboardComposerDockProps = {\n children: React.ReactNode;\n /** Home-indicator inset when the keyboard is closed. */\n closedInset: number;\n keyboardVisible?: boolean;\n /** Expo Go: swipe up on the composer focuses this field (opens the keyboard). */\n onSwipeUp?: () => void;\n};\n\n/**\n * Native swipe region when keyboard-controller is linked: swipe up opens the\n * keyboard, swipe down closes it and the keys follow the finger (iOS interpolator).\n */\nexport function KeyboardAwareScreen({ children, style }: { children: React.ReactNode; style?: StyleProp<ViewStyle> }) {\n if (isKeyboardControllerAvailable()) {\n const KeyboardGestureArea = require('react-native-keyboard-controller')\n .KeyboardGestureArea as React.ComponentType<{\n style?: StyleProp<ViewStyle>;\n interpolator?: 'ios' | 'linear';\n showOnSwipeUp?: boolean;\n enableSwipeToDismiss?: boolean;\n textInputNativeID?: string;\n children?: React.ReactNode;\n }>;\n return (\n <KeyboardGestureArea\n style={[styles.flex, style]}\n interpolator=\"ios\"\n showOnSwipeUp\n enableSwipeToDismiss\n textInputNativeID={COMPOSER_INPUT_NATIVE_ID}\n >\n {children}\n </KeyboardGestureArea>\n );\n }\n return <View style={[styles.flex, style]}>{children}</View>;\n}\n\nfunction configureKeyboardLayout(duration?: number) {\n if (Platform.OS !== 'ios') return;\n LayoutAnimation.configureNext({\n duration: duration && duration > 0 ? duration : 250,\n update: {\n type: LayoutAnimation.Types.keyboard,\n },\n });\n}\n\n/** Keyboard height used by the dock spacer. Chat reads this so it scrolls after the list shrinks. */\nexport function useKeyboardLiftHeight(): number {\n const [height, setHeight] = useState(0);\n\n useEffect(() => {\n const show = Keyboard.addListener(Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow', (e) => {\n const next = e.endCoordinates?.height ?? 0;\n configureKeyboardLayout(e.duration);\n setHeight(next);\n });\n const hide = Keyboard.addListener(Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide', (e) => {\n configureKeyboardLayout(e.duration);\n setHeight(0);\n });\n return () => {\n show.remove();\n hide.remove();\n };\n }, []);\n\n return Platform.OS === 'android' ? 0 : height;\n}\n\n/**\n * In-flow spacer = full keyboard height so the composer docks on the keys.\n * Native swipe lives on KeyboardAwareScreen; Expo Go uses a composer pan.\n */\nexport function KeyboardComposerDock({ children, closedInset, onSwipeUp }: KeyboardComposerDockProps) {\n const keyboardHeight = useKeyboardLiftHeight();\n const closedPadding = Math.max(closedInset, 0);\n const useNativeSwipe = isKeyboardControllerAvailable();\n const onSwipeUpRef = useRef(onSwipeUp);\n onSwipeUpRef.current = onSwipeUp;\n const fallbackGestures = useRef(\n PanResponder.create({\n onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dy) > 12 && Math.abs(g.dy) > Math.abs(g.dx) * 1.2,\n onPanResponderRelease: (_, g) => {\n if (g.dy < -28 || g.vy < -0.55) onSwipeUpRef.current?.();\n else if (g.dy > 28 || g.vy > 0.55) dismissKeyboard();\n },\n }),\n ).current;\n\n return (\n <>\n <View\n style={[styles.dock, { paddingBottom: Math.max(0, closedPadding - keyboardHeight) }]}\n {...(useNativeSwipe ? null : fallbackGestures.panHandlers)}\n >\n {children}\n </View>\n {Platform.OS === 'ios' ? <View style={{ height: keyboardHeight }} pointerEvents=\"none\" /> : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: {\n flex: 1,\n },\n dock: {\n width: '100%',\n alignItems: 'center',\n zIndex: 20,\n elevation: 20,\n },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsx,jsxs,Fragment}from'react/jsx-runtime';import React,{useMemo,useCallback}from'react';import {useColorScheme,StyleSheet,View,ScrollView,Pressable}from'react-native';import {useSafeAreaInsets,SafeAreaView}from'react-native-safe-area-context';import {StatusBar}from'expo-status-bar';import {useNavigation,CommonActions,DrawerActions}from'@react-navigation/native';import {getHeaderTitle}from'@react-navigation/elements';import {MaterialCommunityIcons}from'@expo/vector-icons';import {Text}from'@admin-layout/gluestack-ui-mobile';import GatewayConnector from'../GatewayConnector/GatewayConnector.js';import {tryWebBuilderBack}from'../../screens/WebBuilder/webbuilderBackHandler.js';import {config}from'../../config/env-config.js';import {resolveAppTitleFromSurfaceUrl}from'../../features/apps/resolveSurfaceUrl.js';import {navigateToNewChatHome}from'../../utils/navigateToNewChatHome.js';import {HeaderMoreMenu}from'./HeaderMoreMenu.js';import {HeaderSkillsButton}from'./HeaderSkillsButton.js';import {HeaderTasksButton}from'./HeaderTasksButton.js';import {HeaderToolbarButton}from'./HeaderToolbarButton.js';const ICON_SIZE = 22;
|
|
1
|
+
import {jsx,jsxs,Fragment}from'react/jsx-runtime';import React,{useMemo,useCallback}from'react';import {useColorScheme,StyleSheet,View,ScrollView,Pressable}from'react-native';import {dismissKeyboard}from'../../utils/keyboardController.js';import {useSafeAreaInsets,SafeAreaView}from'react-native-safe-area-context';import {StatusBar}from'expo-status-bar';import {useNavigation,CommonActions,DrawerActions}from'@react-navigation/native';import {getHeaderTitle}from'@react-navigation/elements';import {MaterialCommunityIcons}from'@expo/vector-icons';import {Text}from'@admin-layout/gluestack-ui-mobile';import GatewayConnector from'../GatewayConnector/GatewayConnector.js';import {tryWebBuilderBack}from'../../screens/WebBuilder/webbuilderBackHandler.js';import {config}from'../../config/env-config.js';import {resolveAppTitleFromSurfaceUrl}from'../../features/apps/resolveSurfaceUrl.js';import {navigateToNewChatHome}from'../../utils/navigateToNewChatHome.js';import {HeaderMoreMenu}from'./HeaderMoreMenu.js';import {HeaderSkillsButton}from'./HeaderSkillsButton.js';import {HeaderTasksButton}from'./HeaderTasksButton.js';import {HeaderToolbarButton}from'./HeaderToolbarButton.js';const ICON_SIZE = 22;
|
|
2
2
|
function resolveTitle(options, route) {
|
|
3
3
|
var _a, _b, _c, _d;
|
|
4
4
|
const paramTitle = (_a = route == null ? void 0 : route.params) == null ? void 0 : _a.appTitle;
|
|
@@ -93,7 +93,10 @@ const NavigationHeader = (props) => {
|
|
|
93
93
|
/* @__PURE__ */ jsx(StatusBar, { style: isDark ? "light" : "dark" }),
|
|
94
94
|
/* @__PURE__ */ jsx(SafeAreaView, { edges: ["top"], style: {
|
|
95
95
|
backgroundColor: surfaceColor
|
|
96
|
-
}, children: /* @__PURE__ */ jsxs(View, {
|
|
96
|
+
}, children: /* @__PURE__ */ jsxs(View, { onStartShouldSetResponderCapture: () => {
|
|
97
|
+
dismissKeyboard();
|
|
98
|
+
return false;
|
|
99
|
+
}, style: [styles.row, {
|
|
97
100
|
backgroundColor: surfaceColor,
|
|
98
101
|
borderBottomColor: dividerColor,
|
|
99
102
|
paddingTop: insets.top > 0 ? 0 : 6
|
|
@@ -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 { 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 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 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 width: '100%',\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 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 width: '100%',\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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"}
|
package/lib/config/env-config.js
CHANGED
|
@@ -58,9 +58,15 @@ const baseConfig = cleanEnv(env, {
|
|
|
58
58
|
SURFACE_URL_TEMPLATE: str({
|
|
59
59
|
default: "https://{slug}-surface.yantra-app-v1.cdebase.dev/"
|
|
60
60
|
}),
|
|
61
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Characters gallery manifest (`characters.json`). Empty by default →
|
|
63
|
+
* DERIVED from SURFACE_URL_TEMPLATE + the wipe-immune `characters-native`
|
|
64
|
+
* slug (see below), so a prod build reads prod and a dev build reads dev
|
|
65
|
+
* with no per-profile URL to maintain. Set explicitly only to pin a
|
|
66
|
+
* non-standard origin.
|
|
67
|
+
*/
|
|
62
68
|
CHARACTERS_NATIVE_MANIFEST_URL: str({
|
|
63
|
-
default: "
|
|
69
|
+
default: ""
|
|
64
70
|
}),
|
|
65
71
|
APP_NAME: str({
|
|
66
72
|
default: "Yantra"
|
|
@@ -89,6 +95,11 @@ const baseConfig = cleanEnv(env, {
|
|
|
89
95
|
default: ""
|
|
90
96
|
})
|
|
91
97
|
});
|
|
98
|
+
function resolveCharactersManifestUrl(explicit, template) {
|
|
99
|
+
if (explicit) return explicit;
|
|
100
|
+
const base = (template || "https://{slug}-surface.yantra-app-v1.cdebase.dev/").replace("{slug}", "characters-native").replace(/\/+$/, "");
|
|
101
|
+
return `${base}/native/characters.json`;
|
|
102
|
+
}
|
|
92
103
|
function resolveAgentGatewayGraphqlUrl() {
|
|
93
104
|
if (baseConfig.USE_PROXY_STAGING_GATEWAY && baseConfig.PROXY_STAGING_GATEWAY_URL) {
|
|
94
105
|
return baseConfig.PROXY_STAGING_GATEWAY_URL;
|
|
@@ -108,6 +119,7 @@ const agentGatewayGraphqlUrl = resolveAgentGatewayGraphqlUrl();
|
|
|
108
119
|
const clampedCdecliTimeoutSec = Math.min(600, Math.max(15, Math.round(baseConfig.CDECLI_CHAT_RESPONSE_TIMEOUT_SEC)));
|
|
109
120
|
const config = __spreadProps(__spreadValues({}, baseConfig), {
|
|
110
121
|
CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: clampedCdecliTimeoutSec,
|
|
122
|
+
CHARACTERS_NATIVE_MANIFEST_URL: resolveCharactersManifestUrl(baseConfig.CHARACTERS_NATIVE_MANIFEST_URL, baseConfig.SURFACE_URL_TEMPLATE),
|
|
111
123
|
AGENT_GATEWAY_GRAPHQL_URL: agentGatewayGraphqlUrl,
|
|
112
124
|
AGENT_GATEWAY_WS_URL: resolveAgentGatewayWsUrl(agentGatewayGraphqlUrl)
|
|
113
125
|
});export{config};//# sourceMappingURL=env-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-config.js","sources":["../../src/config/env-config.ts"],"sourcesContent":["import { str, cleanEnv, bool, num } from 'envalid';\n\nconst env = (process as { APP_ENV?: NodeJS.ProcessEnv; env?: NodeJS.ProcessEnv }).APP_ENV || process.env;\n\nconst baseConfig = cleanEnv(env, {\n GRAPHQL_URL: str({ default: 'http://localhost:8080/graphql' }),\n CLIENT_URL: str({ default: 'http://localhost:3000' }),\n /** Standalone Web Builder surface embedded in the mobile WebView shell. */\n WEB_BUILDER_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Design surface — local vite is 5174/4174 next to canvas 5175. */\n DESIGN_SURFACE_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Canvas surface embedded in the same WebView shell. */\n CANVAS_SURFACE_URL: str({ default: 'http://localhost:5175/' }),\n /**\n * GraphQL backend whose JWT keys the canvas index will verify.\n * Must stay in lockstep with canvas-surface `.env.development`\n * (`VITE_BACKEND_GRAPHQL_URL` / `VITE_SURFACE_INDEX_URL`). A locally\n * minted token 401s against `surface-index-backend.yantra-app-v1`.\n */\n CANVAS_BACKEND_GRAPHQL_URL: str({ default: 'https://ideback.yantra-app-v1.cdebase.dev/graphql' }),\n /** Explicit canvas index GraphQL URL. Empty → derived from the canvas auth backend. */\n SURFACE_INDEX_URL: str({ default: '' }),\n /**\n * Origin template for every other deployed surface: `{slug}` is the app's\n * `surfaceSlug`. One var instead of 20+ near-identical URLs, and it keeps the\n * environment (dev cluster / prod) in one place.\n */\n SURFACE_URL_TEMPLATE: str({ default: 'https://{slug}-surface.yantra-app-v1.cdebase.dev/' }),\n
|
|
1
|
+
{"version":3,"file":"env-config.js","sources":["../../src/config/env-config.ts"],"sourcesContent":["import { str, cleanEnv, bool, num } from 'envalid';\n\nconst env = (process as { APP_ENV?: NodeJS.ProcessEnv; env?: NodeJS.ProcessEnv }).APP_ENV || process.env;\n\nconst baseConfig = cleanEnv(env, {\n GRAPHQL_URL: str({ default: 'http://localhost:8080/graphql' }),\n CLIENT_URL: str({ default: 'http://localhost:3000' }),\n /** Standalone Web Builder surface embedded in the mobile WebView shell. */\n WEB_BUILDER_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Design surface — local vite is 5174/4174 next to canvas 5175. */\n DESIGN_SURFACE_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Canvas surface embedded in the same WebView shell. */\n CANVAS_SURFACE_URL: str({ default: 'http://localhost:5175/' }),\n /**\n * GraphQL backend whose JWT keys the canvas index will verify.\n * Must stay in lockstep with canvas-surface `.env.development`\n * (`VITE_BACKEND_GRAPHQL_URL` / `VITE_SURFACE_INDEX_URL`). A locally\n * minted token 401s against `surface-index-backend.yantra-app-v1`.\n */\n CANVAS_BACKEND_GRAPHQL_URL: str({ default: 'https://ideback.yantra-app-v1.cdebase.dev/graphql' }),\n /** Explicit canvas index GraphQL URL. Empty → derived from the canvas auth backend. */\n SURFACE_INDEX_URL: str({ default: '' }),\n /**\n * Origin template for every other deployed surface: `{slug}` is the app's\n * `surfaceSlug`. One var instead of 20+ near-identical URLs, and it keeps the\n * environment (dev cluster / prod) in one place.\n */\n SURFACE_URL_TEMPLATE: str({ default: 'https://{slug}-surface.yantra-app-v1.cdebase.dev/' }),\n /**\n * Characters gallery manifest (`characters.json`). Empty by default →\n * DERIVED from SURFACE_URL_TEMPLATE + the wipe-immune `characters-native`\n * slug (see below), so a prod build reads prod and a dev build reads dev\n * with no per-profile URL to maintain. Set explicitly only to pin a\n * non-standard origin.\n */\n CHARACTERS_NATIVE_MANIFEST_URL: str({ default: '' }),\n APP_NAME: str({ default: 'Yantra' }),\n GROQ_API_KEY: str({ default: '' }),\n CDECLI_AGENT_ENDPOINT: str({ default: 'https://cdecli-agent.cdebase.dev' }),\n CDECLI_AGENT_AUTH_TOKEN: str({ default: '' }),\n /** Seconds to wait for CDeCLI stream completion before timing out (then fallback chat API runs). Min 15, max 600. */\n /** Aligned with web `useCdecliChannel` (120s). Mobile hook uses the same constant inline. */\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: num({ default: 120 }),\n BACKEND_URL: str({ default: '' }),\n USE_PROXY_STAGING_GATEWAY: bool({ default: false }),\n PROXY_STAGING_GATEWAY_URL: str({ default: '' }),\n});\n\n/**\n * Where the app fetches the characters gallery manifest.\n *\n * Mirrors metro.federation.js `charactersRemoteUrl()`: the manifest lives on\n * the dedicated `characters-native` artifacts slug, NOT `character-surface`.\n * The bulk web-surface republish redeploys character-surface from its pinned\n * web bundle and wipes anything hand-added under /native, so the gallery data\n * (like the federated remote) must ride the wipe-immune slug. The origin\n * DERIVES from SURFACE_URL_TEMPLATE, so prod builds read prod and dev builds\n * read dev automatically. An explicit CHARACTERS_NATIVE_MANIFEST_URL still\n * wins for a one-off pin.\n */\nfunction resolveCharactersManifestUrl(explicit: string, template: string): string {\n if (explicit) return explicit;\n const base = (template || 'https://{slug}-surface.yantra-app-v1.cdebase.dev/')\n .replace('{slug}', 'characters-native')\n .replace(/\\/+$/, '');\n return `${base}/native/characters.json`;\n}\n\nfunction resolveAgentGatewayGraphqlUrl(): string {\n if (baseConfig.USE_PROXY_STAGING_GATEWAY && baseConfig.PROXY_STAGING_GATEWAY_URL) {\n return baseConfig.PROXY_STAGING_GATEWAY_URL;\n }\n if (baseConfig.GRAPHQL_URL) return baseConfig.GRAPHQL_URL;\n if (baseConfig.BACKEND_URL) return `${baseConfig.BACKEND_URL.replace(/\\/$/, '')}/graphql`;\n return '/graphql';\n}\n\nfunction resolveBaseWsUrl(graphqlUrl: string): string {\n const base = graphqlUrl.replace(/\\/graphql$/, '');\n return base.replace(/^http/, 'ws');\n}\n\nfunction resolveAgentGatewayWsUrl(graphqlUrl: string): string {\n return `${resolveBaseWsUrl(graphqlUrl)}/ws/openclaw-chat`;\n}\n\nconst agentGatewayGraphqlUrl = resolveAgentGatewayGraphqlUrl();\n\nconst clampedCdecliTimeoutSec = Math.min(600, Math.max(15, Math.round(baseConfig.CDECLI_CHAT_RESPONSE_TIMEOUT_SEC)));\n\nexport const config = {\n ...baseConfig,\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: clampedCdecliTimeoutSec,\n CHARACTERS_NATIVE_MANIFEST_URL: resolveCharactersManifestUrl(\n baseConfig.CHARACTERS_NATIVE_MANIFEST_URL,\n baseConfig.SURFACE_URL_TEMPLATE,\n ),\n AGENT_GATEWAY_GRAPHQL_URL: agentGatewayGraphqlUrl,\n AGENT_GATEWAY_WS_URL: resolveAgentGatewayWsUrl(agentGatewayGraphqlUrl),\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {jsxs,jsx}from'react/jsx-runtime';import {useState,useRef,useCallback,useEffect}from'react';import {View,StyleSheet,ActivityIndicator,Text,Pressable}from'react-native';import {Feather}from'@expo/vector-icons';import {requireOptionalNativeModule}from'expo-modules-core';function getSpeechNative() {
|
|
2
|
+
try {
|
|
3
|
+
return requireOptionalNativeModule("ExpoSpeechRecognition");
|
|
4
|
+
} catch (e) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
function NativeDictationBar({
|
|
9
|
+
isDark,
|
|
10
|
+
onInterim,
|
|
11
|
+
onTranscriptionComplete,
|
|
12
|
+
onCancel,
|
|
13
|
+
onFallback
|
|
14
|
+
}) {
|
|
15
|
+
const [transcript, setTranscript] = useState("");
|
|
16
|
+
const [starting, setStarting] = useState(true);
|
|
17
|
+
const settledRef = useRef(false);
|
|
18
|
+
const transcriptRef = useRef("");
|
|
19
|
+
const moduleRef = useRef(null);
|
|
20
|
+
const finish = useCallback((mode, error) => {
|
|
21
|
+
var _a;
|
|
22
|
+
if (settledRef.current) return;
|
|
23
|
+
settledRef.current = true;
|
|
24
|
+
try {
|
|
25
|
+
(_a = moduleRef.current) == null ? void 0 : _a.abort();
|
|
26
|
+
} catch (e) {
|
|
27
|
+
}
|
|
28
|
+
if (mode === "complete") onTranscriptionComplete(transcriptRef.current.trim());
|
|
29
|
+
else if (mode === "cancel") onCancel();
|
|
30
|
+
else onFallback(error);
|
|
31
|
+
}, [onTranscriptionComplete, onCancel, onFallback]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const speech = getSpeechNative();
|
|
34
|
+
if (!speech) {
|
|
35
|
+
finish("fallback", "Speech recognition is not available.");
|
|
36
|
+
return void 0;
|
|
37
|
+
}
|
|
38
|
+
moduleRef.current = speech;
|
|
39
|
+
const resultSub = speech.addListener("result", (event) => {
|
|
40
|
+
var _a, _b, _c;
|
|
41
|
+
const text = (_c = (_b = (_a = event.results) == null ? void 0 : _a[0]) == null ? void 0 : _b.transcript) != null ? _c : "";
|
|
42
|
+
setStarting(false);
|
|
43
|
+
setTranscript(text);
|
|
44
|
+
transcriptRef.current = text;
|
|
45
|
+
onInterim(text);
|
|
46
|
+
});
|
|
47
|
+
const errorSub = speech.addListener("error", (event) => {
|
|
48
|
+
if (event.error === "no-speech") {
|
|
49
|
+
finish(transcriptRef.current.trim() ? "complete" : "cancel");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
finish("fallback", event.message || event.error || "Dictation failed.");
|
|
53
|
+
});
|
|
54
|
+
const endSub = speech.addListener("end", () => {
|
|
55
|
+
finish(transcriptRef.current.trim() ? "complete" : "cancel");
|
|
56
|
+
});
|
|
57
|
+
let cancelled = false;
|
|
58
|
+
void (async () => {
|
|
59
|
+
try {
|
|
60
|
+
const perm = await speech.requestPermissionsAsync();
|
|
61
|
+
if (cancelled) return;
|
|
62
|
+
if (!perm.granted) {
|
|
63
|
+
finish("fallback", "Speech recognition permission was not granted.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
speech.start({
|
|
67
|
+
lang: "en-US",
|
|
68
|
+
interimResults: true,
|
|
69
|
+
continuous: true,
|
|
70
|
+
requiresOnDeviceRecognition: false
|
|
71
|
+
});
|
|
72
|
+
if (!cancelled) setStarting(false);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (!cancelled) finish("fallback", err instanceof Error ? err.message : String(err));
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
return () => {
|
|
78
|
+
cancelled = true;
|
|
79
|
+
resultSub.remove();
|
|
80
|
+
errorSub.remove();
|
|
81
|
+
endSub.remove();
|
|
82
|
+
if (!settledRef.current) {
|
|
83
|
+
try {
|
|
84
|
+
speech.abort();
|
|
85
|
+
} catch (e) {
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}, [finish, onInterim]);
|
|
90
|
+
const done = useCallback(() => {
|
|
91
|
+
var _a;
|
|
92
|
+
try {
|
|
93
|
+
(_a = moduleRef.current) == null ? void 0 : _a.stop();
|
|
94
|
+
} catch (e) {
|
|
95
|
+
finish("complete");
|
|
96
|
+
}
|
|
97
|
+
}, [finish]);
|
|
98
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles.bar, isDark && styles.barDark], accessibilityLabel: "Dictation in progress", children: [
|
|
99
|
+
/* @__PURE__ */ jsxs(View, { style: styles.status, children: [
|
|
100
|
+
starting ? /* @__PURE__ */ jsx(ActivityIndicator, { size: "small", color: isDark ? "#a5b4fc" : "#6366f1" }) : /* @__PURE__ */ jsx(View, { style: styles.dot }),
|
|
101
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.transcript, isDark && styles.transcriptDark], numberOfLines: 2, children: transcript || (starting ? "Starting\u2026" : "Listening\u2026") })
|
|
102
|
+
] }),
|
|
103
|
+
/* @__PURE__ */ jsxs(View, { style: styles.actions, children: [
|
|
104
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: () => finish("cancel"), hitSlop: 10, style: styles.iconBtn, accessibilityRole: "button", accessibilityLabel: "Cancel dictation", children: /* @__PURE__ */ jsx(Feather, { name: "x", size: 20, color: isDark ? "#94a3b8" : "#64748b" }) }),
|
|
105
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: done, hitSlop: 10, style: styles.doneBtn, accessibilityRole: "button", accessibilityLabel: "Finish dictation", children: /* @__PURE__ */ jsx(Feather, { name: "check", size: 20, color: "#ffffff" }) })
|
|
106
|
+
] })
|
|
107
|
+
] });
|
|
108
|
+
}
|
|
109
|
+
const styles = StyleSheet.create({
|
|
110
|
+
bar: {
|
|
111
|
+
flexDirection: "row",
|
|
112
|
+
alignItems: "center",
|
|
113
|
+
justifyContent: "space-between",
|
|
114
|
+
gap: 12,
|
|
115
|
+
paddingHorizontal: 14,
|
|
116
|
+
paddingVertical: 12,
|
|
117
|
+
borderRadius: 24,
|
|
118
|
+
backgroundColor: "#f1f5f9"
|
|
119
|
+
},
|
|
120
|
+
barDark: {
|
|
121
|
+
backgroundColor: "#1e293b"
|
|
122
|
+
},
|
|
123
|
+
status: {
|
|
124
|
+
flex: 1,
|
|
125
|
+
flexDirection: "row",
|
|
126
|
+
alignItems: "center",
|
|
127
|
+
gap: 10
|
|
128
|
+
},
|
|
129
|
+
dot: {
|
|
130
|
+
width: 10,
|
|
131
|
+
height: 10,
|
|
132
|
+
borderRadius: 5,
|
|
133
|
+
backgroundColor: "#ef4444"
|
|
134
|
+
},
|
|
135
|
+
transcript: {
|
|
136
|
+
flex: 1,
|
|
137
|
+
fontSize: 15,
|
|
138
|
+
color: "#0f172a"
|
|
139
|
+
},
|
|
140
|
+
transcriptDark: {
|
|
141
|
+
color: "#e2e8f0"
|
|
142
|
+
},
|
|
143
|
+
actions: {
|
|
144
|
+
flexDirection: "row",
|
|
145
|
+
alignItems: "center",
|
|
146
|
+
gap: 8
|
|
147
|
+
},
|
|
148
|
+
iconBtn: {
|
|
149
|
+
width: 40,
|
|
150
|
+
height: 40,
|
|
151
|
+
alignItems: "center",
|
|
152
|
+
justifyContent: "center"
|
|
153
|
+
},
|
|
154
|
+
doneBtn: {
|
|
155
|
+
width: 40,
|
|
156
|
+
height: 40,
|
|
157
|
+
borderRadius: 20,
|
|
158
|
+
backgroundColor: "#6366f1",
|
|
159
|
+
alignItems: "center",
|
|
160
|
+
justifyContent: "center"
|
|
161
|
+
}
|
|
162
|
+
});export{NativeDictationBar};//# sourceMappingURL=NativeDictationBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeDictationBar.js","sources":["../../../src/features/audio-input/NativeDictationBar.tsx"],"sourcesContent":["/**\n * Live on-device dictation using Apple's SFSpeechRecognizer.\n * Talks to the native module through `requireOptionalNativeModule` so Expo Go\n * (which does not ship ExpoSpeechRecognition) never evaluates\n * `expo-speech-recognition`'s throwing `requireNativeModule` import.\n */\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native';\nimport { Feather } from '@expo/vector-icons';\nimport { requireOptionalNativeModule } from 'expo-modules-core';\n\nexport interface NativeDictationBarProps {\n isDark: boolean;\n onInterim: (text: string) => void;\n onTranscriptionComplete: (text: string) => void;\n onCancel: () => void;\n onFallback: (error?: string) => void;\n}\n\ntype SpeechNativeModule = {\n abort: () => void;\n stop: () => void;\n requestPermissionsAsync: () => Promise<{ granted: boolean }>;\n start: (options: Record<string, unknown>) => void;\n addListener: (\n event: string,\n listener: (event: { results?: Array<{ transcript?: string }>; error?: string; message?: string }) => void,\n ) => { remove: () => void };\n};\n\nfunction getSpeechNative(): SpeechNativeModule | null {\n try {\n return requireOptionalNativeModule<SpeechNativeModule>('ExpoSpeechRecognition');\n } catch {\n return null;\n }\n}\n\nexport function NativeDictationBar({\n isDark,\n onInterim,\n onTranscriptionComplete,\n onCancel,\n onFallback,\n}: NativeDictationBarProps) {\n const [transcript, setTranscript] = useState('');\n const [starting, setStarting] = useState(true);\n const settledRef = useRef(false);\n const transcriptRef = useRef('');\n const moduleRef = useRef<SpeechNativeModule | null>(null);\n\n const finish = useCallback(\n (mode: 'complete' | 'cancel' | 'fallback', error?: string) => {\n if (settledRef.current) return;\n settledRef.current = true;\n try {\n moduleRef.current?.abort();\n } catch {\n /* already stopped */\n }\n if (mode === 'complete') onTranscriptionComplete(transcriptRef.current.trim());\n else if (mode === 'cancel') onCancel();\n else onFallback(error);\n },\n [onTranscriptionComplete, onCancel, onFallback],\n );\n\n useEffect(() => {\n const speech = getSpeechNative();\n if (!speech) {\n finish('fallback', 'Speech recognition is not available.');\n return undefined;\n }\n moduleRef.current = speech;\n\n const resultSub = speech.addListener('result', (event) => {\n const text = event.results?.[0]?.transcript ?? '';\n setStarting(false);\n setTranscript(text);\n transcriptRef.current = text;\n onInterim(text);\n });\n const errorSub = speech.addListener('error', (event) => {\n if (event.error === 'no-speech') {\n finish(transcriptRef.current.trim() ? 'complete' : 'cancel');\n return;\n }\n finish('fallback', event.message || event.error || 'Dictation failed.');\n });\n const endSub = speech.addListener('end', () => {\n finish(transcriptRef.current.trim() ? 'complete' : 'cancel');\n });\n\n let cancelled = false;\n void (async () => {\n try {\n const perm = await speech.requestPermissionsAsync();\n if (cancelled) return;\n if (!perm.granted) {\n finish('fallback', 'Speech recognition permission was not granted.');\n return;\n }\n speech.start({\n lang: 'en-US',\n interimResults: true,\n continuous: true,\n requiresOnDeviceRecognition: false,\n });\n if (!cancelled) setStarting(false);\n } catch (err) {\n if (!cancelled) finish('fallback', err instanceof Error ? err.message : String(err));\n }\n })();\n\n return () => {\n cancelled = true;\n resultSub.remove();\n errorSub.remove();\n endSub.remove();\n if (!settledRef.current) {\n try {\n speech.abort();\n } catch {\n /* noop */\n }\n }\n };\n }, [finish, onInterim]);\n\n const done = useCallback(() => {\n try {\n moduleRef.current?.stop();\n } catch {\n finish('complete');\n }\n }, [finish]);\n\n return (\n <View style={[styles.bar, isDark && styles.barDark]} accessibilityLabel=\"Dictation in progress\">\n <View style={styles.status}>\n {starting ? (\n <ActivityIndicator size=\"small\" color={isDark ? '#a5b4fc' : '#6366f1'} />\n ) : (\n <View style={styles.dot} />\n )}\n <Text style={[styles.transcript, isDark && styles.transcriptDark]} numberOfLines={2}>\n {transcript || (starting ? 'Starting…' : 'Listening…')}\n </Text>\n </View>\n <View style={styles.actions}>\n <Pressable\n onPress={() => finish('cancel')}\n hitSlop={10}\n style={styles.iconBtn}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Cancel dictation\"\n >\n <Feather name=\"x\" size={20} color={isDark ? '#94a3b8' : '#64748b'} />\n </Pressable>\n <Pressable\n onPress={done}\n hitSlop={10}\n style={styles.doneBtn}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Finish dictation\"\n >\n <Feather name=\"check\" size={20} color=\"#ffffff\" />\n </Pressable>\n </View>\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n bar: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n paddingHorizontal: 14,\n paddingVertical: 12,\n borderRadius: 24,\n backgroundColor: '#f1f5f9',\n },\n barDark: { backgroundColor: '#1e293b' },\n status: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: 10 },\n dot: { width: 10, height: 10, borderRadius: 5, backgroundColor: '#ef4444' },\n transcript: { flex: 1, fontSize: 15, color: '#0f172a' },\n transcriptDark: { color: '#e2e8f0' },\n actions: { flexDirection: 'row', alignItems: 'center', gap: 8 },\n iconBtn: { width: 40, height: 40, alignItems: 'center', justifyContent: 'center' },\n doneBtn: {\n width: 40,\n height: 40,\n borderRadius: 20,\n backgroundColor: '#6366f1',\n alignItems: 'center',\n justifyContent: 'center',\n },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {requireOptionalNativeModule}from'expo-modules-core';function isNativeDictationAvailable() {
|
|
2
|
+
try {
|
|
3
|
+
const mod = requireOptionalNativeModule("ExpoSpeechRecognition");
|
|
4
|
+
if (!mod) return false;
|
|
5
|
+
return typeof mod.isRecognitionAvailable === "function" ? mod.isRecognitionAvailable() : true;
|
|
6
|
+
} catch (e) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
}export{isNativeDictationAvailable};//# sourceMappingURL=nativeDictation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeDictation.js","sources":["../../../src/features/audio-input/nativeDictation.ts"],"sourcesContent":["/**\n * Availability probe for Apple's on-device speech recognition\n * (SFSpeechRecognizer via expo-speech-recognition) - the iOS-built-in mic the\n * chat composer prefers, with the record -> Whisper recorder as the fallback.\n *\n * The check deliberately goes through requireOptionalNativeModule rather than\n * importing `expo-speech-recognition`: that package calls\n * `requireNativeModule(\"ExpoSpeechRecognition\")` at module-eval time, which\n * THROWS on any binary that shipped before the native module was linked.\n * Reading the module optionally lets a stale binary answer \"unavailable\" and\n * fall back to Whisper instead of crashing - `NativeDictationBar` (which does\n * import the full JS API) is only ever mounted once this returns true.\n */\nimport { requireOptionalNativeModule } from 'expo-modules-core';\n\ninterface SpeechNativeModule {\n isRecognitionAvailable?: () => boolean;\n}\n\n/** True only when this binary can do native on-device dictation right now. */\nexport function isNativeDictationAvailable(): boolean {\n try {\n const mod = requireOptionalNativeModule<SpeechNativeModule>('ExpoSpeechRecognition');\n if (!mod) return false;\n // Newer builds expose isRecognitionAvailable(); if it is missing the\n // module is still linked, so treat presence as available.\n return typeof mod.isRecognitionAvailable === 'function' ? mod.isRecognitionAvailable() : true;\n } catch {\n return false;\n }\n}\n"],"names":[],"mappings":"4DAmBO,SAAS,0BAAsC,GAAA;AACpD,EAAI,IAAA;AACF,IAAM,MAAA,GAAA,GAAM,4BAAgD,uBAAuB,CAAA;AACnF,IAAI,IAAA,CAAC,KAAY,OAAA,KAAA;AAGjB,IAAA,OAAO,OAAO,GAAI,CAAA,sBAAA,KAA2B,UAAa,GAAA,GAAA,CAAI,wBAA2B,GAAA,IAAA;AAAA,GACnF,CAAA,OAAA,CAAA,EAAA;AACN,IAAO,OAAA,KAAA;AAAA;AAEX"}
|