@adminide-stack/yantra-mobile 12.0.44-alpha.1 → 12.0.44-alpha.10

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.
@@ -107,7 +107,7 @@ const MOBILE_APP_CATALOG = [{
107
107
  }, {
108
108
  key: "expenses",
109
109
  label: "Expenses",
110
- icon: "receipt-outline",
110
+ icon: "receipt",
111
111
  group: "Money",
112
112
  prompt: "Summarise my spend this month and flag anything unusual.",
113
113
  nativeRoute: "webbuilder",
@@ -1 +1 @@
1
- {"version":3,"file":"mobileAppCatalog.js","sources":["../../../src/features/apps/mobileAppCatalog.ts"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport type { MaterialCommunityIcons } from '@expo/vector-icons';\n\ntype IconName = ComponentProps<typeof MaterialCommunityIcons>['name'];\n\nexport type AppGroupId = 'Create' | 'Automate' | 'Sell' | 'Money' | 'Team' | 'More';\n\nexport type MobileAppItem = {\n key: string;\n label: string;\n icon: IconName;\n group: AppGroupId;\n /** Prompt sent as the first chat turn when the app has no native screen. */\n prompt: string;\n /**\n * Which surface host opens this app, if it has one. `webbuilder` is the\n * historical name of the shared WebView surface shell (`screens/WebBuilder`),\n * which is not web-builder-specific: it takes a `url` route param, mints the\n * system token, injects the bridge + cdecli token, stamps `embed=mobile` and\n * owns the timeout/retry UI. Anything with a deployed surface SPA can use it.\n */\n nativeRoute?: 'webbuilder' | 'canvas-native';\n /**\n * Deployed surface SPA for this app, as the `<slug>-surface` name. Resolved\n * against SURFACE_URL_TEMPLATE so one env var covers every surface and stays\n * per-environment, instead of 20+ near-identical URLs in eas.json.\n *\n * The slug is the SURFACE's name, which is not always the tile key\n * (issue-ticket -> issues, shop -> shopping, notebook -> notebooklm).\n */\n surfaceSlug?: string;\n /**\n * Explicit env override, for the two surfaces that already had a dedicated\n * var and are the ones people actually run locally. Wins over `surfaceSlug`.\n */\n surfaceUrlKey?: 'WEB_BUILDER_URL' | 'CANVAS_SURFACE_URL';\n};\n\n/**\n * Mobile Apps launcher. Labels, groups, and prompts stay in lockstep with the\n * browser ChatTopBar Apps menu (`packages-modules/account/browser`).\n */\nexport const MOBILE_APP_CATALOG: readonly MobileAppItem[] = [\n {\n key: 'design',\n label: 'Design',\n icon: 'palette-outline',\n group: 'Create',\n prompt: 'Design a 10-slide pitch deck for a coffee subscription startup',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'design',\n },\n {\n key: 'canvas',\n label: 'Canvas',\n icon: 'view-grid-outline',\n group: 'Create',\n prompt: 'Open a canvas and help me lay out the assets for this project.',\n nativeRoute: 'webbuilder',\n surfaceUrlKey: 'CANVAS_SURFACE_URL',\n surfaceSlug: 'canvas',\n },\n {\n key: 'canvas-native',\n label: 'Canvas Native',\n icon: 'vector-square',\n group: 'Create',\n prompt: 'Open a canvas and help me lay out the assets for this project.',\n // Renders through Module Federation: the viewer downloads from the\n // canvas-surface origin on open. First native surface; the classic\n // Canvas tile keeps the full web editor in the WebView host.\n nativeRoute: 'canvas-native',\n },\n {\n key: 'webbuilder',\n label: 'Web Builder',\n icon: 'application-outline',\n group: 'Create',\n prompt: 'Build a landing page for my bakery with a menu and a contact form',\n nativeRoute: 'webbuilder',\n surfaceUrlKey: 'WEB_BUILDER_URL',\n surfaceSlug: 'webbuilder',\n },\n {\n key: 'paper2poster',\n label: 'Paper 2 Poster',\n icon: 'presentation',\n group: 'Create',\n prompt: 'Turn this research paper into a conference poster I can edit.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'paper2poster',\n },\n {\n key: 'codezen',\n label: 'Codezen',\n icon: 'code-braces',\n group: 'Create',\n prompt: 'Clone my repository and fix the failing test',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'codezen',\n },\n {\n key: 'character',\n label: 'Characters',\n icon: 'drama-masks',\n group: 'Create',\n prompt: 'Create a stoic philosophy mentor character I can chat with',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'character',\n },\n {\n key: 'workflow',\n label: 'Workflow',\n icon: 'sitemap',\n group: 'Automate',\n prompt: 'Build a workflow that runs every morning and sends me a summary of what changed.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'workflow',\n },\n {\n key: 'computer',\n label: 'Computer',\n icon: 'monitor',\n group: 'Automate',\n prompt: 'Open a browser and compare the top 5 CRM tools with screenshots',\n },\n {\n key: 'crm',\n label: 'CRM',\n icon: 'account-group-outline',\n group: 'Sell',\n prompt: 'Look at my pipeline and tell me which deals are going cold and what I should send them.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'crm',\n },\n {\n key: 'salesiq',\n label: 'SalesIQ',\n icon: 'radar',\n group: 'Sell',\n prompt: 'Show me who is on my website right now',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'salesiq',\n },\n {\n key: 'inbox',\n label: 'Inbox',\n icon: 'inbox-outline',\n group: 'Sell',\n prompt: 'Go through my inbox, tell me what actually needs a reply, and draft those replies.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'inbox',\n },\n {\n key: 'mailcampaign',\n label: 'Mail Campaigns',\n icon: 'bullhorn-outline',\n group: 'Sell',\n prompt: 'Draft an email campaign announcing what we shipped this month.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'mailcampaign',\n },\n {\n key: 'expenses',\n label: 'Expenses',\n icon: 'receipt-outline',\n group: 'Money',\n prompt: 'Summarise my spend this month and flag anything unusual.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'expenses',\n },\n {\n key: 'cards-wallet',\n label: 'Cards & Wallet',\n icon: 'credit-card-outline',\n group: 'Money',\n prompt: 'Issue a $200 virtual card for monthly ad spend',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'cards-wallet',\n },\n {\n key: 'billing',\n label: 'Billing',\n icon: 'currency-usd',\n group: 'Money',\n prompt: 'Create an invoice for a $2,400 consulting project',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'billing',\n },\n {\n key: 'kpi-motivation',\n label: 'KPI Motivation',\n icon: 'trophy-outline',\n group: 'Team',\n prompt: 'Set up a weekly sales KPI scoreboard for my team',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'kpi-motivation',\n },\n {\n key: 'issue-ticket',\n label: 'Issue Ticket',\n icon: 'bug-outline',\n group: 'Team',\n prompt: 'Create a bug board and triage my open issues',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'issues',\n },\n {\n key: 'notebook',\n label: 'Study',\n icon: 'school-outline',\n group: 'Team',\n prompt: 'Make a study guide from my lecture notes',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'notebooklm',\n },\n {\n key: 'resume',\n label: 'Resume',\n icon: 'file-account-outline',\n group: 'Team',\n prompt: 'Draft a resume for a senior product designer with 8 years of experience',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'resume',\n },\n {\n key: 'job-search',\n label: 'Job Search',\n icon: 'briefcase-outline',\n group: 'Team',\n prompt: 'Find remote senior backend engineer roles and tailor my resume for one',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'job-search',\n },\n {\n key: 'shop',\n label: 'Shop',\n icon: 'cart-outline',\n group: 'More',\n prompt: 'Compare the best options for what I need and show me the tradeoffs.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'shopping',\n },\n {\n key: 'travel',\n label: 'Travel',\n icon: 'airplane',\n group: 'More',\n prompt: 'Plan a 4-day trip for me: flights, somewhere to stay, and what to do each day.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'travel',\n },\n {\n key: 'social-events',\n label: 'yantra.live',\n icon: 'ticket-outline',\n group: 'More',\n prompt: 'What concerts are happening nearby this weekend?',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'social-events',\n },\n];\n\nexport const APP_GROUP_ORDER: readonly AppGroupId[] = ['Create', 'Automate', 'Sell', 'Money', 'Team', 'More'];\n\nexport function matchesAppQuery(label: string, query: string): boolean {\n const q = query.toLowerCase().replace(/[^a-z0-9]/g, '');\n if (!q) return true;\n return label\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '')\n .includes(q);\n}\n\nexport function groupMobileApps(items: readonly MobileAppItem[], query: string) {\n const hits = items.filter((item) => matchesAppQuery(item.label, query));\n return APP_GROUP_ORDER.map((label) => ({\n label,\n items: hits.filter((item) => item.group === label),\n })).filter((group) => group.items.length > 0);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mobileAppCatalog.js","sources":["../../../src/features/apps/mobileAppCatalog.ts"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport type { MaterialCommunityIcons } from '@expo/vector-icons';\n\ntype IconName = ComponentProps<typeof MaterialCommunityIcons>['name'];\n\nexport type AppGroupId = 'Create' | 'Automate' | 'Sell' | 'Money' | 'Team' | 'More';\n\nexport type MobileAppItem = {\n key: string;\n label: string;\n icon: IconName;\n group: AppGroupId;\n /** Prompt sent as the first chat turn when the app has no native screen. */\n prompt: string;\n /**\n * Which surface host opens this app, if it has one. `webbuilder` is the\n * historical name of the shared WebView surface shell (`screens/WebBuilder`),\n * which is not web-builder-specific: it takes a `url` route param, mints the\n * system token, injects the bridge + cdecli token, stamps `embed=mobile` and\n * owns the timeout/retry UI. Anything with a deployed surface SPA can use it.\n */\n nativeRoute?: 'webbuilder' | 'canvas-native';\n /**\n * Deployed surface SPA for this app, as the `<slug>-surface` name. Resolved\n * against SURFACE_URL_TEMPLATE so one env var covers every surface and stays\n * per-environment, instead of 20+ near-identical URLs in eas.json.\n *\n * The slug is the SURFACE's name, which is not always the tile key\n * (issue-ticket -> issues, shop -> shopping, notebook -> notebooklm).\n */\n surfaceSlug?: string;\n /**\n * Explicit env override, for the two surfaces that already had a dedicated\n * var and are the ones people actually run locally. Wins over `surfaceSlug`.\n */\n surfaceUrlKey?: 'WEB_BUILDER_URL' | 'CANVAS_SURFACE_URL';\n};\n\n/**\n * Mobile Apps launcher. Labels, groups, and prompts stay in lockstep with the\n * browser ChatTopBar Apps menu (`packages-modules/account/browser`).\n */\nexport const MOBILE_APP_CATALOG: readonly MobileAppItem[] = [\n {\n key: 'design',\n label: 'Design',\n icon: 'palette-outline',\n group: 'Create',\n prompt: 'Design a 10-slide pitch deck for a coffee subscription startup',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'design',\n },\n {\n key: 'canvas',\n label: 'Canvas',\n icon: 'view-grid-outline',\n group: 'Create',\n prompt: 'Open a canvas and help me lay out the assets for this project.',\n nativeRoute: 'webbuilder',\n surfaceUrlKey: 'CANVAS_SURFACE_URL',\n surfaceSlug: 'canvas',\n },\n {\n key: 'canvas-native',\n label: 'Canvas Native',\n icon: 'vector-square',\n group: 'Create',\n prompt: 'Open a canvas and help me lay out the assets for this project.',\n // Renders through Module Federation: the viewer downloads from the\n // canvas-surface origin on open. First native surface; the classic\n // Canvas tile keeps the full web editor in the WebView host.\n nativeRoute: 'canvas-native',\n },\n {\n key: 'webbuilder',\n label: 'Web Builder',\n icon: 'application-outline',\n group: 'Create',\n prompt: 'Build a landing page for my bakery with a menu and a contact form',\n nativeRoute: 'webbuilder',\n surfaceUrlKey: 'WEB_BUILDER_URL',\n surfaceSlug: 'webbuilder',\n },\n {\n key: 'paper2poster',\n label: 'Paper 2 Poster',\n icon: 'presentation',\n group: 'Create',\n prompt: 'Turn this research paper into a conference poster I can edit.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'paper2poster',\n },\n {\n key: 'codezen',\n label: 'Codezen',\n icon: 'code-braces',\n group: 'Create',\n prompt: 'Clone my repository and fix the failing test',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'codezen',\n },\n {\n key: 'character',\n label: 'Characters',\n icon: 'drama-masks',\n group: 'Create',\n prompt: 'Create a stoic philosophy mentor character I can chat with',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'character',\n },\n {\n key: 'workflow',\n label: 'Workflow',\n icon: 'sitemap',\n group: 'Automate',\n prompt: 'Build a workflow that runs every morning and sends me a summary of what changed.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'workflow',\n },\n {\n key: 'computer',\n label: 'Computer',\n icon: 'monitor',\n group: 'Automate',\n prompt: 'Open a browser and compare the top 5 CRM tools with screenshots',\n },\n {\n key: 'crm',\n label: 'CRM',\n icon: 'account-group-outline',\n group: 'Sell',\n prompt: 'Look at my pipeline and tell me which deals are going cold and what I should send them.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'crm',\n },\n {\n key: 'salesiq',\n label: 'SalesIQ',\n icon: 'radar',\n group: 'Sell',\n prompt: 'Show me who is on my website right now',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'salesiq',\n },\n {\n key: 'inbox',\n label: 'Inbox',\n icon: 'inbox-outline',\n group: 'Sell',\n prompt: 'Go through my inbox, tell me what actually needs a reply, and draft those replies.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'inbox',\n },\n {\n key: 'mailcampaign',\n label: 'Mail Campaigns',\n icon: 'bullhorn-outline',\n group: 'Sell',\n prompt: 'Draft an email campaign announcing what we shipped this month.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'mailcampaign',\n },\n {\n key: 'expenses',\n label: 'Expenses',\n icon: 'receipt',\n group: 'Money',\n prompt: 'Summarise my spend this month and flag anything unusual.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'expenses',\n },\n {\n key: 'cards-wallet',\n label: 'Cards & Wallet',\n icon: 'credit-card-outline',\n group: 'Money',\n prompt: 'Issue a $200 virtual card for monthly ad spend',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'cards-wallet',\n },\n {\n key: 'billing',\n label: 'Billing',\n icon: 'currency-usd',\n group: 'Money',\n prompt: 'Create an invoice for a $2,400 consulting project',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'billing',\n },\n {\n key: 'kpi-motivation',\n label: 'KPI Motivation',\n icon: 'trophy-outline',\n group: 'Team',\n prompt: 'Set up a weekly sales KPI scoreboard for my team',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'kpi-motivation',\n },\n {\n key: 'issue-ticket',\n label: 'Issue Ticket',\n icon: 'bug-outline',\n group: 'Team',\n prompt: 'Create a bug board and triage my open issues',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'issues',\n },\n {\n key: 'notebook',\n label: 'Study',\n icon: 'school-outline',\n group: 'Team',\n prompt: 'Make a study guide from my lecture notes',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'notebooklm',\n },\n {\n key: 'resume',\n label: 'Resume',\n icon: 'file-account-outline',\n group: 'Team',\n prompt: 'Draft a resume for a senior product designer with 8 years of experience',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'resume',\n },\n {\n key: 'job-search',\n label: 'Job Search',\n icon: 'briefcase-outline',\n group: 'Team',\n prompt: 'Find remote senior backend engineer roles and tailor my resume for one',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'job-search',\n },\n {\n key: 'shop',\n label: 'Shop',\n icon: 'cart-outline',\n group: 'More',\n prompt: 'Compare the best options for what I need and show me the tradeoffs.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'shopping',\n },\n {\n key: 'travel',\n label: 'Travel',\n icon: 'airplane',\n group: 'More',\n prompt: 'Plan a 4-day trip for me: flights, somewhere to stay, and what to do each day.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'travel',\n },\n {\n key: 'social-events',\n label: 'yantra.live',\n icon: 'ticket-outline',\n group: 'More',\n prompt: 'What concerts are happening nearby this weekend?',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'social-events',\n },\n];\n\nexport const APP_GROUP_ORDER: readonly AppGroupId[] = ['Create', 'Automate', 'Sell', 'Money', 'Team', 'More'];\n\nexport function matchesAppQuery(label: string, query: string): boolean {\n const q = query.toLowerCase().replace(/[^a-z0-9]/g, '');\n if (!q) return true;\n return label\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '')\n .includes(q);\n}\n\nexport function groupMobileApps(items: readonly MobileAppItem[], query: string) {\n const hits = items.filter((item) => matchesAppQuery(item.label, query));\n return APP_GROUP_ORDER.map((label) => ({\n label,\n items: hits.filter((item) => item.group === label),\n })).filter((group) => group.items.length > 0);\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useImageAttachments.js","sources":["../../../src/features/attachments/useImageAttachments.ts"],"sourcesContent":["/**\n * Image attachments for the native composer.\n *\n * The transport was already there — `useChatStream.sendMessage(content,\n * attachments)` carries `MessageAttachment[]` and the gateway media lane is\n * covered by `aiwork/e2e-tests/gateway-media-upload.spec.ts`. What was missing\n * was any way to produce one on a phone: the composer shipped with\n * `image`/`camera`/`attach` hard-disabled, and nothing in the mobile package\n * touched `expo-image-picker` even though it is a dependency and the photo and\n * camera permission strings are already declared in `app.json`.\n *\n * Payload size is the whole game here. A modern iPhone photo is ~3-5 MB and\n * ~4000px wide; base64 inflates that by a third, and it travels inline on the\n * chat message. So we ask the picker to downscale and re-encode before we ever\n * see the bytes, then hard-reject anything still oversized rather than let a\n * send hang on a slow uplink.\n */\nimport { useCallback, useMemo, useState } from 'react';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\n\n/** Longest edge, in px, we send. Plenty for a model to read; ~10x smaller than source. */\nconst MAX_EDGE = 1280;\n/** JPEG quality handed to the picker (0-1). */\nconst PICKER_QUALITY = 0.7;\n/** Refuse anything above this after re-encoding — a send is better failed than hung. */\nconst MAX_BYTES = 4 * 1024 * 1024;\n/** Nothing sensible is this small; treat as a failed decode. */\nconst MIN_BYTES = 64;\n\nexport interface ImageAttachmentsApi {\n /** Attachments staged for the next send. */\n pending: MessageAttachment[];\n /** True while the picker/encode is in flight, for the toolbar spinner. */\n busy: boolean;\n /** Human-readable failure for the composer's error banner, or null. */\n error: string | null;\n pickFromLibrary: () => Promise<void>;\n captureFromCamera: () => Promise<void>;\n remove: (id: string) => void;\n clear: () => void;\n /** Pass to `sendMessage` — undefined when empty, which is what it expects. */\n forSend: () => MessageAttachment[] | undefined;\n}\n\ntype PickedAsset = {\n uri?: string | null;\n base64?: string | null;\n mimeType?: string | null;\n fileName?: string | null;\n fileSize?: number | null;\n width?: number | null;\n height?: number | null;\n};\n\n/** Base64 decodes to 3 bytes per 4 chars, minus `=` padding. */\nfunction base64Bytes(base64: string): number {\n const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;\n return Math.floor((base64.length * 3) / 4) - padding;\n}\n\nfunction toAttachment(asset: PickedAsset, index: number): MessageAttachment | null {\n const base64 = asset.base64?.trim();\n if (!base64) return null;\n const size = base64Bytes(base64);\n if (size < MIN_BYTES || size > MAX_BYTES) return null;\n const mimeType = asset.mimeType?.trim() || 'image/jpeg';\n const name = asset.fileName?.trim() || `image-${Date.now()}-${index}.jpg`;\n return {\n // Local id only — the gateway assigns its own.\n id: `img-${Date.now()}-${index}`,\n name,\n type: 'file',\n mimeType,\n dataUrl: `data:${mimeType};base64,${base64}`,\n size,\n };\n}\n\n/**\n * Lazily required so a unit test or a non-Expo bundle importing this hook does\n * not hard-fail on the native module.\n */\nfunction loadPicker() {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require\n return require('expo-image-picker') as typeof import('expo-image-picker');\n}\n\nexport function useImageAttachments(): ImageAttachmentsApi {\n const [pending, setPending] = useState<MessageAttachment[]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const run = useCallback(async (mode: 'library' | 'camera') => {\n setError(null);\n setBusy(true);\n try {\n const picker = loadPicker();\n\n const permission =\n mode === 'camera'\n ? await picker.requestCameraPermissionsAsync()\n : await picker.requestMediaLibraryPermissionsAsync();\n if (!permission.granted) {\n setError(\n mode === 'camera'\n ? 'Camera access is off for Yantra. Turn it on in Settings to attach a photo.'\n : 'Photo access is off for Yantra. Turn it on in Settings to attach an image.',\n );\n return;\n }\n\n const options = {\n // `base64` is what the message carries; `quality` + the picker's\n // own resize keep it small enough to travel inline.\n base64: true,\n quality: PICKER_QUALITY,\n allowsMultipleSelection: mode === 'library',\n mediaTypes: ['images'] as const,\n // Selection limit mirrors MAX_BYTES: four 1280px JPEGs still fit\n // comfortably inside a single turn.\n selectionLimit: 4,\n exif: false,\n };\n\n const result =\n mode === 'camera'\n ? await picker.launchCameraAsync({ ...options, allowsMultipleSelection: false })\n : await picker.launchImageLibraryAsync(options);\n\n if (result.canceled) return;\n\n const mapped = (result.assets ?? [])\n .map((asset, i) => toAttachment(asset as PickedAsset, i))\n .filter((a): a is MessageAttachment => a !== null);\n\n if (mapped.length === 0) {\n setError('That image was too large to attach. Try a smaller one.');\n return;\n }\n setPending((prev) => [...prev, ...mapped]);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Could not attach that image.');\n } finally {\n setBusy(false);\n }\n }, []);\n\n const pickFromLibrary = useCallback(() => run('library'), [run]);\n const captureFromCamera = useCallback(() => run('camera'), [run]);\n const remove = useCallback((id: string) => setPending((prev) => prev.filter((a) => a.id !== id)), []);\n const clear = useCallback(() => setPending([]), []);\n const forSend = useCallback(() => (pending.length > 0 ? pending : undefined), [pending]);\n\n return useMemo(\n () => ({ pending, busy, error, pickFromLibrary, captureFromCamera, remove, clear, forSend }),\n [pending, busy, error, pickFromLibrary, captureFromCamera, remove, clear, forSend],\n );\n}\n\nexport const IMAGE_ATTACHMENT_LIMITS = { MAX_EDGE, MAX_BYTES, PICKER_QUALITY } as const;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useImageAttachments.js","sources":["../../../src/features/attachments/useImageAttachments.ts"],"sourcesContent":["/**\n * Image attachments for the native composer.\n *\n * The transport was already there — `useChatStream.sendMessage(content,\n * attachments)` carries `MessageAttachment[]` and the gateway media lane is\n * covered by `aiwork/e2e-tests/gateway-media-upload.spec.ts`. What was missing\n * was any way to produce one on a phone: the composer shipped with\n * `image`/`camera`/`attach` hard-disabled, and nothing in the mobile package\n * touched `expo-image-picker` even though it is a dependency and the photo and\n * camera permission strings are already declared in `app.json`.\n *\n * Payload size is the whole game here. A modern iPhone photo is ~3-5 MB and\n * ~4000px wide; base64 inflates that by a third, and it travels inline on the\n * chat message. So we ask the picker to downscale and re-encode before we ever\n * see the bytes, then hard-reject anything still oversized rather than let a\n * send hang on a slow uplink.\n */\nimport { useCallback, useMemo, useState } from 'react';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\n\n/** Longest edge, in px, we send. Plenty for a model to read; ~10x smaller than source. */\nconst MAX_EDGE = 1280;\n/** JPEG quality handed to the picker (0-1). */\nconst PICKER_QUALITY = 0.7;\n/** Refuse anything above this after re-encoding — a send is better failed than hung. */\nconst MAX_BYTES = 4 * 1024 * 1024;\n/** Nothing sensible is this small; treat as a failed decode. */\nconst MIN_BYTES = 64;\n\nexport interface ImageAttachmentsApi {\n /** Attachments staged for the next send. */\n pending: MessageAttachment[];\n /** True while the picker/encode is in flight, for the toolbar spinner. */\n busy: boolean;\n /** Human-readable failure for the composer's error banner, or null. */\n error: string | null;\n pickFromLibrary: () => Promise<void>;\n captureFromCamera: () => Promise<void>;\n remove: (id: string) => void;\n clear: () => void;\n /** Pass to `sendMessage` — undefined when empty, which is what it expects. */\n forSend: () => MessageAttachment[] | undefined;\n}\n\ntype PickedAsset = {\n uri?: string | null;\n base64?: string | null;\n mimeType?: string | null;\n fileName?: string | null;\n fileSize?: number | null;\n width?: number | null;\n height?: number | null;\n};\n\n/** Base64 decodes to 3 bytes per 4 chars, minus `=` padding. */\nfunction base64Bytes(base64: string): number {\n const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;\n return Math.floor((base64.length * 3) / 4) - padding;\n}\n\nfunction toAttachment(asset: PickedAsset, index: number): MessageAttachment | null {\n const base64 = asset.base64?.trim();\n if (!base64) return null;\n const size = base64Bytes(base64);\n if (size < MIN_BYTES || size > MAX_BYTES) return null;\n const mimeType = asset.mimeType?.trim() || 'image/jpeg';\n const name = asset.fileName?.trim() || `image-${Date.now()}-${index}.jpg`;\n return {\n // Local id only — the gateway assigns its own.\n id: `img-${Date.now()}-${index}`,\n name,\n type: 'file',\n mimeType,\n dataUrl: `data:${mimeType};base64,${base64}`,\n size,\n };\n}\n\n/**\n * Lazily required so a unit test or a non-Expo bundle importing this hook does\n * not hard-fail on the native module.\n */\nfunction loadPicker() {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require\n return require('expo-image-picker') as typeof import('expo-image-picker');\n}\n\nexport function useImageAttachments(): ImageAttachmentsApi {\n const [pending, setPending] = useState<MessageAttachment[]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const run = useCallback(async (mode: 'library' | 'camera') => {\n setError(null);\n setBusy(true);\n try {\n const picker = loadPicker();\n\n const permission =\n mode === 'camera'\n ? await picker.requestCameraPermissionsAsync()\n : await picker.requestMediaLibraryPermissionsAsync();\n if (!permission.granted) {\n setError(\n mode === 'camera'\n ? 'Camera access is off for Yantra. Turn it on in Settings to attach a photo.'\n : 'Photo access is off for Yantra. Turn it on in Settings to attach an image.',\n );\n return;\n }\n\n const options: import('expo-image-picker').ImagePickerOptions = {\n // `base64` is what the message carries; `quality` + the picker's\n // own resize keep it small enough to travel inline.\n base64: true,\n quality: PICKER_QUALITY,\n allowsMultipleSelection: mode === 'library',\n mediaTypes: ['images'],\n // Selection limit mirrors MAX_BYTES: four 1280px JPEGs still fit\n // comfortably inside a single turn.\n selectionLimit: 4,\n exif: false,\n };\n\n const result =\n mode === 'camera'\n ? await picker.launchCameraAsync({ ...options, allowsMultipleSelection: false })\n : await picker.launchImageLibraryAsync(options);\n\n if (result.canceled) return;\n\n const mapped = (result.assets ?? [])\n .map((asset, i) => toAttachment(asset as PickedAsset, i))\n .filter((a): a is MessageAttachment => a !== null);\n\n if (mapped.length === 0) {\n setError('That image was too large to attach. Try a smaller one.');\n return;\n }\n setPending((prev) => [...prev, ...mapped]);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Could not attach that image.');\n } finally {\n setBusy(false);\n }\n }, []);\n\n const pickFromLibrary = useCallback(() => run('library'), [run]);\n const captureFromCamera = useCallback(() => run('camera'), [run]);\n const remove = useCallback((id: string) => setPending((prev) => prev.filter((a) => a.id !== id)), []);\n const clear = useCallback(() => setPending([]), []);\n const forSend = useCallback(() => (pending.length > 0 ? pending : undefined), [pending]);\n\n return useMemo(\n () => ({ pending, busy, error, pickFromLibrary, captureFromCamera, remove, clear, forSend }),\n [pending, busy, error, pickFromLibrary, captureFromCamera, remove, clear, forSend],\n );\n}\n\nexport const IMAGE_ATTACHMENT_LIMITS = { MAX_EDGE, MAX_BYTES, PICKER_QUALITY } as const;\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"canvasCore.js","sources":["../../../src/features/canvas/canvasCore.ts"],"sourcesContent":["/**\n * Platform-agnostic canvas document model — the native twin of the web\n * surface's `state/boards.ts` (`@yantra/canvas-surface`).\n *\n * The shapes are copied, not imported: the surface package builds for the DOM\n * (react-dom peer, vite, `crypto.randomUUID`), so importing it would drag the\n * web toolchain into Metro. The contract that actually matters is the persisted\n * JSON — `PersistedCanvasState` version 1 — and tests below pin this file to\n * fixtures of that JSON, so drift between the copies fails a test rather than\n * corrupting a board.\n *\n * Everything here is pure data + math so it runs identically under Metro,\n * vite, and jest: no RN imports, no DOM globals.\n */\n\nexport interface CanvasItem {\n id: string;\n type: 'image' | 'video' | 'audio';\n src: string;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n generatedAssetName?: string;\n}\n\nexport interface PersistedCanvasState {\n version: 1;\n savedAt: number;\n items: CanvasItem[];\n zoom: number;\n title?: string;\n}\n\n/** Parse a persisted board, tolerating the unknown: bad rows drop, not throw. */\nexport function parseBoardState(raw: unknown): PersistedCanvasState | null {\n if (!raw || typeof raw !== 'object') return null;\n const candidate = raw as Partial<PersistedCanvasState>;\n if (candidate.version !== 1 || !Array.isArray(candidate.items)) return null;\n const items = candidate.items.filter(isRenderableItem);\n return {\n version: 1,\n savedAt: typeof candidate.savedAt === 'number' ? candidate.savedAt : 0,\n items,\n zoom: clampZoom(typeof candidate.zoom === 'number' ? candidate.zoom : 1),\n ...(typeof candidate.title === 'string' && candidate.title ? { title: candidate.title } : {}),\n };\n}\n\n/** An item the viewer can draw. `blob:` URLs died with the web tab that made them. */\nexport function isRenderableItem(item: unknown): item is CanvasItem {\n if (!item || typeof item !== 'object') return false;\n const c = item as Partial<CanvasItem>;\n return (\n typeof c.id === 'string' &&\n (c.type === 'image' || c.type === 'video' || c.type === 'audio') &&\n typeof c.src === 'string' &&\n c.src.length > 0 &&\n !c.src.startsWith('blob:') &&\n [c.x, c.y, c.width, c.height].every((n) => typeof n === 'number' && Number.isFinite(n)) &&\n (c.width as number) > 0 &&\n (c.height as number) > 0\n );\n}\n\nexport const MIN_ZOOM = 0.25;\nexport const MAX_ZOOM = 4;\n\nexport function clampZoom(zoom: number): number {\n if (!Number.isFinite(zoom)) return 1;\n return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));\n}\n\nexport interface BoardBounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\n/** Union of item rects; null for an empty board (an empty union has no bounds). */\nexport function boardBounds(items: readonly CanvasItem[]): BoardBounds | null {\n if (items.length === 0) return null;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const it of items) {\n minX = Math.min(minX, it.x);\n minY = Math.min(minY, it.y);\n maxX = Math.max(maxX, it.x + it.width);\n maxY = Math.max(maxY, it.y + it.height);\n }\n return { minX, minY, maxX, maxY };\n}\n\nexport interface FitTransform {\n /** Uniform scale applied to board coordinates. */\n scale: number;\n /** Screen-space translation, applied after scaling. */\n translateX: number;\n translateY: number;\n}\n\n/**\n * Fit the whole board inside a viewport with a margin — the viewer's initial\n * camera. Pure math so pinch/pan gestures can start from a reproducible state.\n */\nexport function fitToViewport(\n bounds: BoardBounds,\n viewportWidth: number,\n viewportHeight: number,\n margin = 24,\n): FitTransform {\n const boardW = Math.max(1, bounds.maxX - bounds.minX);\n const boardH = Math.max(1, bounds.maxY - bounds.minY);\n const availW = Math.max(1, viewportWidth - margin * 2);\n const availH = Math.max(1, viewportHeight - margin * 2);\n const scale = clampZoom(Math.min(availW / boardW, availH / boardH));\n // Center the scaled board in the viewport.\n const translateX = (viewportWidth - boardW * scale) / 2 - bounds.minX * scale;\n const translateY = (viewportHeight - boardH * scale) / 2 - bounds.minY * scale;\n return { scale, translateX, translateY };\n}\n\n/** Painter's order: stable sort by zIndex so overlapping media stack as authored. */\nexport function paintOrder(items: readonly CanvasItem[]): CanvasItem[] {\n return [...items].sort((a, b) => a.zIndex - b.zIndex || a.id.localeCompare(b.id));\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAmCO,SAAS,gBAAgB,GAA2C,EAAA;AACzE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAiB,OAAA,IAAA;AAC5C,EAAA,MAAM,SAAY,GAAA,GAAA;AAClB,EAAI,IAAA,SAAA,CAAU,YAAY,CAAK,IAAA,CAAC,MAAM,OAAQ,CAAA,SAAA,CAAU,KAAK,CAAA,EAAU,OAAA,IAAA;AACvE,EAAA,MAAM,KAAQ,GAAA,SAAA,CAAU,KAAM,CAAA,MAAA,CAAO,gBAAgB,CAAA;AACrD,EAAO,OAAA,cAAA,CAAA;AAAA,IACL,OAAS,EAAA,CAAA;AAAA,IACT,SAAS,OAAO,SAAA,CAAU,OAAY,KAAA,QAAA,GAAW,UAAU,OAAU,GAAA,CAAA;AAAA,IACrE,KAAA;AAAA,IACA,IAAA,EAAM,UAAU,OAAO,SAAA,CAAU,SAAS,QAAW,GAAA,SAAA,CAAU,OAAO,CAAC;AAAA,GAAA,EACnE,OAAO,SAAA,CAAU,KAAU,KAAA,QAAA,IAAY,UAAU,KAAQ,GAAA;AAAA,IAC3D,OAAO,SAAU,CAAA;AAAA,MACf,EAAC,CAAA;AAET;AAGO,SAAS,iBAAiB,IAAmC,EAAA;AAClE,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,UAAiB,OAAA,KAAA;AAC9C,EAAA,MAAM,CAAI,GAAA,IAAA;AACV,EAAO,OAAA,OAAO,EAAE,EAAO,KAAA,QAAA,KAAa,EAAE,IAAS,KAAA,OAAA,IAAW,CAAE,CAAA,IAAA,KAAS,OAAW,IAAA,CAAA,CAAE,SAAS,OAAY,CAAA,IAAA,OAAO,CAAE,CAAA,GAAA,KAAQ,QAAY,IAAA,CAAA,CAAE,IAAI,MAAS,GAAA,CAAA,IAAK,CAAC,CAAA,CAAE,GAAI,CAAA,UAAA,CAAW,OAAO,CAAK,IAAA,CAAC,CAAE,CAAA,CAAA,EAAG,CAAE,CAAA,CAAA,EAAG,EAAE,KAAO,EAAA,CAAA,CAAE,MAAM,CAAA,CAAE,KAAM,CAAA,CAAA,CAAA,KAAK,OAAO,CAAM,KAAA,QAAA,IAAY,MAAO,CAAA,QAAA,CAAS,CAAC,CAAC,KAAK,CAAE,CAAA,KAAA,GAAkB,CAAK,IAAA,CAAA,CAAE,MAAmB,GAAA,CAAA;AAC/T;AACO,MAAM,QAAW,GAAA;AACjB,MAAM,QAAW,GAAA;AACjB,SAAS,UAAU,IAAsB,EAAA;AAC9C,EAAA,IAAI,CAAC,MAAA,CAAO,QAAS,CAAA,IAAI,GAAU,OAAA,CAAA;AACnC,EAAA,OAAO,KAAK,GAAI,CAAA,QAAA,EAAU,KAAK,GAAI,CAAA,QAAA,EAAU,IAAI,CAAC,CAAA;AACpD"}
1
+ {"version":3,"file":"canvasCore.js","sources":["../../../src/features/canvas/canvasCore.ts"],"sourcesContent":["/**\n * Platform-agnostic canvas document model — the native twin of the web\n * surface's `state/boards.ts` (`@yantra/canvas-surface`).\n *\n * The shapes are copied, not imported: the surface package builds for the DOM\n * (react-dom peer, vite, `crypto.randomUUID`), so importing it would drag the\n * web toolchain into Metro. The contract that actually matters is the persisted\n * JSON — `PersistedCanvasState` version 1 — and tests below pin this file to\n * fixtures of that JSON, so drift between the copies fails a test rather than\n * corrupting a board.\n *\n * Everything here is pure data + math so it runs identically under Metro,\n * vite, and jest: no RN imports, no DOM globals.\n */\n\nexport interface CanvasItem {\n id: string;\n type: 'image' | 'video' | 'audio';\n src: string;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n generatedAssetName?: string;\n}\n\nexport interface PersistedCanvasState {\n version: 1;\n savedAt: number;\n items: CanvasItem[];\n zoom: number;\n title?: string;\n}\n\n/** Parse a persisted board, tolerating the unknown: bad rows drop, not throw. */\nexport function parseBoardState(raw: unknown): PersistedCanvasState | null {\n if (!raw || typeof raw !== 'object') return null;\n const candidate = raw as Partial<PersistedCanvasState>;\n if (candidate.version !== 1 || !Array.isArray(candidate.items)) return null;\n const items = candidate.items.filter(isRenderableItem);\n return {\n version: 1,\n savedAt: typeof candidate.savedAt === 'number' ? candidate.savedAt : 0,\n items,\n zoom: clampZoom(typeof candidate.zoom === 'number' ? candidate.zoom : 1),\n ...(typeof candidate.title === 'string' && candidate.title ? { title: candidate.title } : {}),\n };\n}\n\n/** An item the viewer can draw. `blob:` URLs died with the web tab that made them. */\nexport function isRenderableItem(item: unknown): item is CanvasItem {\n if (!item || typeof item !== 'object') return false;\n const c = item as Partial<CanvasItem>;\n return (\n typeof c.id === 'string' &&\n (c.type === 'image' || c.type === 'video' || c.type === 'audio') &&\n typeof c.src === 'string' &&\n c.src.length > 0 &&\n !c.src.startsWith('blob:') &&\n [c.x, c.y, c.width, c.height].every((n) => typeof n === 'number' && Number.isFinite(n)) &&\n (c.width as number) > 0 &&\n (c.height as number) > 0\n );\n}\n\n/** Floor for item edits - a rect can never be resized away entirely. */\nexport const MIN_ITEM_SIZE = 24;\n\nexport interface ItemFrame {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport type ResizeCorner = 'tl' | 'tr' | 'bl' | 'br';\n\n/**\n * Resize `frame` by dragging `corner` by (dx, dy) board units, keeping the\n * OPPOSITE corner anchored - the gesture the selection handles drive. Both\n * axes move independently (free-form resize); each side clamps at\n * MIN_ITEM_SIZE so a rect can shrink to a nub but never invert or vanish.\n *\n * Marked as a worklet: the resize handles call this per-frame on the UI\n * thread. The directive is inert everywhere else (plain string in node/jest).\n */\nexport function resizeFrame(frame: ItemFrame, corner: ResizeCorner, dx: number, dy: number): ItemFrame {\n 'worklet';\n\n const left = corner === 'tl' || corner === 'bl';\n const top = corner === 'tl' || corner === 'tr';\n\n const width = Math.max(MIN_ITEM_SIZE, left ? frame.width - dx : frame.width + dx);\n const height = Math.max(MIN_ITEM_SIZE, top ? frame.height - dy : frame.height + dy);\n\n return {\n // Anchor the opposite corner: a left/top edge moves by however much the\n // clamped size actually changed, not by the raw drag delta.\n x: left ? frame.x + (frame.width - width) : frame.x,\n y: top ? frame.y + (frame.height - height) : frame.y,\n width,\n height,\n };\n}\n\n/** New items array with `id`'s frame replaced - the commit step after a drag\n * or resize gesture ends. Unknown ids return the array unchanged. */\nexport function applyItemFrame(items: readonly CanvasItem[], id: string, frame: ItemFrame): CanvasItem[] {\n return items.map((item) => (item.id === id ? { ...item, ...frame } : item));\n}\n\nexport const MIN_ZOOM = 0.25;\nexport const MAX_ZOOM = 4;\n\nexport function clampZoom(zoom: number): number {\n if (!Number.isFinite(zoom)) return 1;\n return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));\n}\n\nexport interface BoardBounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\n/** Union of item rects; null for an empty board (an empty union has no bounds). */\nexport function boardBounds(items: readonly CanvasItem[]): BoardBounds | null {\n if (items.length === 0) return null;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const it of items) {\n minX = Math.min(minX, it.x);\n minY = Math.min(minY, it.y);\n maxX = Math.max(maxX, it.x + it.width);\n maxY = Math.max(maxY, it.y + it.height);\n }\n return { minX, minY, maxX, maxY };\n}\n\nexport interface FitTransform {\n /** Uniform scale applied to board coordinates. */\n scale: number;\n /** Screen-space translation, applied after scaling. */\n translateX: number;\n translateY: number;\n}\n\n/**\n * Fit the whole board inside a viewport with a margin — the viewer's initial\n * camera. Pure math so pinch/pan gestures can start from a reproducible state.\n */\nexport function fitToViewport(\n bounds: BoardBounds,\n viewportWidth: number,\n viewportHeight: number,\n margin = 24,\n): FitTransform {\n const boardW = Math.max(1, bounds.maxX - bounds.minX);\n const boardH = Math.max(1, bounds.maxY - bounds.minY);\n const availW = Math.max(1, viewportWidth - margin * 2);\n const availH = Math.max(1, viewportHeight - margin * 2);\n const scale = clampZoom(Math.min(availW / boardW, availH / boardH));\n // Center the scaled board in the viewport.\n const translateX = (viewportWidth - boardW * scale) / 2 - bounds.minX * scale;\n const translateY = (viewportHeight - boardH * scale) / 2 - bounds.minY * scale;\n return { scale, translateX, translateY };\n}\n\n/** Painter's order: stable sort by zIndex so overlapping media stack as authored. */\nexport function paintOrder(items: readonly CanvasItem[]): CanvasItem[] {\n return [...items].sort((a, b) => a.zIndex - b.zIndex || a.id.localeCompare(b.id));\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAmCO,SAAS,gBAAgB,GAA2C,EAAA;AACzE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAiB,OAAA,IAAA;AAC5C,EAAA,MAAM,SAAY,GAAA,GAAA;AAClB,EAAI,IAAA,SAAA,CAAU,YAAY,CAAK,IAAA,CAAC,MAAM,OAAQ,CAAA,SAAA,CAAU,KAAK,CAAA,EAAU,OAAA,IAAA;AACvE,EAAA,MAAM,KAAQ,GAAA,SAAA,CAAU,KAAM,CAAA,MAAA,CAAO,gBAAgB,CAAA;AACrD,EAAO,OAAA,cAAA,CAAA;AAAA,IACL,OAAS,EAAA,CAAA;AAAA,IACT,SAAS,OAAO,SAAA,CAAU,OAAY,KAAA,QAAA,GAAW,UAAU,OAAU,GAAA,CAAA;AAAA,IACrE,KAAA;AAAA,IACA,IAAA,EAAM,UAAU,OAAO,SAAA,CAAU,SAAS,QAAW,GAAA,SAAA,CAAU,OAAO,CAAC;AAAA,GAAA,EACnE,OAAO,SAAA,CAAU,KAAU,KAAA,QAAA,IAAY,UAAU,KAAQ,GAAA;AAAA,IAC3D,OAAO,SAAU,CAAA;AAAA,MACf,EAAC,CAAA;AAET;AAGO,SAAS,iBAAiB,IAAmC,EAAA;AAClE,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,UAAiB,OAAA,KAAA;AAC9C,EAAA,MAAM,CAAI,GAAA,IAAA;AACV,EAAO,OAAA,OAAO,EAAE,EAAO,KAAA,QAAA,KAAa,EAAE,IAAS,KAAA,OAAA,IAAW,CAAE,CAAA,IAAA,KAAS,OAAW,IAAA,CAAA,CAAE,SAAS,OAAY,CAAA,IAAA,OAAO,CAAE,CAAA,GAAA,KAAQ,QAAY,IAAA,CAAA,CAAE,IAAI,MAAS,GAAA,CAAA,IAAK,CAAC,CAAA,CAAE,GAAI,CAAA,UAAA,CAAW,OAAO,CAAK,IAAA,CAAC,CAAE,CAAA,CAAA,EAAG,CAAE,CAAA,CAAA,EAAG,EAAE,KAAO,EAAA,CAAA,CAAE,MAAM,CAAA,CAAE,KAAM,CAAA,CAAA,CAAA,KAAK,OAAO,CAAM,KAAA,QAAA,IAAY,MAAO,CAAA,QAAA,CAAS,CAAC,CAAC,KAAK,CAAE,CAAA,KAAA,GAAkB,CAAK,IAAA,CAAA,CAAE,MAAmB,GAAA,CAAA;AAC/T;AA8CO,MAAM,QAAW,GAAA;AACjB,MAAM,QAAW,GAAA;AACjB,SAAS,UAAU,IAAsB,EAAA;AAC9C,EAAA,IAAI,CAAC,MAAA,CAAO,QAAS,CAAA,IAAI,GAAU,OAAA,CAAA;AACnC,EAAA,OAAO,KAAK,GAAI,CAAA,QAAA,EAAU,KAAK,GAAI,CAAA,QAAA,EAAU,IAAI,CAAC,CAAA;AACpD"}
@@ -0,0 +1,56 @@
1
+ import {jsxs,jsx}from'react/jsx-runtime';import {useState,useRef,useEffect,useCallback}from'react';import {Clipboard,Share,View,StyleSheet,TouchableOpacity}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';const ICON_SIZE = 16;
2
+ const ICON_COLOR = "#64748b";
3
+ const COPIED_COLOR = "#10b981";
4
+ function ActionButton({
5
+ icon,
6
+ label,
7
+ onPress,
8
+ color = ICON_COLOR
9
+ }) {
10
+ return /* @__PURE__ */ jsx(TouchableOpacity, { onPress, style: styles.button, hitSlop: {
11
+ top: 8,
12
+ bottom: 8,
13
+ left: 6,
14
+ right: 6
15
+ }, accessibilityRole: "button", accessibilityLabel: label, children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: icon, size: ICON_SIZE, color }) });
16
+ }
17
+ function MessageActionBar({
18
+ text,
19
+ onRegenerate
20
+ }) {
21
+ const [copied, setCopied] = useState(false);
22
+ const copiedTimer = useRef(null);
23
+ useEffect(() => () => {
24
+ if (copiedTimer.current) clearTimeout(copiedTimer.current);
25
+ }, []);
26
+ const handleCopy = useCallback(() => {
27
+ Clipboard.setString(text);
28
+ setCopied(true);
29
+ if (copiedTimer.current) clearTimeout(copiedTimer.current);
30
+ copiedTimer.current = setTimeout(() => setCopied(false), 2e3);
31
+ }, [text]);
32
+ const handleShare = useCallback(() => {
33
+ void Share.share({
34
+ message: text
35
+ });
36
+ }, [text]);
37
+ return /* @__PURE__ */ jsxs(View, { style: styles.row, accessibilityRole: "toolbar", accessibilityLabel: "Message actions", children: [
38
+ /* @__PURE__ */ jsx(ActionButton, { icon: copied ? "check" : "content-copy", label: copied ? "Copied" : "Copy", onPress: handleCopy, color: copied ? COPIED_COLOR : ICON_COLOR }),
39
+ onRegenerate ? /* @__PURE__ */ jsx(ActionButton, { icon: "refresh", label: "Try again", onPress: onRegenerate }) : null,
40
+ /* @__PURE__ */ jsx(ActionButton, { icon: "share-variant-outline", label: "Share", onPress: handleShare })
41
+ ] });
42
+ }
43
+ const styles = StyleSheet.create({
44
+ row: {
45
+ flexDirection: "row",
46
+ alignItems: "center",
47
+ gap: 4
48
+ },
49
+ button: {
50
+ height: 28,
51
+ width: 28,
52
+ borderRadius: 8,
53
+ alignItems: "center",
54
+ justifyContent: "center"
55
+ }
56
+ });export{MessageActionBar,MessageActionBar as default};//# sourceMappingURL=MessageActionBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageActionBar.js","sources":["../../../src/features/chat/MessageActionBar.tsx"],"sourcesContent":["/**\n * Action row under a completed assistant message — the mobile counterpart of\n * the web chat's MessageActionBar (copy / try again / share). Rendered through\n * MessagesContainerUI's `renderMessageActions` slot.\n *\n * Read-aloud is deliberately absent for now: it needs `expo-speech`, a native\n * module the installed binaries don't carry yet. It joins the bar in the build\n * that adds the dependency; everything here works with the current binary.\n */\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n// Clipboard is deprecated in RN core but still functional on 0.79, and the\n// community package is not in the dependency set — using core avoids putting a\n// new native module between the user and a working Copy button.\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nimport { Clipboard, Share, StyleSheet, TouchableOpacity, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\n\nexport interface MessageActionBarProps {\n /** The assistant message's text — copied and shared verbatim. */\n text: string;\n /** Re-run the turn that produced this message. Omit to hide the button\n * (e.g. while a turn is streaming, to avoid double-sends). */\n onRegenerate?: () => void;\n}\n\nconst ICON_SIZE = 16;\nconst ICON_COLOR = '#64748b';\nconst COPIED_COLOR = '#10b981';\n\ninterface ActionButtonProps {\n icon: React.ComponentProps<typeof MaterialCommunityIcons>['name'];\n label: string;\n onPress: () => void;\n color?: string;\n}\n\nfunction ActionButton({ icon, label, onPress, color = ICON_COLOR }: ActionButtonProps) {\n return (\n <TouchableOpacity\n onPress={onPress}\n style={styles.button}\n hitSlop={{ top: 8, bottom: 8, left: 6, right: 6 }}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n >\n <MaterialCommunityIcons name={icon} size={ICON_SIZE} color={color} />\n </TouchableOpacity>\n );\n}\n\nexport function MessageActionBar({ text, onRegenerate }: MessageActionBarProps) {\n const [copied, setCopied] = useState(false);\n const copiedTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(\n () => () => {\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n },\n [],\n );\n\n const handleCopy = useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n Clipboard.setString(text);\n setCopied(true);\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n copiedTimer.current = setTimeout(() => setCopied(false), 2000);\n }, [text]);\n\n const handleShare = useCallback(() => {\n void Share.share({ message: text });\n }, [text]);\n\n return (\n <View style={styles.row} accessibilityRole=\"toolbar\" accessibilityLabel=\"Message actions\">\n <ActionButton\n icon={copied ? 'check' : 'content-copy'}\n label={copied ? 'Copied' : 'Copy'}\n onPress={handleCopy}\n color={copied ? COPIED_COLOR : ICON_COLOR}\n />\n {onRegenerate ? <ActionButton icon=\"refresh\" label=\"Try again\" onPress={onRegenerate} /> : null}\n <ActionButton icon=\"share-variant-outline\" label=\"Share\" onPress={handleShare} />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n },\n button: {\n height: 28,\n width: 28,\n borderRadius: 8,\n alignItems: 'center',\n justifyContent: 'center',\n },\n});\n\nexport default MessageActionBar;\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useCdecliChannel.js","sources":["../../src/hooks/useCdecliChannel.ts"],"sourcesContent":["/**\n * useCdecliChannel — wires the cdecli-serve messenger-gateway channel into the mobile chat UI.\n *\n * Kept in sync with `packages-modules/account/browser/src/hooks/useCdecliChannel.ts`.\n * When the CDeCLI channel is connected:\n * - `sendMessage(text)` calls `gatewaySendMessage`\n * - `MessengerStreamDelta` subscription delivers streaming chunks via `onChunk`\n * - `GatewayInboundMessageByChannel` delivers the final reply via `onComplete`\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport {\n useGatewaySendMessageMutation,\n useGatewayInboundMessageByChannelSubscription,\n useMessengerStreamDeltaSubscription,\n} from 'common/graphql';\n\nfunction stripModelCostHeader(content: string): string {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n return normalized.replace(\n /^\\s*(?:[^\\w\\n]+\\s*)?[a-z0-9][a-z0-9._-]*\\s*\\(\\s*\\$[\\d.]+\\s*\\/\\s*MTok\\s+in\\s*\\)\\s*\\n+/i,\n '',\n );\n}\n\nexport type SteerResult = { ok: true } | { ok: false; error: string };\n\nexport interface CdecliChannelCallbacks {\n onChunk: (text: string) => void;\n onComplete: (text: string) => void;\n onError: (error: string) => void;\n}\n\nexport function isNoActiveSessionError(message: string): boolean {\n return /no active session/i.test(message);\n}\n\n/** Same 120s window as web — deep CDeCLI queries can exceed 45s. */\nconst CDECLI_RESPONSE_TIMEOUT_MS = 300_000;\n\nexport function useCdecliChannel(\n isConnected: boolean,\n accountId: string,\n channelId: string | undefined,\n callbacks: CdecliChannelCallbacks,\n model?: string,\n skill?: string,\n) {\n const [sendMutation] = useGatewaySendMessageMutation();\n const cbRef = useRef(callbacks);\n cbRef.current = callbacks;\n\n const pendingRef = useRef<{ text: string; sentAt: number } | null>(null);\n const hasReceivedDeltasRef = useRef(false);\n const reconnectedStreamRef = useRef(false);\n const streamCompletedRef = useRef(false);\n const accumulatedLenRef = useRef(0);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const streamSkip = !channelId;\n const streamChannelId = channelId || accountId;\n\n useMessengerStreamDeltaSubscription({\n variables: { channelId: streamChannelId },\n skip: streamSkip,\n onData: ({ data }) => {\n const delta = data?.data?.messengerStreamDelta;\n if (!delta) return;\n\n if (delta.isFinal) return;\n\n if (streamCompletedRef.current) return;\n\n if (!pendingRef.current) {\n if (!reconnectedStreamRef.current) {\n reconnectedStreamRef.current = true;\n accumulatedLenRef.current = 0;\n }\n }\n\n hasReceivedDeltasRef.current = true;\n\n const fullText = stripModelCostHeader(delta.text ?? '');\n const newChunk = fullText.substring(accumulatedLenRef.current);\n accumulatedLenRef.current = fullText.length;\n\n if (newChunk) {\n cbRef.current.onChunk(newChunk);\n }\n },\n onError: (err) => {\n console.error('[useCdecliChannel] stream delta subscription error:', err);\n },\n });\n\n useGatewayInboundMessageByChannelSubscription({\n variables: { channelId: streamChannelId },\n skip: !isConnected || streamSkip,\n onData: ({ data }) => {\n const msg = data?.data?.gatewayInboundMessageByChannel;\n if (!msg?.text) return;\n const sanitizedText = stripModelCostHeader(msg.text);\n\n if (!hasReceivedDeltasRef.current) {\n cbRef.current.onChunk(sanitizedText);\n }\n\n cbRef.current.onComplete(sanitizedText);\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = true;\n accumulatedLenRef.current = 0;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n },\n onError: (err) => {\n console.error('[useCdecliChannel] subscription error:', err);\n cbRef.current.onError(err.message || 'CDeCLI subscription error');\n },\n });\n\n const sendMessage = useCallback(\n async (text: string, chatId = 'messenger'): Promise<boolean> => {\n if (!isConnected) return false;\n\n pendingRef.current = { text, sentAt: Date.now() };\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n ...(model || skill\n ? { metadata: { ...(model && { model }), ...(skill && { skill }) } }\n : {}),\n },\n },\n });\n\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI send failed';\n cbRef.current.onError(errMsg);\n pendingRef.current = null;\n return false;\n }\n\n timeoutRef.current = setTimeout(() => {\n if (pendingRef.current) {\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n timeoutRef.current = null;\n cbRef.current.onError(\n 'CDeCLI agent did not respond within 300 seconds. The query may still be processing.',\n );\n }\n }, CDECLI_RESPONSE_TIMEOUT_MS);\n\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n cbRef.current.onError(msg);\n pendingRef.current = null;\n return false;\n }\n },\n [isConnected, accountId, channelId, sendMutation, model, skill],\n );\n\n useEffect(\n () => () => {\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n },\n [],\n );\n\n /**\n * Inject a follow-up into the turn that is currently streaming.\n * Same `gatewaySendMessage` mutation with `metadata.steer = true` (browser\n * `useCdecliChannel.steer`). Do NOT reset streaming refs: the existing\n * delta subscription must keep running.\n *\n * \"Cannot steer: no active session\" is an expected race before cdecli has\n * started the turn. Callers should queue and retry; do not `console.error`\n * (that pops the RN LogBox and looks like a crash).\n */\n const steer = useCallback(\n async (text: string, chatId = 'messenger'): Promise<SteerResult> => {\n if (!isConnected) return { ok: false, error: 'CDeCLI is not connected.' };\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n metadata: { steer: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI steer failed';\n if (!isNoActiveSessionError(errMsg)) {\n console.warn('[useCdecliChannel] steer failed:', errMsg);\n }\n return { ok: false, error: errMsg };\n }\n return { ok: true };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn('[useCdecliChannel] steer mutation error:', msg);\n return { ok: false, error: msg };\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n /**\n * Abort the in-flight turn. `metadata.cancel = true` maps to\n * `POST /v1/chat/cancel` on cdecli-serve (browser parity).\n */\n const cancel = useCallback(\n async (chatId = 'messenger'): Promise<boolean> => {\n if (!isConnected) return false;\n pendingRef.current = null;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text: '',\n metadata: { cancel: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n console.error('[useCdecliChannel] cancel failed:', payload?.error || 'CDeCLI cancel failed');\n return false;\n }\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[useCdecliChannel] cancel mutation error:', msg);\n return false;\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n return { sendMessage, steer, cancel };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useCdecliChannel.js","sources":["../../src/hooks/useCdecliChannel.ts"],"sourcesContent":["/**\n * useCdecliChannel — wires the cdecli-serve messenger-gateway channel into the mobile chat UI.\n *\n * Kept in sync with `packages-modules/account/browser/src/hooks/useCdecliChannel.ts`.\n * When the CDeCLI channel is connected:\n * - `sendMessage(text)` calls `gatewaySendMessage`\n * - `MessengerStreamDelta` subscription delivers streaming chunks via `onChunk`\n * - `GatewayInboundMessageByChannel` delivers the final reply via `onComplete`\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport {\n useGatewaySendMessageMutation,\n useGatewayInboundMessageByChannelSubscription,\n useMessengerStreamDeltaSubscription,\n} from 'common/graphql';\n\nfunction stripModelCostHeader(content: string): string {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n return normalized.replace(\n /^\\s*(?:[^\\w\\n]+\\s*)?[a-z0-9][a-z0-9._-]*\\s*\\(\\s*\\$[\\d.]+\\s*\\/\\s*MTok\\s+in\\s*\\)\\s*\\n+/i,\n '',\n );\n}\n\n// `error?: undefined` on the success arm keeps `result.error` reachable on the\n// union: with strictNullChecks off (repo-wide), TS will not narrow the\n// discriminated union after an `if (result.ok) continue`.\nexport type SteerResult = { ok: true; error?: undefined } | { ok: false; error: string };\n\nexport interface CdecliChannelCallbacks {\n onChunk: (text: string) => void;\n onComplete: (text: string) => void;\n onError: (error: string) => void;\n}\n\nexport function isNoActiveSessionError(message: string): boolean {\n return /no active session/i.test(message);\n}\n\n/** Same 120s window as web — deep CDeCLI queries can exceed 45s. */\nconst CDECLI_RESPONSE_TIMEOUT_MS = 300_000;\n\nexport function useCdecliChannel(\n isConnected: boolean,\n accountId: string,\n channelId: string | undefined,\n callbacks: CdecliChannelCallbacks,\n model?: string,\n skill?: string,\n) {\n const [sendMutation] = useGatewaySendMessageMutation();\n const cbRef = useRef(callbacks);\n cbRef.current = callbacks;\n\n const pendingRef = useRef<{ text: string; sentAt: number } | null>(null);\n const hasReceivedDeltasRef = useRef(false);\n const reconnectedStreamRef = useRef(false);\n const streamCompletedRef = useRef(false);\n const accumulatedLenRef = useRef(0);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const streamSkip = !channelId;\n const streamChannelId = channelId || accountId;\n\n useMessengerStreamDeltaSubscription({\n variables: { channelId: streamChannelId },\n skip: streamSkip,\n onData: ({ data }) => {\n const delta = data?.data?.messengerStreamDelta;\n if (!delta) return;\n\n if (delta.isFinal) return;\n\n if (streamCompletedRef.current) return;\n\n if (!pendingRef.current) {\n if (!reconnectedStreamRef.current) {\n reconnectedStreamRef.current = true;\n accumulatedLenRef.current = 0;\n }\n }\n\n hasReceivedDeltasRef.current = true;\n\n const fullText = stripModelCostHeader(delta.text ?? '');\n const newChunk = fullText.substring(accumulatedLenRef.current);\n accumulatedLenRef.current = fullText.length;\n\n if (newChunk) {\n cbRef.current.onChunk(newChunk);\n }\n },\n onError: (err) => {\n console.error('[useCdecliChannel] stream delta subscription error:', err);\n },\n });\n\n useGatewayInboundMessageByChannelSubscription({\n variables: { channelId: streamChannelId },\n skip: !isConnected || streamSkip,\n onData: ({ data }) => {\n const msg = data?.data?.gatewayInboundMessageByChannel;\n if (!msg?.text) return;\n const sanitizedText = stripModelCostHeader(msg.text);\n\n if (!hasReceivedDeltasRef.current) {\n cbRef.current.onChunk(sanitizedText);\n }\n\n cbRef.current.onComplete(sanitizedText);\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = true;\n accumulatedLenRef.current = 0;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n },\n onError: (err) => {\n console.error('[useCdecliChannel] subscription error:', err);\n cbRef.current.onError(err.message || 'CDeCLI subscription error');\n },\n });\n\n const sendMessage = useCallback(\n async (text: string, chatId = 'messenger'): Promise<boolean> => {\n if (!isConnected) return false;\n\n pendingRef.current = { text, sentAt: Date.now() };\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n ...(model || skill\n ? { metadata: { ...(model && { model }), ...(skill && { skill }) } }\n : {}),\n },\n },\n });\n\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI send failed';\n cbRef.current.onError(errMsg);\n pendingRef.current = null;\n return false;\n }\n\n timeoutRef.current = setTimeout(() => {\n if (pendingRef.current) {\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n timeoutRef.current = null;\n cbRef.current.onError(\n 'CDeCLI agent did not respond within 300 seconds. The query may still be processing.',\n );\n }\n }, CDECLI_RESPONSE_TIMEOUT_MS);\n\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n cbRef.current.onError(msg);\n pendingRef.current = null;\n return false;\n }\n },\n [isConnected, accountId, channelId, sendMutation, model, skill],\n );\n\n useEffect(\n () => () => {\n pendingRef.current = null;\n hasReceivedDeltasRef.current = false;\n reconnectedStreamRef.current = false;\n streamCompletedRef.current = false;\n accumulatedLenRef.current = 0;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n },\n [],\n );\n\n /**\n * Inject a follow-up into the turn that is currently streaming.\n * Same `gatewaySendMessage` mutation with `metadata.steer = true` (browser\n * `useCdecliChannel.steer`). Do NOT reset streaming refs: the existing\n * delta subscription must keep running.\n *\n * \"Cannot steer: no active session\" is an expected race before cdecli has\n * started the turn. Callers should queue and retry; do not `console.error`\n * (that pops the RN LogBox and looks like a crash).\n */\n const steer = useCallback(\n async (text: string, chatId = 'messenger'): Promise<SteerResult> => {\n if (!isConnected) return { ok: false, error: 'CDeCLI is not connected.' };\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text,\n metadata: { steer: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n const errMsg = payload?.error || 'CDeCLI steer failed';\n if (!isNoActiveSessionError(errMsg)) {\n console.warn('[useCdecliChannel] steer failed:', errMsg);\n }\n return { ok: false, error: errMsg };\n }\n return { ok: true };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn('[useCdecliChannel] steer mutation error:', msg);\n return { ok: false, error: msg };\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n /**\n * Abort the in-flight turn. `metadata.cancel = true` maps to\n * `POST /v1/chat/cancel` on cdecli-serve (browser parity).\n */\n const cancel = useCallback(\n async (chatId = 'messenger'): Promise<boolean> => {\n if (!isConnected) return false;\n pendingRef.current = null;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n try {\n const result = await sendMutation({\n variables: {\n input: {\n channelType: 'cdecli-serve',\n accountId,\n chatId,\n text: '',\n metadata: { cancel: true },\n },\n },\n });\n const payload = result.data?.gatewaySendMessage;\n if (!payload?.success) {\n console.error('[useCdecliChannel] cancel failed:', payload?.error || 'CDeCLI cancel failed');\n return false;\n }\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[useCdecliChannel] cancel mutation error:', msg);\n return false;\n }\n },\n [isConnected, accountId, sendMutation],\n );\n\n return { sendMessage, steer, cancel };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAYA,SAAS,qBAAqB,OAAyB,EAAA;AACrD,EAAA,MAAM,UAAa,GAAA,OAAA,CAAQ,OAAQ,CAAA,OAAA,EAAS,IAAI,CAAA;AAChD,EAAO,OAAA,UAAA,CAAW,OAAQ,CAAA,uFAAA,EAAyF,EAAE,CAAA;AACvH;AAiBO,SAAS,uBAAuB,OAA0B,EAAA;AAC/D,EAAO,OAAA,oBAAA,CAAqB,KAAK,OAAO,CAAA;AAC1C;AAGA,MAAM,0BAA6B,GAAA,GAAA;AAC5B,SAAS,iBAAiB,WAAsB,EAAA,SAAA,EAAmB,SAA+B,EAAA,SAAA,EAAmC,OAAgB,KAAgB,EAAA;AAC1K,EAAM,MAAA,CAAC,YAAY,CAAA,GAAI,6BAA8B,EAAA;AACrD,EAAM,MAAA,KAAA,GAAQ,OAAO,SAAS,CAAA;AAC9B,EAAA,KAAA,CAAM,OAAU,GAAA,SAAA;AAChB,EAAM,MAAA,UAAA,GAAa,OAGT,IAAI,CAAA;AACd,EAAM,MAAA,oBAAA,GAAuB,OAAO,KAAK,CAAA;AACzC,EAAM,MAAA,oBAAA,GAAuB,OAAO,KAAK,CAAA;AACzC,EAAM,MAAA,kBAAA,GAAqB,OAAO,KAAK,CAAA;AACvC,EAAM,MAAA,iBAAA,GAAoB,OAAO,CAAC,CAAA;AAClC,EAAM,MAAA,UAAA,GAAa,OAA6C,IAAI,CAAA;AACpE,EAAA,MAAM,aAAa,CAAC,SAAA;AACpB,EAAA,MAAM,kBAAkB,SAAa,IAAA,SAAA;AACrC,EAAoC,mCAAA,CAAA;AAAA,IAClC,SAAW,EAAA;AAAA,MACT,SAAW,EAAA;AAAA,KACb;AAAA,IACA,IAAM,EAAA,UAAA;AAAA,IACN,QAAQ,CAAC;AAAA,MACP;AAAA,KACI,KAAA;AA5DV,MAAA,IAAA,EAAA,EAAA,EAAA;AA6DM,MAAM,MAAA,KAAA,GAAA,CAAQ,EAAM,GAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,IAAA,KAAN,IAAY,GAAA,MAAA,GAAA,EAAA,CAAA,oBAAA;AAC1B,MAAA,IAAI,CAAC,KAAO,EAAA;AACZ,MAAA,IAAI,MAAM,OAAS,EAAA;AACnB,MAAA,IAAI,mBAAmB,OAAS,EAAA;AAChC,MAAI,IAAA,CAAC,WAAW,OAAS,EAAA;AACvB,QAAI,IAAA,CAAC,qBAAqB,OAAS,EAAA;AACjC,UAAA,oBAAA,CAAqB,OAAU,GAAA,IAAA;AAC/B,UAAA,iBAAA,CAAkB,OAAU,GAAA,CAAA;AAAA;AAC9B;AAEF,MAAA,oBAAA,CAAqB,OAAU,GAAA,IAAA;AAC/B,MAAA,MAAM,QAAW,GAAA,oBAAA,CAAA,CAAqB,EAAM,GAAA,KAAA,CAAA,IAAA,KAAN,YAAc,EAAE,CAAA;AACtD,MAAA,MAAM,QAAW,GAAA,QAAA,CAAS,SAAU,CAAA,iBAAA,CAAkB,OAAO,CAAA;AAC7D,MAAA,iBAAA,CAAkB,UAAU,QAAS,CAAA,MAAA;AACrC,MAAA,IAAI,QAAU,EAAA;AACZ,QAAM,KAAA,CAAA,OAAA,CAAQ,QAAQ,QAAQ,CAAA;AAAA;AAChC,KACF;AAAA,IACA,SAAS,CAAO,GAAA,KAAA;AACd,MAAQ,OAAA,CAAA,KAAA,CAAM,uDAAuD,GAAG,CAAA;AAAA;AAC1E,GACD,CAAA;AACD,EAA8C,6CAAA,CAAA;AAAA,IAC5C,SAAW,EAAA;AAAA,MACT,SAAW,EAAA;AAAA,KACb;AAAA,IACA,IAAA,EAAM,CAAC,WAAe,IAAA,UAAA;AAAA,IACtB,QAAQ,CAAC;AAAA,MACP;AAAA,KACI,KAAA;AA1FV,MAAA,IAAA,EAAA;AA2FM,MAAM,MAAA,GAAA,GAAA,CAAM,EAAM,GAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,IAAA,KAAN,IAAY,GAAA,MAAA,GAAA,EAAA,CAAA,8BAAA;AACxB,MAAI,IAAA,EAAC,2BAAK,IAAM,CAAA,EAAA;AAChB,MAAM,MAAA,aAAA,GAAgB,oBAAqB,CAAA,GAAA,CAAI,IAAI,CAAA;AACnD,MAAI,IAAA,CAAC,qBAAqB,OAAS,EAAA;AACjC,QAAM,KAAA,CAAA,OAAA,CAAQ,QAAQ,aAAa,CAAA;AAAA;AAErC,MAAM,KAAA,CAAA,OAAA,CAAQ,WAAW,aAAa,CAAA;AACtC,MAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,MAAA,oBAAA,CAAqB,OAAU,GAAA,KAAA;AAC/B,MAAA,oBAAA,CAAqB,OAAU,GAAA,KAAA;AAC/B,MAAA,kBAAA,CAAmB,OAAU,GAAA,IAAA;AAC7B,MAAA,iBAAA,CAAkB,OAAU,GAAA,CAAA;AAC5B,MAAA,IAAI,WAAW,OAAS,EAAA;AACtB,QAAA,YAAA,CAAa,WAAW,OAAO,CAAA;AAC/B,QAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AAAA;AACvB,KACF;AAAA,IACA,SAAS,CAAO,GAAA,KAAA;AACd,MAAQ,OAAA,CAAA,KAAA,CAAM,0CAA0C,GAAG,CAAA;AAC3D,MAAA,KAAA,CAAM,OAAQ,CAAA,OAAA,CAAQ,GAAI,CAAA,OAAA,IAAW,2BAA2B,CAAA;AAAA;AAClE,GACD,CAAA;AACD,EAAA,MAAM,WAAc,GAAA,WAAA,CAAY,OAAO,IAAA,EAAc,SAAS,WAAkC,KAAA;AAjHlG,IAAA,IAAA,EAAA;AAkHI,IAAI,IAAA,CAAC,aAAoB,OAAA,KAAA;AACzB,IAAA,UAAA,CAAW,OAAU,GAAA;AAAA,MACnB,IAAA;AAAA,MACA,MAAA,EAAQ,KAAK,GAAI;AAAA,KACnB;AACA,IAAA,oBAAA,CAAqB,OAAU,GAAA,KAAA;AAC/B,IAAA,oBAAA,CAAqB,OAAU,GAAA,KAAA;AAC/B,IAAA,kBAAA,CAAmB,OAAU,GAAA,KAAA;AAC7B,IAAA,iBAAA,CAAkB,OAAU,GAAA,CAAA;AAC5B,IAAI,IAAA;AACF,MAAM,MAAA,MAAA,GAAS,MAAM,YAAa,CAAA;AAAA,QAChC,SAAW,EAAA;AAAA,UACT,KAAO,EAAA,cAAA,CAAA;AAAA,YACL,WAAa,EAAA,cAAA;AAAA,YACb,SAAA;AAAA,YACA,MAAA;AAAA,YACA;AAAA,WAAA,EACI,SAAS,KAAQ,GAAA;AAAA,YACnB,QAAA,EAAU,kCACJ,KAAS,IAAA;AAAA,cACX;AAAA,gBAEE,KAAS,IAAA;AAAA,cACX;AAAA,aACF;AAAA,cAEA,EAAC;AAAA;AAET,OACD,CAAA;AACD,MAAM,MAAA,OAAA,GAAA,CAAU,EAAO,GAAA,MAAA,CAAA,IAAA,KAAP,IAAa,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,kBAAA;AAC7B,MAAI,IAAA,EAAC,mCAAS,OAAS,CAAA,EAAA;AACrB,QAAM,MAAA,MAAA,GAAA,CAAS,mCAAS,KAAS,KAAA,oBAAA;AACjC,QAAM,KAAA,CAAA,OAAA,CAAQ,QAAQ,MAAM,CAAA;AAC5B,QAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,QAAO,OAAA,KAAA;AAAA;AAET,MAAW,UAAA,CAAA,OAAA,GAAU,WAAW,MAAM;AACpC,QAAA,IAAI,WAAW,OAAS,EAAA;AACtB,UAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,UAAA,oBAAA,CAAqB,OAAU,GAAA,KAAA;AAC/B,UAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,UAAM,KAAA,CAAA,OAAA,CAAQ,QAAQ,qFAAqF,CAAA;AAAA;AAC7G,SACC,0BAA0B,CAAA;AAC7B,MAAO,OAAA,IAAA;AAAA,aACA,GAAK,EAAA;AACZ,MAAA,MAAM,MAAM,GAAe,YAAA,KAAA,GAAQ,GAAI,CAAA,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAM,KAAA,CAAA,OAAA,CAAQ,QAAQ,GAAG,CAAA;AACzB,MAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,MAAO,OAAA,KAAA;AAAA;AACT,GACF,EAAG,CAAC,WAAa,EAAA,SAAA,EAAW,WAAW,YAAc,EAAA,KAAA,EAAO,KAAK,CAAC,CAAA;AAClE,EAAA,SAAA,CAAU,MAAM,MAAM;AACpB,IAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,IAAA,oBAAA,CAAqB,OAAU,GAAA,KAAA;AAC/B,IAAA,oBAAA,CAAqB,OAAU,GAAA,KAAA;AAC/B,IAAA,kBAAA,CAAmB,OAAU,GAAA,KAAA;AAC7B,IAAA,iBAAA,CAAkB,OAAU,GAAA,CAAA;AAC5B,IAAA,IAAI,WAAW,OAAS,EAAA;AACtB,MAAA,YAAA,CAAa,WAAW,OAAO,CAAA;AAC/B,MAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AAAA;AACvB,GACF,EAAG,EAAE,CAAA;AAYL,EAAA,MAAM,KAAQ,GAAA,WAAA,CAAY,OAAO,IAAA,EAAc,SAAS,WAAsC,KAAA;AA7LhG,IAAA,IAAA,EAAA;AA8LI,IAAI,IAAA,CAAC,aAAoB,OAAA;AAAA,MACvB,EAAI,EAAA,KAAA;AAAA,MACJ,KAAO,EAAA;AAAA,KACT;AACA,IAAI,IAAA;AACF,MAAM,MAAA,MAAA,GAAS,MAAM,YAAa,CAAA;AAAA,QAChC,SAAW,EAAA;AAAA,UACT,KAAO,EAAA;AAAA,YACL,WAAa,EAAA,cAAA;AAAA,YACb,SAAA;AAAA,YACA,MAAA;AAAA,YACA,IAAA;AAAA,YACA,QAAU,EAAA;AAAA,cACR,KAAO,EAAA;AAAA;AACT;AACF;AACF,OACD,CAAA;AACD,MAAM,MAAA,OAAA,GAAA,CAAU,EAAO,GAAA,MAAA,CAAA,IAAA,KAAP,IAAa,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,kBAAA;AAC7B,MAAI,IAAA,EAAC,mCAAS,OAAS,CAAA,EAAA;AACrB,QAAM,MAAA,MAAA,GAAA,CAAS,mCAAS,KAAS,KAAA,qBAAA;AACjC,QAAI,IAAA,CAAC,sBAAuB,CAAA,MAAM,CAAG,EAAA;AACnC,UAAQ,OAAA,CAAA,IAAA,CAAK,oCAAoC,MAAM,CAAA;AAAA;AAEzD,QAAO,OAAA;AAAA,UACL,EAAI,EAAA,KAAA;AAAA,UACJ,KAAO,EAAA;AAAA,SACT;AAAA;AAEF,MAAO,OAAA;AAAA,QACL,EAAI,EAAA;AAAA,OACN;AAAA,aACO,GAAK,EAAA;AACZ,MAAA,MAAM,MAAM,GAAe,YAAA,KAAA,GAAQ,GAAI,CAAA,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAQ,OAAA,CAAA,IAAA,CAAK,4CAA4C,GAAG,CAAA;AAC5D,MAAO,OAAA;AAAA,QACL,EAAI,EAAA,KAAA;AAAA,QACJ,KAAO,EAAA;AAAA,OACT;AAAA;AACF,GACC,EAAA,CAAC,WAAa,EAAA,SAAA,EAAW,YAAY,CAAC,CAAA;AAMzC,EAAA,MAAM,MAAS,GAAA,WAAA,CAAY,OAAO,MAAA,GAAS,WAAkC,KAAA;AA5O/E,IAAA,IAAA,EAAA;AA6OI,IAAI,IAAA,CAAC,aAAoB,OAAA,KAAA;AACzB,IAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,IAAA,IAAI,WAAW,OAAS,EAAA;AACtB,MAAA,YAAA,CAAa,WAAW,OAAO,CAAA;AAC/B,MAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AAAA;AAEvB,IAAI,IAAA;AACF,MAAM,MAAA,MAAA,GAAS,MAAM,YAAa,CAAA;AAAA,QAChC,SAAW,EAAA;AAAA,UACT,KAAO,EAAA;AAAA,YACL,WAAa,EAAA,cAAA;AAAA,YACb,SAAA;AAAA,YACA,MAAA;AAAA,YACA,IAAM,EAAA,EAAA;AAAA,YACN,QAAU,EAAA;AAAA,cACR,MAAQ,EAAA;AAAA;AACV;AACF;AACF,OACD,CAAA;AACD,MAAM,MAAA,OAAA,GAAA,CAAU,EAAO,GAAA,MAAA,CAAA,IAAA,KAAP,IAAa,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,kBAAA;AAC7B,MAAI,IAAA,EAAC,mCAAS,OAAS,CAAA,EAAA;AACrB,QAAA,OAAA,CAAQ,KAAM,CAAA,mCAAA,EAAA,CAAqC,OAAS,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAA,KAAA,KAAS,sBAAsB,CAAA;AAC3F,QAAO,OAAA,KAAA;AAAA;AAET,MAAO,OAAA,IAAA;AAAA,aACA,GAAK,EAAA;AACZ,MAAA,MAAM,MAAM,GAAe,YAAA,KAAA,GAAQ,GAAI,CAAA,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAQ,OAAA,CAAA,KAAA,CAAM,6CAA6C,GAAG,CAAA;AAC9D,MAAO,OAAA,KAAA;AAAA;AACT,GACC,EAAA,CAAC,WAAa,EAAA,SAAA,EAAW,YAAY,CAAC,CAAA;AACzC,EAAO,OAAA;AAAA,IACL,WAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AACF"}
@@ -1,13 +1,33 @@
1
- import {useState,useEffect}from'react';import {Platform,Keyboard}from'react-native';function useKeyboardBottomOffset() {
1
+ import {useState,useEffect}from'react';import {Platform,Keyboard,LayoutAnimation}from'react-native';function syncNextLayoutToKeyboard(event) {
2
+ if (Platform.OS !== "ios") return;
3
+ const duration = (event == null ? void 0 : event.duration) && event.duration > 0 ? event.duration : 250;
4
+ LayoutAnimation.configureNext({
5
+ duration,
6
+ create: {
7
+ type: LayoutAnimation.Types.keyboard,
8
+ property: LayoutAnimation.Properties.opacity
9
+ },
10
+ update: {
11
+ type: LayoutAnimation.Types.keyboard
12
+ },
13
+ delete: {
14
+ type: LayoutAnimation.Types.keyboard,
15
+ property: LayoutAnimation.Properties.opacity
16
+ }
17
+ });
18
+ }
19
+ function useKeyboardBottomOffset() {
2
20
  const [keyboardHeight, setKeyboardHeight] = useState(0);
3
21
  useEffect(() => {
4
22
  const showEvent = Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow";
5
23
  const hideEvent = Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide";
6
24
  const show = Keyboard.addListener(showEvent, (event) => {
7
25
  var _a, _b;
26
+ syncNextLayoutToKeyboard(event);
8
27
  setKeyboardHeight((_b = (_a = event.endCoordinates) == null ? void 0 : _a.height) != null ? _b : 0);
9
28
  });
10
- const hide = Keyboard.addListener(hideEvent, () => {
29
+ const hide = Keyboard.addListener(hideEvent, (event) => {
30
+ syncNextLayoutToKeyboard(event);
11
31
  setKeyboardHeight(0);
12
32
  });
13
33
  return () => {
@@ -1 +1 @@
1
- {"version":3,"file":"useKeyboardBottomOffset.js","sources":["../../src/hooks/useKeyboardBottomOffset.ts"],"sourcesContent":["/**\n * Keyboard visibility for compacting chrome (suggestions, template peeks).\n * Composer lift is handled by KeyboardComposerDock, not this hook.\n */\nimport { useEffect, useState } from 'react';\nimport { Keyboard, Platform } from 'react-native';\n\nexport type KeyboardBottomOffset = {\n keyboardHeight: number;\n keyboardVisible: boolean;\n};\n\nexport function useKeyboardBottomOffset(): KeyboardBottomOffset {\n const [keyboardHeight, setKeyboardHeight] = useState(0);\n\n useEffect(() => {\n const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';\n const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';\n\n const show = Keyboard.addListener(showEvent, (event) => {\n setKeyboardHeight(event.endCoordinates?.height ?? 0);\n });\n const hide = Keyboard.addListener(hideEvent, () => {\n setKeyboardHeight(0);\n });\n\n return () => {\n show.remove();\n hide.remove();\n };\n }, []);\n\n return {\n keyboardHeight,\n keyboardVisible: keyboardHeight > 0,\n };\n}\n"],"names":[],"mappings":"oFAUO,SAAS,uBAAgD,GAAA;AAC9D,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAAS,CAAC,CAAA;AACtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,SAAY,GAAA,QAAA,CAAS,EAAO,KAAA,KAAA,GAAQ,kBAAqB,GAAA,iBAAA;AAC/D,IAAA,MAAM,SAAY,GAAA,QAAA,CAAS,EAAO,KAAA,KAAA,GAAQ,kBAAqB,GAAA,iBAAA;AAC/D,IAAA,MAAM,IAAO,GAAA,QAAA,CAAS,WAAY,CAAA,SAAA,EAAW,CAAS,KAAA,KAAA;AAf1D,MAAA,IAAA,EAAA,EAAA,EAAA;AAgBM,MAAA,iBAAA,CAAA,CAAkB,EAAM,GAAA,CAAA,EAAA,GAAA,KAAA,CAAA,cAAA,KAAN,IAAsB,GAAA,MAAA,GAAA,EAAA,CAAA,MAAA,KAAtB,YAAgC,CAAC,CAAA;AAAA,KACpD,CAAA;AACD,IAAA,MAAM,IAAO,GAAA,QAAA,CAAS,WAAY,CAAA,SAAA,EAAW,MAAM;AACjD,MAAA,iBAAA,CAAkB,CAAC,CAAA;AAAA,KACpB,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,MAAO,EAAA;AACZ,MAAA,IAAA,CAAK,MAAO,EAAA;AAAA,KACd;AAAA,GACF,EAAG,EAAE,CAAA;AACL,EAAO,OAAA;AAAA,IACL,cAAA;AAAA,IACA,iBAAiB,cAAiB,GAAA;AAAA,GACpC;AACF"}
1
+ {"version":3,"file":"useKeyboardBottomOffset.js","sources":["../../src/hooks/useKeyboardBottomOffset.ts"],"sourcesContent":["/**\n * Keyboard visibility for compacting chrome (suggestions, template peeks).\n * Composer lift is handled by KeyboardComposerDock, not this hook.\n */\nimport { useEffect, useState } from 'react';\nimport { Keyboard, LayoutAnimation, Platform, type KeyboardEvent } from 'react-native';\n\nexport type KeyboardBottomOffset = {\n keyboardHeight: number;\n keyboardVisible: boolean;\n};\n\n/**\n * Animate the NEXT layout pass with the keyboard's own duration and curve, so\n * everything laid out off this hook (list padding, compacted chrome) glides in\n * sync with the keyboard instead of snapping. iOS supplies duration/easing on\n * the event; Android's softwareKeyboardLayoutMode=\"resize\" already animates\n * the window resize itself.\n */\nfunction syncNextLayoutToKeyboard(event: KeyboardEvent) {\n if (Platform.OS !== 'ios') return;\n const duration = event?.duration && event.duration > 0 ? event.duration : 250;\n LayoutAnimation.configureNext({\n duration,\n create: { type: LayoutAnimation.Types.keyboard, property: LayoutAnimation.Properties.opacity },\n update: { type: LayoutAnimation.Types.keyboard },\n delete: { type: LayoutAnimation.Types.keyboard, property: LayoutAnimation.Properties.opacity },\n });\n}\n\nexport function useKeyboardBottomOffset(): KeyboardBottomOffset {\n const [keyboardHeight, setKeyboardHeight] = useState(0);\n\n useEffect(() => {\n const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';\n const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';\n\n const show = Keyboard.addListener(showEvent, (event) => {\n syncNextLayoutToKeyboard(event);\n setKeyboardHeight(event.endCoordinates?.height ?? 0);\n });\n const hide = Keyboard.addListener(hideEvent, (event) => {\n syncNextLayoutToKeyboard(event);\n setKeyboardHeight(0);\n });\n\n return () => {\n show.remove();\n hide.remove();\n };\n }, []);\n\n return {\n keyboardHeight,\n keyboardVisible: keyboardHeight > 0,\n };\n}\n"],"names":[],"mappings":"oGAkBA,SAAS,yBAAyB,KAAsB,EAAA;AACtD,EAAI,IAAA,QAAA,CAAS,OAAO,KAAO,EAAA;AAC3B,EAAA,MAAM,YAAW,KAAO,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,QAAA,KAAY,MAAM,QAAW,GAAA,CAAA,GAAI,MAAM,QAAW,GAAA,GAAA;AAC1E,EAAA,eAAA,CAAgB,aAAc,CAAA;AAAA,IAC5B,QAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,IAAA,EAAM,gBAAgB,KAAM,CAAA,QAAA;AAAA,MAC5B,QAAA,EAAU,gBAAgB,UAAW,CAAA;AAAA,KACvC;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,IAAA,EAAM,gBAAgB,KAAM,CAAA;AAAA,KAC9B;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,IAAA,EAAM,gBAAgB,KAAM,CAAA,QAAA;AAAA,MAC5B,QAAA,EAAU,gBAAgB,UAAW,CAAA;AAAA;AACvC,GACD,CAAA;AACH;AACO,SAAS,uBAAgD,GAAA;AAC9D,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAAS,CAAC,CAAA;AACtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,SAAY,GAAA,QAAA,CAAS,EAAO,KAAA,KAAA,GAAQ,kBAAqB,GAAA,iBAAA;AAC/D,IAAA,MAAM,SAAY,GAAA,QAAA,CAAS,EAAO,KAAA,KAAA,GAAQ,kBAAqB,GAAA,iBAAA;AAC/D,IAAA,MAAM,IAAO,GAAA,QAAA,CAAS,WAAY,CAAA,SAAA,EAAW,CAAS,KAAA,KAAA;AAzC1D,MAAA,IAAA,EAAA,EAAA,EAAA;AA0CM,MAAA,wBAAA,CAAyB,KAAK,CAAA;AAC9B,MAAA,iBAAA,CAAA,CAAkB,EAAM,GAAA,CAAA,EAAA,GAAA,KAAA,CAAA,cAAA,KAAN,IAAsB,GAAA,MAAA,GAAA,EAAA,CAAA,MAAA,KAAtB,YAAgC,CAAC,CAAA;AAAA,KACpD,CAAA;AACD,IAAA,MAAM,IAAO,GAAA,QAAA,CAAS,WAAY,CAAA,SAAA,EAAW,CAAS,KAAA,KAAA;AACpD,MAAA,wBAAA,CAAyB,KAAK,CAAA;AAC9B,MAAA,iBAAA,CAAkB,CAAC,CAAA;AAAA,KACpB,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,MAAO,EAAA;AACZ,MAAA,IAAA,CAAK,MAAO,EAAA;AAAA,KACd;AAAA,GACF,EAAG,EAAE,CAAA;AACL,EAAO,OAAA;AAAA,IACL,cAAA;AAAA,IACA,iBAAiB,cAAiB,GAAA;AAAA,GACpC;AACF"}
@@ -162,6 +162,8 @@ function usePrerequisiteIds() {
162
162
  if (!accountSettingsUri) return;
163
163
  await writeSettings({
164
164
  variables: {
165
+ // The URI scalar's TS type is the vscode URI class, but the wire
166
+ // format is this serializable POJO (same shape toUriInput emits).
165
167
  editingUri: accountSettingsUri,
166
168
  settings: {
167
169
  "account.default.organization": orgToSet,
@@ -1 +1 @@
1
- {"version":3,"file":"usePrerequisiteIds.js","sources":["../../src/hooks/usePrerequisiteIds.ts"],"sourcesContent":["import { DEFAULT_PRODUCTION_TAG_ID } from '@adminide-stack/core/lib/constants/defaultIds.js';\nimport { useContextData } from '@adminide-stack/platform-client/lib/hooks/useContextData.js';\nimport {\n orgChangeAction,\n resourceGroupChangeAction,\n} from '@adminide-stack/platform-client/lib/redux/actions/org-action.js';\nimport { isAuthenticatedSelector } from '@adminide-stack/user-auth0-client';\nimport { ConfigurationTarget, ContributionSchemaId } from 'common';\nimport {\n useAccountProfileQuery,\n useCreateVaultMutation,\n useGetProjectsLazyQuery,\n useGetUserOrganizationsQuery,\n useGetUserOrganizationsWithDetailsQuery,\n useQuickCreateProjectForAccountBkMutation,\n useWriteSettingsMutation,\n} from 'common/graphql';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useDispatch, useSelector } from 'react-redux';\nimport { useAccountDefaultSettings } from './useAccountDefaultSettings';\nimport { isUnhydratedCdecodeUri, settingsUriForAccount, toUriInput } from '../utils/cdecodeUri';\n\nconst uuidToObjectId = (uuid: string) => uuid.replace(/-/g, '').substring(0, 24);\n\nconst PROJECT_NAME = 'DEFAULT_YANTRA_PROJECT';\nconst TAG_ID = uuidToObjectId(DEFAULT_PRODUCTION_TAG_ID);\n/** SystemContributionExtensionNames.Account — owns `account.default.*`. */\nconst ACCOUNT_EXTENSION = 'account';\n\n/**\n * DEV ONLY — known working project UUID for local mobile bootstrap when create/list\n * cannot resolve `projectId`. Never use on staging/prod: createSecretApiToken needs a\n * real project that resolves to a Mongo ObjectId (unknown UUID → ObjectId cast 400).\n */\nconst TESTING_PROJECT_UUID = '9a8ac704-1040-4836-9b72-48b771ca91b1';\n\nconst ORG_RESOLVE_POLL_MS = 2000;\nconst PROFILE_POLL_MS = 1500;\n\n// ── Module-level project fix (parity with browser) ───────────────────────────\n// Several screens/hooks mount `usePrerequisiteIds` at once. Per-instance refs race\n// and can create multiple orphan projects. Keep a single-flight guard + user id so\n// adopt/create/persist runs once per account session.\n// Resolved project must also be shared — otherwise WebBuilderPrewarm can \"win\" the\n// flight and HomeScreen never sees projectId (submit stuck on \"not ready\").\nlet projectFixInFlight = false;\nlet projectFixUserId: string | null = null;\nlet sharedResolvedProjectId: string | null = null;\nconst sharedProjectListeners = new Set<() => void>();\n\nfunction publishSharedResolvedProjectId(projectUuid: string): void {\n sharedResolvedProjectId = projectUuid;\n sharedProjectListeners.forEach((listener) => listener());\n}\n\nfunction pickDefaultOrgSlug(\n orgs: Array<{ name?: string | null; title?: string | null } | null | undefined> | null | undefined,\n): string | null {\n if (!orgs?.length) return null;\n const first = orgs.find((o) => typeof o?.name === 'string' && o.name.trim().length > 0);\n return first?.name?.trim() ?? null;\n}\n\n/**\n * Org + project prerequisites for mobile (parity with browser `usePrerequisiteIds`).\n *\n * Settings use the same `account.default` config as web (`useSettingsLoader` → `useSettings` on mobile).\n * After verify-user, account-level settings (`//accounts/{id}#settings`) and org membership are polled\n * until `organization` is available, then route context is synced on Home.\n *\n * Scenario: org set but no `account.default.project` → adopt an existing project in the org\n * (or create one), persist settings, and bind resourceGroup — same as browser Scenario 2.\n */\nexport function usePrerequisiteIds() {\n const dispatch = useDispatch();\n const isAuthenticated = useSelector(isAuthenticatedSelector);\n\n const { data: contextData, complete: contextComplete } = useContextData();\n const contextLoading = !contextComplete;\n const cdecodeUri = contextData?.cdecodeUri;\n const contextUserId = contextData?.userId ?? null;\n\n const contextResourceUri = useMemo(() => {\n if (isUnhydratedCdecodeUri(cdecodeUri)) return undefined;\n return toUriInput(cdecodeUri);\n }, [cdecodeUri]);\n\n const {\n data: accountProfileData,\n loading: userLoading,\n refetch: refetchProfile,\n } = useAccountProfileQuery({\n fetchPolicy: 'cache-and-network',\n errorPolicy: 'all',\n skip: !isAuthenticated,\n });\n const profileUserId = accountProfileData?.accountProfile?.user?.id ?? null;\n const effectiveUserId = isAuthenticated ? profileUserId || contextUserId : null;\n\n useEffect(() => {\n if (!isAuthenticated || profileUserId) return;\n const timer = setInterval(() => {\n refetchProfile().catch(() => undefined);\n }, PROFILE_POLL_MS);\n return () => clearInterval(timer);\n }, [isAuthenticated, profileUserId, refetchProfile]);\n\n // Step 1 (web): account.default via settings loader — context cdecodeUri when hydrated\n const {\n organization: orgFromContextSettings,\n project: projectFromContextSettings,\n loading: contextSettingsLoading,\n refetch: refetchContextSettings,\n } = useAccountDefaultSettings({\n resourceUri: contextResourceUri,\n skip: !isAuthenticated || !contextResourceUri,\n });\n\n const accountResourceUri = useMemo(() => {\n if (!effectiveUserId || orgFromContextSettings) return undefined;\n return settingsUriForAccount(effectiveUserId);\n }, [effectiveUserId, orgFromContextSettings]);\n\n // Mobile bootstrap: read account.default from account document before org is on the route\n const {\n organization: orgFromAccountSettings,\n project: projectFromAccountSettings,\n loading: accountSettingsLoading,\n refetch: refetchAccountSettings,\n } = useAccountDefaultSettings({\n resourceUri: accountResourceUri,\n skip: !isAuthenticated || !accountResourceUri,\n });\n\n const {\n data: orgsData,\n loading: orgsLoading,\n refetch: refetchOrgs,\n } = useGetUserOrganizationsWithDetailsQuery({\n skip: !isAuthenticated || !effectiveUserId,\n fetchPolicy: 'cache-and-network',\n });\n\n const {\n data: orgsByUserData,\n loading: orgsByUserLoading,\n refetch: refetchOrgsByUser,\n } = useGetUserOrganizationsQuery({\n variables: { userId: effectiveUserId ?? undefined },\n skip: !isAuthenticated || !effectiveUserId,\n fetchPolicy: 'cache-and-network',\n });\n\n const orgFromMembership = useMemo(() => {\n const fromDetails = pickDefaultOrgSlug(orgsData?.getUserOrganizationsWithDetails);\n if (fromDetails) return fromDetails;\n return pickDefaultOrgSlug(orgsByUserData?.getUserOrganizations);\n }, [orgsData, orgsByUserData]);\n\n const orgFromContextPath = useMemo(() => {\n if (isUnhydratedCdecodeUri(cdecodeUri)) return null;\n const { path } = toUriInput(cdecodeUri);\n const match = path.match(/^\\/([^/]+)\\//);\n return match?.[1]?.trim() || null;\n }, [cdecodeUri]);\n\n const orgName = orgFromContextSettings || orgFromAccountSettings || orgFromMembership || orgFromContextPath || null;\n\n const rawSettingsProjectIdRaw = projectFromContextSettings || projectFromAccountSettings || null;\n // Staging may have persisted the local testing UUID; treat it as unset so bootstrap can mint a real project.\n const rawSettingsProjectId =\n !__DEV__ && rawSettingsProjectIdRaw === TESTING_PROJECT_UUID ? null : rawSettingsProjectIdRaw;\n\n useEffect(() => {\n if (!isAuthenticated || orgName || !effectiveUserId) return;\n const timer = setInterval(() => {\n refetchContextSettings?.()?.catch(() => undefined);\n refetchAccountSettings?.()?.catch(() => undefined);\n refetchOrgs().catch(() => undefined);\n refetchOrgsByUser().catch(() => undefined);\n }, ORG_RESOLVE_POLL_MS);\n return () => clearInterval(timer);\n }, [\n isAuthenticated,\n orgName,\n effectiveUserId,\n refetchContextSettings,\n refetchAccountSettings,\n refetchOrgs,\n refetchOrgsByUser,\n ]);\n\n const settingsProjectId = rawSettingsProjectId;\n\n const [resolvedProjectId, setResolvedProjectId] = useState<string | null>(() => sharedResolvedProjectId);\n const [isInitializingProject, setIsInitializingProject] = useState(false);\n\n // Cross-instance sync: when another hook wins the project bootstrap, adopt it.\n useEffect(() => {\n const onShared = () => {\n if (sharedResolvedProjectId) setResolvedProjectId(sharedResolvedProjectId);\n };\n sharedProjectListeners.add(onShared);\n onShared();\n return () => {\n sharedProjectListeners.delete(onShared);\n };\n }, []);\n\n // New account session → clear shared fallback so we don't leak another user's project.\n useEffect(() => {\n if (!effectiveUserId) return;\n if (projectFixUserId && projectFixUserId !== effectiveUserId) {\n sharedResolvedProjectId = null;\n projectFixInFlight = false;\n setResolvedProjectId(null);\n }\n }, [effectiveUserId]);\n\n const projectId = settingsProjectId || resolvedProjectId || sharedResolvedProjectId;\n const settingsLoading = contextSettingsLoading || accountSettingsLoading;\n // Wait for settings to settle so we don't create before an existing default loads.\n const needsProjectCreation = !settingsLoading && !!orgName && !rawSettingsProjectId && !projectId;\n\n const [fetchProjects] = useGetProjectsLazyQuery();\n const [createProject, { error: createError, loading: projectCreating }] =\n useQuickCreateProjectForAccountBkMutation();\n const [createVault, { error: vaultCreateError }] = useCreateVaultMutation();\n const [writeSettings] = useWriteSettingsMutation();\n\n const accountSettingsUri = useMemo(() => {\n if (!effectiveUserId) return null;\n return settingsUriForAccount(effectiveUserId);\n }, [effectiveUserId]);\n\n const persistDefaults = useCallback(\n async (orgToSet: string, projectUuid: string) => {\n if (!accountSettingsUri) return;\n await writeSettings({\n variables: {\n editingUri: accountSettingsUri,\n settings: {\n 'account.default.organization': orgToSet,\n 'account.default.project': projectUuid,\n },\n target: ConfigurationTarget.USER,\n schemaId: ContributionSchemaId.Configuration,\n extensionName: ACCOUNT_EXTENSION,\n },\n });\n },\n [accountSettingsUri, writeSettings],\n );\n\n const refetchDefaults = useCallback(async () => {\n await Promise.all([\n refetchContextSettings?.()?.catch(() => undefined) ?? Promise.resolve(),\n refetchAccountSettings?.()?.catch(() => undefined) ?? Promise.resolve(),\n ]);\n }, [refetchContextSettings, refetchAccountSettings]);\n\n // Scenario 2: default org present but no project → adopt existing (or create once),\n // then persist so reload / other mounts do not create orphan projects.\n useEffect(() => {\n if (!needsProjectCreation || !effectiveUserId || userLoading || !orgName) {\n return;\n }\n\n if (projectFixUserId !== effectiveUserId) {\n projectFixUserId = effectiveUserId;\n projectFixInFlight = false;\n sharedResolvedProjectId = null;\n }\n\n if (projectFixInFlight) {\n return;\n }\n\n projectFixInFlight = true;\n setIsInitializingProject(true);\n\n (async () => {\n try {\n const existing = await fetchProjects({ variables: { orgName, limit: 50 } });\n let projectUuid =\n (existing.data?.getProjects?.data || []).find((p) => p?.projectId)?.projectId ?? undefined;\n let newMongoProjectId: string | undefined;\n\n if (!projectUuid) {\n const created = await createProject({\n variables: {\n input: {\n accountId: effectiveUserId,\n projectName: PROJECT_NAME,\n },\n },\n });\n newMongoProjectId = created.data?.quickCreateProjectForAccount?.id ?? undefined;\n if (newMongoProjectId) {\n const after = await fetchProjects({ variables: { orgName, limit: 50 } });\n projectUuid =\n (after.data?.getProjects?.data || []).find((p) => p?.id === newMongoProjectId)?.projectId ??\n // createSecretApiToken accepts Mongo ObjectId directly when no UUID dashes.\n newMongoProjectId;\n await createVault({\n variables: {\n input: {\n orgName,\n projectId: newMongoProjectId,\n },\n },\n }).catch((error) =>\n console.error('[usePrerequisiteIds] Vault creation failed:', error?.message),\n );\n } else {\n console.warn('[usePrerequisiteIds] Project creation returned no id');\n }\n }\n\n if (!projectUuid) {\n if (__DEV__) {\n console.warn(\n `[usePrerequisiteIds] Could not resolve a project UUID — using testing project ${TESTING_PROJECT_UUID}`,\n );\n projectUuid = TESTING_PROJECT_UUID;\n } else {\n console.error(\n '[usePrerequisiteIds] Could not resolve a project UUID — refusing testing fallback outside __DEV__',\n );\n projectFixInFlight = false;\n return;\n }\n }\n\n setResolvedProjectId(projectUuid);\n publishSharedResolvedProjectId(projectUuid);\n await persistDefaults(orgName, projectUuid);\n dispatch(orgChangeAction({ orgName, userId: effectiveUserId }));\n dispatch(resourceGroupChangeAction({ resourceGroup: projectUuid }));\n await refetchDefaults();\n } catch (error) {\n console.error('[usePrerequisiteIds] Project bootstrap failed:', (error as Error)?.message);\n if (__DEV__) {\n console.warn(\n `[usePrerequisiteIds] Falling back to testing project ${TESTING_PROJECT_UUID} after bootstrap error`,\n );\n setResolvedProjectId(TESTING_PROJECT_UUID);\n publishSharedResolvedProjectId(TESTING_PROJECT_UUID);\n try {\n await persistDefaults(orgName, TESTING_PROJECT_UUID);\n dispatch(orgChangeAction({ orgName, userId: effectiveUserId }));\n dispatch(resourceGroupChangeAction({ resourceGroup: TESTING_PROJECT_UUID }));\n await refetchDefaults();\n } catch (persistError) {\n console.error(\n '[usePrerequisiteIds] Testing fallback persist failed:',\n (persistError as Error)?.message,\n );\n projectFixInFlight = false;\n }\n } else {\n projectFixInFlight = false;\n }\n } finally {\n setIsInitializingProject(false);\n }\n })();\n }, [\n createProject,\n createVault,\n dispatch,\n fetchProjects,\n needsProjectCreation,\n orgName,\n persistDefaults,\n refetchDefaults,\n effectiveUserId,\n userLoading,\n ]);\n\n const isOrgLoading =\n isAuthenticated &&\n !orgName &&\n (userLoading ||\n contextLoading ||\n settingsLoading ||\n orgsLoading ||\n orgsByUserLoading ||\n Boolean(effectiveUserId));\n\n const isProjectLoading =\n !!orgName &&\n !rawSettingsProjectId &&\n !projectId &&\n (isInitializingProject || projectCreating || settingsLoading);\n\n const isLoading = isOrgLoading || isProjectLoading;\n\n return {\n projectId,\n orgName,\n accountUserId: effectiveUserId ?? null,\n tagId: TAG_ID,\n loading: isLoading,\n /** True while org slug is still unknown (Home should wait before syncing route). */\n orgLoading: isOrgLoading,\n errors: { createError, vaultCreateError },\n };\n}\n"],"names":["_a","_b","_c","_d"],"mappings":"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"}
1
+ {"version":3,"file":"usePrerequisiteIds.js","sources":["../../src/hooks/usePrerequisiteIds.ts"],"sourcesContent":["import { DEFAULT_PRODUCTION_TAG_ID } from '@adminide-stack/core/lib/constants/defaultIds.js';\nimport { useContextData } from '@adminide-stack/platform-client/lib/hooks/useContextData.js';\nimport {\n orgChangeAction,\n resourceGroupChangeAction,\n} from '@adminide-stack/platform-client/lib/redux/actions/org-action.js';\nimport { isAuthenticatedSelector } from '@adminide-stack/user-auth0-client';\nimport { ConfigurationTarget, ContributionSchemaId } from 'common';\nimport {\n useAccountProfileQuery,\n useCreateVaultMutation,\n useGetProjectsLazyQuery,\n useGetUserOrganizationsQuery,\n useGetUserOrganizationsWithDetailsQuery,\n useQuickCreateProjectForAccountBkMutation,\n useWriteSettingsMutation,\n} from 'common/graphql';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useDispatch, useSelector } from 'react-redux';\nimport { useAccountDefaultSettings } from './useAccountDefaultSettings';\nimport { isUnhydratedCdecodeUri, settingsUriForAccount, toUriInput } from '../utils/cdecodeUri';\n\nconst uuidToObjectId = (uuid: string) => uuid.replace(/-/g, '').substring(0, 24);\n\nconst PROJECT_NAME = 'DEFAULT_YANTRA_PROJECT';\nconst TAG_ID = uuidToObjectId(DEFAULT_PRODUCTION_TAG_ID);\n/** SystemContributionExtensionNames.Account — owns `account.default.*`. */\nconst ACCOUNT_EXTENSION = 'account';\n\n/**\n * DEV ONLY — known working project UUID for local mobile bootstrap when create/list\n * cannot resolve `projectId`. Never use on staging/prod: createSecretApiToken needs a\n * real project that resolves to a Mongo ObjectId (unknown UUID → ObjectId cast 400).\n */\nconst TESTING_PROJECT_UUID = '9a8ac704-1040-4836-9b72-48b771ca91b1';\n\nconst ORG_RESOLVE_POLL_MS = 2000;\nconst PROFILE_POLL_MS = 1500;\n\n// ── Module-level project fix (parity with browser) ───────────────────────────\n// Several screens/hooks mount `usePrerequisiteIds` at once. Per-instance refs race\n// and can create multiple orphan projects. Keep a single-flight guard + user id so\n// adopt/create/persist runs once per account session.\n// Resolved project must also be shared — otherwise WebBuilderPrewarm can \"win\" the\n// flight and HomeScreen never sees projectId (submit stuck on \"not ready\").\nlet projectFixInFlight = false;\nlet projectFixUserId: string | null = null;\nlet sharedResolvedProjectId: string | null = null;\nconst sharedProjectListeners = new Set<() => void>();\n\nfunction publishSharedResolvedProjectId(projectUuid: string): void {\n sharedResolvedProjectId = projectUuid;\n sharedProjectListeners.forEach((listener) => listener());\n}\n\nfunction pickDefaultOrgSlug(\n orgs: Array<{ name?: string | null; title?: string | null } | null | undefined> | null | undefined,\n): string | null {\n if (!orgs?.length) return null;\n const first = orgs.find((o) => typeof o?.name === 'string' && o.name.trim().length > 0);\n return first?.name?.trim() ?? null;\n}\n\n/**\n * Org + project prerequisites for mobile (parity with browser `usePrerequisiteIds`).\n *\n * Settings use the same `account.default` config as web (`useSettingsLoader` → `useSettings` on mobile).\n * After verify-user, account-level settings (`//accounts/{id}#settings`) and org membership are polled\n * until `organization` is available, then route context is synced on Home.\n *\n * Scenario: org set but no `account.default.project` → adopt an existing project in the org\n * (or create one), persist settings, and bind resourceGroup — same as browser Scenario 2.\n */\nexport function usePrerequisiteIds() {\n const dispatch = useDispatch();\n const isAuthenticated = useSelector(isAuthenticatedSelector);\n\n const { data: contextData, complete: contextComplete } = useContextData();\n const contextLoading = !contextComplete;\n const cdecodeUri = contextData?.cdecodeUri;\n const contextUserId = contextData?.userId ?? null;\n\n const contextResourceUri = useMemo(() => {\n if (isUnhydratedCdecodeUri(cdecodeUri)) return undefined;\n return toUriInput(cdecodeUri);\n }, [cdecodeUri]);\n\n const {\n data: accountProfileData,\n loading: userLoading,\n refetch: refetchProfile,\n } = useAccountProfileQuery({\n fetchPolicy: 'cache-and-network',\n errorPolicy: 'all',\n skip: !isAuthenticated,\n });\n const profileUserId = accountProfileData?.accountProfile?.user?.id ?? null;\n const effectiveUserId = isAuthenticated ? profileUserId || contextUserId : null;\n\n useEffect(() => {\n if (!isAuthenticated || profileUserId) return;\n const timer = setInterval(() => {\n refetchProfile().catch(() => undefined);\n }, PROFILE_POLL_MS);\n return () => clearInterval(timer);\n }, [isAuthenticated, profileUserId, refetchProfile]);\n\n // Step 1 (web): account.default via settings loader — context cdecodeUri when hydrated\n const {\n organization: orgFromContextSettings,\n project: projectFromContextSettings,\n loading: contextSettingsLoading,\n refetch: refetchContextSettings,\n } = useAccountDefaultSettings({\n resourceUri: contextResourceUri,\n skip: !isAuthenticated || !contextResourceUri,\n });\n\n const accountResourceUri = useMemo(() => {\n if (!effectiveUserId || orgFromContextSettings) return undefined;\n return settingsUriForAccount(effectiveUserId);\n }, [effectiveUserId, orgFromContextSettings]);\n\n // Mobile bootstrap: read account.default from account document before org is on the route\n const {\n organization: orgFromAccountSettings,\n project: projectFromAccountSettings,\n loading: accountSettingsLoading,\n refetch: refetchAccountSettings,\n } = useAccountDefaultSettings({\n resourceUri: accountResourceUri,\n skip: !isAuthenticated || !accountResourceUri,\n });\n\n const {\n data: orgsData,\n loading: orgsLoading,\n refetch: refetchOrgs,\n } = useGetUserOrganizationsWithDetailsQuery({\n skip: !isAuthenticated || !effectiveUserId,\n fetchPolicy: 'cache-and-network',\n });\n\n const {\n data: orgsByUserData,\n loading: orgsByUserLoading,\n refetch: refetchOrgsByUser,\n } = useGetUserOrganizationsQuery({\n variables: { userId: effectiveUserId ?? undefined },\n skip: !isAuthenticated || !effectiveUserId,\n fetchPolicy: 'cache-and-network',\n });\n\n const orgFromMembership = useMemo(() => {\n const fromDetails = pickDefaultOrgSlug(orgsData?.getUserOrganizationsWithDetails);\n if (fromDetails) return fromDetails;\n return pickDefaultOrgSlug(orgsByUserData?.getUserOrganizations);\n }, [orgsData, orgsByUserData]);\n\n const orgFromContextPath = useMemo(() => {\n if (isUnhydratedCdecodeUri(cdecodeUri)) return null;\n const { path } = toUriInput(cdecodeUri);\n const match = path.match(/^\\/([^/]+)\\//);\n return match?.[1]?.trim() || null;\n }, [cdecodeUri]);\n\n const orgName = orgFromContextSettings || orgFromAccountSettings || orgFromMembership || orgFromContextPath || null;\n\n const rawSettingsProjectIdRaw = projectFromContextSettings || projectFromAccountSettings || null;\n // Staging may have persisted the local testing UUID; treat it as unset so bootstrap can mint a real project.\n const rawSettingsProjectId =\n !__DEV__ && rawSettingsProjectIdRaw === TESTING_PROJECT_UUID ? null : rawSettingsProjectIdRaw;\n\n useEffect(() => {\n if (!isAuthenticated || orgName || !effectiveUserId) return;\n const timer = setInterval(() => {\n refetchContextSettings?.()?.catch(() => undefined);\n refetchAccountSettings?.()?.catch(() => undefined);\n refetchOrgs().catch(() => undefined);\n refetchOrgsByUser().catch(() => undefined);\n }, ORG_RESOLVE_POLL_MS);\n return () => clearInterval(timer);\n }, [\n isAuthenticated,\n orgName,\n effectiveUserId,\n refetchContextSettings,\n refetchAccountSettings,\n refetchOrgs,\n refetchOrgsByUser,\n ]);\n\n const settingsProjectId = rawSettingsProjectId;\n\n const [resolvedProjectId, setResolvedProjectId] = useState<string | null>(() => sharedResolvedProjectId);\n const [isInitializingProject, setIsInitializingProject] = useState(false);\n\n // Cross-instance sync: when another hook wins the project bootstrap, adopt it.\n useEffect(() => {\n const onShared = () => {\n if (sharedResolvedProjectId) setResolvedProjectId(sharedResolvedProjectId);\n };\n sharedProjectListeners.add(onShared);\n onShared();\n return () => {\n sharedProjectListeners.delete(onShared);\n };\n }, []);\n\n // New account session → clear shared fallback so we don't leak another user's project.\n useEffect(() => {\n if (!effectiveUserId) return;\n if (projectFixUserId && projectFixUserId !== effectiveUserId) {\n sharedResolvedProjectId = null;\n projectFixInFlight = false;\n setResolvedProjectId(null);\n }\n }, [effectiveUserId]);\n\n const projectId = settingsProjectId || resolvedProjectId || sharedResolvedProjectId;\n const settingsLoading = contextSettingsLoading || accountSettingsLoading;\n // Wait for settings to settle so we don't create before an existing default loads.\n const needsProjectCreation = !settingsLoading && !!orgName && !rawSettingsProjectId && !projectId;\n\n const [fetchProjects] = useGetProjectsLazyQuery();\n const [createProject, { error: createError, loading: projectCreating }] =\n useQuickCreateProjectForAccountBkMutation();\n const [createVault, { error: vaultCreateError }] = useCreateVaultMutation();\n const [writeSettings] = useWriteSettingsMutation();\n\n const accountSettingsUri = useMemo(() => {\n if (!effectiveUserId) return null;\n return settingsUriForAccount(effectiveUserId);\n }, [effectiveUserId]);\n\n const persistDefaults = useCallback(\n async (orgToSet: string, projectUuid: string) => {\n if (!accountSettingsUri) return;\n await writeSettings({\n variables: {\n // The URI scalar's TS type is the vscode URI class, but the wire\n // format is this serializable POJO (same shape toUriInput emits).\n editingUri:\n accountSettingsUri as unknown as import('@vscode-alt/monaco-editor/esm/vs/base/common/uri.js').URI,\n settings: {\n 'account.default.organization': orgToSet,\n 'account.default.project': projectUuid,\n },\n target: ConfigurationTarget.USER,\n schemaId: ContributionSchemaId.Configuration,\n extensionName: ACCOUNT_EXTENSION,\n },\n });\n },\n [accountSettingsUri, writeSettings],\n );\n\n const refetchDefaults = useCallback(async () => {\n await Promise.all([\n refetchContextSettings?.()?.catch(() => undefined) ?? Promise.resolve(),\n refetchAccountSettings?.()?.catch(() => undefined) ?? Promise.resolve(),\n ]);\n }, [refetchContextSettings, refetchAccountSettings]);\n\n // Scenario 2: default org present but no project → adopt existing (or create once),\n // then persist so reload / other mounts do not create orphan projects.\n useEffect(() => {\n if (!needsProjectCreation || !effectiveUserId || userLoading || !orgName) {\n return;\n }\n\n if (projectFixUserId !== effectiveUserId) {\n projectFixUserId = effectiveUserId;\n projectFixInFlight = false;\n sharedResolvedProjectId = null;\n }\n\n if (projectFixInFlight) {\n return;\n }\n\n projectFixInFlight = true;\n setIsInitializingProject(true);\n\n (async () => {\n try {\n const existing = await fetchProjects({ variables: { orgName, limit: 50 } });\n let projectUuid =\n (existing.data?.getProjects?.data || []).find((p) => p?.projectId)?.projectId ?? undefined;\n let newMongoProjectId: string | undefined;\n\n if (!projectUuid) {\n const created = await createProject({\n variables: {\n input: {\n accountId: effectiveUserId,\n projectName: PROJECT_NAME,\n },\n },\n });\n newMongoProjectId = created.data?.quickCreateProjectForAccount?.id ?? undefined;\n if (newMongoProjectId) {\n const after = await fetchProjects({ variables: { orgName, limit: 50 } });\n projectUuid =\n (after.data?.getProjects?.data || []).find((p) => p?.id === newMongoProjectId)?.projectId ??\n // createSecretApiToken accepts Mongo ObjectId directly when no UUID dashes.\n newMongoProjectId;\n await createVault({\n variables: {\n input: {\n orgName,\n projectId: newMongoProjectId,\n },\n },\n }).catch((error) =>\n console.error('[usePrerequisiteIds] Vault creation failed:', error?.message),\n );\n } else {\n console.warn('[usePrerequisiteIds] Project creation returned no id');\n }\n }\n\n if (!projectUuid) {\n if (__DEV__) {\n console.warn(\n `[usePrerequisiteIds] Could not resolve a project UUID — using testing project ${TESTING_PROJECT_UUID}`,\n );\n projectUuid = TESTING_PROJECT_UUID;\n } else {\n console.error(\n '[usePrerequisiteIds] Could not resolve a project UUID — refusing testing fallback outside __DEV__',\n );\n projectFixInFlight = false;\n return;\n }\n }\n\n setResolvedProjectId(projectUuid);\n publishSharedResolvedProjectId(projectUuid);\n await persistDefaults(orgName, projectUuid);\n dispatch(orgChangeAction({ orgName, userId: effectiveUserId }));\n dispatch(resourceGroupChangeAction({ resourceGroup: projectUuid }));\n await refetchDefaults();\n } catch (error) {\n console.error('[usePrerequisiteIds] Project bootstrap failed:', (error as Error)?.message);\n if (__DEV__) {\n console.warn(\n `[usePrerequisiteIds] Falling back to testing project ${TESTING_PROJECT_UUID} after bootstrap error`,\n );\n setResolvedProjectId(TESTING_PROJECT_UUID);\n publishSharedResolvedProjectId(TESTING_PROJECT_UUID);\n try {\n await persistDefaults(orgName, TESTING_PROJECT_UUID);\n dispatch(orgChangeAction({ orgName, userId: effectiveUserId }));\n dispatch(resourceGroupChangeAction({ resourceGroup: TESTING_PROJECT_UUID }));\n await refetchDefaults();\n } catch (persistError) {\n console.error(\n '[usePrerequisiteIds] Testing fallback persist failed:',\n (persistError as Error)?.message,\n );\n projectFixInFlight = false;\n }\n } else {\n projectFixInFlight = false;\n }\n } finally {\n setIsInitializingProject(false);\n }\n })();\n }, [\n createProject,\n createVault,\n dispatch,\n fetchProjects,\n needsProjectCreation,\n orgName,\n persistDefaults,\n refetchDefaults,\n effectiveUserId,\n userLoading,\n ]);\n\n const isOrgLoading =\n isAuthenticated &&\n !orgName &&\n (userLoading ||\n contextLoading ||\n settingsLoading ||\n orgsLoading ||\n orgsByUserLoading ||\n Boolean(effectiveUserId));\n\n const isProjectLoading =\n !!orgName &&\n !rawSettingsProjectId &&\n !projectId &&\n (isInitializingProject || projectCreating || settingsLoading);\n\n const isLoading = isOrgLoading || isProjectLoading;\n\n return {\n projectId,\n orgName,\n accountUserId: effectiveUserId ?? null,\n tagId: TAG_ID,\n loading: isLoading,\n /** True while org slug is still unknown (Home should wait before syncing route). */\n orgLoading: isOrgLoading,\n errors: { createError, vaultCreateError },\n };\n}\n"],"names":["_a","_b","_c","_d"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {jsxs,jsx}from'react/jsx-runtime';import {useMemo,useEffect,useState,useRef,useCallback}from'react';import {useColorScheme,useWindowDimensions,Keyboard,TouchableWithoutFeedback,StyleSheet,View}from'react-native';import {getDefaultLeftItems,getDefaultRightItems,Box,Text,InputToolBar}from'@admin-layout/gluestack-ui-mobile';import {useSafeAreaInsets,SafeAreaView}from'react-native-safe-area-context';import {useNavigation,useRoute,CommonActions}from'@react-navigation/native';import {MessagesContainerUI}from'@messenger-box/platform-mobile';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useChatStream}from'../../hooks/useChatStream.js';import {useKeyboardBottomOffset}from'../../hooks/useKeyboardBottomOffset.js';import {KeyboardComposerDock}from'../../components/KeyboardComposerDock.js';import {YantraBrandLoader,YANTRA_LOADER_SIZE_COMPACT}from'../../components/YantraBrandLoader.js';import ThinkingIndicator from'../../components/ThinkingIndicator.js';import {mobileTokens}from'../../theme/mobileTokens.js';import DeepSearchModal from'../Home/components/DeepSearchModal.js';import {normalizeSummaryText,extractDeepSearchSources}from'../Home/deepSearchUtils.js';import {AudioRecorderPanel}from'../../features/audio-input/AudioRecorderPanel.js';import {useImageAttachments}from'../../features/attachments/useImageAttachments.js';import {MicErrorBoundary}from'../../features/audio-input/MicErrorBoundary.js';import {requestMicPermission}from'../../features/audio-input/useAudioPermission.js';var __defProp = Object.defineProperty;
1
+ import {jsx,jsxs}from'react/jsx-runtime';import {useMemo,useEffect,useCallback,useState,useRef}from'react';import {useColorScheme,useWindowDimensions,Keyboard,TouchableWithoutFeedback,StyleSheet,View}from'react-native';import {getDefaultLeftItems,getDefaultRightItems,Box,Text,InputToolBar}from'@admin-layout/gluestack-ui-mobile';import {useSafeAreaInsets,SafeAreaView}from'react-native-safe-area-context';import {useNavigation,useRoute,CommonActions}from'@react-navigation/native';import {MessagesContainerUI}from'@messenger-box/platform-mobile';import {MessageActionBar}from'../../features/chat/MessageActionBar.js';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useChatStream}from'../../hooks/useChatStream.js';import {useKeyboardBottomOffset}from'../../hooks/useKeyboardBottomOffset.js';import {KeyboardComposerDock}from'../../components/KeyboardComposerDock.js';import {YantraBrandLoader,YANTRA_LOADER_SIZE_COMPACT}from'../../components/YantraBrandLoader.js';import ThinkingIndicator from'../../components/ThinkingIndicator.js';import {mobileTokens}from'../../theme/mobileTokens.js';import DeepSearchModal from'../Home/components/DeepSearchModal.js';import {normalizeSummaryText,extractDeepSearchSources}from'../Home/deepSearchUtils.js';import {AudioRecorderPanel}from'../../features/audio-input/AudioRecorderPanel.js';import {useImageAttachments}from'../../features/attachments/useImageAttachments.js';import {MicErrorBoundary}from'../../features/audio-input/MicErrorBoundary.js';import {requestMicPermission}from'../../features/audio-input/useAudioPermission.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -79,6 +79,23 @@ function ChatScreen() {
79
79
  sendMessage,
80
80
  cancel
81
81
  } = chat;
82
+ const regenerateFrom = useCallback((messageId) => {
83
+ var _a2;
84
+ const match = /^msg-(\d+)-assistant$/.exec(messageId);
85
+ if (!match || !channelId) return;
86
+ for (let i = Number(match[1]) - 1; i >= 0; i -= 1) {
87
+ const prior = chat.messages[i];
88
+ if ((prior == null ? void 0 : prior.role) === "user" && ((_a2 = prior.content) == null ? void 0 : _a2.trim())) {
89
+ void chat.sendMessage(prior.content, void 0, channelId);
90
+ return;
91
+ }
92
+ }
93
+ }, [chat, channelId]);
94
+ const chatBusy = isLoading || isStreaming;
95
+ const renderMessageActions = useCallback((message) => message.role === "assistant" ? /* @__PURE__ */ jsx(MessageActionBar, { text: message.content, onRegenerate: chatBusy ? void 0 : () => regenerateFrom(message.id) }) : null, [chatBusy, regenerateFrom]);
96
+ const messageActionsSlot = {
97
+ renderMessageActions
98
+ };
82
99
  const imageAttachments = useImageAttachments();
83
100
  const [value, setValue] = useState("");
84
101
  const valueRef = useRef(value);
@@ -327,11 +344,12 @@ function ChatScreen() {
327
344
  }], children: "Connecting gateway\u2026" })
328
345
  ] }) : /* @__PURE__ */ jsx(Box, { flex: 1, width: "100%", alignSelf: "stretch", children: /* @__PURE__ */ jsx(
329
346
  MessagesContainerUI,
330
- {
347
+ __spreadProps(__spreadValues({
331
348
  mode: "chat",
332
349
  showBackButton: false,
333
350
  compactTop: true,
334
- isKeyboardInternallyHandled: false,
351
+ isKeyboardInternallyHandled: false
352
+ }, messageActionsSlot), {
335
353
  messagesContainerStyle: {
336
354
  paddingHorizontal: 0,
337
355
  paddingTop: 0,
@@ -359,7 +377,7 @@ function ChatScreen() {
359
377
  onStop: isStreaming ? cancel : void 0,
360
378
  renderPlanInputToolbar: renderNoToolbar,
361
379
  renderBuildInputToolbar: renderNoToolbar
362
- }
380
+ })
363
381
  ) }),
364
382
  showSendingLoader && !pinSendingLoaderNearComposer ? /* @__PURE__ */ jsx(View, { pointerEvents: "none", style: styles.sendingLoaderEmptyState, children: /* @__PURE__ */ jsx(ThinkingIndicator, { color: secondaryTextColor }) }) : null,
365
383
  /* @__PURE__ */ jsxs(KeyboardComposerDock, { closedInset: insets.bottom, keyboardVisible, children: [
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/screens/Chat/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Keyboard,\n StyleSheet,\n TextInput,\n TouchableWithoutFeedback,\n View,\n useColorScheme,\n useWindowDimensions,\n} from 'react-native';\nimport { Box, InputToolBar, Text, getDefaultLeftItems, getDefaultRightItems } from '@admin-layout/gluestack-ui-mobile';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { useNavigation, useRoute, CommonActions } from '@react-navigation/native';\nimport { MessagesContainerUI } from '@messenger-box/platform-mobile';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { useChatStream, type UseChatStreamRouting } from '../../hooks/useChatStream';\nimport { useKeyboardBottomOffset } from '../../hooks/useKeyboardBottomOffset';\nimport { KeyboardComposerDock } from '../../components/KeyboardComposerDock';\nimport { YantraBrandLoader, YANTRA_LOADER_SIZE_COMPACT } from '../../components/YantraBrandLoader';\nimport ThinkingIndicator from '../../components/ThinkingIndicator';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport DeepSearchModal from '../Home/components/DeepSearchModal';\nimport { extractDeepSearchSources, normalizeSummaryText, type DeepSearchSourceItem } from '../Home/deepSearchUtils';\nimport type { ModeSubmission, RoutingMode } from '../Home/types';\nimport { AudioRecorderPanel } from '../../features/audio-input/AudioRecorderPanel';\nimport { useImageAttachments } from '../../features/attachments/useImageAttachments';\nimport { MicErrorBoundary } from '../../features/audio-input/MicErrorBoundary';\nimport { requestMicPermission } from '../../features/audio-input/useAudioPermission';\n\n/** Route params passed by Home (or by deep-link) when entering the Chat surface. */\nexport interface ChatScreenRouteParams {\n /** Channel id is required — the screen is keyed on the conversation. */\n channelId: string;\n /** Org slug used by gateway/account context. */\n orgName?: string | null;\n /**\n * First user message to auto-fire when the screen mounts. Home generates\n * this when the user submits from the empty composer so the assistant\n * starts streaming on Chat without an extra round trip.\n */\n initialQuery?: string | null;\n /**\n * Seed for the composer's mode (`'chat'` | `'deep-search'` | `'build'`).\n *\n * Set by `HomeScreen` to carry the user's last selection across the\n * navigation hop (\"research from home → research-shaped composer on chat\").\n * `ChatHistoryScreen` does NOT forward this — revisits always land on the\n * default `'chat'` mode, matching Home's defaults, and the user is free to\n * switch from there. Build-mode send hands off to Web Builder.\n *\n * After mount, this param is purely a seed: the screen keeps its own\n * `activeMode` so the user can toggle freely while inside the thread.\n */\n initialMode?: RoutingMode;\n /** Optional attachments forwarded with the initial message. */\n initialAttachments?: ModeSubmission['attachments'];\n}\n\n/** Stable prop identities — a fresh object/function per render defeats the\n * memoisation inside MessagesContainerUI during streaming. */\nconst CHAT_CURRENT_USER = { id: 'user' } as const;\nconst renderNoToolbar = () => null;\n\nexport default function ChatScreen() {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n\n const params = (route?.params ?? {}) as Partial<ChatScreenRouteParams>;\n const channelId = useMemo(() => {\n const raw = typeof params.channelId === 'string' ? params.channelId.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.channelId]);\n const initialQuery = useMemo(() => {\n const raw = typeof params.initialQuery === 'string' ? params.initialQuery.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.initialQuery]);\n const initialAttachments = params.initialAttachments;\n\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const { width: screenWidth } = useWindowDimensions();\n const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));\n\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const secondaryTextColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n const insets = useSafeAreaInsets();\n const { keyboardHeight, keyboardVisible } = useKeyboardBottomOffset();\n\n /**\n * Gateway + chat stream routing.\n *\n * The CDeCLI lifecycle is owned app-wide by `CdecliConnectionProvider`,\n * so we just register this screen's channelId and read the shared status.\n * This avoids racing `gatewayConnect` mutations with the header's\n * `GatewayConnector` (which previously ran its own `useCdecliAutoConnect`\n * and could clobber the chat session binding).\n */\n const cdecli = useCdecliConnection();\n const effectivePersistenceMode = cdecli.persistenceMode ?? 'backend';\n\n useEffect(() => {\n if (!channelId) return undefined;\n cdecli.setActiveChannelId(channelId);\n return () => {\n cdecli.setActiveChannelId(undefined);\n };\n }, [channelId, cdecli.setActiveChannelId]);\n\n const chatRouting: UseChatStreamRouting = useMemo(\n () => ({\n channelConnected: cdecli.channelConnected,\n accountId: cdecli.accountId,\n persistenceMode: effectivePersistenceMode,\n }),\n [cdecli.channelConnected, cdecli.accountId, effectivePersistenceMode],\n );\n\n const chat = useChatStream(channelId, chatRouting);\n\n /**\n * Gifted-shaped transcript rows, memoised on `messages` alone.\n *\n * This screen re-renders on every streamed token — `useChatStream` does\n * `setResponse((r) => r + text)` per delta. Building this array inline in\n * the JSX therefore handed `PlanModeView` a fresh `messages` identity on\n * every token, which invalidated its own `useMemo([messages, …])`, re-mapped\n * every row, and re-rendered every bubble. Assistant bubbles render through\n * `react-native-markdown-display`, so that meant re-parsing the markdown of\n * the whole thread once per token — O(messages) parses per delta, on the JS\n * thread, which is exactly when the UI has to stay responsive.\n *\n * `messages` is already stable upstream (`useChatApi` memoises it on the\n * Apollo result), so this only rebuilds when a message is actually added or\n * changed.\n */\n const transcriptRows = useMemo(\n () =>\n chat.messages.map((msg, index) => ({\n id: `msg-${index}-${msg.role}`,\n role: msg.role,\n content: msg.content,\n metadata: (msg as { metadata?: unknown }).metadata,\n })),\n [chat.messages],\n );\n const { messages, response, error: chatError, isLoading, isStreaming, messagesLoading, sendMessage, cancel } = chat;\n\n const imageAttachments = useImageAttachments();\n\n /*\n * Composer state — kept local so it doesn't leak across navigations.\n *\n * `valueRef` mirrors the controlled `value` so `handleSend` can read the\n * latest text without taking a dependency on it. Without this, `handleSend`\n * (and therefore `micSendButton.onSend`) would be recreated on every\n * keystroke, which is unnecessary churn for `InputToolBar`.\n *\n * `inputRef` is forwarded to InputToolBar's TextInput so we can call\n * `.clear()` imperatively after sending. On iOS, the native text buffer\n * can stay desynced from the controlled `value` for a frame when a state\n * update is followed by an async dispatch in the same gesture — the\n * \"send-and-clear\" race. The imperative clear closes that gap deterministically.\n */\n const [value, setValue] = useState('');\n const valueRef = useRef(value);\n valueRef.current = value;\n const inputRef = useRef<TextInput>(null);\n const trimmed = value.trim();\n const hasQuery = trimmed.length > 0;\n const canSubmit = hasQuery && Boolean(channelId);\n\n /**\n * Composer mode is FREELY user-controlled, mirroring `HomeScreen`.\n *\n * Seed:\n * • From Home (which forwards `initialMode` alongside `initialQuery`):\n * start in whatever mode the user picked there so the \"research from\n * home → research-shaped chat\" hand-off feels continuous.\n * • From ChatHistory (which intentionally does NOT pass `initialMode`):\n * default to `'chat'`, same as Home's empty composer.\n *\n * Post-mount this is a normal local state — the search/zap pills toggle\n * it on tap, and every place that previously branched on\n * `params.initialMode` now branches on `activeMode` instead.\n */\n const [activeMode, setActiveMode] = useState<RoutingMode>(() =>\n params.initialMode === 'deep-search' ? 'deep-search' : params.initialMode === 'build' ? 'build' : 'chat',\n );\n const handleModeSwitch = useCallback((mode: RoutingMode) => {\n setActiveMode(mode);\n }, []);\n const isDeepSearchMode = activeMode === 'deep-search';\n const isBuildMode = activeMode === 'build';\n\n /**\n * Inline voice recorder state — parity with HomeScreen and the web\n * `YantraSearchComposer.showAudioRecorder` flow. When active, the panel\n * fully replaces the InputToolBar so the toolbar's mic→send button\n * doesn't compete with the panel's own send/cancel affordances.\n */\n const [showAudioRecorder, setShowAudioRecorder] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n\n /**\n * Auto-fire the initial query once when the screen mounts on a fresh channel.\n * Home creates the channel optimistically and forwards the user prompt here so\n * the first assistant token arrives without an extra interaction.\n *\n * Wait for CDeCLI to finish connecting (or fail) before auto-firing — chat is\n * cdecli-only and `sendMessage` rejects sends while the gateway is disconnected.\n */\n const autoFiredRef = useRef(false);\n useEffect(() => {\n if (autoFiredRef.current) return;\n if (!channelId || !initialQuery) return;\n if (cdecli.status !== 'connected' && cdecli.status !== 'error') return;\n\n autoFiredRef.current = true;\n // Deep-search auto-fire from Home: open the structured modal at the\n // same instant we kick off the send so the user sees the research view\n // streaming in rather than raw assistant turns. Tied to the\n // sendMessage call (same event) to avoid a race where the modal opens\n // before/after the actual send.\n //\n // We branch on the LOCAL `isDeepSearchMode` instead of\n // `params.initialMode`. At auto-fire time they're equal (the local\n // state was seeded from the param), and using the local state means\n // future toggles drive the same code path consistently.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(initialQuery, initialAttachments as any, channelId);\n try {\n navigation.setParams({ initialQuery: null, initialAttachments: null });\n } catch {\n /* setParams may be unavailable in tests; clearing is best-effort. */\n }\n }, [channelId, initialQuery, initialAttachments, sendMessage, navigation, cdecli.status, isDeepSearchMode]);\n\n const handleSend = useCallback(\n (text?: string) => {\n const t = (text ?? valueRef.current).trim();\n if (!t || !channelId) return;\n // Clear both ways: the controlled state (so React's model stays\n // consistent on next render) AND the native buffer via the ref\n // (so the visible text disappears on the same frame the user\n // pressed send, even before React flushes).\n setValue('');\n inputRef.current?.clear();\n\n // Build mode: hand off to Web Builder on this channel (web `/c/:id/webbuilder`).\n if (isBuildMode) {\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: {\n ...(params.orgName ? { orgName: params.orgName } : {}),\n channelId,\n message: t,\n },\n }),\n );\n return;\n }\n\n // Deep-search mode: every new query pops the structured research\n // modal back open (parity with the previous Home flow, where every\n // submit re-opened the DeepSearchModal). Without this, a user who\n // closed the modal once would see plain assistant turns for every\n // subsequent send. Reads the LOCAL `isDeepSearchMode` so the user\n // can toggle modes mid-thread and have sends behave accordingly.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(t, imageAttachments.forSend(), channelId);\n imageAttachments.clear();\n },\n [channelId, sendMessage, isDeepSearchMode, isBuildMode, navigation, params.orgName, imageAttachments],\n );\n\n const handleValueChange = useCallback((e: any) => {\n setValue(e?.nativeEvent?.text ?? '');\n }, []);\n\n /**\n * Mic affordance — web parity (`handleMicClick` in `YantraSearchComposer.tsx`).\n * The shared `MicSendButton` in `InputToolBar.tsx` only routes to `onMic`\n * when the input has no content, so we only need to handle the empty-input\n * case here.\n *\n * Permission is requested HERE, before the panel mounts. The previous flow\n * flipped `showAudioRecorder=true` immediately, which mounted\n * `AudioRecorderPanel` and constructed the native `AVAudioRecorder` via\n * `useAudioRecorder()` during the panel's render phase — before iOS had\n * granted mic access. On SDK 53 + `newArchEnabled: true` + Hermes that\n * ordering hard-crashes TestFlight builds even though it works in Expo Go\n * (Expo Go pre-caches permission). Asking up front means iOS shows the\n * system alert first and the panel only mounts (and therefore the native\n * recorder is only allocated) once permission is granted.\n *\n * `expo-audio` is lazy-imported so a missing/broken native module surfaces\n * as a user-visible banner instead of a synchronous TurboModule crash.\n */\n const handleMicPress = useCallback(() => {\n if (hasQuery) return;\n setVoiceError(null);\n Keyboard.dismiss();\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 }, [hasQuery]);\n\n /**\n * On a successful Whisper round-trip, paste the transcript into the input\n * field, close the recorder, and let the user review/send manually. Matches\n * web's `handleTranscriptionComplete`: we deliberately do NOT auto-fire\n * `sendMessage` because the user often wants to edit the dictation first.\n */\n const handleTranscriptionComplete = useCallback((text: string) => {\n const cleaned = (text ?? '').trim();\n setShowAudioRecorder(false);\n if (!cleaned) return;\n setValue((prev) => {\n const next = prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned;\n /*\n * Keep `inputRef`'s native text in sync with our controlled value\n * for the same reason `handleSend` does (the iOS native buffer\n * can lag the React state across a single gesture). `setNativeProps`\n * is the safe way to do this without re-rendering.\n */\n requestAnimationFrame(() => {\n inputRef.current?.setNativeProps?.({ text: next });\n inputRef.current?.focus?.();\n });\n return next;\n });\n }, []);\n\n const handleRecorderCancel = useCallback(() => {\n setShowAudioRecorder(false);\n }, []);\n\n const handleRecorderError = useCallback((error: string) => {\n setVoiceError(error);\n }, []);\n\n const waitingForAssistant = useMemo(() => {\n if ((!isLoading && !isStreaming) || messages.length === 0) return false;\n if ((response ?? '').trim()) return false;\n return messages[messages.length - 1]?.role === 'user';\n }, [isLoading, isStreaming, messages, response]);\n\n const composerScrollBottomPadding = 24 + (keyboardVisible ? keyboardHeight : 0);\n\n /*\n * NOTE: the previous read-only `isDeepSearchChannel` derivation has been\n * removed. Mode is now a freely-toggleable local state (`activeMode`)\n * driven by tapping the search/zap pills, mirroring HomeScreen. All\n * downstream branches use `isDeepSearchMode` declared with the rest of\n * the composer state above.\n */\n\n /**\n * Deep-search overlay state.\n *\n * Restored from the previous Home-screen flow (commit history): a deep-search\n * channel renders the structured `DeepSearchModal` (query / live summary /\n * sources / research process) on top of the regular Chat conversation. Closing\n * the modal reveals the same channel's MessagesContainerUI underneath so the\n * user can still see the raw turns.\n *\n * Trigger semantics — IMPORTANT:\n * • Opens ONLY when a request is actually fired in this session:\n * - Home → Chat auto-fire of `initialQuery`\n * - User sends a new message in a deep-search channel from the composer\n * - Explicit retry from inside the modal\n * • Does NOT open on plain entry from ChatHistoryScreen. That's a revisit\n * of an already-completed thread — no new API call, nothing live to\n * stream, so popping the modal would just be a confusing flash. The\n * user still sees the deep-search rendering in the chat conversation\n * underneath, and any new send re-opens the live view.\n *\n * Local UI state (accordions, open flag) lives here; data state (query /\n * summary / sources) is DERIVED from the chat stream, not stored separately,\n * so there's no drift between the modal and the underlying conversation.\n */\n const [isDeepSearchModalOpen, setIsDeepSearchModalOpen] = useState(false);\n const [researchProcessOpen, setResearchProcessOpen] = useState(true);\n const [sourcesAccordionOpen, setSourcesAccordionOpen] = useState(true);\n\n /**\n * Modal data is always scoped to the CURRENT run, not the whole channel.\n * In a multi-turn deep-search channel each send is its own \"run\": one user\n * query → one assistant summary. If we sourced from \"first user message\" /\n * \"any assistant message\", a follow-up send would keep showing the previous\n * run's query and stale sources during the transient window between the new\n * user message being appended and the first stream token arriving.\n *\n * Cursor: the LAST user message in the thread. The assistant content for\n * the current run is either:\n * • `response` while the stream is filling (token-by-token), OR\n * • the assistant message that comes AFTER the last user (run complete), OR\n * • empty — covers the brief \"user message appended, no response yet\"\n * window so the modal flips to \"Running...\" with no stale body.\n */\n const lastUserIndex = useMemo(() => {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n if (messages[i]?.role === 'user') return i;\n }\n return -1;\n }, [messages]);\n\n const deepSearchQuery = useMemo(() => {\n if (lastUserIndex >= 0) {\n const txt = messages[lastUserIndex]?.content?.trim();\n if (txt) return txt;\n }\n return initialQuery ?? null;\n }, [messages, lastUserIndex, initialQuery]);\n\n const latestAssistantContent = useMemo(() => {\n if (response && response.trim()) return response;\n if (lastUserIndex < 0) return '';\n // Look for an assistant turn strictly AFTER the last user message.\n // Anything before it belongs to a prior run and must not leak into\n // the modal for the current one.\n for (let i = lastUserIndex + 1; i < messages.length; i += 1) {\n if (messages[i]?.role === 'assistant') {\n return messages[i]?.content ?? '';\n }\n }\n return '';\n }, [response, messages, lastUserIndex]);\n\n const deepSearchSummary = useMemo(() => normalizeSummaryText(latestAssistantContent), [latestAssistantContent]);\n const deepSearchSources: DeepSearchSourceItem[] = useMemo(\n () => extractDeepSearchSources(latestAssistantContent),\n [latestAssistantContent],\n );\n\n const handleDeepSearchClose = useCallback(() => {\n if (isStreaming) cancel();\n setIsDeepSearchModalOpen(false);\n }, [isStreaming, cancel]);\n\n const handleDeepSearchRetry = useCallback(() => {\n if (!deepSearchQuery || isStreaming || !channelId) return;\n void sendMessage(deepSearchQuery, undefined, channelId);\n }, [deepSearchQuery, isStreaming, channelId, sendMessage]);\n const leftItems = useMemo(\n () =>\n getDefaultLeftItems({\n search: { active: activeMode === 'chat', onClick: () => handleModeSwitch('chat') },\n zap: { active: activeMode === 'deep-search', onClick: () => handleModeSwitch('deep-search') },\n lightbulb: {\n active: activeMode === 'build',\n onClick: () => handleModeSwitch('build'),\n },\n }),\n [activeMode, handleModeSwitch],\n );\n const rightItems = useMemo(\n () =>\n getDefaultRightItems({\n tag: { enabled: false },\n chip: { enabled: false },\n // Attaching an image was disabled here even though the transport\n // (`sendMessage(content, attachments)`) and the gateway media lane\n // already carried it, and `expo-image-picker` was already a\n // dependency with its permission strings declared in app.json.\n camera: {\n enabled: true,\n loading: imageAttachments.busy,\n onClick: () => {\n void imageAttachments.captureFromCamera();\n },\n },\n image: {\n enabled: true,\n loading: imageAttachments.busy,\n onClick: () => {\n void imageAttachments.pickFromLibrary();\n },\n },\n attach: { enabled: false },\n }),\n [imageAttachments],\n );\n /**\n * Composer placeholder.\n *\n * Mirrors Home so the composer feels like the same affordance across the\n * \"first message\" and \"continuing thread\" surfaces — only the surrounding\n * UI changes, the input stays a stable anchor. We intentionally do NOT\n * surface a \"Loading conversation…\" state in the placeholder: the message\n * list already shows a dedicated hydrating loader, and switching the\n * placeholder for ~1 frame creates a visible flash on every entry.\n */\n const inputPlaceholder = isDeepSearchMode\n ? 'Research anything...'\n : isBuildMode\n ? 'Describe an app to build...'\n : 'Ask anything...';\n\n const inputConfig = useMemo(\n () => ({\n value,\n onChange: handleValueChange,\n placeholder: inputPlaceholder,\n disabled: !channelId,\n inputRef,\n returnKeyType: 'send',\n blurOnSubmit: false,\n onSubmitEditing: () => handleSend(),\n }),\n [value, handleValueChange, inputPlaceholder, channelId, handleSend],\n );\n const micSendButton = useMemo(\n () => ({\n hasContent: hasQuery,\n onSend: () => handleSend(),\n onMic: handleMicPress,\n disabled: !channelId,\n // Empty + streaming → Stop. Typed follow-up → Send (steer). Never lock the composer.\n isLoading: canSubmit ? false : isLoading,\n onStop: isStreaming && !canSubmit ? cancel : undefined,\n steerable: isLoading || isStreaming,\n }),\n [canSubmit, handleSend, handleMicPress, isLoading, channelId, isStreaming, cancel, hasQuery],\n );\n\n /**\n * Loader visibility:\n * - `isHydrating`: Apollo channel history is being fetched and we have nothing to show yet.\n * - `isWaitingForGateway`: Home navigated us here with an `initialQuery`, but CDeCLI is still\n * establishing the workspace session, so the auto-fire is deferred. Show a \"Connecting…\"\n * placeholder instead of an empty thread so the user doesn't think their send was dropped.\n */\n const isHydrating = messagesLoading && messages.length === 0 && !response;\n const isWaitingForGateway =\n !autoFiredRef.current &&\n !!channelId &&\n !!initialQuery &&\n cdecli.status !== 'connected' &&\n cdecli.status !== 'error';\n const showSendingLoader = waitingForAssistant;\n const pinSendingLoaderNearComposer = messages.length > 0 || Boolean((response ?? '').trim());\n\n return (\n <SafeAreaView edges={['left', 'right']} style={{ flex: 1, backgroundColor: surfaceColor }}>\n {/* Tap anywhere outside an input to dismiss the keyboard. */}\n <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>\n <Box flex={1} width=\"100%\" position=\"relative\">\n {(chatError || cdecli.error) && (\n <Box\n mb=\"$2\"\n mx=\"$4\"\n p=\"$3\"\n borderRadius=\"$md\"\n style={{\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderWidth: 1,\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n }}\n >\n <Text fontSize=\"$sm\" style={{ color: isDark ? '#fecaca' : '#991b1b' }}>\n {chatError || cdecli.error}\n </Text>\n </Box>\n )}\n {!channelId ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>No channel selected</Text>\n </Box>\n ) : isHydrating ? (\n /**\n * Channel hydration (entering Chat from history or a deep\n * link) reuses the same `ThinkingIndicator` row as the\n * chat-history list — thin spinning arc + muted caption.\n * Keeps the loading vocabulary consistent across screens\n * and avoids the previous branded loader + \"Loading\n * conversation\" copy that read as a different state.\n */\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <ThinkingIndicator color={secondaryTextColor} />\n </Box>\n ) : isWaitingForGateway ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>Connecting gateway…</Text>\n </Box>\n ) : (\n <Box flex={1} width=\"100%\" alignSelf=\"stretch\">\n <MessagesContainerUI\n mode=\"chat\"\n showBackButton={false}\n compactTop\n /**\n * The composer lives OUTSIDE this container (KeyboardComposerDock\n * lifts it on the UI thread) and the container already pads by the\n * keyboard height via composerScrollBottomPadding. GiftedChat's\n * default internal handling ALSO translates the message plane by\n * the keyboard height to protect its own (here: nonexistent)\n * toolbar - double compensation that pushed short threads entirely\n * off-screen while typing.\n */\n isKeyboardInternallyHandled={false}\n messagesContainerStyle={{\n paddingHorizontal: 0,\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n alignSelf: 'center',\n width: contentMaxWidth,\n }}\n listContentStyle={{\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n width: contentMaxWidth,\n alignSelf: 'center',\n justifyContent: 'flex-end',\n }}\n messages={transcriptRows}\n streamingContent={response}\n currentUser={CHAT_CURRENT_USER}\n onSend={handleSend}\n disabled={!channelId}\n isLoading={isLoading}\n onStop={isStreaming ? cancel : undefined}\n renderPlanInputToolbar={renderNoToolbar}\n renderBuildInputToolbar={renderNoToolbar}\n />\n </Box>\n )}\n {showSendingLoader && !pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderEmptyState}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <KeyboardComposerDock closedInset={insets.bottom} keyboardVisible={keyboardVisible}>\n {showSendingLoader && pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderInDock}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <View style={[styles.bottomComposerInner, { width: contentMaxWidth }]}>\n {voiceError ? (\n <View\n style={[\n styles.voiceErrorBanner,\n {\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n },\n ]}\n >\n <Text style={[styles.voiceErrorText, { color: isDark ? '#fecaca' : '#991b1b' }]}>\n {voiceError}\n </Text>\n </View>\n ) : null}\n {showAudioRecorder ? (\n /*\n * Render-time JS errors thrown by `useAudioRecorder`\n * (e.g. expo-audio native module missing, recorder\n * constructor throws in a release build) are caught\n * by the boundary and converted into a soft cancel\n * via the same handlers the panel itself uses on\n * runtime errors. Without this, a throw during the\n * panel's render phase kills the JS thread in\n * release / TestFlight.\n */\n <MicErrorBoundary onCancel={handleRecorderCancel} onError={handleRecorderError}>\n <AudioRecorderPanel\n isDark={isDark}\n onTranscriptionComplete={handleTranscriptionComplete}\n onCancel={handleRecorderCancel}\n onError={handleRecorderError}\n />\n </MicErrorBoundary>\n ) : (\n <InputToolBar\n inputConfig={inputConfig}\n leftItems={leftItems}\n rightItems={rightItems}\n templateButton={null}\n templateModalConfig={null}\n micSendButton={micSendButton}\n />\n )}\n </View>\n </KeyboardComposerDock>\n </Box>\n {/*\n * DeepSearchModal is rendered OUTSIDE the keyboard-dismiss wrapper so\n * taps inside the modal don't dismiss the keyboard, and it's a native\n * <Modal> internally so it correctly sits on top of the Chat surface\n * (composer included) on both iOS and Android.\n */}\n </TouchableWithoutFeedback>\n {isDeepSearchMode ? (\n <DeepSearchModal\n visible={isDeepSearchModalOpen}\n query={deepSearchQuery}\n summaryText={deepSearchSummary}\n sources={deepSearchSources}\n isStreaming={isStreaming}\n researchProcessOpen={researchProcessOpen}\n sourcesAccordionOpen={sourcesAccordionOpen}\n onToggleResearchProcess={() => setResearchProcessOpen((prev) => !prev)}\n onToggleSourcesAccordion={() => setSourcesAccordionOpen((prev) => !prev)}\n onRetry={handleDeepSearchRetry}\n onStop={cancel}\n onClose={handleDeepSearchClose}\n />\n ) : null}\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n statusText: {\n marginTop: 14,\n fontSize: 13,\n fontWeight: '500',\n },\n bottomComposerInner: {\n paddingHorizontal: 14,\n paddingTop: 10,\n paddingBottom: 4,\n },\n voiceErrorBanner: {\n marginBottom: 8,\n paddingHorizontal: 12,\n paddingVertical: 8,\n borderRadius: 10,\n borderWidth: 1,\n },\n voiceErrorText: {\n fontSize: 12,\n fontWeight: '500',\n },\n sendingLoaderEmptyState: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: 40,\n },\n sendingLoaderInDock: {\n alignItems: 'center',\n justifyContent: 'flex-end',\n paddingBottom: 8,\n },\n});\n"],"names":["_a","_b"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/screens/Chat/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Keyboard,\n StyleSheet,\n TextInput,\n TouchableWithoutFeedback,\n View,\n useColorScheme,\n useWindowDimensions,\n} from 'react-native';\nimport { Box, InputToolBar, Text, getDefaultLeftItems, getDefaultRightItems } from '@admin-layout/gluestack-ui-mobile';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { useNavigation, useRoute, CommonActions } from '@react-navigation/native';\nimport { MessagesContainerUI } from '@messenger-box/platform-mobile';\nimport { MessageActionBar } from '../../features/chat/MessageActionBar';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { useChatStream, type UseChatStreamRouting } from '../../hooks/useChatStream';\nimport { useKeyboardBottomOffset } from '../../hooks/useKeyboardBottomOffset';\nimport { KeyboardComposerDock } from '../../components/KeyboardComposerDock';\nimport { YantraBrandLoader, YANTRA_LOADER_SIZE_COMPACT } from '../../components/YantraBrandLoader';\nimport ThinkingIndicator from '../../components/ThinkingIndicator';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport DeepSearchModal from '../Home/components/DeepSearchModal';\nimport { extractDeepSearchSources, normalizeSummaryText, type DeepSearchSourceItem } from '../Home/deepSearchUtils';\nimport type { ModeSubmission, RoutingMode } from '../Home/types';\nimport { AudioRecorderPanel } from '../../features/audio-input/AudioRecorderPanel';\nimport { useImageAttachments } from '../../features/attachments/useImageAttachments';\nimport { MicErrorBoundary } from '../../features/audio-input/MicErrorBoundary';\nimport { requestMicPermission } from '../../features/audio-input/useAudioPermission';\n\n/** Route params passed by Home (or by deep-link) when entering the Chat surface. */\nexport interface ChatScreenRouteParams {\n /** Channel id is required — the screen is keyed on the conversation. */\n channelId: string;\n /** Org slug used by gateway/account context. */\n orgName?: string | null;\n /**\n * First user message to auto-fire when the screen mounts. Home generates\n * this when the user submits from the empty composer so the assistant\n * starts streaming on Chat without an extra round trip.\n */\n initialQuery?: string | null;\n /**\n * Seed for the composer's mode (`'chat'` | `'deep-search'` | `'build'`).\n *\n * Set by `HomeScreen` to carry the user's last selection across the\n * navigation hop (\"research from home → research-shaped composer on chat\").\n * `ChatHistoryScreen` does NOT forward this — revisits always land on the\n * default `'chat'` mode, matching Home's defaults, and the user is free to\n * switch from there. Build-mode send hands off to Web Builder.\n *\n * After mount, this param is purely a seed: the screen keeps its own\n * `activeMode` so the user can toggle freely while inside the thread.\n */\n initialMode?: RoutingMode;\n /** Optional attachments forwarded with the initial message. */\n initialAttachments?: ModeSubmission['attachments'];\n}\n\n/** Stable prop identities — a fresh object/function per render defeats the\n * memoisation inside MessagesContainerUI during streaming. */\nconst CHAT_CURRENT_USER = { id: 'user' } as const;\nconst renderNoToolbar = () => null;\n\nexport default function ChatScreen() {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n\n const params = (route?.params ?? {}) as Partial<ChatScreenRouteParams>;\n const channelId = useMemo(() => {\n const raw = typeof params.channelId === 'string' ? params.channelId.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.channelId]);\n const initialQuery = useMemo(() => {\n const raw = typeof params.initialQuery === 'string' ? params.initialQuery.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.initialQuery]);\n const initialAttachments = params.initialAttachments;\n\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const { width: screenWidth } = useWindowDimensions();\n const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));\n\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const secondaryTextColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n const insets = useSafeAreaInsets();\n const { keyboardHeight, keyboardVisible } = useKeyboardBottomOffset();\n\n /**\n * Gateway + chat stream routing.\n *\n * The CDeCLI lifecycle is owned app-wide by `CdecliConnectionProvider`,\n * so we just register this screen's channelId and read the shared status.\n * This avoids racing `gatewayConnect` mutations with the header's\n * `GatewayConnector` (which previously ran its own `useCdecliAutoConnect`\n * and could clobber the chat session binding).\n */\n const cdecli = useCdecliConnection();\n const effectivePersistenceMode = cdecli.persistenceMode ?? 'backend';\n\n useEffect(() => {\n if (!channelId) return undefined;\n cdecli.setActiveChannelId(channelId);\n return () => {\n cdecli.setActiveChannelId(undefined);\n };\n }, [channelId, cdecli.setActiveChannelId]);\n\n const chatRouting: UseChatStreamRouting = useMemo(\n () => ({\n channelConnected: cdecli.channelConnected,\n accountId: cdecli.accountId,\n persistenceMode: effectivePersistenceMode,\n }),\n [cdecli.channelConnected, cdecli.accountId, effectivePersistenceMode],\n );\n\n const chat = useChatStream(channelId, chatRouting);\n\n /**\n * Gifted-shaped transcript rows, memoised on `messages` alone.\n *\n * This screen re-renders on every streamed token — `useChatStream` does\n * `setResponse((r) => r + text)` per delta. Building this array inline in\n * the JSX therefore handed `PlanModeView` a fresh `messages` identity on\n * every token, which invalidated its own `useMemo([messages, …])`, re-mapped\n * every row, and re-rendered every bubble. Assistant bubbles render through\n * `react-native-markdown-display`, so that meant re-parsing the markdown of\n * the whole thread once per token — O(messages) parses per delta, on the JS\n * thread, which is exactly when the UI has to stay responsive.\n *\n * `messages` is already stable upstream (`useChatApi` memoises it on the\n * Apollo result), so this only rebuilds when a message is actually added or\n * changed.\n */\n const transcriptRows = useMemo(\n () =>\n chat.messages.map((msg, index) => ({\n id: `msg-${index}-${msg.role}`,\n role: msg.role,\n content: msg.content,\n metadata: (msg as { metadata?: unknown }).metadata,\n })),\n [chat.messages],\n );\n const { messages, response, error: chatError, isLoading, isStreaming, messagesLoading, sendMessage, cancel } = chat;\n\n /**\n * \"Try again\" on an assistant message: resend the nearest preceding user\n * prompt on the same channel. Row ids are `msg-<index>-<role>` (see\n * transcriptRows), so the transcript index comes straight out of the id.\n */\n const regenerateFrom = useCallback(\n (messageId: string) => {\n const match = /^msg-(\\d+)-assistant$/.exec(messageId);\n if (!match || !channelId) return;\n for (let i = Number(match[1]) - 1; i >= 0; i -= 1) {\n const prior = chat.messages[i];\n if (prior?.role === 'user' && prior.content?.trim()) {\n void chat.sendMessage(prior.content, undefined, channelId);\n return;\n }\n }\n },\n [chat, channelId],\n );\n\n const chatBusy = isLoading || isStreaming;\n const renderMessageActions = useCallback(\n (message: { id: string; role: string; content: string }) =>\n message.role === 'assistant' ? (\n <MessageActionBar\n text={message.content}\n onRegenerate={chatBusy ? undefined : () => regenerateFrom(message.id)}\n />\n ) : null,\n [chatBusy, regenerateFrom],\n );\n\n /**\n * TEMPORARY spread-cast: `renderMessageActions` ships in\n * @messenger-box/platform-mobile after 10.0.3-alpha.366 (messenger-box\n * 817c5dbf5, pending Jenkins publish). Until the bump, the installed types\n * don't know the prop and the installed runtime ignores it - inline this as\n * a normal prop when the dependency is bumped.\n */\n const messageActionsSlot = {\n renderMessageActions,\n } as Partial<React.ComponentProps<typeof MessagesContainerUI>>;\n\n const imageAttachments = useImageAttachments();\n\n /*\n * Composer state — kept local so it doesn't leak across navigations.\n *\n * `valueRef` mirrors the controlled `value` so `handleSend` can read the\n * latest text without taking a dependency on it. Without this, `handleSend`\n * (and therefore `micSendButton.onSend`) would be recreated on every\n * keystroke, which is unnecessary churn for `InputToolBar`.\n *\n * `inputRef` is forwarded to InputToolBar's TextInput so we can call\n * `.clear()` imperatively after sending. On iOS, the native text buffer\n * can stay desynced from the controlled `value` for a frame when a state\n * update is followed by an async dispatch in the same gesture — the\n * \"send-and-clear\" race. The imperative clear closes that gap deterministically.\n */\n const [value, setValue] = useState('');\n const valueRef = useRef(value);\n valueRef.current = value;\n const inputRef = useRef<TextInput>(null);\n const trimmed = value.trim();\n const hasQuery = trimmed.length > 0;\n const canSubmit = hasQuery && Boolean(channelId);\n\n /**\n * Composer mode is FREELY user-controlled, mirroring `HomeScreen`.\n *\n * Seed:\n * • From Home (which forwards `initialMode` alongside `initialQuery`):\n * start in whatever mode the user picked there so the \"research from\n * home → research-shaped chat\" hand-off feels continuous.\n * • From ChatHistory (which intentionally does NOT pass `initialMode`):\n * default to `'chat'`, same as Home's empty composer.\n *\n * Post-mount this is a normal local state — the search/zap pills toggle\n * it on tap, and every place that previously branched on\n * `params.initialMode` now branches on `activeMode` instead.\n */\n const [activeMode, setActiveMode] = useState<RoutingMode>(() =>\n params.initialMode === 'deep-search' ? 'deep-search' : params.initialMode === 'build' ? 'build' : 'chat',\n );\n const handleModeSwitch = useCallback((mode: RoutingMode) => {\n setActiveMode(mode);\n }, []);\n const isDeepSearchMode = activeMode === 'deep-search';\n const isBuildMode = activeMode === 'build';\n\n /**\n * Inline voice recorder state — parity with HomeScreen and the web\n * `YantraSearchComposer.showAudioRecorder` flow. When active, the panel\n * fully replaces the InputToolBar so the toolbar's mic→send button\n * doesn't compete with the panel's own send/cancel affordances.\n */\n const [showAudioRecorder, setShowAudioRecorder] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n\n /**\n * Auto-fire the initial query once when the screen mounts on a fresh channel.\n * Home creates the channel optimistically and forwards the user prompt here so\n * the first assistant token arrives without an extra interaction.\n *\n * Wait for CDeCLI to finish connecting (or fail) before auto-firing — chat is\n * cdecli-only and `sendMessage` rejects sends while the gateway is disconnected.\n */\n const autoFiredRef = useRef(false);\n useEffect(() => {\n if (autoFiredRef.current) return;\n if (!channelId || !initialQuery) return;\n if (cdecli.status !== 'connected' && cdecli.status !== 'error') return;\n\n autoFiredRef.current = true;\n // Deep-search auto-fire from Home: open the structured modal at the\n // same instant we kick off the send so the user sees the research view\n // streaming in rather than raw assistant turns. Tied to the\n // sendMessage call (same event) to avoid a race where the modal opens\n // before/after the actual send.\n //\n // We branch on the LOCAL `isDeepSearchMode` instead of\n // `params.initialMode`. At auto-fire time they're equal (the local\n // state was seeded from the param), and using the local state means\n // future toggles drive the same code path consistently.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(initialQuery, initialAttachments as any, channelId);\n try {\n navigation.setParams({ initialQuery: null, initialAttachments: null });\n } catch {\n /* setParams may be unavailable in tests; clearing is best-effort. */\n }\n }, [channelId, initialQuery, initialAttachments, sendMessage, navigation, cdecli.status, isDeepSearchMode]);\n\n const handleSend = useCallback(\n (text?: string) => {\n const t = (text ?? valueRef.current).trim();\n if (!t || !channelId) return;\n // Clear both ways: the controlled state (so React's model stays\n // consistent on next render) AND the native buffer via the ref\n // (so the visible text disappears on the same frame the user\n // pressed send, even before React flushes).\n setValue('');\n inputRef.current?.clear();\n\n // Build mode: hand off to Web Builder on this channel (web `/c/:id/webbuilder`).\n if (isBuildMode) {\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: {\n ...(params.orgName ? { orgName: params.orgName } : {}),\n channelId,\n message: t,\n },\n }),\n );\n return;\n }\n\n // Deep-search mode: every new query pops the structured research\n // modal back open (parity with the previous Home flow, where every\n // submit re-opened the DeepSearchModal). Without this, a user who\n // closed the modal once would see plain assistant turns for every\n // subsequent send. Reads the LOCAL `isDeepSearchMode` so the user\n // can toggle modes mid-thread and have sends behave accordingly.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(t, imageAttachments.forSend(), channelId);\n imageAttachments.clear();\n },\n [channelId, sendMessage, isDeepSearchMode, isBuildMode, navigation, params.orgName, imageAttachments],\n );\n\n const handleValueChange = useCallback((e: any) => {\n setValue(e?.nativeEvent?.text ?? '');\n }, []);\n\n /**\n * Mic affordance — web parity (`handleMicClick` in `YantraSearchComposer.tsx`).\n * The shared `MicSendButton` in `InputToolBar.tsx` only routes to `onMic`\n * when the input has no content, so we only need to handle the empty-input\n * case here.\n *\n * Permission is requested HERE, before the panel mounts. The previous flow\n * flipped `showAudioRecorder=true` immediately, which mounted\n * `AudioRecorderPanel` and constructed the native `AVAudioRecorder` via\n * `useAudioRecorder()` during the panel's render phase — before iOS had\n * granted mic access. On SDK 53 + `newArchEnabled: true` + Hermes that\n * ordering hard-crashes TestFlight builds even though it works in Expo Go\n * (Expo Go pre-caches permission). Asking up front means iOS shows the\n * system alert first and the panel only mounts (and therefore the native\n * recorder is only allocated) once permission is granted.\n *\n * `expo-audio` is lazy-imported so a missing/broken native module surfaces\n * as a user-visible banner instead of a synchronous TurboModule crash.\n */\n const handleMicPress = useCallback(() => {\n if (hasQuery) return;\n setVoiceError(null);\n Keyboard.dismiss();\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 }, [hasQuery]);\n\n /**\n * On a successful Whisper round-trip, paste the transcript into the input\n * field, close the recorder, and let the user review/send manually. Matches\n * web's `handleTranscriptionComplete`: we deliberately do NOT auto-fire\n * `sendMessage` because the user often wants to edit the dictation first.\n */\n const handleTranscriptionComplete = useCallback((text: string) => {\n const cleaned = (text ?? '').trim();\n setShowAudioRecorder(false);\n if (!cleaned) return;\n setValue((prev) => {\n const next = prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned;\n /*\n * Keep `inputRef`'s native text in sync with our controlled value\n * for the same reason `handleSend` does (the iOS native buffer\n * can lag the React state across a single gesture). `setNativeProps`\n * is the safe way to do this without re-rendering.\n */\n requestAnimationFrame(() => {\n inputRef.current?.setNativeProps?.({ text: next });\n inputRef.current?.focus?.();\n });\n return next;\n });\n }, []);\n\n const handleRecorderCancel = useCallback(() => {\n setShowAudioRecorder(false);\n }, []);\n\n const handleRecorderError = useCallback((error: string) => {\n setVoiceError(error);\n }, []);\n\n const waitingForAssistant = useMemo(() => {\n if ((!isLoading && !isStreaming) || messages.length === 0) return false;\n if ((response ?? '').trim()) return false;\n return messages[messages.length - 1]?.role === 'user';\n }, [isLoading, isStreaming, messages, response]);\n\n const composerScrollBottomPadding = 24 + (keyboardVisible ? keyboardHeight : 0);\n\n /*\n * NOTE: the previous read-only `isDeepSearchChannel` derivation has been\n * removed. Mode is now a freely-toggleable local state (`activeMode`)\n * driven by tapping the search/zap pills, mirroring HomeScreen. All\n * downstream branches use `isDeepSearchMode` declared with the rest of\n * the composer state above.\n */\n\n /**\n * Deep-search overlay state.\n *\n * Restored from the previous Home-screen flow (commit history): a deep-search\n * channel renders the structured `DeepSearchModal` (query / live summary /\n * sources / research process) on top of the regular Chat conversation. Closing\n * the modal reveals the same channel's MessagesContainerUI underneath so the\n * user can still see the raw turns.\n *\n * Trigger semantics — IMPORTANT:\n * • Opens ONLY when a request is actually fired in this session:\n * - Home → Chat auto-fire of `initialQuery`\n * - User sends a new message in a deep-search channel from the composer\n * - Explicit retry from inside the modal\n * • Does NOT open on plain entry from ChatHistoryScreen. That's a revisit\n * of an already-completed thread — no new API call, nothing live to\n * stream, so popping the modal would just be a confusing flash. The\n * user still sees the deep-search rendering in the chat conversation\n * underneath, and any new send re-opens the live view.\n *\n * Local UI state (accordions, open flag) lives here; data state (query /\n * summary / sources) is DERIVED from the chat stream, not stored separately,\n * so there's no drift between the modal and the underlying conversation.\n */\n const [isDeepSearchModalOpen, setIsDeepSearchModalOpen] = useState(false);\n const [researchProcessOpen, setResearchProcessOpen] = useState(true);\n const [sourcesAccordionOpen, setSourcesAccordionOpen] = useState(true);\n\n /**\n * Modal data is always scoped to the CURRENT run, not the whole channel.\n * In a multi-turn deep-search channel each send is its own \"run\": one user\n * query → one assistant summary. If we sourced from \"first user message\" /\n * \"any assistant message\", a follow-up send would keep showing the previous\n * run's query and stale sources during the transient window between the new\n * user message being appended and the first stream token arriving.\n *\n * Cursor: the LAST user message in the thread. The assistant content for\n * the current run is either:\n * • `response` while the stream is filling (token-by-token), OR\n * • the assistant message that comes AFTER the last user (run complete), OR\n * • empty — covers the brief \"user message appended, no response yet\"\n * window so the modal flips to \"Running...\" with no stale body.\n */\n const lastUserIndex = useMemo(() => {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n if (messages[i]?.role === 'user') return i;\n }\n return -1;\n }, [messages]);\n\n const deepSearchQuery = useMemo(() => {\n if (lastUserIndex >= 0) {\n const txt = messages[lastUserIndex]?.content?.trim();\n if (txt) return txt;\n }\n return initialQuery ?? null;\n }, [messages, lastUserIndex, initialQuery]);\n\n const latestAssistantContent = useMemo(() => {\n if (response && response.trim()) return response;\n if (lastUserIndex < 0) return '';\n // Look for an assistant turn strictly AFTER the last user message.\n // Anything before it belongs to a prior run and must not leak into\n // the modal for the current one.\n for (let i = lastUserIndex + 1; i < messages.length; i += 1) {\n if (messages[i]?.role === 'assistant') {\n return messages[i]?.content ?? '';\n }\n }\n return '';\n }, [response, messages, lastUserIndex]);\n\n const deepSearchSummary = useMemo(() => normalizeSummaryText(latestAssistantContent), [latestAssistantContent]);\n const deepSearchSources: DeepSearchSourceItem[] = useMemo(\n () => extractDeepSearchSources(latestAssistantContent),\n [latestAssistantContent],\n );\n\n const handleDeepSearchClose = useCallback(() => {\n if (isStreaming) cancel();\n setIsDeepSearchModalOpen(false);\n }, [isStreaming, cancel]);\n\n const handleDeepSearchRetry = useCallback(() => {\n if (!deepSearchQuery || isStreaming || !channelId) return;\n void sendMessage(deepSearchQuery, undefined, channelId);\n }, [deepSearchQuery, isStreaming, channelId, sendMessage]);\n const leftItems = useMemo(\n () =>\n getDefaultLeftItems({\n search: { active: activeMode === 'chat', onClick: () => handleModeSwitch('chat') },\n zap: { active: activeMode === 'deep-search', onClick: () => handleModeSwitch('deep-search') },\n lightbulb: {\n active: activeMode === 'build',\n onClick: () => handleModeSwitch('build'),\n },\n }),\n [activeMode, handleModeSwitch],\n );\n const rightItems = useMemo(\n () =>\n getDefaultRightItems({\n tag: { enabled: false },\n chip: { enabled: false },\n // Attaching an image was disabled here even though the transport\n // (`sendMessage(content, attachments)`) and the gateway media lane\n // already carried it, and `expo-image-picker` was already a\n // dependency with its permission strings declared in app.json.\n camera: {\n enabled: true,\n loading: imageAttachments.busy,\n onClick: () => {\n void imageAttachments.captureFromCamera();\n },\n },\n image: {\n enabled: true,\n loading: imageAttachments.busy,\n onClick: () => {\n void imageAttachments.pickFromLibrary();\n },\n },\n attach: { enabled: false },\n }),\n [imageAttachments],\n );\n /**\n * Composer placeholder.\n *\n * Mirrors Home so the composer feels like the same affordance across the\n * \"first message\" and \"continuing thread\" surfaces — only the surrounding\n * UI changes, the input stays a stable anchor. We intentionally do NOT\n * surface a \"Loading conversation…\" state in the placeholder: the message\n * list already shows a dedicated hydrating loader, and switching the\n * placeholder for ~1 frame creates a visible flash on every entry.\n */\n const inputPlaceholder = isDeepSearchMode\n ? 'Research anything...'\n : isBuildMode\n ? 'Describe an app to build...'\n : 'Ask anything...';\n\n const inputConfig = useMemo(\n () => ({\n value,\n onChange: handleValueChange,\n placeholder: inputPlaceholder,\n disabled: !channelId,\n inputRef,\n returnKeyType: 'send',\n blurOnSubmit: false,\n onSubmitEditing: () => handleSend(),\n }),\n [value, handleValueChange, inputPlaceholder, channelId, handleSend],\n );\n const micSendButton = useMemo(\n () => ({\n hasContent: hasQuery,\n onSend: () => handleSend(),\n onMic: handleMicPress,\n disabled: !channelId,\n // Empty + streaming → Stop. Typed follow-up → Send (steer). Never lock the composer.\n isLoading: canSubmit ? false : isLoading,\n onStop: isStreaming && !canSubmit ? cancel : undefined,\n steerable: isLoading || isStreaming,\n }),\n [canSubmit, handleSend, handleMicPress, isLoading, channelId, isStreaming, cancel, hasQuery],\n );\n\n /**\n * Loader visibility:\n * - `isHydrating`: Apollo channel history is being fetched and we have nothing to show yet.\n * - `isWaitingForGateway`: Home navigated us here with an `initialQuery`, but CDeCLI is still\n * establishing the workspace session, so the auto-fire is deferred. Show a \"Connecting…\"\n * placeholder instead of an empty thread so the user doesn't think their send was dropped.\n */\n const isHydrating = messagesLoading && messages.length === 0 && !response;\n const isWaitingForGateway =\n !autoFiredRef.current &&\n !!channelId &&\n !!initialQuery &&\n cdecli.status !== 'connected' &&\n cdecli.status !== 'error';\n const showSendingLoader = waitingForAssistant;\n const pinSendingLoaderNearComposer = messages.length > 0 || Boolean((response ?? '').trim());\n\n return (\n <SafeAreaView edges={['left', 'right']} style={{ flex: 1, backgroundColor: surfaceColor }}>\n {/* Tap anywhere outside an input to dismiss the keyboard. */}\n <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>\n <Box flex={1} width=\"100%\" position=\"relative\">\n {(chatError || cdecli.error) && (\n <Box\n mb=\"$2\"\n mx=\"$4\"\n p=\"$3\"\n borderRadius=\"$md\"\n style={{\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderWidth: 1,\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n }}\n >\n <Text fontSize=\"$sm\" style={{ color: isDark ? '#fecaca' : '#991b1b' }}>\n {chatError || cdecli.error}\n </Text>\n </Box>\n )}\n {!channelId ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>No channel selected</Text>\n </Box>\n ) : isHydrating ? (\n /**\n * Channel hydration (entering Chat from history or a deep\n * link) reuses the same `ThinkingIndicator` row as the\n * chat-history list — thin spinning arc + muted caption.\n * Keeps the loading vocabulary consistent across screens\n * and avoids the previous branded loader + \"Loading\n * conversation\" copy that read as a different state.\n */\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <ThinkingIndicator color={secondaryTextColor} />\n </Box>\n ) : isWaitingForGateway ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>Connecting gateway…</Text>\n </Box>\n ) : (\n <Box flex={1} width=\"100%\" alignSelf=\"stretch\">\n <MessagesContainerUI\n mode=\"chat\"\n showBackButton={false}\n compactTop\n /**\n * The composer lives OUTSIDE this container (KeyboardComposerDock\n * lifts it on the UI thread) and the container already pads by the\n * keyboard height via composerScrollBottomPadding. GiftedChat's\n * default internal handling ALSO translates the message plane by\n * the keyboard height to protect its own (here: nonexistent)\n * toolbar - double compensation that pushed short threads entirely\n * off-screen while typing.\n */\n isKeyboardInternallyHandled={false}\n {...messageActionsSlot}\n messagesContainerStyle={{\n paddingHorizontal: 0,\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n alignSelf: 'center',\n width: contentMaxWidth,\n }}\n listContentStyle={{\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n width: contentMaxWidth,\n alignSelf: 'center',\n justifyContent: 'flex-end',\n }}\n messages={transcriptRows}\n streamingContent={response}\n currentUser={CHAT_CURRENT_USER}\n onSend={handleSend}\n disabled={!channelId}\n isLoading={isLoading}\n onStop={isStreaming ? cancel : undefined}\n renderPlanInputToolbar={renderNoToolbar}\n renderBuildInputToolbar={renderNoToolbar}\n />\n </Box>\n )}\n {showSendingLoader && !pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderEmptyState}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <KeyboardComposerDock closedInset={insets.bottom} keyboardVisible={keyboardVisible}>\n {showSendingLoader && pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderInDock}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <View style={[styles.bottomComposerInner, { width: contentMaxWidth }]}>\n {voiceError ? (\n <View\n style={[\n styles.voiceErrorBanner,\n {\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n },\n ]}\n >\n <Text style={[styles.voiceErrorText, { color: isDark ? '#fecaca' : '#991b1b' }]}>\n {voiceError}\n </Text>\n </View>\n ) : null}\n {showAudioRecorder ? (\n /*\n * Render-time JS errors thrown by `useAudioRecorder`\n * (e.g. expo-audio native module missing, recorder\n * constructor throws in a release build) are caught\n * by the boundary and converted into a soft cancel\n * via the same handlers the panel itself uses on\n * runtime errors. Without this, a throw during the\n * panel's render phase kills the JS thread in\n * release / TestFlight.\n */\n <MicErrorBoundary onCancel={handleRecorderCancel} onError={handleRecorderError}>\n <AudioRecorderPanel\n isDark={isDark}\n onTranscriptionComplete={handleTranscriptionComplete}\n onCancel={handleRecorderCancel}\n onError={handleRecorderError}\n />\n </MicErrorBoundary>\n ) : (\n <InputToolBar\n inputConfig={inputConfig}\n leftItems={leftItems}\n rightItems={rightItems}\n templateButton={null}\n templateModalConfig={null}\n micSendButton={micSendButton}\n />\n )}\n </View>\n </KeyboardComposerDock>\n </Box>\n {/*\n * DeepSearchModal is rendered OUTSIDE the keyboard-dismiss wrapper so\n * taps inside the modal don't dismiss the keyboard, and it's a native\n * <Modal> internally so it correctly sits on top of the Chat surface\n * (composer included) on both iOS and Android.\n */}\n </TouchableWithoutFeedback>\n {isDeepSearchMode ? (\n <DeepSearchModal\n visible={isDeepSearchModalOpen}\n query={deepSearchQuery}\n summaryText={deepSearchSummary}\n sources={deepSearchSources}\n isStreaming={isStreaming}\n researchProcessOpen={researchProcessOpen}\n sourcesAccordionOpen={sourcesAccordionOpen}\n onToggleResearchProcess={() => setResearchProcessOpen((prev) => !prev)}\n onToggleSourcesAccordion={() => setSourcesAccordionOpen((prev) => !prev)}\n onRetry={handleDeepSearchRetry}\n onStop={cancel}\n onClose={handleDeepSearchClose}\n />\n ) : null}\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n statusText: {\n marginTop: 14,\n fontSize: 13,\n fontWeight: '500',\n },\n bottomComposerInner: {\n paddingHorizontal: 14,\n paddingTop: 10,\n paddingBottom: 4,\n },\n voiceErrorBanner: {\n marginBottom: 8,\n paddingHorizontal: 12,\n paddingVertical: 8,\n borderRadius: 10,\n borderWidth: 1,\n },\n voiceErrorText: {\n fontSize: 12,\n fontWeight: '500',\n },\n sendingLoaderEmptyState: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: 40,\n },\n sendingLoaderInDock: {\n alignItems: 'center',\n justifyContent: 'flex-end',\n paddingBottom: 8,\n },\n});\n"],"names":["_a","_b"],"mappings":"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"}
@@ -398,11 +398,42 @@ true;
398
398
  isLoading && /* @__PURE__ */ jsx(View, { style: [styles.loadingOverlay, {
399
399
  backgroundColor: surfaceColor
400
400
  }], pointerEvents: "none", children: /* @__PURE__ */ jsx(ActivityIndicator, { size: "large", color: mobileTokens.color.primary }) }),
401
- /* @__PURE__ */ jsx(WebView, __spreadValues({ ref: webViewRef, source: {
402
- uri: mfeConfig.url
403
- }, style: styles.webview, onLoadStart: handleLoadStart, onLoadEnd: handleLoadEnd, onError: handleError, onHttpError: handleHttpError, onMessage: handleMessage, onNavigationStateChange: handleNavigationStateChange, injectedJavaScriptBeforeContentLoaded: injectedBeforeContent, injectedJavaScript: reinjectAfterLoad, cacheEnabled: mfeConfig.cachePolicy !== "reload", cacheMode, javaScriptEnabled: true, domStorageEnabled: true, sharedCookiesEnabled: true, thirdPartyCookiesEnabled: true, startInLoadingState: true, scalesPageToFit: true, originWhitelist: ["*"], mixedContentMode: "always", allowsInlineMediaPlayback: false, mediaPlaybackRequiresUserAction: true, setSupportMultipleWindows: false, allowsBackForwardNavigationGestures: true }, Platform.OS === "android" ? {
404
- overScrollMode: "never"
405
- } : null), `${reloadKey}-${(_a = handoffParams.channelId) != null ? _a : "none"}-${(_b = handoffParams.snapshotId) != null ? _b : "nosnap"}-${(_c = authToken == null ? void 0 : authToken.slice(-8)) != null ? _c : "none"}`)
401
+ /* @__PURE__ */ jsx(
402
+ WebView,
403
+ __spreadValues({
404
+ ref: webViewRef,
405
+ source: {
406
+ uri: mfeConfig.url
407
+ },
408
+ style: styles.webview,
409
+ onLoadStart: handleLoadStart,
410
+ onLoadEnd: handleLoadEnd,
411
+ onError: handleError,
412
+ onHttpError: handleHttpError,
413
+ onMessage: handleMessage,
414
+ onNavigationStateChange: handleNavigationStateChange,
415
+ injectedJavaScriptBeforeContentLoaded: injectedBeforeContent,
416
+ injectedJavaScript: reinjectAfterLoad,
417
+ cacheEnabled: mfeConfig.cachePolicy !== "reload",
418
+ cacheMode,
419
+ javaScriptEnabled: true,
420
+ domStorageEnabled: true,
421
+ sharedCookiesEnabled: true,
422
+ thirdPartyCookiesEnabled: true,
423
+ startInLoadingState: true,
424
+ scalesPageToFit: true,
425
+ originWhitelist: ["*"],
426
+ mixedContentMode: "always",
427
+ mediaCapturePermissionGrantType: "grant",
428
+ allowsInlineMediaPlayback: true,
429
+ mediaPlaybackRequiresUserAction: true,
430
+ setSupportMultipleWindows: false,
431
+ allowsBackForwardNavigationGestures: true
432
+ }, Platform.OS === "android" ? {
433
+ overScrollMode: "never"
434
+ } : null),
435
+ `${reloadKey}-${(_a = handoffParams.channelId) != null ? _a : "none"}-${(_b = handoffParams.snapshotId) != null ? _b : "nosnap"}-${(_c = authToken == null ? void 0 : authToken.slice(-8)) != null ? _c : "none"}`
436
+ )
406
437
  ] });
407
438
  }
408
439
  const styles = StyleSheet.create({
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/screens/WebBuilder/index.tsx"],"sourcesContent":["/**\n * WebBuilder — native shell hosting the webbuilder-surface WebView.\n *\n * Mints the org system JWT (same as CDeCLI) and hands it to the surface via\n * `?token=&state=` (SurfaceLoginGate.captureLoginCallback) + localStorage\n * `cdecli_token`, so the standalone \"Sign in with Yantra\" gate is skipped.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n ActivityIndicator,\n AppState,\n type AppStateStatus,\n Platform,\n Pressable,\n StyleSheet,\n Text,\n useColorScheme,\n View,\n} from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport {\n WebView,\n type WebViewMessageEvent,\n type WebViewNavigation,\n type WebViewErrorEvent,\n type WebViewHttpErrorEvent,\n} from 'react-native-webview';\nimport { useNavigation, useRoute } from '@react-navigation/native';\nimport { config } from '../../config/env-config';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport {\n AnalyticsBridgeHandler,\n AuthBridgeHandler,\n getPackagerHost,\n NativeWebViewBridge,\n NavigationBridgeHandler,\n resolveMobileWebUrl,\n WEB_BRIDGE_BOOTSTRAP,\n WebViewManager,\n} from '../../bridge';\nimport {\n appendSurfaceAuthParams,\n buildCdecliTokenInjection,\n buildSurfaceGateRecoveryScript,\n} from '../../hooks/mintSurfaceSystemToken';\nimport { useObtainSystemToken } from '../../hooks/useObtainSystemToken';\nimport { usePrerequisiteIds } from '../../hooks/usePrerequisiteIds';\nimport { WebViewWithNavigation } from './WebViewWithNavigation';\nimport { setWebBuilderBackHandler } from './webbuilderBackHandler';\nimport {\n getWarmWebBuilderSession,\n setWarmWebBuilderSession,\n warmWebBuilderSession,\n clearWarmWebBuilderSession,\n} from './webbuilderWarmCache';\n\nexport type MicroFrontendCachePolicy = 'default' | 'reload' | 'cache-else-load';\n\nexport interface MicroFrontendConfig {\n url: string;\n preload?: boolean;\n cachePolicy?: MicroFrontendCachePolicy;\n}\n\nexport interface WebBuilderRouteParams {\n orgName?: string | null;\n /** Optional override URL; defaults to WEB_BUILDER_URL from env. */\n url?: string | null;\n /** Channel to open / continue in the surface (`?channelId=`). */\n channelId?: string | null;\n /** Yantra project UUID (`?projectId=`). Defaults to channelId on the surface if omitted. */\n projectId?: string | null;\n /** Optional first Agent prompt to auto-send after hydrate (`?message=`). */\n message?: string | null;\n /** E2B snapshot for template remix (`?snapshotId=`). */\n snapshotId?: string | null;\n /** Yantra form / catalog template id (`?templateId=`). */\n templateId?: string | null;\n /** Display title for the handoff template (`?templateTitle=`). */\n templateTitle?: string | null;\n /** Stack template hint (`?seedTemplate=` e.g. vite-react). */\n seedTemplate?: string | null;\n deployUrl?: string | null;\n previewUrl?: string | null;\n}\n\nfunction makeHandoffState(): string {\n return `mobile-webview-${Date.now().toString(36)}`;\n}\n\nexport default function WebBuilderScreen() {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n\n const webViewRef = useRef<WebView>(null);\n const bridgeRef = useRef<NativeWebViewBridge | null>(null);\n\n const [isLoading, setIsLoading] = useState(true);\n const [hasError, setHasError] = useState(false);\n const [errorDetail, setErrorDetail] = useState<string | null>(null);\n const [canGoBack, setCanGoBack] = useState(false);\n const previewOpenRef = useRef(false);\n const [reloadKey, setReloadKey] = useState(0);\n const warm = getWarmWebBuilderSession();\n const [authToken, setAuthToken] = useState<string | null>(() => warm?.token ?? null);\n const [authBackend, setAuthBackend] = useState<string | null>(() => warm?.backend ?? null);\n const [authState, setAuthState] = useState<string>(() => makeHandoffState());\n // If Home already warmed the session, skip the full-screen Preparing gate.\n const [authReady, setAuthReady] = useState(() => Boolean(warm?.token));\n const [authError, setAuthError] = useState<string | null>(null);\n const [mintGeneration, setMintGeneration] = useState(0);\n\n const { orgName, projectId, tagId } = usePrerequisiteIds();\n // Same Apollo session the rest of the app uses (web harness pastes this JWT).\n // Raw fetch + SecureStore Auth0 Bearer gets 401 on local GraphQL; Apollo does not.\n const { obtainSystemToken } = useObtainSystemToken(true);\n\n const packagerHost = getPackagerHost();\n\n const handoffParams = useMemo(() => {\n const params = route?.params as WebBuilderRouteParams | undefined;\n const read = (key: keyof WebBuilderRouteParams) => {\n const value = params?.[key];\n return typeof value === 'string' ? value.trim() : '';\n };\n const channelId = read('channelId');\n const projectIdParam = read('projectId');\n const message = read('message');\n const snapshotId = read('snapshotId');\n const templateId = read('templateId');\n const templateTitle = read('templateTitle');\n const seedTemplate = read('seedTemplate');\n const deployUrl = read('deployUrl');\n const previewUrl = read('previewUrl');\n return {\n channelId: channelId || null,\n projectId: projectIdParam || null,\n message: message || null,\n snapshotId: snapshotId || null,\n templateId: templateId || null,\n templateTitle: templateTitle || null,\n seedTemplate: seedTemplate || null,\n deployUrl: deployUrl || null,\n previewUrl: previewUrl || null,\n };\n }, [route?.params]);\n\n const routeOrgName = useMemo(() => {\n const raw = (route?.params as WebBuilderRouteParams | undefined)?.orgName;\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [route?.params]);\n const effectiveOrgName = orgName || routeOrgName;\n const effectiveProjectId = projectId || handoffParams.projectId;\n\n const baseUrl = useMemo(() => {\n const fromParams = (route?.params as WebBuilderRouteParams | undefined)?.url;\n const raw = typeof fromParams === 'string' && fromParams.trim() ? fromParams.trim() : config.WEB_BUILDER_URL;\n const resolved = resolveMobileWebUrl(raw, packagerHost);\n const stamp = (url: URL) => {\n // Always mark mobile WebView embeds so the surface hides harness chrome\n // (cdecli JWT bar + @yantra/webbuilder-surface label).\n url.searchParams.set('embed', 'mobile');\n // Snapshot remix: omit channelId/projectId/previewUrl/deployUrl so the surface\n // mints a fresh listen channel+project from snapshotId (does not reconnect a\n // live sandbox or poll an empty mobile-precreated channel).\n const isRemix = Boolean(handoffParams.snapshotId);\n if (!isRemix && handoffParams.channelId) url.searchParams.set('channelId', handoffParams.channelId);\n if (!isRemix && handoffParams.projectId) url.searchParams.set('projectId', handoffParams.projectId);\n if (handoffParams.message) url.searchParams.set('message', handoffParams.message);\n if (handoffParams.snapshotId) url.searchParams.set('snapshotId', handoffParams.snapshotId);\n if (handoffParams.templateId) url.searchParams.set('templateId', handoffParams.templateId);\n if (handoffParams.templateTitle) url.searchParams.set('templateTitle', handoffParams.templateTitle);\n if (handoffParams.seedTemplate) url.searchParams.set('seedTemplate', handoffParams.seedTemplate);\n };\n try {\n const url = new URL(resolved);\n stamp(url);\n return url.toString();\n } catch {\n const sep = resolved.includes('?') ? '&' : '?';\n const parts: string[] = ['embed=mobile'];\n const isRemix = Boolean(handoffParams.snapshotId);\n if (!isRemix && handoffParams.channelId) {\n parts.push(`channelId=${encodeURIComponent(handoffParams.channelId)}`);\n }\n if (!isRemix && handoffParams.projectId) {\n parts.push(`projectId=${encodeURIComponent(handoffParams.projectId)}`);\n }\n if (handoffParams.message) parts.push(`message=${encodeURIComponent(handoffParams.message)}`);\n if (handoffParams.snapshotId) parts.push(`snapshotId=${encodeURIComponent(handoffParams.snapshotId)}`);\n if (handoffParams.templateId) parts.push(`templateId=${encodeURIComponent(handoffParams.templateId)}`);\n if (handoffParams.templateTitle) {\n parts.push(`templateTitle=${encodeURIComponent(handoffParams.templateTitle)}`);\n }\n if (handoffParams.seedTemplate) {\n parts.push(`seedTemplate=${encodeURIComponent(handoffParams.seedTemplate)}`);\n }\n return `${resolved}${sep}${parts.join('&')}`;\n }\n }, [route?.params, packagerHost, handoffParams]);\n\n /** Same GRAPHQL_URL the rest of the app uses — rewritten for device LAN. */\n const graphqlUrl = useMemo(() => resolveMobileWebUrl(config.GRAPHQL_URL, packagerHost), [packagerHost]);\n\n useEffect(() => {\n let cancelled = false;\n const handoffState = makeHandoffState();\n setAuthState(handoffState);\n setAuthError(null);\n\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] surface=', baseUrl, 'graphql=', graphqlUrl);\n }\n\n // Prefer Home prewarm — never clear authReady / show Preparing if we already have a token.\n const cached = getWarmWebBuilderSession();\n if (cached?.token) {\n setAuthToken(cached.token);\n setAuthBackend(cached.backend || graphqlUrl);\n setAuthReady(true);\n return () => {\n cancelled = true;\n };\n }\n\n (async () => {\n try {\n // Don't hard-block on GetUserSystemToken loading — warm falls back to raw mint.\n const session = await warmWebBuilderSession({\n graphqlUrl,\n orgName: effectiveOrgName,\n projectId: effectiveProjectId,\n tagId,\n obtainSystemToken,\n });\n if (cancelled) return;\n setAuthToken(session.token);\n setAuthBackend(session.backend);\n setWarmWebBuilderSession(session);\n setAuthReady(true);\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] session ready length=', session.token.length);\n }\n } catch (err) {\n if (cancelled) return;\n // Still missing org/project — keep preparing a short while until they arrive.\n if (!effectiveOrgName || !effectiveProjectId) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] waiting for org/project…');\n }\n return;\n }\n const message = err instanceof Error ? err.message : 'Token mint failed';\n if (/Waiting for org\\/project/i.test(message)) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] waiting for org/project…');\n }\n return;\n }\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] surface token mint failed:', message);\n setAuthError(message);\n setAuthToken(null);\n setAuthBackend(null);\n setAuthReady(true);\n }\n })();\n\n // Absolute ceiling so Preparing never hangs indefinitely.\n const failsafe = setTimeout(() => {\n if (cancelled) return;\n setAuthReady((ready) => {\n if (ready) return ready;\n setAuthError('Timed out preparing Web Builder. Ensure you are signed in with an org, then retry.');\n return true;\n });\n }, 20000);\n\n return () => {\n cancelled = true;\n clearTimeout(failsafe);\n };\n }, [baseUrl, graphqlUrl, obtainSystemToken, effectiveOrgName, effectiveProjectId, tagId, mintGeneration]);\n\n const mfeUrl = useMemo(() => {\n if (!authToken) return baseUrl;\n return appendSurfaceAuthParams(baseUrl, authToken, authState);\n }, [baseUrl, authToken, authState]);\n\n const injectedBeforeContent = useMemo(() => {\n const parts = [WEB_BRIDGE_BOOTSTRAP];\n if (authToken && authBackend) {\n parts.unshift(buildCdecliTokenInjection(authToken, authBackend, authState));\n }\n return parts.join('\\n');\n }, [authToken, authBackend, authState]);\n\n /** If the SPA still shows the login gate after load, force one handoff reload. */\n const reinjectAfterLoad = useMemo(() => {\n if (!authToken || !authBackend) return undefined;\n return buildSurfaceGateRecoveryScript(authToken, authBackend, authState);\n }, [authToken, authBackend, authState]);\n\n const mfeConfig: MicroFrontendConfig = useMemo(\n () => ({\n url: mfeUrl,\n cachePolicy: 'default',\n }),\n [mfeUrl],\n );\n\n const webViewManager = WebViewManager.getInstance();\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const textColor = isDark ? '#f8fafc' : mobileTokens.color.text;\n const mutedColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n // Bridge + service handlers\n useEffect(() => {\n const bridge = new NativeWebViewBridge(webViewRef);\n bridgeRef.current = bridge;\n // eslint-disable-next-line no-new\n new AuthBridgeHandler(bridge);\n // eslint-disable-next-line no-new\n new NavigationBridgeHandler(bridge, () => navigation);\n // eslint-disable-next-line no-new\n new AnalyticsBridgeHandler(bridge);\n\n return () => {\n bridge.dispose();\n bridgeRef.current = null;\n };\n }, [navigation]);\n\n useEffect(() => {\n if (!authToken) return;\n const id = mfeConfig.url;\n webViewManager.registerWebView(id, webViewRef);\n return () => {\n webViewManager.unregisterWebView(id);\n };\n }, [authToken, mfeConfig.url, webViewManager]);\n\n useEffect(() => {\n const handleAppStateChange = (nextAppState: AppStateStatus) => {\n if (nextAppState === 'background') {\n webViewRef.current?.clearCache?.(true);\n }\n };\n const subscription = AppState.addEventListener('change', handleAppStateChange);\n return () => subscription.remove();\n }, []);\n\n useEffect(() => {\n if (!authReady || !authToken || hasError) return;\n const timer = setTimeout(() => {\n setIsLoading((loading) => {\n if (!loading) return loading;\n const detail = `Timed out loading ${mfeConfig.url}. Is WEB_BUILDER_URL reachable from this device?`;\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder]', detail);\n setErrorDetail(detail);\n setHasError(true);\n return false;\n });\n }, 20000);\n return () => clearTimeout(timer);\n }, [authReady, authToken, hasError, mfeConfig.url, reloadKey]);\n\n const handleLoadStart = useCallback(() => {\n setIsLoading(true);\n setHasError(false);\n setErrorDetail(null);\n }, []);\n\n const handleLoadEnd = useCallback(() => {\n setIsLoading(false);\n webViewManager.updateUsage(mfeConfig.url);\n }, [mfeConfig.url, webViewManager]);\n\n const handleError = useCallback(\n (event: WebViewErrorEvent) => {\n const { description, code, url } = event.nativeEvent;\n const detail = [description, code != null ? `code ${code}` : null, url || mfeConfig.url]\n .filter(Boolean)\n .join(' · ');\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] load error:', detail);\n }\n setErrorDetail(detail);\n setHasError(true);\n setIsLoading(false);\n },\n [mfeConfig.url],\n );\n\n const handleHttpError = useCallback(\n (event: WebViewHttpErrorEvent) => {\n const { statusCode, description, url } = event.nativeEvent;\n if (statusCode < 400) return;\n const detail = `HTTP ${statusCode}${description ? `: ${description}` : ''} · ${url || mfeConfig.url}`;\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] http error:', detail);\n }\n setErrorDetail(detail);\n setHasError(true);\n setIsLoading(false);\n },\n [mfeConfig.url],\n );\n\n const handleMessage = useCallback((event: WebViewMessageEvent) => {\n try {\n const raw = event?.nativeEvent?.data;\n if (typeof raw === 'string' && raw.includes('wb-preview')) {\n const parsed = JSON.parse(raw) as { type?: string; open?: boolean };\n if (parsed?.type === 'wb-preview') {\n previewOpenRef.current = Boolean(parsed.open);\n }\n }\n } catch {\n /* non-JSON bridge frames are handled below */\n }\n bridgeRef.current?.handleMessage(event);\n }, []);\n\n const handleNavigationStateChange = useCallback((navState: WebViewNavigation) => {\n setCanGoBack(Boolean(navState.canGoBack));\n }, []);\n\n const handleRetry = useCallback(() => {\n clearWarmWebBuilderSession();\n setHasError(false);\n setErrorDetail(null);\n setAuthError(null);\n setAuthToken(null);\n setAuthBackend(null);\n setAuthReady(false);\n setIsLoading(true);\n setMintGeneration((g) => g + 1);\n setReloadKey((k) => k + 1);\n }, []);\n\n const handleNativeGoBack = useCallback(() => {\n if (navigation.canGoBack()) {\n navigation.goBack();\n return;\n }\n navigation.navigate('MainStack.Layout.Home' as never);\n }, [navigation]);\n\n // Header / hardware back: only intercept when in-app preview is open\n // (dismiss → stay on WebBuilder). Do NOT consume SPA WebView history —\n // handoff/pushState makes canGoBack true and trapped users on this screen.\n useEffect(() => {\n setWebBuilderBackHandler(() => {\n if (previewOpenRef.current) {\n webViewRef.current?.injectJavaScript(`\n(function () {\n try { window.__yantraWbNativeBack && window.__yantraWbNativeBack(); } catch (e) {}\n})();\ntrue;\n`);\n previewOpenRef.current = false;\n return true;\n }\n return false;\n });\n return () => setWebBuilderBackHandler(null);\n }, []);\n\n const cacheMode =\n mfeConfig.cachePolicy === 'cache-else-load' ? ('LOAD_CACHE_ELSE_NETWORK' as const) : ('LOAD_DEFAULT' as const);\n\n const showAuthSpinner = !authReady;\n const showAuthFailure = authReady && !authToken;\n\n if (showAuthSpinner) {\n return (\n <SafeAreaView\n edges={['left', 'right', 'bottom']}\n style={[styles.container, { backgroundColor: surfaceColor }]}\n >\n <View style={styles.centered}>\n <ActivityIndicator size=\"large\" color={mobileTokens.color.primary} />\n <Text style={[styles.errorBody, { color: mutedColor, marginTop: 12 }]}>Preparing Web Builder…</Text>\n </View>\n </SafeAreaView>\n );\n }\n\n if (showAuthFailure || hasError) {\n return (\n <SafeAreaView\n edges={['left', 'right', 'bottom']}\n style={[styles.container, { backgroundColor: surfaceColor }]}\n >\n <View style={styles.centered}>\n <Text style={[styles.errorTitle, { color: textColor }]}>\n {showAuthFailure ? 'Could not open Web Builder' : 'Failed to load micro frontend'}\n </Text>\n <Text style={[styles.errorBody, { color: mutedColor }]}>\n {showAuthFailure\n ? authError ||\n 'Sign-in token could not be minted for the surface. Ensure you are logged in with an org.'\n : `Could not open ${baseUrl}. Check WEB_BUILDER_URL / network, then retry.`}\n </Text>\n {errorDetail ? (\n <Text style={[styles.errorMeta, { color: mutedColor }]} selectable>\n {errorDetail}\n </Text>\n ) : null}\n <Pressable\n onPress={handleRetry}\n style={[styles.retryButton, { backgroundColor: mobileTokens.color.primary }]}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Retry loading WebBuilder\"\n >\n <Text style={styles.retryLabel}>Retry</Text>\n </Pressable>\n </View>\n </SafeAreaView>\n );\n }\n\n return (\n <SafeAreaView edges={['left', 'right', 'bottom']} style={[styles.container, { backgroundColor: surfaceColor }]}>\n <WebViewWithNavigation webViewRef={webViewRef} canGoBack={canGoBack} onGoBack={handleNativeGoBack} />\n\n {isLoading && (\n <View style={[styles.loadingOverlay, { backgroundColor: surfaceColor }]} pointerEvents=\"none\">\n <ActivityIndicator size=\"large\" color={mobileTokens.color.primary} />\n </View>\n )}\n\n <WebView\n key={`${reloadKey}-${handoffParams.channelId ?? 'none'}-${handoffParams.snapshotId ?? 'nosnap'}-${authToken?.slice(-8) ?? 'none'}`}\n ref={webViewRef}\n source={{\n uri: mfeConfig.url,\n }}\n style={styles.webview}\n onLoadStart={handleLoadStart}\n onLoadEnd={handleLoadEnd}\n onError={handleError}\n onHttpError={handleHttpError}\n onMessage={handleMessage}\n onNavigationStateChange={handleNavigationStateChange}\n injectedJavaScriptBeforeContentLoaded={injectedBeforeContent}\n injectedJavaScript={reinjectAfterLoad}\n cacheEnabled={mfeConfig.cachePolicy !== 'reload'}\n cacheMode={cacheMode}\n javaScriptEnabled\n domStorageEnabled\n sharedCookiesEnabled\n thirdPartyCookiesEnabled\n startInLoadingState\n scalesPageToFit\n originWhitelist={['*']}\n mixedContentMode=\"always\"\n allowsInlineMediaPlayback={false}\n mediaPlaybackRequiresUserAction\n setSupportMultipleWindows={false}\n allowsBackForwardNavigationGestures\n {...(Platform.OS === 'android' ? { overScrollMode: 'never' as const } : null)}\n />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n },\n webview: {\n flex: 1,\n backgroundColor: 'transparent',\n },\n loadingOverlay: {\n ...StyleSheet.absoluteFillObject,\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: 1000,\n },\n centered: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n paddingHorizontal: 24,\n gap: 12,\n },\n errorTitle: {\n fontSize: 17,\n fontWeight: '600',\n textAlign: 'center',\n },\n errorBody: {\n fontSize: 14,\n textAlign: 'center',\n marginBottom: 4,\n lineHeight: 20,\n },\n errorMeta: {\n fontSize: 12,\n textAlign: 'center',\n marginBottom: 8,\n lineHeight: 16,\n },\n retryButton: {\n paddingHorizontal: 20,\n paddingVertical: 12,\n borderRadius: mobileTokens.radius.md,\n },\n retryLabel: {\n color: '#ffffff',\n fontSize: 15,\n fontWeight: '600',\n },\n});\n"],"names":["_a","_b"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/screens/WebBuilder/index.tsx"],"sourcesContent":["/**\n * WebBuilder — native shell hosting the webbuilder-surface WebView.\n *\n * Mints the org system JWT (same as CDeCLI) and hands it to the surface via\n * `?token=&state=` (SurfaceLoginGate.captureLoginCallback) + localStorage\n * `cdecli_token`, so the standalone \"Sign in with Yantra\" gate is skipped.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n ActivityIndicator,\n AppState,\n type AppStateStatus,\n Platform,\n Pressable,\n StyleSheet,\n Text,\n useColorScheme,\n View,\n} from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { WebView, type WebViewMessageEvent, type WebViewNavigation } from 'react-native-webview';\nimport type { WebViewErrorEvent, WebViewHttpErrorEvent } from 'react-native-webview/lib/WebViewTypes';\nimport { useNavigation, useRoute } from '@react-navigation/native';\nimport { config } from '../../config/env-config';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport {\n AnalyticsBridgeHandler,\n AuthBridgeHandler,\n getPackagerHost,\n NativeWebViewBridge,\n NavigationBridgeHandler,\n resolveMobileWebUrl,\n WEB_BRIDGE_BOOTSTRAP,\n WebViewManager,\n} from '../../bridge';\nimport {\n appendSurfaceAuthParams,\n buildCdecliTokenInjection,\n buildSurfaceGateRecoveryScript,\n} from '../../hooks/mintSurfaceSystemToken';\nimport { useObtainSystemToken } from '../../hooks/useObtainSystemToken';\nimport { usePrerequisiteIds } from '../../hooks/usePrerequisiteIds';\nimport { WebViewWithNavigation } from './WebViewWithNavigation';\nimport { setWebBuilderBackHandler } from './webbuilderBackHandler';\nimport {\n getWarmWebBuilderSession,\n setWarmWebBuilderSession,\n warmWebBuilderSession,\n clearWarmWebBuilderSession,\n} from './webbuilderWarmCache';\n\nexport type MicroFrontendCachePolicy = 'default' | 'reload' | 'cache-else-load';\n\nexport interface MicroFrontendConfig {\n url: string;\n preload?: boolean;\n cachePolicy?: MicroFrontendCachePolicy;\n}\n\nexport interface WebBuilderRouteParams {\n orgName?: string | null;\n /** Optional override URL; defaults to WEB_BUILDER_URL from env. */\n url?: string | null;\n /** Channel to open / continue in the surface (`?channelId=`). */\n channelId?: string | null;\n /** Yantra project UUID (`?projectId=`). Defaults to channelId on the surface if omitted. */\n projectId?: string | null;\n /** Optional first Agent prompt to auto-send after hydrate (`?message=`). */\n message?: string | null;\n /** E2B snapshot for template remix (`?snapshotId=`). */\n snapshotId?: string | null;\n /** Yantra form / catalog template id (`?templateId=`). */\n templateId?: string | null;\n /** Display title for the handoff template (`?templateTitle=`). */\n templateTitle?: string | null;\n /** Stack template hint (`?seedTemplate=` e.g. vite-react). */\n seedTemplate?: string | null;\n deployUrl?: string | null;\n previewUrl?: string | null;\n}\n\nfunction makeHandoffState(): string {\n return `mobile-webview-${Date.now().toString(36)}`;\n}\n\nexport default function WebBuilderScreen() {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n\n const webViewRef = useRef<WebView>(null);\n const bridgeRef = useRef<NativeWebViewBridge | null>(null);\n\n const [isLoading, setIsLoading] = useState(true);\n const [hasError, setHasError] = useState(false);\n const [errorDetail, setErrorDetail] = useState<string | null>(null);\n const [canGoBack, setCanGoBack] = useState(false);\n const previewOpenRef = useRef(false);\n const [reloadKey, setReloadKey] = useState(0);\n const warm = getWarmWebBuilderSession();\n const [authToken, setAuthToken] = useState<string | null>(() => warm?.token ?? null);\n const [authBackend, setAuthBackend] = useState<string | null>(() => warm?.backend ?? null);\n const [authState, setAuthState] = useState<string>(() => makeHandoffState());\n // If Home already warmed the session, skip the full-screen Preparing gate.\n const [authReady, setAuthReady] = useState(() => Boolean(warm?.token));\n const [authError, setAuthError] = useState<string | null>(null);\n const [mintGeneration, setMintGeneration] = useState(0);\n\n const { orgName, projectId, tagId } = usePrerequisiteIds();\n // Same Apollo session the rest of the app uses (web harness pastes this JWT).\n // Raw fetch + SecureStore Auth0 Bearer gets 401 on local GraphQL; Apollo does not.\n const { obtainSystemToken } = useObtainSystemToken(true);\n\n const packagerHost = getPackagerHost();\n\n const handoffParams = useMemo(() => {\n const params = route?.params as WebBuilderRouteParams | undefined;\n const read = (key: keyof WebBuilderRouteParams) => {\n const value = params?.[key];\n return typeof value === 'string' ? value.trim() : '';\n };\n const channelId = read('channelId');\n const projectIdParam = read('projectId');\n const message = read('message');\n const snapshotId = read('snapshotId');\n const templateId = read('templateId');\n const templateTitle = read('templateTitle');\n const seedTemplate = read('seedTemplate');\n const deployUrl = read('deployUrl');\n const previewUrl = read('previewUrl');\n return {\n channelId: channelId || null,\n projectId: projectIdParam || null,\n message: message || null,\n snapshotId: snapshotId || null,\n templateId: templateId || null,\n templateTitle: templateTitle || null,\n seedTemplate: seedTemplate || null,\n deployUrl: deployUrl || null,\n previewUrl: previewUrl || null,\n };\n }, [route?.params]);\n\n const routeOrgName = useMemo(() => {\n const raw = (route?.params as WebBuilderRouteParams | undefined)?.orgName;\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [route?.params]);\n const effectiveOrgName = orgName || routeOrgName;\n const effectiveProjectId = projectId || handoffParams.projectId;\n\n const baseUrl = useMemo(() => {\n const fromParams = (route?.params as WebBuilderRouteParams | undefined)?.url;\n const raw = typeof fromParams === 'string' && fromParams.trim() ? fromParams.trim() : config.WEB_BUILDER_URL;\n const resolved = resolveMobileWebUrl(raw, packagerHost);\n const stamp = (url: URL) => {\n // Always mark mobile WebView embeds so the surface hides harness chrome\n // (cdecli JWT bar + @yantra/webbuilder-surface label).\n url.searchParams.set('embed', 'mobile');\n // Snapshot remix: omit channelId/projectId/previewUrl/deployUrl so the surface\n // mints a fresh listen channel+project from snapshotId (does not reconnect a\n // live sandbox or poll an empty mobile-precreated channel).\n const isRemix = Boolean(handoffParams.snapshotId);\n if (!isRemix && handoffParams.channelId) url.searchParams.set('channelId', handoffParams.channelId);\n if (!isRemix && handoffParams.projectId) url.searchParams.set('projectId', handoffParams.projectId);\n if (handoffParams.message) url.searchParams.set('message', handoffParams.message);\n if (handoffParams.snapshotId) url.searchParams.set('snapshotId', handoffParams.snapshotId);\n if (handoffParams.templateId) url.searchParams.set('templateId', handoffParams.templateId);\n if (handoffParams.templateTitle) url.searchParams.set('templateTitle', handoffParams.templateTitle);\n if (handoffParams.seedTemplate) url.searchParams.set('seedTemplate', handoffParams.seedTemplate);\n };\n try {\n const url = new URL(resolved);\n stamp(url);\n return url.toString();\n } catch {\n const sep = resolved.includes('?') ? '&' : '?';\n const parts: string[] = ['embed=mobile'];\n const isRemix = Boolean(handoffParams.snapshotId);\n if (!isRemix && handoffParams.channelId) {\n parts.push(`channelId=${encodeURIComponent(handoffParams.channelId)}`);\n }\n if (!isRemix && handoffParams.projectId) {\n parts.push(`projectId=${encodeURIComponent(handoffParams.projectId)}`);\n }\n if (handoffParams.message) parts.push(`message=${encodeURIComponent(handoffParams.message)}`);\n if (handoffParams.snapshotId) parts.push(`snapshotId=${encodeURIComponent(handoffParams.snapshotId)}`);\n if (handoffParams.templateId) parts.push(`templateId=${encodeURIComponent(handoffParams.templateId)}`);\n if (handoffParams.templateTitle) {\n parts.push(`templateTitle=${encodeURIComponent(handoffParams.templateTitle)}`);\n }\n if (handoffParams.seedTemplate) {\n parts.push(`seedTemplate=${encodeURIComponent(handoffParams.seedTemplate)}`);\n }\n return `${resolved}${sep}${parts.join('&')}`;\n }\n }, [route?.params, packagerHost, handoffParams]);\n\n /** Same GRAPHQL_URL the rest of the app uses — rewritten for device LAN. */\n const graphqlUrl = useMemo(() => resolveMobileWebUrl(config.GRAPHQL_URL, packagerHost), [packagerHost]);\n\n useEffect(() => {\n let cancelled = false;\n const handoffState = makeHandoffState();\n setAuthState(handoffState);\n setAuthError(null);\n\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] surface=', baseUrl, 'graphql=', graphqlUrl);\n }\n\n // Prefer Home prewarm — never clear authReady / show Preparing if we already have a token.\n const cached = getWarmWebBuilderSession();\n if (cached?.token) {\n setAuthToken(cached.token);\n setAuthBackend(cached.backend || graphqlUrl);\n setAuthReady(true);\n return () => {\n cancelled = true;\n };\n }\n\n (async () => {\n try {\n // Don't hard-block on GetUserSystemToken loading — warm falls back to raw mint.\n const session = await warmWebBuilderSession({\n graphqlUrl,\n orgName: effectiveOrgName,\n projectId: effectiveProjectId,\n tagId,\n obtainSystemToken,\n });\n if (cancelled) return;\n setAuthToken(session.token);\n setAuthBackend(session.backend);\n setWarmWebBuilderSession(session);\n setAuthReady(true);\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] session ready length=', session.token.length);\n }\n } catch (err) {\n if (cancelled) return;\n // Still missing org/project — keep preparing a short while until they arrive.\n if (!effectiveOrgName || !effectiveProjectId) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] waiting for org/project…');\n }\n return;\n }\n const message = err instanceof Error ? err.message : 'Token mint failed';\n if (/Waiting for org\\/project/i.test(message)) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] waiting for org/project…');\n }\n return;\n }\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] surface token mint failed:', message);\n setAuthError(message);\n setAuthToken(null);\n setAuthBackend(null);\n setAuthReady(true);\n }\n })();\n\n // Absolute ceiling so Preparing never hangs indefinitely.\n const failsafe = setTimeout(() => {\n if (cancelled) return;\n setAuthReady((ready) => {\n if (ready) return ready;\n setAuthError('Timed out preparing Web Builder. Ensure you are signed in with an org, then retry.');\n return true;\n });\n }, 20000);\n\n return () => {\n cancelled = true;\n clearTimeout(failsafe);\n };\n }, [baseUrl, graphqlUrl, obtainSystemToken, effectiveOrgName, effectiveProjectId, tagId, mintGeneration]);\n\n const mfeUrl = useMemo(() => {\n if (!authToken) return baseUrl;\n return appendSurfaceAuthParams(baseUrl, authToken, authState);\n }, [baseUrl, authToken, authState]);\n\n const injectedBeforeContent = useMemo(() => {\n const parts = [WEB_BRIDGE_BOOTSTRAP];\n if (authToken && authBackend) {\n parts.unshift(buildCdecliTokenInjection(authToken, authBackend, authState));\n }\n return parts.join('\\n');\n }, [authToken, authBackend, authState]);\n\n /** If the SPA still shows the login gate after load, force one handoff reload. */\n const reinjectAfterLoad = useMemo(() => {\n if (!authToken || !authBackend) return undefined;\n return buildSurfaceGateRecoveryScript(authToken, authBackend, authState);\n }, [authToken, authBackend, authState]);\n\n const mfeConfig: MicroFrontendConfig = useMemo(\n () => ({\n url: mfeUrl,\n cachePolicy: 'default',\n }),\n [mfeUrl],\n );\n\n const webViewManager = WebViewManager.getInstance();\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const textColor = isDark ? '#f8fafc' : mobileTokens.color.text;\n const mutedColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n // Bridge + service handlers\n useEffect(() => {\n const bridge = new NativeWebViewBridge(webViewRef);\n bridgeRef.current = bridge;\n // eslint-disable-next-line no-new\n new AuthBridgeHandler(bridge);\n // eslint-disable-next-line no-new\n new NavigationBridgeHandler(bridge, () => navigation);\n // eslint-disable-next-line no-new\n new AnalyticsBridgeHandler(bridge);\n\n return () => {\n bridge.dispose();\n bridgeRef.current = null;\n };\n }, [navigation]);\n\n useEffect(() => {\n if (!authToken) return;\n const id = mfeConfig.url;\n webViewManager.registerWebView(id, webViewRef);\n return () => {\n webViewManager.unregisterWebView(id);\n };\n }, [authToken, mfeConfig.url, webViewManager]);\n\n useEffect(() => {\n const handleAppStateChange = (nextAppState: AppStateStatus) => {\n if (nextAppState === 'background') {\n webViewRef.current?.clearCache?.(true);\n }\n };\n const subscription = AppState.addEventListener('change', handleAppStateChange);\n return () => subscription.remove();\n }, []);\n\n useEffect(() => {\n if (!authReady || !authToken || hasError) return;\n const timer = setTimeout(() => {\n setIsLoading((loading) => {\n if (!loading) return loading;\n const detail = `Timed out loading ${mfeConfig.url}. Is WEB_BUILDER_URL reachable from this device?`;\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder]', detail);\n setErrorDetail(detail);\n setHasError(true);\n return false;\n });\n }, 20000);\n return () => clearTimeout(timer);\n }, [authReady, authToken, hasError, mfeConfig.url, reloadKey]);\n\n const handleLoadStart = useCallback(() => {\n setIsLoading(true);\n setHasError(false);\n setErrorDetail(null);\n }, []);\n\n const handleLoadEnd = useCallback(() => {\n setIsLoading(false);\n webViewManager.updateUsage(mfeConfig.url);\n }, [mfeConfig.url, webViewManager]);\n\n const handleError = useCallback(\n (event: WebViewErrorEvent) => {\n const { description, code, url } = event.nativeEvent;\n const detail = [description, code != null ? `code ${code}` : null, url || mfeConfig.url]\n .filter(Boolean)\n .join(' · ');\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] load error:', detail);\n }\n setErrorDetail(detail);\n setHasError(true);\n setIsLoading(false);\n },\n [mfeConfig.url],\n );\n\n const handleHttpError = useCallback(\n (event: WebViewHttpErrorEvent) => {\n const { statusCode, description, url } = event.nativeEvent;\n if (statusCode < 400) return;\n const detail = `HTTP ${statusCode}${description ? `: ${description}` : ''} · ${url || mfeConfig.url}`;\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] http error:', detail);\n }\n setErrorDetail(detail);\n setHasError(true);\n setIsLoading(false);\n },\n [mfeConfig.url],\n );\n\n const handleMessage = useCallback((event: WebViewMessageEvent) => {\n try {\n const raw = event?.nativeEvent?.data;\n if (typeof raw === 'string' && raw.includes('wb-preview')) {\n const parsed = JSON.parse(raw) as { type?: string; open?: boolean };\n if (parsed?.type === 'wb-preview') {\n previewOpenRef.current = Boolean(parsed.open);\n }\n }\n } catch {\n /* non-JSON bridge frames are handled below */\n }\n bridgeRef.current?.handleMessage(event);\n }, []);\n\n const handleNavigationStateChange = useCallback((navState: WebViewNavigation) => {\n setCanGoBack(Boolean(navState.canGoBack));\n }, []);\n\n const handleRetry = useCallback(() => {\n clearWarmWebBuilderSession();\n setHasError(false);\n setErrorDetail(null);\n setAuthError(null);\n setAuthToken(null);\n setAuthBackend(null);\n setAuthReady(false);\n setIsLoading(true);\n setMintGeneration((g) => g + 1);\n setReloadKey((k) => k + 1);\n }, []);\n\n const handleNativeGoBack = useCallback(() => {\n if (navigation.canGoBack()) {\n navigation.goBack();\n return;\n }\n navigation.navigate('MainStack.Layout.Home' as never);\n }, [navigation]);\n\n // Header / hardware back: only intercept when in-app preview is open\n // (dismiss → stay on WebBuilder). Do NOT consume SPA WebView history —\n // handoff/pushState makes canGoBack true and trapped users on this screen.\n useEffect(() => {\n setWebBuilderBackHandler(() => {\n if (previewOpenRef.current) {\n webViewRef.current?.injectJavaScript(`\n(function () {\n try { window.__yantraWbNativeBack && window.__yantraWbNativeBack(); } catch (e) {}\n})();\ntrue;\n`);\n previewOpenRef.current = false;\n return true;\n }\n return false;\n });\n return () => setWebBuilderBackHandler(null);\n }, []);\n\n const cacheMode =\n mfeConfig.cachePolicy === 'cache-else-load' ? ('LOAD_CACHE_ELSE_NETWORK' as const) : ('LOAD_DEFAULT' as const);\n\n const showAuthSpinner = !authReady;\n const showAuthFailure = authReady && !authToken;\n\n if (showAuthSpinner) {\n return (\n <SafeAreaView\n edges={['left', 'right', 'bottom']}\n style={[styles.container, { backgroundColor: surfaceColor }]}\n >\n <View style={styles.centered}>\n <ActivityIndicator size=\"large\" color={mobileTokens.color.primary} />\n <Text style={[styles.errorBody, { color: mutedColor, marginTop: 12 }]}>Preparing Web Builder…</Text>\n </View>\n </SafeAreaView>\n );\n }\n\n if (showAuthFailure || hasError) {\n return (\n <SafeAreaView\n edges={['left', 'right', 'bottom']}\n style={[styles.container, { backgroundColor: surfaceColor }]}\n >\n <View style={styles.centered}>\n <Text style={[styles.errorTitle, { color: textColor }]}>\n {showAuthFailure ? 'Could not open Web Builder' : 'Failed to load micro frontend'}\n </Text>\n <Text style={[styles.errorBody, { color: mutedColor }]}>\n {showAuthFailure\n ? authError ||\n 'Sign-in token could not be minted for the surface. Ensure you are logged in with an org.'\n : `Could not open ${baseUrl}. Check WEB_BUILDER_URL / network, then retry.`}\n </Text>\n {errorDetail ? (\n <Text style={[styles.errorMeta, { color: mutedColor }]} selectable>\n {errorDetail}\n </Text>\n ) : null}\n <Pressable\n onPress={handleRetry}\n style={[styles.retryButton, { backgroundColor: mobileTokens.color.primary }]}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Retry loading WebBuilder\"\n >\n <Text style={styles.retryLabel}>Retry</Text>\n </Pressable>\n </View>\n </SafeAreaView>\n );\n }\n\n return (\n <SafeAreaView edges={['left', 'right', 'bottom']} style={[styles.container, { backgroundColor: surfaceColor }]}>\n <WebViewWithNavigation webViewRef={webViewRef} canGoBack={canGoBack} onGoBack={handleNativeGoBack} />\n\n {isLoading && (\n <View style={[styles.loadingOverlay, { backgroundColor: surfaceColor }]} pointerEvents=\"none\">\n <ActivityIndicator size=\"large\" color={mobileTokens.color.primary} />\n </View>\n )}\n\n <WebView\n key={`${reloadKey}-${handoffParams.channelId ?? 'none'}-${handoffParams.snapshotId ?? 'nosnap'}-${authToken?.slice(-8) ?? 'none'}`}\n ref={webViewRef}\n source={{\n uri: mfeConfig.url,\n }}\n style={styles.webview}\n onLoadStart={handleLoadStart}\n onLoadEnd={handleLoadEnd}\n onError={handleError}\n onHttpError={handleHttpError}\n onMessage={handleMessage}\n onNavigationStateChange={handleNavigationStateChange}\n injectedJavaScriptBeforeContentLoaded={injectedBeforeContent}\n injectedJavaScript={reinjectAfterLoad}\n cacheEnabled={mfeConfig.cachePolicy !== 'reload'}\n cacheMode={cacheMode}\n javaScriptEnabled\n domStorageEnabled\n sharedCookiesEnabled\n thirdPartyCookiesEnabled\n startInLoadingState\n scalesPageToFit\n originWhitelist={['*']}\n mixedContentMode=\"always\"\n // Surfaces run the shared AI chat, whose voice input records via\n // getUserMedia. WKWebView denies capture unless the host grants it\n // (the app already holds NSMicrophoneUsageDescription / RECORD_AUDIO),\n // which is why the record button in a surface silently did nothing.\n mediaCapturePermissionGrantType=\"grant\"\n // Inline playback so canvas/board videos play in place instead of\n // being hijacked into the fullscreen player.\n allowsInlineMediaPlayback\n mediaPlaybackRequiresUserAction\n setSupportMultipleWindows={false}\n allowsBackForwardNavigationGestures\n {...(Platform.OS === 'android' ? { overScrollMode: 'never' as const } : null)}\n />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n },\n webview: {\n flex: 1,\n backgroundColor: 'transparent',\n },\n loadingOverlay: {\n ...StyleSheet.absoluteFillObject,\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: 1000,\n },\n centered: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n paddingHorizontal: 24,\n gap: 12,\n },\n errorTitle: {\n fontSize: 17,\n fontWeight: '600',\n textAlign: 'center',\n },\n errorBody: {\n fontSize: 14,\n textAlign: 'center',\n marginBottom: 4,\n lineHeight: 20,\n },\n errorMeta: {\n fontSize: 12,\n textAlign: 'center',\n marginBottom: 8,\n lineHeight: 16,\n },\n retryButton: {\n paddingHorizontal: 20,\n paddingVertical: 12,\n borderRadius: mobileTokens.radius.md,\n },\n retryLabel: {\n color: '#ffffff',\n fontSize: 15,\n fontWeight: '600',\n },\n});\n"],"names":["_a","_b"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminide-stack/yantra-mobile",
3
- "version": "12.0.44-alpha.1",
3
+ "version": "12.0.44-alpha.10",
4
4
  "description": "Sample core for higher packages to depend on",
5
5
  "license": "ISC",
6
6
  "author": "CDMBase LLC",
@@ -25,7 +25,7 @@
25
25
  "uuid": "^9.0.0"
26
26
  },
27
27
  "devDependencies": {
28
- "common": "12.0.43-alpha.15"
28
+ "common": "12.0.44-alpha.4"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@admin-layout/gluestack-ui-mobile": "*",
@@ -41,7 +41,7 @@
41
41
  "@messenger-box/platform-mobile": "*",
42
42
  "@react-native-async-storage/async-storage": "*",
43
43
  "@react-navigation/native": "*",
44
- "common": "12.0.43-alpha.15",
44
+ "common": "12.0.44-alpha.4",
45
45
  "expo-constants": "*",
46
46
  "expo-secure-store": "*",
47
47
  "lodash": "*",
@@ -56,5 +56,5 @@
56
56
  "typescript": {
57
57
  "definition": "lib/index.d.ts"
58
58
  },
59
- "gitHead": "456cb3b1a4253f0d429405049d0037d77dad470d"
59
+ "gitHead": "f15bd1362323e1a9db5f11b8120ebb3b8f2e68f9"
60
60
  }