@adminide-stack/yantra-mobile 12.0.131 → 12.0.132-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/CustomDrawer.js +2 -2
- package/lib/components/CustomDrawer.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +7 -1
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/apps/nativeSurfaceTwin.js +35 -0
- package/lib/features/apps/nativeSurfaceTwin.js.map +1 -0
- package/lib/features/canvas/CanvasBoardsGrid.js +49 -49
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
- package/lib/features/canvas/CanvasExperience.js +69 -28
- package/lib/features/canvas/CanvasExperience.js.map +1 -1
- package/lib/features/canvas/audioEditor/AudioWaveform.js +1 -1
- package/lib/features/canvas/designCatalog.js +63 -39
- package/lib/features/canvas/designCatalog.js.map +1 -1
- package/lib/features/canvas/designCategories.js +56 -0
- package/lib/features/canvas/designCategories.js.map +1 -1
- package/lib/features/canvas/generator/DirectorSheet.js +3 -2
- package/lib/features/canvas/generator/DirectorSheet.js.map +1 -1
- package/lib/features/canvas/home/HeroComposer.js +165 -76
- package/lib/features/canvas/home/HeroComposer.js.map +1 -1
- package/lib/features/canvas/home/HeroMonitor.js +75 -46
- package/lib/features/canvas/home/HeroMonitor.js.map +1 -1
- package/lib/features/canvas/home/TemplatesGallery.js +273 -138
- package/lib/features/canvas/home/TemplatesGallery.js.map +1 -1
- package/lib/features/canvas/home/templatesGallerySources.js +221 -0
- package/lib/features/canvas/home/templatesGallerySources.js.map +1 -0
- package/lib/features/canvas/homeWork.js +12 -11
- package/lib/features/canvas/homeWork.js.map +1 -1
- package/lib/features/canvas/lazyEditors.js +51 -0
- package/lib/features/canvas/lazyEditors.js.map +1 -0
- package/lib/features/canvas/rankedCatalogSearch.js +33 -23
- package/lib/features/canvas/rankedCatalogSearch.js.map +1 -1
- package/lib/features/canvas/set/SetViewportWebView.js +1 -1
- package/lib/features/canvas/set/agent/tools.js +1 -1
- package/lib/features/canvas/studioCatalog.js +2 -2
- package/lib/features/canvas/studioCatalog.js.map +1 -1
- package/lib/features/canvas/templateSearch.js +8 -1
- package/lib/features/canvas/templateSearch.js.map +1 -1
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +1 -1
- package/lib/features/design/DesignEditorExperience.js +103 -29
- package/lib/features/design/DesignEditorExperience.js.map +1 -1
- package/lib/features/design/DesignExperience.js +4 -3
- package/lib/features/design/DesignExperience.js.map +1 -1
- package/lib/features/design/doc/aiDesign.js +1 -1
- package/lib/features/design/doc/aiDesign.js.map +1 -1
- package/lib/features/design/doc/artifacts.js +40 -13
- package/lib/features/design/doc/artifacts.js.map +1 -1
- package/lib/features/design/doc/chart.js +387 -13
- package/lib/features/design/doc/chart.js.map +1 -1
- package/lib/features/design/doc/copyStyle.js +47 -0
- package/lib/features/design/doc/copyStyle.js.map +1 -0
- package/lib/features/design/doc/docOps.js +22 -4
- package/lib/features/design/doc/docOps.js.map +1 -1
- package/lib/features/design/doc/geometry.js +32 -18
- package/lib/features/design/doc/geometry.js.map +1 -1
- package/lib/features/design/doc/newDoc.js +5 -1
- package/lib/features/design/doc/newDoc.js.map +1 -1
- package/lib/features/design/doc/resize.js +101 -0
- package/lib/features/design/doc/resize.js.map +1 -0
- package/lib/features/design/doc/sizes.js +15 -2
- package/lib/features/design/doc/sizes.js.map +1 -1
- package/lib/features/design/editor/ChartDataPanel.js +49 -9
- package/lib/features/design/editor/ChartDataPanel.js.map +1 -1
- package/lib/features/design/editor/CropOverlay.js +1 -1
- package/lib/features/design/editor/DesignCanvas.js +14 -13
- package/lib/features/design/editor/DesignCanvas.js.map +1 -1
- package/lib/features/design/editor/ExportSheet.js +8 -4
- package/lib/features/design/editor/ExportSheet.js.map +1 -1
- package/lib/features/design/editor/LayerTools.js +37 -5
- package/lib/features/design/editor/LayerTools.js.map +1 -1
- package/lib/features/design/editor/Slideshow.js +30 -5
- package/lib/features/design/editor/Slideshow.js.map +1 -1
- package/lib/features/design/editor/useDesignSave.js +21 -36
- package/lib/features/design/editor/useDesignSave.js.map +1 -1
- package/lib/features/design/export/exportDesign.js +3 -1
- package/lib/features/design/export/exportDesign.js.map +1 -1
- package/lib/features/design/home/DesignHome.js +7 -2
- package/lib/features/design/home/DesignHome.js.map +1 -1
- package/lib/features/design/render/DesignPageView.js +1 -1
- package/lib/features/design/render/DesignPageView.js.map +1 -1
- package/lib/features/design/render/PageCapture.js +11 -10
- package/lib/features/design/render/PageCapture.js.map +1 -1
- package/lib/features/design/render/fontRegistry.js +27 -3
- package/lib/features/design/render/fontRegistry.js.map +1 -1
- package/lib/features/design/render/svgParts.js +27 -74
- package/lib/features/design/render/svgParts.js.map +1 -1
- package/lib/features/devices/brands/qnScale.js +7 -2
- package/lib/features/devices/brands/qnScale.js.map +1 -1
- package/lib/features/devices/brands/uuids.js +2 -1
- package/lib/features/devices/brands/uuids.js.map +1 -1
- package/lib/features/devices/devices.js +2 -1
- package/lib/features/devices/devices.js.map +1 -1
- package/lib/features/docs/DocBlockRow.js +1 -1
- package/lib/features/docs/docArtifacts.js +2 -2
- package/lib/features/docs/docArtifacts.js.map +1 -1
- package/lib/features/health/healthSync.js +3 -1
- package/lib/features/health/healthSync.js.map +1 -1
- package/lib/features/health/nativeHealth.js +8 -0
- package/lib/features/health/nativeHealth.js.map +1 -0
- package/lib/features/links/openInApp.js +11 -1
- package/lib/features/links/openInApp.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +135 -28
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +14 -6
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/components/PreviewFrame.js +28 -3
- package/lib/features/webbuilder/components/PreviewFrame.js.map +1 -1
- package/lib/features/webbuilder/components/PreviewScreen.js +1 -1
- package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -1
- package/lib/features/webbuilder/components/ProjectChat.js +24 -5
- package/lib/features/webbuilder/components/ProjectChat.js.map +1 -1
- package/lib/features/webbuilder/components/ProjectsScreen.js +18 -2
- package/lib/features/webbuilder/components/ProjectsScreen.js.map +1 -1
- package/lib/features/webbuilder/components/ui.js +20 -6
- package/lib/features/webbuilder/components/ui.js.map +1 -1
- package/lib/features/webbuilder/exportCode.js +52 -0
- package/lib/features/webbuilder/exportCode.js.map +1 -0
- package/lib/features/webbuilder/siteAddress.js +71 -0
- package/lib/features/webbuilder/siteAddress.js.map +1 -0
- package/lib/features/webbuilder/widgetBlocks.js +30 -0
- package/lib/features/webbuilder/widgetBlocks.js.map +1 -0
- package/lib/screens/Chat/index.js +5 -6
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/ChatHistory/index.js +3 -2
- package/lib/screens/ChatHistory/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js +20 -4
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/WebBuilderCodePrewarm.js +18 -0
- package/lib/screens/Home/components/WebBuilderCodePrewarm.js.map +1 -0
- package/lib/screens/WebBuilderNative/index.js +1 -1
- package/lib/screens/WebBuilderNative/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/keepAlive.js +112 -0
- package/lib/screens/WebBuilderNative/keepAlive.js.map +1 -0
- package/lib/screens/WebBuilderNative/runningBuilds.js +40 -0
- package/lib/screens/WebBuilderNative/runningBuilds.js.map +1 -0
- package/lib/screens/WebBuilderNative/useSandboxKeepAlive.js +57 -0
- package/lib/screens/WebBuilderNative/useSandboxKeepAlive.js.map +1 -0
- package/lib/screens/WebBuilderNative/useWebBuilderGallery.js +73 -14
- package/lib/screens/WebBuilderNative/useWebBuilderGallery.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +143 -34
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderJobs.js +17 -5
- package/lib/screens/WebBuilderNative/useWebBuilderJobs.js.map +1 -1
- package/lib/screens/WebBuilderNative/versionUndo.js +144 -0
- package/lib/screens/WebBuilderNative/versionUndo.js.map +1 -0
- package/lib/screens/WebBuilderNative/webbuilderSnapshotKey.js +1 -0
- package/lib/screens/WebBuilderNative/webbuilderSnapshotKey.js.map +1 -0
- package/lib/screens/WebBuilderNative/webbuilderTransport.js +90 -6
- package/lib/screens/WebBuilderNative/webbuilderTransport.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HomeScreen.js","sources":["../../../src/screens/Home/HomeScreen.tsx"],"sourcesContent":["import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n InteractionManager,\n Keyboard,\n Platform,\n Pressable,\n ScrollView,\n StyleSheet,\n TextInput,\n View,\n useWindowDimensions,\n type NativeSyntheticEvent,\n type TextInputChangeEventData,\n} from 'react-native';\nimport { InputToolBar, Text, getDefaultLeftItems } from '@admin-layout/gluestack-ui-mobile';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport {\n useNavigation,\n useRoute,\n useFocusEffect,\n CommonActions,\n type NavigationProp,\n type ParamListBase,\n type RouteProp,\n} from '@react-navigation/native';\nimport { useDispatch, useSelector } from 'react-redux';\nimport { v4 as uuidv4 } from 'uuid';\nimport { KeyboardAwareScreen, KeyboardComposerDock } from '../../components/KeyboardComposerDock';\nimport { useKeyboardBottomOffset } from '../../hooks/useKeyboardBottomOffset';\nimport { dismissKeyboard } from '../../utils/keyboardController';\nimport { usePrerequisiteIds } from '../../hooks/usePrerequisiteIds';\nimport { syncMobileOrgRouteContext } from '../../utils/syncMobileOrgRouteContext';\nimport { useChatMutations, usePrefetchChatHistory } from '../../hooks/useChatApi';\nimport { hydrateChatHistorySnapshot, persistChatHistorySnapshot } from '../../features/chat/chatHistorySnapshot';\nimport { AudioRecorderPanel } from '../../features/audio-input/AudioRecorderPanel';\nimport { MicErrorBoundary } from '../../features/audio-input/MicErrorBoundary';\nimport { requestMicPermission } from '../../features/audio-input/useAudioPermission';\nimport type { ModeSubmission, RoutingMode } from './types';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { useAppTheme } from '../../theme/AppThemeProvider';\nimport { type BuildTemplateCard } from '../../features/templates/buildTemplateCards';\nimport { useMarketplaceTemplateGroups } from '../../hooks/useMarketplaceTemplateGroups';\nimport { useImageAttachments } from '../../features/attachments/useImageAttachments';\nimport { ComposerAttachmentBar } from '../../features/attachments/ComposerAttachmentBar';\nimport { useComposerAttachMenu } from '../../features/attachments/ComposerAttachMenu';\nimport { stashComposerAttachments } from '../../features/attachments/composerAttachmentHandoff';\nimport { BuildTemplatesSection } from './components/BuildTemplatesSection';\nimport { ChooseTemplateModal } from './components/ChooseTemplateModal';\nimport { HomeSuggestions } from './components/HomeSuggestions';\nimport { WebBuilderPrewarm } from './components/WebBuilderPrewarm';\nimport { CanvasPrewarm } from './components/CanvasPrewarm';\nimport { afterNativeModalClose, dispatchDrawerAction, resetDrawerClosed } from '../../utils/drawerNavigation';\n\n/**\n * Build the channel `title` we persist on creation. This is the server-side mode\n * signal (web parity: `useYantraComposerChannelSubmit`): the backend inspects the\n * title prefix to route deep-search requests differently from plain chat. The\n * UI never displays this raw string — `buildSessionFromChannel` filters\n * `chat-channel-…` / `deep-search-…` titles out of the history label cascade\n * and derives the visible label from the user's first message instead.\n *\n * Previously we used the user's prompt directly as the title for friendlier\n * history rows, but that silently disabled the server's mode detection — every\n * \"deep-search\" submission landed as a plain chat. Restored to the web scheme.\n */\nfunction buildChannelTitle(mode: RoutingMode, channelId: string): string {\n if (mode === 'deep-search') return `deep-search-${channelId}`;\n if (mode === 'build') return `build-channel-${channelId}`;\n return `chat-channel-${channelId}`;\n}\n\nexport type { RoutingMode, ModeSubmission };\n\nexport interface HomeScreenProps {\n initialMode?: RoutingMode;\n onSubmit?: (submission: ModeSubmission) => void;\n onStop?: () => void;\n isLoading?: boolean;\n disabled?: boolean;\n}\n\ninterface EmptyStateSectionProps {\n isDark: boolean;\n secondaryTextColor: string;\n primaryTextColor: string;\n activeMode: RoutingMode;\n selectedTemplateGroup: string | null;\n selectedBuildTemplateId: string | null;\n compact: boolean;\n onInjectPrompt: (prompt: string, mode?: RoutingMode) => void;\n onOpenRoute?: (name: string) => void;\n}\n\nconst EMPTY_STATE_TITLES: Record<RoutingMode, string> = {\n build: 'What should we build?',\n 'deep-search': 'What should we research?',\n chat: 'Ask anything',\n};\n\nfunction emptyStateSubtitle(mode: RoutingMode, hasTemplate: boolean, hasTemplateGroup: boolean): string {\n if (mode === 'deep-search') return 'Source-backed answers from the web.';\n if (mode !== 'build') return 'Chat, Deep Search, or Build from the composer.';\n if (hasTemplate) return 'Describe the project, then send.';\n return hasTemplateGroup ? 'Tap a starter below, then send.' : 'Tap Template to pick a group, then send.';\n}\n\nfunction composerPlaceholder(mode: RoutingMode, hasTemplate: boolean): string {\n if (mode === 'deep-search') return 'Research anything...';\n if (mode !== 'build') return 'Ask anything...';\n return hasTemplate ? 'Build me: describe your project…' : 'Describe an app to build...';\n}\n\n/** The web-builder seed for a template's stack name. */\nfunction seedTemplateFor(stack: string): 'nextjs' | 'vue' | 'vite-react' {\n if (stack.includes('next')) return 'nextjs';\n return stack.includes('vue') ? 'vue' : 'vite-react';\n}\n\n/** What Home reads from its route. */\ntype HomeRouteParams = {\n orgName?: string | null;\n hideNavigationHeader?: boolean;\n newChatNonce?: string | number;\n initialSessionId?: string | null;\n};\n\n/** How long a send waits for the workspace to resolve before it is dropped. */\nconst SEND_WAIT_MS = 20_000;\n\nconst EmptyStateSection = React.memo(function EmptyStateSection({\n isDark,\n secondaryTextColor,\n primaryTextColor,\n activeMode,\n selectedTemplateGroup,\n selectedBuildTemplateId,\n compact,\n onInjectPrompt,\n onOpenRoute,\n}: EmptyStateSectionProps) {\n const title = EMPTY_STATE_TITLES[activeMode];\n const subtitle = emptyStateSubtitle(activeMode, Boolean(selectedBuildTemplateId), Boolean(selectedTemplateGroup));\n\n return (\n <View style={styles.emptyInner}>\n <Text\n style={[\n styles.emptyCenterTitle,\n compact && styles.emptyCenterTitleCompact,\n { color: primaryTextColor },\n ]}\n >\n {title}\n </Text>\n <Text style={[styles.emptySubtitle, compact && styles.emptySubtitleCompact, { color: secondaryTextColor }]}>\n {subtitle}\n </Text>\n {activeMode === 'chat' ? (\n <HomeSuggestions\n isDark={isDark}\n compact={compact}\n primaryTextColor={primaryTextColor}\n secondaryTextColor={secondaryTextColor}\n onInjectPrompt={onInjectPrompt}\n onOpenRoute={onOpenRoute}\n />\n ) : null}\n </View>\n );\n});\n\nfunction HomeScreenContent({\n initialMode = 'chat',\n onSubmit: onSubmitProp,\n isLoading: isLoadingProp = false,\n disabled = false,\n}: HomeScreenProps) {\n const { width: screenWidth } = useWindowDimensions();\n const { isDark } = useAppTheme();\n const navigation = useNavigation<NavigationProp<ParamListBase>>();\n const route = useRoute<RouteProp<Record<string, HomeRouteParams | undefined>, string>>();\n const dispatch = useDispatch();\n const syncedRouteOrgRef = useRef<string | null>(null);\n const mobileRoutePath = useSelector(\n (state: { router?: { location?: { currentRoute?: { path?: string } } } }) =>\n state.router?.location?.currentRoute?.path,\n );\n\n const [value, setValue] = useState('');\n const inputRef = useRef<TextInput>(null);\n /**\n * Home stays mounted under the chat stack. `setValue('')` on submit does not\n * always clear the iOS TextInput buffer, so Back would show the prompt that\n * was already sent. Bump this to remount the toolbar, and clear again on focus.\n */\n const [composerEpoch, setComposerEpoch] = useState(0);\n const clearComposerOnFocusRef = useRef(false);\n\n const resetComposer = useCallback(() => {\n setValue('');\n setComposerEpoch((n) => n + 1);\n inputRef.current?.clear();\n }, []);\n\n useFocusEffect(\n useCallback(() => {\n resetDrawerClosed(navigation);\n const task = InteractionManager.runAfterInteractions(() => {\n resetDrawerClosed(navigation);\n });\n if (route?.params?.hideNavigationHeader) {\n navigation.setParams?.({ hideNavigationHeader: undefined });\n }\n if (clearComposerOnFocusRef.current) {\n clearComposerOnFocusRef.current = false;\n resetComposer();\n }\n return () => {\n task.cancel();\n dispatchDrawerAction(navigation, 'close');\n };\n }, [navigation, resetComposer, route?.params?.hideNavigationHeader]),\n );\n const [activeMode, setActiveMode] = useState<RoutingMode>(initialMode);\n /**\n * `showAudioRecorder` swaps the InputToolBar for the inline voice recorder\n * panel — same pattern as the web composer\n * (`YantraSearchComposer.tsx`'s `showAudioRecorder` branch).\n */\n const [showAudioRecorder, setShowAudioRecorder] = useState(false);\n /**\n * Build-mode template group (`codeAssistant`, …) — same picker web uses before\n * `DefaultFormTemplatesSection` loads remix cards with `snapshotId`.\n */\n const [selectedTemplateGroup, setSelectedTemplateGroup] = useState<string | null>(null);\n /** Armed remix card — submit sends input `message` + this card's `snapshotId`. */\n const [selectedBuildTemplate, setSelectedBuildTemplate] = useState<BuildTemplateCard | null>(null);\n const [showTemplateModal, setShowTemplateModal] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n const composerAttachments = useImageAttachments();\n const { rightItems, menu: attachMenu } = useComposerAttachMenu(composerAttachments, isDark);\n const clearComposerAttachments = composerAttachments.clear;\n const newChatNonce = route?.params?.newChatNonce;\n\n useEffect(() => {\n if (newChatNonce == null) return;\n resetComposer();\n setActiveMode('chat');\n setShowAudioRecorder(false);\n setSelectedTemplateGroup(null);\n setSelectedBuildTemplate(null);\n setShowTemplateModal(false);\n setVoiceError(null);\n clearComposerAttachments();\n navigation.setParams?.({ newChatNonce: undefined });\n }, [newChatNonce, clearComposerAttachments, navigation, resetComposer]);\n\n const { createChannel } = useChatMutations();\n const { orgName: resolvedOrgName, projectId, tagId, accountUserId, orgLoading } = usePrerequisiteIds();\n const routeOrgName = ((route?.params?.orgName as string | undefined) ?? '').trim() || null;\n const effectiveOrgName = resolvedOrgName || routeOrgName || null;\n const effectiveProjectId = projectId || null;\n const { sessions: prefetchedHistory, sessionsLoaded: historyPrefetched } = usePrefetchChatHistory(effectiveOrgName);\n useEffect(() => {\n void hydrateChatHistorySnapshot();\n }, []);\n useEffect(() => {\n if (!effectiveOrgName || !accountUserId || !historyPrefetched) return;\n persistChatHistorySnapshot(accountUserId, effectiveOrgName, prefetchedHistory);\n }, [accountUserId, effectiveOrgName, historyPrefetched, prefetchedHistory]);\n\n const { groups: marketplaceTemplateGroups, loading: templateGroupsLoading } = useMarketplaceTemplateGroups({\n orgName: effectiveOrgName,\n enabled: true,\n });\n\n const trimmedQuery = value.trim();\n const isBuildMePrefixOnly = /^build\\s*me\\s*:?\\s*$/i.test(trimmedQuery);\n const hasQuery = trimmedQuery.length > 0 && !isBuildMePrefixOnly;\n const hasAttachments = composerAttachments.pending.length > 0;\n // The workspace (org) resolves over the network a beat after Home paints. A send\n // before then waits for it, instead of the composer reading \"Initializing\n // workspace...\" and refusing to send for the first second of every launch.\n const workspaceReady = Boolean(routeOrgName || effectiveOrgName);\n const canSubmit = hasQuery || hasAttachments;\n const [sendWhenReady, setSendWhenReady] = useState(false);\n const isLoading = isLoadingProp;\n const isBuildMode = activeMode === 'build';\n const inputPlaceholder = composerPlaceholder(activeMode, Boolean(selectedBuildTemplate));\n\n const insets = useSafeAreaInsets();\n const { keyboardVisible } = useKeyboardBottomOffset();\n const emptyScrollRef = useRef<ScrollView>(null);\n\n useEffect(() => {\n if (!keyboardVisible) return;\n emptyScrollRef.current?.scrollTo({ y: 0, animated: true });\n }, [keyboardVisible]);\n\n const handleModeSwitch = useCallback((mode: RoutingMode) => {\n setActiveMode(mode);\n if (mode !== 'build') {\n setShowTemplateModal(false);\n setSelectedTemplateGroup(null);\n setSelectedBuildTemplate(null);\n }\n }, []);\n\n /**\n * Mirrors the web `useYantraComposerChannelSubmit`: on submit we generate a client-side\n * channel id, fire-and-forget the createChannel mutation, then navigate immediately to\n * the Chat screen with the user's prompt. The Chat screen mounts, awaits the in-flight\n * creation just before saveMessages, and starts streaming the assistant response.\n */\n const navigateToChat = useCallback(\n (channelId: string, query: string, mode: RoutingMode, attachments?: ModeSubmission['attachments']) => {\n const params: Record<string, unknown> = {\n channelId,\n orgName: effectiveOrgName ?? routeOrgName ?? undefined,\n initialQuery: query,\n initialMode: mode,\n // Chat asks the brain whether this belongs in Shop or another app - once,\n // with the user's message already on screen, and carries the ask (and this\n // channel) there if so. Asking here first held the message back for up to\n // two seconds after Send.\n };\n if (attachments && attachments.length > 0) {\n params.initialAttachments = attachments;\n }\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.Chat',\n params,\n }),\n );\n },\n [navigation, effectiveOrgName, routeOrgName],\n );\n\n /** Starter chips with a real native screen navigate there directly. */\n const handleOpenRoute = React.useCallback(\n (name: string) => {\n dispatchDrawerAction(navigation, 'close');\n afterNativeModalClose(() => {\n navigation.dispatch(\n CommonActions.navigate({\n name,\n params: { orgName: effectiveOrgName ?? routeOrgName ?? undefined },\n }),\n );\n });\n },\n [navigation, effectiveOrgName, routeOrgName],\n );\n\n type WebBuilderHandoff = {\n message: string;\n snapshotId?: string;\n templateId?: string;\n templateTitle?: string;\n seedTemplate?: string;\n deployUrl?: string;\n previewUrl?: string;\n };\n\n /**\n * Build mode → Web Builder (`/c/:channelId/webbuilder`).\n * Template remix passes `snapshotId` so the surface boots from that E2B snapshot.\n */\n const navigateToWebBuilder = useCallback(\n (channelId: string, handoff: WebBuilderHandoff) => {\n // Snapshot remix: do not stamp shared org projectId — surface mints a fresh\n // channel+project (web Templates picker parity). Passing DEFAULT_YANTRA_PROJECT\n // made results merge into existing gallery tiles (Counter App).\n const isRemix = Boolean(handoff.snapshotId?.trim());\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: {\n orgName: effectiveOrgName ?? routeOrgName ?? undefined,\n // Snapshot remix: omit channelId — surface mints a fresh listen\n // channel. Passing the pre-created id made hydrate re-bind poll onto\n // an empty channel while the build workflow published to the minted id.\n ...(!isRemix ? { channelId } : {}),\n ...(!isRemix && effectiveProjectId ? { projectId: effectiveProjectId } : {}),\n message: handoff.message,\n ...(handoff.snapshotId ? { snapshotId: handoff.snapshotId } : {}),\n ...(handoff.templateId ? { templateId: handoff.templateId } : {}),\n ...(handoff.templateTitle ? { templateTitle: handoff.templateTitle } : {}),\n ...(handoff.seedTemplate ? { seedTemplate: handoff.seedTemplate } : {}),\n },\n }),\n );\n },\n [navigation, effectiveOrgName, routeOrgName, effectiveProjectId],\n );\n\n /**\n * Tap a Yantra card → arm it (store snapshotId). Do NOT navigate yet.\n * Composer shows \"Build me: \" — user writes the project brief (no template title).\n */\n const handleUseBuildTemplate = useCallback((card: BuildTemplateCard) => {\n const snapshotId = card.snapshotId?.trim();\n if (!snapshotId) {\n console.warn('[HomeScreen] template missing snapshotId — select another remixable card.');\n }\n setSelectedBuildTemplate(card);\n setValue((prev) => {\n const trimmed = prev.trim();\n // Keep whatever the user already typed; otherwise seed only the prefix.\n if (trimmed && !/^build\\s*me\\s*:?\\s*$/i.test(trimmed)) return prev;\n return 'Build me: ';\n });\n }, []);\n\n const handleSelectTemplateGroup = useCallback((groupId: string) => {\n setSelectedTemplateGroup(groupId);\n setSelectedBuildTemplate(null);\n setShowTemplateModal(false);\n }, []);\n\n const handleClearBuildTemplate = useCallback(() => {\n if (selectedBuildTemplate) {\n setSelectedBuildTemplate(null);\n return;\n }\n setSelectedTemplateGroup(null);\n }, [selectedBuildTemplate]);\n\n const handleSubmit = useCallback(async () => {\n if (!canSubmit || isLoading || disabled) return;\n if (!workspaceReady) {\n setSendWhenReady(true);\n return;\n }\n\n const attachmentsToForward = composerAttachments.forSend();\n const submission: ModeSubmission = {\n mode: activeMode,\n query: trimmedQuery,\n attachments: attachmentsToForward,\n };\n if (onSubmitProp) {\n onSubmitProp(submission);\n }\n\n if (!effectiveOrgName) {\n console.warn('[HomeScreen] orgName not ready — skipping submit.');\n return;\n }\n // Project can lag behind org after a competing hook stole bootstrap; use the\n // known testing project so Build/Chat are not stuck on \"not ready\".\n const submitProjectId = effectiveProjectId || '9a8ac704-1040-4836-9b72-48b771ca91b1';\n if (!effectiveProjectId) {\n console.warn('[HomeScreen] projectId not ready — using testing project fallback for submit.');\n }\n\n const queryToForward = trimmedQuery;\n // Nothing waits on the network between Send and the user's message on screen:\n // whether the ask belongs in Shop or another app is Chat's call, made while\n // the message already shows there.\n const requestedChannelId = uuidv4();\n /**\n * Title is the server's mode signal (`deep-search-…` / `build-channel-…` / `chat-channel-…`).\n * It's NOT the history label — the history list derives that from the\n * first user message via `buildSessionFromChannel`.\n */\n const title = buildChannelTitle(activeMode, requestedChannelId);\n\n clearComposerOnFocusRef.current = true;\n resetComposer();\n composerAttachments.clear();\n stashComposerAttachments(requestedChannelId, attachmentsToForward);\n\n void createChannel({\n id: requestedChannelId,\n title,\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: null,\n systemPrompt: null,\n orgName: effectiveOrgName,\n projectId: submitProjectId,\n }).catch((err) => {\n console.error('[HomeScreen] createChannel failed:', err);\n });\n\n if (activeMode === 'build') {\n const tpl = selectedBuildTemplate;\n const snapshotId = tpl?.snapshotId?.trim() || undefined;\n // Stack for webbuilder modelConfig.template — never marketplace keys\n // like aieditor-code-extractor. Do NOT pass previewUrl (live E2B host)\n // or the surface/backend may reconnect that sandbox instead of remixing.\n const rawStack = (tpl?.templateName || '').toLowerCase();\n const seedTemplate = snapshotId ? seedTemplateFor(rawStack) : undefined;\n navigateToWebBuilder(requestedChannelId, {\n message: queryToForward,\n snapshotId,\n templateId: tpl ? tpl.formTemplateId || tpl.id : undefined,\n templateTitle: tpl?.title,\n seedTemplate,\n });\n setSelectedBuildTemplate(null);\n return;\n }\n\n navigateToChat(requestedChannelId, queryToForward, activeMode);\n }, [\n canSubmit,\n workspaceReady,\n isLoading,\n disabled,\n activeMode,\n trimmedQuery,\n onSubmitProp,\n effectiveOrgName,\n effectiveProjectId,\n createChannel,\n navigateToChat,\n navigateToWebBuilder,\n selectedBuildTemplate,\n composerAttachments,\n resetComposer,\n ]);\n\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const primaryTextColor = isDark ? '#e5e7eb' : mobileTokens.color.text;\n const secondaryTextColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));\n\n /**\n * After verify-user, Home mounts with empty `route.params.orgName`. Settings load via\n * `usePrerequisiteIds` (single useSettings). Merge-navigate does not re-fire LOCATION_CHANGE\n * on the same path; sync params + LOCATION_CHANGE + orgChangeAction like refresh does.\n */\n useEffect(() => {\n const currentRouteOrgName = (route?.params?.orgName as string | undefined)?.trim() || '';\n if (currentRouteOrgName) {\n syncedRouteOrgRef.current = currentRouteOrgName;\n return;\n }\n const orgToApply = resolvedOrgName;\n if (!orgToApply || orgLoading) {\n return;\n }\n if (syncedRouteOrgRef.current === orgToApply) {\n return;\n }\n\n syncedRouteOrgRef.current = orgToApply;\n syncMobileOrgRouteContext(dispatch, orgToApply, {\n userId: accountUserId,\n routePath: mobileRoutePath,\n });\n navigation.dispatch(\n CommonActions.navigate({\n name: route?.name ?? 'MainStack.Layout.Home',\n params: { ...(route?.params || {}), orgName: orgToApply },\n merge: true,\n }),\n );\n }, [\n dispatch,\n navigation,\n route?.name,\n route?.params,\n route?.params?.orgName,\n resolvedOrgName,\n accountUserId,\n mobileRoutePath,\n orgLoading,\n ]);\n\n const handleValueChange = useCallback((e: NativeSyntheticEvent<TextInputChangeEventData>) => {\n setValue(e.nativeEvent.text);\n }, []);\n\n const handleInjectPrompt = useCallback((prompt: string, mode?: RoutingMode) => {\n setValue(prompt);\n if (mode) setActiveMode(mode);\n }, []);\n\n /**\n * Mic affordance — web parity (`handleMicClick` in `YantraSearchComposer.tsx`).\n *\n * Only opens the recorder when the input is empty: if the user already has\n * a draft, the same button must act as Send (the `MicSendButton` in\n * `InputToolBar.tsx` already swaps its glyph from mic→send based on\n * `hasContent`, so this branch only fires when the icon is visibly a mic).\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 const handleTranscriptionComplete = useCallback((text: string) => {\n const cleaned = (text ?? '').trim();\n setShowAudioRecorder(false);\n if (!cleaned) return;\n /*\n * Append on top of any existing draft (web `setQuery((prev) => …)`).\n * Single-space separator keeps the transcript readable when the user\n * dictates multiple times before sending.\n */\n setValue((prev) => (prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned));\n }, []);\n\n const handleRecorderCancel = useCallback(() => {\n setShowAudioRecorder(false);\n }, []);\n\n const handleRecorderError = useCallback((error: string) => {\n /*\n * Surface the failure to the user but don't trap them in the recorder —\n * `AudioRecorderPanel` already calls `onCancel` after an error, so we\n * just record the message here for the (lightweight) banner below.\n */\n setVoiceError(error);\n }, []);\n\n const leftItems = useMemo(\n () =>\n getDefaultLeftItems({\n search: {\n active: activeMode === 'chat',\n onClick: () => handleModeSwitch('chat'),\n },\n zap: {\n active: activeMode === 'deep-search',\n onClick: () => handleModeSwitch('deep-search'),\n },\n lightbulb: {\n active: activeMode === 'build',\n onClick: () => handleModeSwitch('build'),\n },\n }),\n [activeMode, handleModeSwitch],\n );\n\n const templateModalItems = useMemo(\n () =>\n marketplaceTemplateGroups.map((group) => ({\n id: group.id,\n label: group.label,\n description: group.description,\n category: group.category,\n })),\n [marketplaceTemplateGroups],\n );\n\n const selectedTemplateLabel = useMemo(() => {\n if (selectedBuildTemplate?.title?.trim()) return selectedBuildTemplate.title.trim();\n if (!selectedTemplateGroup) return undefined;\n return marketplaceTemplateGroups.find((g) => g.id === selectedTemplateGroup)?.label || selectedTemplateGroup;\n }, [marketplaceTemplateGroups, selectedTemplateGroup, selectedBuildTemplate]);\n\n const templateButton = useMemo(() => {\n if (!isBuildMode) return null;\n return {\n label: 'Template',\n count: marketplaceTemplateGroups.length,\n selectedLabel: selectedTemplateLabel,\n onClick: () => setShowTemplateModal(true),\n onClearTemplate: handleClearBuildTemplate,\n disabled: isLoading || disabled || (templateGroupsLoading && marketplaceTemplateGroups.length === 0),\n };\n }, [\n isBuildMode,\n marketplaceTemplateGroups.length,\n selectedTemplateLabel,\n handleClearBuildTemplate,\n isLoading,\n disabled,\n templateGroupsLoading,\n ]);\n\n const templateModalConfig = useMemo(() => {\n if (!isBuildMode) return null;\n return {\n isOpen: showTemplateModal,\n onClose: () => setShowTemplateModal(false),\n templates: templateModalItems,\n selectedId: selectedTemplateGroup,\n onSelect: handleSelectTemplateGroup,\n title: 'Choose Template',\n };\n }, [isBuildMode, showTemplateModal, templateModalItems, selectedTemplateGroup, handleSelectTemplateGroup]);\n\n const renderTemplateModal = useCallback(\n (config: {\n isOpen: boolean;\n onClose: () => void;\n templates: Array<{ id: string; label: string; description?: string; category?: string }>;\n selectedId: string | null;\n onSelect: (id: string) => void;\n suggestedId?: string | null;\n title?: string;\n }) => (\n <ChooseTemplateModal\n isOpen={config.isOpen}\n onClose={config.onClose}\n templates={config.templates}\n selectedId={config.selectedId}\n onSelect={config.onSelect}\n suggestedId={config.suggestedId}\n title={config.title}\n isDark={isDark}\n loading={templateGroupsLoading}\n />\n ),\n [isDark, templateGroupsLoading],\n );\n\n // Send what was waiting for the workspace as soon as it resolves; clearing the\n // text cancels it, and it gives up rather than spin forever.\n useEffect(() => {\n if (!sendWhenReady) return undefined;\n if (!canSubmit) {\n setSendWhenReady(false);\n return undefined;\n }\n if (workspaceReady) {\n setSendWhenReady(false);\n void handleSubmit();\n return undefined;\n }\n const timer = setTimeout(() => {\n console.warn('[HomeScreen] workspace never resolved - dropping the queued send.');\n setSendWhenReady(false);\n }, SEND_WAIT_MS);\n return () => clearTimeout(timer);\n }, [sendWhenReady, canSubmit, workspaceReady, handleSubmit]);\n\n const inputConfig = useMemo(\n () => ({\n value,\n onChange: handleValueChange,\n placeholder: inputPlaceholder,\n disabled: isLoading || disabled,\n inputRef,\n returnKeyType: 'send',\n blurOnSubmit: true,\n onSubmitEditing: () => {\n if (canSubmit) void handleSubmit();\n },\n }),\n [value, handleValueChange, inputPlaceholder, isLoading, disabled, canSubmit, handleSubmit],\n );\n\n const micSendButton = useMemo(\n () => ({\n hasContent: hasQuery || hasAttachments,\n onSend: () => {\n Keyboard.dismiss();\n void handleSubmit();\n },\n onMic: handleMicPress,\n disabled: isLoading || disabled,\n isLoading: isLoading || sendWhenReady,\n }),\n [hasQuery, hasAttachments, handleSubmit, handleMicPress, isLoading, disabled, sendWhenReady],\n );\n\n return (\n <SafeAreaView edges={['left', 'right']} style={{ flex: 1, backgroundColor: surfaceColor }}>\n {/* Mint token + load webbuilder-surface off-screen while user picks a template. */}\n <WebBuilderPrewarm\n enabled={isBuildMode}\n orgName={effectiveOrgName}\n projectId={effectiveProjectId}\n tagId={tagId}\n />\n <CanvasPrewarm orgName={effectiveOrgName} projectId={effectiveProjectId} tagId={tagId} />\n <KeyboardAwareScreen>\n <View style={styles.flex}>\n <View style={styles.flex}>\n <ScrollView\n ref={emptyScrollRef}\n style={styles.flex}\n contentContainerStyle={[\n styles.emptyScroll,\n keyboardVisible ? styles.emptyScrollKeyboardOpen : null,\n ]}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}\n automaticallyAdjustKeyboardInsets={false}\n contentInsetAdjustmentBehavior=\"never\"\n showsVerticalScrollIndicator={false}\n >\n <Pressable style={styles.dismissArea} onPress={dismissKeyboard} accessible={false}>\n <EmptyStateSection\n isDark={isDark}\n secondaryTextColor={secondaryTextColor}\n primaryTextColor={primaryTextColor}\n activeMode={activeMode}\n selectedTemplateGroup={selectedTemplateGroup}\n selectedBuildTemplateId={selectedBuildTemplate?.id ?? null}\n compact={keyboardVisible}\n onInjectPrompt={handleInjectPrompt}\n onOpenRoute={handleOpenRoute}\n />\n </Pressable>\n </ScrollView>\n </View>\n <KeyboardComposerDock closedInset={insets.bottom} onSwipeUp={() => inputRef.current?.focus()}>\n <View style={[styles.composerInner, { width: contentMaxWidth }]}>\n {voiceError || composerAttachments.error ? (\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 || composerAttachments.error}\n </Text>\n </View>\n ) : null}\n {showAudioRecorder ? (\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 <>\n <ComposerAttachmentBar\n attachments={composerAttachments.pending}\n onRemove={composerAttachments.remove}\n isDark={isDark}\n />\n <InputToolBar\n key={composerEpoch}\n inputConfig={inputConfig}\n leftItems={leftItems}\n rightItems={rightItems}\n templateButton={templateButton}\n templateModalConfig={templateModalConfig}\n templateModalRender={renderTemplateModal}\n micSendButton={micSendButton}\n />\n </>\n )}\n {isBuildMode ? (\n <BuildTemplatesSection\n enabled\n compact={keyboardVisible}\n group={selectedTemplateGroup}\n orgName={effectiveOrgName}\n isDark={isDark}\n primaryTextColor={primaryTextColor}\n secondaryTextColor={secondaryTextColor}\n selectedTemplateId={selectedBuildTemplate?.id ?? null}\n onUseTemplate={handleUseBuildTemplate}\n />\n ) : null}\n </View>\n </KeyboardComposerDock>\n </View>\n </KeyboardAwareScreen>\n {attachMenu}\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: {\n flex: 1,\n },\n emptyScroll: {\n flexGrow: 1,\n width: '100%',\n paddingHorizontal: 28,\n justifyContent: 'center',\n paddingVertical: 24,\n },\n emptyScrollKeyboardOpen: {\n justifyContent: 'flex-start',\n paddingTop: 12,\n paddingBottom: 8,\n },\n emptyInner: {\n alignItems: 'center',\n width: '100%',\n },\n dismissArea: {\n width: '100%',\n },\n emptyCenterTitle: {\n fontSize: 28,\n fontWeight: '700',\n textAlign: 'center',\n letterSpacing: -0.5,\n },\n emptyCenterTitleCompact: {\n fontSize: 22,\n },\n emptySubtitle: {\n marginTop: 8,\n fontSize: 15,\n lineHeight: 22,\n textAlign: 'center',\n maxWidth: 320,\n },\n emptySubtitleCompact: {\n marginTop: 4,\n fontSize: 13,\n lineHeight: 18,\n },\n composerInner: {\n paddingHorizontal: 14,\n paddingTop: 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});\n\nconst HomeScreen: FC<HomeScreenProps> = (props) => <HomeScreenContent {...props} />;\n\nexport default HomeScreen;\n"],"names":["React","EmptyStateSection","_a","_b","_c","uuidv4"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HomeScreen.js","sources":["../../../src/screens/Home/HomeScreen.tsx"],"sourcesContent":["import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n InteractionManager,\n Keyboard,\n Platform,\n Pressable,\n ScrollView,\n StyleSheet,\n TextInput,\n View,\n useWindowDimensions,\n type NativeSyntheticEvent,\n type TextInputChangeEventData,\n} from 'react-native';\nimport { InputToolBar, Text, getDefaultLeftItems } from '@admin-layout/gluestack-ui-mobile';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport {\n useNavigation,\n useRoute,\n useFocusEffect,\n CommonActions,\n type NavigationProp,\n type ParamListBase,\n type RouteProp,\n} from '@react-navigation/native';\nimport { useDispatch, useSelector } from 'react-redux';\nimport { v4 as uuidv4 } from 'uuid';\nimport { KeyboardAwareScreen, KeyboardComposerDock } from '../../components/KeyboardComposerDock';\nimport { useKeyboardBottomOffset } from '../../hooks/useKeyboardBottomOffset';\nimport { dismissKeyboard } from '../../utils/keyboardController';\nimport { usePrerequisiteIds } from '../../hooks/usePrerequisiteIds';\nimport { syncMobileOrgRouteContext } from '../../utils/syncMobileOrgRouteContext';\nimport { useChatMutations, usePrefetchChatHistory } from '../../hooks/useChatApi';\nimport { hydrateChatHistorySnapshot, persistChatHistorySnapshot } from '../../features/chat/chatHistorySnapshot';\nimport { AudioRecorderPanel } from '../../features/audio-input/AudioRecorderPanel';\nimport { MicErrorBoundary } from '../../features/audio-input/MicErrorBoundary';\nimport { requestMicPermission } from '../../features/audio-input/useAudioPermission';\nimport type { ModeSubmission, RoutingMode } from './types';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { useAppTheme } from '../../theme/AppThemeProvider';\nimport { type BuildTemplateCard } from '../../features/templates/buildTemplateCards';\nimport { useMarketplaceTemplateGroups } from '../../hooks/useMarketplaceTemplateGroups';\nimport { useImageAttachments } from '../../features/attachments/useImageAttachments';\nimport { ComposerAttachmentBar } from '../../features/attachments/ComposerAttachmentBar';\nimport { useComposerAttachMenu } from '../../features/attachments/ComposerAttachMenu';\nimport { stashComposerAttachments } from '../../features/attachments/composerAttachmentHandoff';\nimport { nativeHandoffParams } from '../../features/apps/nativeAppNavigation';\nimport { BuildTemplatesSection } from './components/BuildTemplatesSection';\nimport { ChooseTemplateModal } from './components/ChooseTemplateModal';\nimport { HomeSuggestions } from './components/HomeSuggestions';\nimport { WebBuilderPrewarm } from './components/WebBuilderPrewarm';\nimport { CanvasPrewarm } from './components/CanvasPrewarm';\nimport { WebBuilderCodePrewarm } from './components/WebBuilderCodePrewarm';\nimport { afterNativeModalClose, dispatchDrawerAction, resetDrawerClosed } from '../../utils/drawerNavigation';\n\n/**\n * Build the channel `title` we persist on creation. This is the server-side mode\n * signal (web parity: `useYantraComposerChannelSubmit`): the backend inspects the\n * title prefix to route deep-search requests differently from plain chat. The\n * UI never displays this raw string — `buildSessionFromChannel` filters\n * `chat-channel-…` / `deep-search-…` titles out of the history label cascade\n * and derives the visible label from the user's first message instead.\n *\n * Previously we used the user's prompt directly as the title for friendlier\n * history rows, but that silently disabled the server's mode detection — every\n * \"deep-search\" submission landed as a plain chat. Restored to the web scheme.\n */\nfunction buildChannelTitle(mode: RoutingMode, channelId: string): string {\n if (mode === 'deep-search') return `deep-search-${channelId}`;\n if (mode === 'build') return `build-channel-${channelId}`;\n return `chat-channel-${channelId}`;\n}\n\nexport type { RoutingMode, ModeSubmission };\n\nexport interface HomeScreenProps {\n initialMode?: RoutingMode;\n onSubmit?: (submission: ModeSubmission) => void;\n onStop?: () => void;\n isLoading?: boolean;\n disabled?: boolean;\n}\n\ninterface EmptyStateSectionProps {\n isDark: boolean;\n secondaryTextColor: string;\n primaryTextColor: string;\n activeMode: RoutingMode;\n selectedTemplateGroup: string | null;\n selectedBuildTemplateId: string | null;\n compact: boolean;\n onInjectPrompt: (prompt: string, mode?: RoutingMode) => void;\n onOpenRoute?: (name: string) => void;\n}\n\nconst EMPTY_STATE_TITLES: Record<RoutingMode, string> = {\n build: 'What should we build?',\n 'deep-search': 'What should we research?',\n chat: 'Ask anything',\n};\n\nfunction emptyStateSubtitle(mode: RoutingMode, hasTemplate: boolean, hasTemplateGroup: boolean): string {\n if (mode === 'deep-search') return 'Source-backed answers from the web.';\n if (mode !== 'build') return 'Chat, Deep Search, or Build from the composer.';\n if (hasTemplate) return 'Describe the project, then send.';\n return hasTemplateGroup ? 'Tap a starter below, then send.' : 'Tap Template to pick a group, then send.';\n}\n\nfunction composerPlaceholder(mode: RoutingMode, hasTemplate: boolean): string {\n if (mode === 'deep-search') return 'Research anything...';\n if (mode !== 'build') return 'Ask anything...';\n return hasTemplate ? 'Build me: describe your project…' : 'Describe an app to build...';\n}\n\n/** The web-builder seed for a template's stack name. */\nfunction seedTemplateFor(stack: string): 'nextjs' | 'vue' | 'vite-react' {\n if (stack.includes('next')) return 'nextjs';\n return stack.includes('vue') ? 'vue' : 'vite-react';\n}\n\n/** What Home reads from its route. */\ntype HomeRouteParams = {\n orgName?: string | null;\n hideNavigationHeader?: boolean;\n newChatNonce?: string | number;\n initialSessionId?: string | null;\n};\n\n/** How long a send waits for the workspace to resolve before it is dropped. */\nconst SEND_WAIT_MS = 20_000;\n\nconst EmptyStateSection = React.memo(function EmptyStateSection({\n isDark,\n secondaryTextColor,\n primaryTextColor,\n activeMode,\n selectedTemplateGroup,\n selectedBuildTemplateId,\n compact,\n onInjectPrompt,\n onOpenRoute,\n}: EmptyStateSectionProps) {\n const title = EMPTY_STATE_TITLES[activeMode];\n const subtitle = emptyStateSubtitle(activeMode, Boolean(selectedBuildTemplateId), Boolean(selectedTemplateGroup));\n\n return (\n <View style={styles.emptyInner}>\n <Text\n style={[\n styles.emptyCenterTitle,\n compact && styles.emptyCenterTitleCompact,\n { color: primaryTextColor },\n ]}\n >\n {title}\n </Text>\n <Text style={[styles.emptySubtitle, compact && styles.emptySubtitleCompact, { color: secondaryTextColor }]}>\n {subtitle}\n </Text>\n {activeMode === 'chat' ? (\n <HomeSuggestions\n isDark={isDark}\n compact={compact}\n primaryTextColor={primaryTextColor}\n secondaryTextColor={secondaryTextColor}\n onInjectPrompt={onInjectPrompt}\n onOpenRoute={onOpenRoute}\n />\n ) : null}\n </View>\n );\n});\n\nfunction HomeScreenContent({\n initialMode = 'chat',\n onSubmit: onSubmitProp,\n isLoading: isLoadingProp = false,\n disabled = false,\n}: HomeScreenProps) {\n const { width: screenWidth } = useWindowDimensions();\n const { isDark } = useAppTheme();\n const navigation = useNavigation<NavigationProp<ParamListBase>>();\n const route = useRoute<RouteProp<Record<string, HomeRouteParams | undefined>, string>>();\n const dispatch = useDispatch();\n const syncedRouteOrgRef = useRef<string | null>(null);\n const mobileRoutePath = useSelector(\n (state: { router?: { location?: { currentRoute?: { path?: string } } } }) =>\n state.router?.location?.currentRoute?.path,\n );\n\n const [value, setValue] = useState('');\n const inputRef = useRef<TextInput>(null);\n /**\n * Home stays mounted under the chat stack. `setValue('')` on submit does not\n * always clear the iOS TextInput buffer, so Back would show the prompt that\n * was already sent. Bump this to remount the toolbar, and clear again on focus.\n */\n const [composerEpoch, setComposerEpoch] = useState(0);\n const clearComposerOnFocusRef = useRef(false);\n\n const resetComposer = useCallback(() => {\n setValue('');\n setComposerEpoch((n) => n + 1);\n inputRef.current?.clear();\n }, []);\n\n useFocusEffect(\n useCallback(() => {\n resetDrawerClosed(navigation);\n const task = InteractionManager.runAfterInteractions(() => {\n resetDrawerClosed(navigation);\n });\n if (route?.params?.hideNavigationHeader) {\n navigation.setParams?.({ hideNavigationHeader: undefined });\n }\n if (clearComposerOnFocusRef.current) {\n clearComposerOnFocusRef.current = false;\n resetComposer();\n }\n return () => {\n task.cancel();\n dispatchDrawerAction(navigation, 'close');\n };\n }, [navigation, resetComposer, route?.params?.hideNavigationHeader]),\n );\n const [activeMode, setActiveMode] = useState<RoutingMode>(initialMode);\n /**\n * `showAudioRecorder` swaps the InputToolBar for the inline voice recorder\n * panel — same pattern as the web composer\n * (`YantraSearchComposer.tsx`'s `showAudioRecorder` branch).\n */\n const [showAudioRecorder, setShowAudioRecorder] = useState(false);\n /**\n * Build-mode template group (`codeAssistant`, …) — same picker web uses before\n * `DefaultFormTemplatesSection` loads remix cards with `snapshotId`.\n */\n const [selectedTemplateGroup, setSelectedTemplateGroup] = useState<string | null>(null);\n /** Armed remix card — submit sends input `message` + this card's `snapshotId`. */\n const [selectedBuildTemplate, setSelectedBuildTemplate] = useState<BuildTemplateCard | null>(null);\n const [showTemplateModal, setShowTemplateModal] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n const composerAttachments = useImageAttachments();\n const { rightItems, menu: attachMenu } = useComposerAttachMenu(composerAttachments, isDark);\n const clearComposerAttachments = composerAttachments.clear;\n const newChatNonce = route?.params?.newChatNonce;\n\n useEffect(() => {\n if (newChatNonce == null) return;\n resetComposer();\n setActiveMode('chat');\n setShowAudioRecorder(false);\n setSelectedTemplateGroup(null);\n setSelectedBuildTemplate(null);\n setShowTemplateModal(false);\n setVoiceError(null);\n clearComposerAttachments();\n navigation.setParams?.({ newChatNonce: undefined });\n }, [newChatNonce, clearComposerAttachments, navigation, resetComposer]);\n\n const { createChannel } = useChatMutations();\n const { orgName: resolvedOrgName, projectId, tagId, accountUserId, orgLoading } = usePrerequisiteIds();\n const routeOrgName = ((route?.params?.orgName as string | undefined) ?? '').trim() || null;\n const effectiveOrgName = resolvedOrgName || routeOrgName || null;\n const effectiveProjectId = projectId || null;\n const { sessions: prefetchedHistory, sessionsLoaded: historyPrefetched } = usePrefetchChatHistory(effectiveOrgName);\n useEffect(() => {\n void hydrateChatHistorySnapshot();\n }, []);\n useEffect(() => {\n if (!effectiveOrgName || !accountUserId || !historyPrefetched) return;\n persistChatHistorySnapshot(accountUserId, effectiveOrgName, prefetchedHistory);\n }, [accountUserId, effectiveOrgName, historyPrefetched, prefetchedHistory]);\n\n const { groups: marketplaceTemplateGroups, loading: templateGroupsLoading } = useMarketplaceTemplateGroups({\n orgName: effectiveOrgName,\n enabled: true,\n });\n\n const trimmedQuery = value.trim();\n const isBuildMePrefixOnly = /^build\\s*me\\s*:?\\s*$/i.test(trimmedQuery);\n const hasQuery = trimmedQuery.length > 0 && !isBuildMePrefixOnly;\n const hasAttachments = composerAttachments.pending.length > 0;\n // The workspace (org) resolves over the network a beat after Home paints. A send\n // before then waits for it, instead of the composer reading \"Initializing\n // workspace...\" and refusing to send for the first second of every launch.\n const workspaceReady = Boolean(routeOrgName || effectiveOrgName);\n const canSubmit = hasQuery || hasAttachments;\n const [sendWhenReady, setSendWhenReady] = useState(false);\n const isLoading = isLoadingProp;\n const isBuildMode = activeMode === 'build';\n const inputPlaceholder = composerPlaceholder(activeMode, Boolean(selectedBuildTemplate));\n\n const insets = useSafeAreaInsets();\n const { keyboardVisible } = useKeyboardBottomOffset();\n const emptyScrollRef = useRef<ScrollView>(null);\n\n useEffect(() => {\n if (!keyboardVisible) return;\n emptyScrollRef.current?.scrollTo({ y: 0, animated: true });\n }, [keyboardVisible]);\n\n const handleModeSwitch = useCallback((mode: RoutingMode) => {\n setActiveMode(mode);\n if (mode !== 'build') {\n setShowTemplateModal(false);\n setSelectedTemplateGroup(null);\n setSelectedBuildTemplate(null);\n }\n }, []);\n\n /**\n * Mirrors the web `useYantraComposerChannelSubmit`: on submit we generate a client-side\n * channel id, fire-and-forget the createChannel mutation, then navigate immediately to\n * the Chat screen with the user's prompt. The Chat screen mounts, awaits the in-flight\n * creation just before saveMessages, and starts streaming the assistant response.\n */\n const navigateToChat = useCallback(\n (channelId: string, query: string, mode: RoutingMode, attachments?: ModeSubmission['attachments']) => {\n const params: Record<string, unknown> = {\n channelId,\n orgName: effectiveOrgName ?? routeOrgName ?? undefined,\n initialQuery: query,\n initialMode: mode,\n // Chat asks the brain whether this belongs in Shop or another app - once,\n // with the user's message already on screen, and carries the ask (and this\n // channel) there if so. Asking here first held the message back for up to\n // two seconds after Send.\n };\n if (attachments && attachments.length > 0) {\n params.initialAttachments = attachments;\n }\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.Chat',\n params,\n }),\n );\n },\n [navigation, effectiveOrgName, routeOrgName],\n );\n\n /** Starter chips with a real native screen navigate there directly. */\n const handleOpenRoute = React.useCallback(\n (name: string) => {\n dispatchDrawerAction(navigation, 'close');\n afterNativeModalClose(() => {\n navigation.dispatch(\n CommonActions.navigate({\n name,\n params: { orgName: effectiveOrgName ?? routeOrgName ?? undefined },\n }),\n );\n });\n },\n [navigation, effectiveOrgName, routeOrgName],\n );\n\n type WebBuilderHandoff = {\n message: string;\n snapshotId?: string;\n templateId?: string;\n templateTitle?: string;\n seedTemplate?: string;\n deployUrl?: string;\n previewUrl?: string;\n };\n\n /**\n * Build mode → Web Builder (`/c/:channelId/webbuilder`).\n * Template remix passes `snapshotId` so the surface boots from that E2B snapshot.\n */\n const navigateToWebBuilder = useCallback(\n (channelId: string, handoff: WebBuilderHandoff) => {\n // Snapshot remix: do not stamp shared org projectId — surface mints a fresh\n // channel+project (web Templates picker parity). Passing DEFAULT_YANTRA_PROJECT\n // made results merge into existing gallery tiles (Counter App).\n const isRemix = Boolean(handoff.snapshotId?.trim());\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: {\n orgName: effectiveOrgName ?? routeOrgName ?? undefined,\n // Snapshot remix: omit channelId — surface mints a fresh listen\n // channel. Passing the pre-created id made hydrate re-bind poll onto\n // an empty channel while the build workflow published to the minted id.\n ...(!isRemix ? { channelId } : {}),\n ...(!isRemix && effectiveProjectId ? { projectId: effectiveProjectId } : {}),\n message: handoff.message,\n ...(handoff.snapshotId ? { snapshotId: handoff.snapshotId } : {}),\n ...(handoff.templateId ? { templateId: handoff.templateId } : {}),\n ...(handoff.templateTitle ? { templateTitle: handoff.templateTitle } : {}),\n ...(handoff.seedTemplate ? { seedTemplate: handoff.seedTemplate } : {}),\n },\n }),\n );\n },\n [navigation, effectiveOrgName, routeOrgName, effectiveProjectId],\n );\n\n /**\n * Tap a Yantra card → arm it (store snapshotId). Do NOT navigate yet.\n * Composer shows \"Build me: \" — user writes the project brief (no template title).\n */\n const handleUseBuildTemplate = useCallback((card: BuildTemplateCard) => {\n const snapshotId = card.snapshotId?.trim();\n if (!snapshotId) {\n console.warn('[HomeScreen] template missing snapshotId — select another remixable card.');\n }\n setSelectedBuildTemplate(card);\n setValue((prev) => {\n const trimmed = prev.trim();\n // Keep whatever the user already typed; otherwise seed only the prefix.\n if (trimmed && !/^build\\s*me\\s*:?\\s*$/i.test(trimmed)) return prev;\n return 'Build me: ';\n });\n }, []);\n\n const handleSelectTemplateGroup = useCallback((groupId: string) => {\n setSelectedTemplateGroup(groupId);\n setSelectedBuildTemplate(null);\n setShowTemplateModal(false);\n }, []);\n\n const handleClearBuildTemplate = useCallback(() => {\n if (selectedBuildTemplate) {\n setSelectedBuildTemplate(null);\n return;\n }\n setSelectedTemplateGroup(null);\n }, [selectedBuildTemplate]);\n\n const handleSubmit = useCallback(async () => {\n if (!canSubmit || isLoading || disabled) return;\n if (!workspaceReady) {\n setSendWhenReady(true);\n return;\n }\n\n const attachmentsToForward = composerAttachments.forSend();\n const submission: ModeSubmission = {\n mode: activeMode,\n query: trimmedQuery,\n attachments: attachmentsToForward,\n };\n if (onSubmitProp) {\n onSubmitProp(submission);\n }\n\n if (!effectiveOrgName) {\n console.warn('[HomeScreen] orgName not ready — skipping submit.');\n return;\n }\n // Project can lag behind org after a competing hook stole bootstrap; use the\n // known testing project so Build/Chat are not stuck on \"not ready\".\n const submitProjectId = effectiveProjectId || '9a8ac704-1040-4836-9b72-48b771ca91b1';\n if (!effectiveProjectId) {\n console.warn('[HomeScreen] projectId not ready — using testing project fallback for submit.');\n }\n\n const queryToForward = trimmedQuery;\n\n // A plain build goes to the native Web Builder, whose agent takes the ask and\n // makes its own project channel - so no build channel is created here. Only a\n // template remix (E2B snapshot) still needs the web surface.\n if (activeMode === 'build' && !selectedBuildTemplate?.snapshotId?.trim()) {\n clearComposerOnFocusRef.current = true;\n resetComposer();\n composerAttachments.clear();\n setSelectedBuildTemplate(null);\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilderNative',\n params: nativeHandoffParams({\n orgName: effectiveOrgName,\n query: queryToForward,\n files: attachmentsToForward,\n }),\n }),\n );\n return;\n }\n\n // Nothing waits on the network between Send and the user's message on screen:\n // whether the ask belongs in Shop or another app is Chat's call, made while\n // the message already shows there.\n const requestedChannelId = uuidv4();\n /**\n * Title is the server's mode signal (`deep-search-…` / `build-channel-…` / `chat-channel-…`).\n * It's NOT the history label — the history list derives that from the\n * first user message via `buildSessionFromChannel`.\n */\n const title = buildChannelTitle(activeMode, requestedChannelId);\n\n clearComposerOnFocusRef.current = true;\n resetComposer();\n composerAttachments.clear();\n stashComposerAttachments(requestedChannelId, attachmentsToForward);\n\n void createChannel({\n id: requestedChannelId,\n title,\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: null,\n systemPrompt: null,\n orgName: effectiveOrgName,\n projectId: submitProjectId,\n }).catch((err) => {\n console.error('[HomeScreen] createChannel failed:', err);\n });\n\n if (activeMode === 'build') {\n const tpl = selectedBuildTemplate;\n const snapshotId = tpl?.snapshotId?.trim() || undefined;\n // Stack for webbuilder modelConfig.template — never marketplace keys\n // like aieditor-code-extractor. Do NOT pass previewUrl (live E2B host)\n // or the surface/backend may reconnect that sandbox instead of remixing.\n const rawStack = (tpl?.templateName || '').toLowerCase();\n const seedTemplate = snapshotId ? seedTemplateFor(rawStack) : undefined;\n navigateToWebBuilder(requestedChannelId, {\n message: queryToForward,\n snapshotId,\n templateId: tpl ? tpl.formTemplateId || tpl.id : undefined,\n templateTitle: tpl?.title,\n seedTemplate,\n });\n setSelectedBuildTemplate(null);\n return;\n }\n\n navigateToChat(requestedChannelId, queryToForward, activeMode);\n }, [\n canSubmit,\n workspaceReady,\n isLoading,\n disabled,\n activeMode,\n trimmedQuery,\n onSubmitProp,\n effectiveOrgName,\n effectiveProjectId,\n createChannel,\n navigateToChat,\n navigateToWebBuilder,\n selectedBuildTemplate,\n composerAttachments,\n resetComposer,\n navigation,\n ]);\n\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const primaryTextColor = isDark ? '#e5e7eb' : mobileTokens.color.text;\n const secondaryTextColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));\n\n /**\n * After verify-user, Home mounts with empty `route.params.orgName`. Settings load via\n * `usePrerequisiteIds` (single useSettings). Merge-navigate does not re-fire LOCATION_CHANGE\n * on the same path; sync params + LOCATION_CHANGE + orgChangeAction like refresh does.\n */\n useEffect(() => {\n const currentRouteOrgName = (route?.params?.orgName as string | undefined)?.trim() || '';\n if (currentRouteOrgName) {\n syncedRouteOrgRef.current = currentRouteOrgName;\n return;\n }\n const orgToApply = resolvedOrgName;\n if (!orgToApply || orgLoading) {\n return;\n }\n if (syncedRouteOrgRef.current === orgToApply) {\n return;\n }\n\n syncedRouteOrgRef.current = orgToApply;\n syncMobileOrgRouteContext(dispatch, orgToApply, {\n userId: accountUserId,\n routePath: mobileRoutePath,\n });\n navigation.dispatch(\n CommonActions.navigate({\n name: route?.name ?? 'MainStack.Layout.Home',\n params: { ...(route?.params || {}), orgName: orgToApply },\n merge: true,\n }),\n );\n }, [\n dispatch,\n navigation,\n route?.name,\n route?.params,\n route?.params?.orgName,\n resolvedOrgName,\n accountUserId,\n mobileRoutePath,\n orgLoading,\n ]);\n\n const handleValueChange = useCallback((e: NativeSyntheticEvent<TextInputChangeEventData>) => {\n setValue(e.nativeEvent.text);\n }, []);\n\n const handleInjectPrompt = useCallback((prompt: string, mode?: RoutingMode) => {\n setValue(prompt);\n if (mode) setActiveMode(mode);\n }, []);\n\n /**\n * Mic affordance — web parity (`handleMicClick` in `YantraSearchComposer.tsx`).\n *\n * Only opens the recorder when the input is empty: if the user already has\n * a draft, the same button must act as Send (the `MicSendButton` in\n * `InputToolBar.tsx` already swaps its glyph from mic→send based on\n * `hasContent`, so this branch only fires when the icon is visibly a mic).\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 const handleTranscriptionComplete = useCallback((text: string) => {\n const cleaned = (text ?? '').trim();\n setShowAudioRecorder(false);\n if (!cleaned) return;\n /*\n * Append on top of any existing draft (web `setQuery((prev) => …)`).\n * Single-space separator keeps the transcript readable when the user\n * dictates multiple times before sending.\n */\n setValue((prev) => (prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned));\n }, []);\n\n const handleRecorderCancel = useCallback(() => {\n setShowAudioRecorder(false);\n }, []);\n\n const handleRecorderError = useCallback((error: string) => {\n /*\n * Surface the failure to the user but don't trap them in the recorder —\n * `AudioRecorderPanel` already calls `onCancel` after an error, so we\n * just record the message here for the (lightweight) banner below.\n */\n setVoiceError(error);\n }, []);\n\n const leftItems = useMemo(\n () =>\n getDefaultLeftItems({\n search: {\n active: activeMode === 'chat',\n onClick: () => handleModeSwitch('chat'),\n },\n zap: {\n active: activeMode === 'deep-search',\n onClick: () => handleModeSwitch('deep-search'),\n },\n lightbulb: {\n active: activeMode === 'build',\n onClick: () => handleModeSwitch('build'),\n },\n }),\n [activeMode, handleModeSwitch],\n );\n\n const templateModalItems = useMemo(\n () =>\n marketplaceTemplateGroups.map((group) => ({\n id: group.id,\n label: group.label,\n description: group.description,\n category: group.category,\n })),\n [marketplaceTemplateGroups],\n );\n\n const selectedTemplateLabel = useMemo(() => {\n if (selectedBuildTemplate?.title?.trim()) return selectedBuildTemplate.title.trim();\n if (!selectedTemplateGroup) return undefined;\n return marketplaceTemplateGroups.find((g) => g.id === selectedTemplateGroup)?.label || selectedTemplateGroup;\n }, [marketplaceTemplateGroups, selectedTemplateGroup, selectedBuildTemplate]);\n\n const templateButton = useMemo(() => {\n if (!isBuildMode) return null;\n return {\n label: 'Template',\n count: marketplaceTemplateGroups.length,\n selectedLabel: selectedTemplateLabel,\n onClick: () => setShowTemplateModal(true),\n onClearTemplate: handleClearBuildTemplate,\n disabled: isLoading || disabled || (templateGroupsLoading && marketplaceTemplateGroups.length === 0),\n };\n }, [\n isBuildMode,\n marketplaceTemplateGroups.length,\n selectedTemplateLabel,\n handleClearBuildTemplate,\n isLoading,\n disabled,\n templateGroupsLoading,\n ]);\n\n const templateModalConfig = useMemo(() => {\n if (!isBuildMode) return null;\n return {\n isOpen: showTemplateModal,\n onClose: () => setShowTemplateModal(false),\n templates: templateModalItems,\n selectedId: selectedTemplateGroup,\n onSelect: handleSelectTemplateGroup,\n title: 'Choose Template',\n };\n }, [isBuildMode, showTemplateModal, templateModalItems, selectedTemplateGroup, handleSelectTemplateGroup]);\n\n const renderTemplateModal = useCallback(\n (config: {\n isOpen: boolean;\n onClose: () => void;\n templates: Array<{ id: string; label: string; description?: string; category?: string }>;\n selectedId: string | null;\n onSelect: (id: string) => void;\n suggestedId?: string | null;\n title?: string;\n }) => (\n <ChooseTemplateModal\n isOpen={config.isOpen}\n onClose={config.onClose}\n templates={config.templates}\n selectedId={config.selectedId}\n onSelect={config.onSelect}\n suggestedId={config.suggestedId}\n title={config.title}\n isDark={isDark}\n loading={templateGroupsLoading}\n />\n ),\n [isDark, templateGroupsLoading],\n );\n\n // Send what was waiting for the workspace as soon as it resolves; clearing the\n // text cancels it, and it gives up rather than spin forever.\n useEffect(() => {\n if (!sendWhenReady) return undefined;\n if (!canSubmit) {\n setSendWhenReady(false);\n return undefined;\n }\n if (workspaceReady) {\n setSendWhenReady(false);\n void handleSubmit();\n return undefined;\n }\n const timer = setTimeout(() => {\n console.warn('[HomeScreen] workspace never resolved - dropping the queued send.');\n setSendWhenReady(false);\n }, SEND_WAIT_MS);\n return () => clearTimeout(timer);\n }, [sendWhenReady, canSubmit, workspaceReady, handleSubmit]);\n\n const inputConfig = useMemo(\n () => ({\n value,\n onChange: handleValueChange,\n placeholder: inputPlaceholder,\n disabled: isLoading || disabled,\n inputRef,\n returnKeyType: 'send',\n blurOnSubmit: true,\n onSubmitEditing: () => {\n if (canSubmit) void handleSubmit();\n },\n }),\n [value, handleValueChange, inputPlaceholder, isLoading, disabled, canSubmit, handleSubmit],\n );\n\n const micSendButton = useMemo(\n () => ({\n hasContent: hasQuery || hasAttachments,\n onSend: () => {\n Keyboard.dismiss();\n void handleSubmit();\n },\n onMic: handleMicPress,\n disabled: isLoading || disabled,\n isLoading: isLoading || sendWhenReady,\n }),\n [hasQuery, hasAttachments, handleSubmit, handleMicPress, isLoading, disabled, sendWhenReady],\n );\n\n return (\n <SafeAreaView edges={['left', 'right']} style={{ flex: 1, backgroundColor: surfaceColor }}>\n {/* Mint token + load webbuilder-surface off-screen while user picks a template. */}\n <WebBuilderPrewarm\n enabled={isBuildMode}\n orgName={effectiveOrgName}\n projectId={effectiveProjectId}\n tagId={tagId}\n />\n <CanvasPrewarm orgName={effectiveOrgName} projectId={effectiveProjectId} tagId={tagId} />\n <WebBuilderCodePrewarm />\n <KeyboardAwareScreen>\n <View style={styles.flex}>\n <View style={styles.flex}>\n <ScrollView\n ref={emptyScrollRef}\n style={styles.flex}\n contentContainerStyle={[\n styles.emptyScroll,\n keyboardVisible ? styles.emptyScrollKeyboardOpen : null,\n ]}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}\n automaticallyAdjustKeyboardInsets={false}\n contentInsetAdjustmentBehavior=\"never\"\n showsVerticalScrollIndicator={false}\n >\n <Pressable style={styles.dismissArea} onPress={dismissKeyboard} accessible={false}>\n <EmptyStateSection\n isDark={isDark}\n secondaryTextColor={secondaryTextColor}\n primaryTextColor={primaryTextColor}\n activeMode={activeMode}\n selectedTemplateGroup={selectedTemplateGroup}\n selectedBuildTemplateId={selectedBuildTemplate?.id ?? null}\n compact={keyboardVisible}\n onInjectPrompt={handleInjectPrompt}\n onOpenRoute={handleOpenRoute}\n />\n </Pressable>\n </ScrollView>\n </View>\n <KeyboardComposerDock closedInset={insets.bottom} onSwipeUp={() => inputRef.current?.focus()}>\n <View style={[styles.composerInner, { width: contentMaxWidth }]}>\n {voiceError || composerAttachments.error ? (\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 || composerAttachments.error}\n </Text>\n </View>\n ) : null}\n {showAudioRecorder ? (\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 <>\n <ComposerAttachmentBar\n attachments={composerAttachments.pending}\n onRemove={composerAttachments.remove}\n isDark={isDark}\n />\n <InputToolBar\n key={composerEpoch}\n inputConfig={inputConfig}\n leftItems={leftItems}\n rightItems={rightItems}\n templateButton={templateButton}\n templateModalConfig={templateModalConfig}\n templateModalRender={renderTemplateModal}\n micSendButton={micSendButton}\n />\n </>\n )}\n {isBuildMode ? (\n <BuildTemplatesSection\n enabled\n compact={keyboardVisible}\n group={selectedTemplateGroup}\n orgName={effectiveOrgName}\n isDark={isDark}\n primaryTextColor={primaryTextColor}\n secondaryTextColor={secondaryTextColor}\n selectedTemplateId={selectedBuildTemplate?.id ?? null}\n onUseTemplate={handleUseBuildTemplate}\n />\n ) : null}\n </View>\n </KeyboardComposerDock>\n </View>\n </KeyboardAwareScreen>\n {attachMenu}\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n flex: {\n flex: 1,\n },\n emptyScroll: {\n flexGrow: 1,\n width: '100%',\n paddingHorizontal: 28,\n justifyContent: 'center',\n paddingVertical: 24,\n },\n emptyScrollKeyboardOpen: {\n justifyContent: 'flex-start',\n paddingTop: 12,\n paddingBottom: 8,\n },\n emptyInner: {\n alignItems: 'center',\n width: '100%',\n },\n dismissArea: {\n width: '100%',\n },\n emptyCenterTitle: {\n fontSize: 28,\n fontWeight: '700',\n textAlign: 'center',\n letterSpacing: -0.5,\n },\n emptyCenterTitleCompact: {\n fontSize: 22,\n },\n emptySubtitle: {\n marginTop: 8,\n fontSize: 15,\n lineHeight: 22,\n textAlign: 'center',\n maxWidth: 320,\n },\n emptySubtitleCompact: {\n marginTop: 4,\n fontSize: 13,\n lineHeight: 18,\n },\n composerInner: {\n paddingHorizontal: 14,\n paddingTop: 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});\n\nconst HomeScreen: FC<HomeScreenProps> = (props) => <HomeScreenContent {...props} />;\n\nexport default HomeScreen;\n"],"names":["React","EmptyStateSection","_a","_b","_c","uuidv4"],"mappings":";;;;;;;;;;;;;;;;;;;AA+CA,SAAS,iBAAA,CAAkB,MAAmB,SAA2B,EAAA;AACvE,EAAA,IAAI,IAAS,KAAA,aAAA,EAAsB,OAAA,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA;AAC3D,EAAA,IAAI,IAAS,KAAA,OAAA,EAAgB,OAAA,CAAA,cAAA,EAAiB,SAAS,CAAA,CAAA;AACvD,EAAA,OAAO,gBAAgB,SAAS,CAAA,CAAA;AAClC;AAoBA,MAAM,kBAAkD,GAAA;AAAA,EACtD,KAAO,EAAA,uBAAA;AAAA,EACP,aAAe,EAAA,0BAAA;AAAA,EACf,IAAM,EAAA;AACR,CAAA;AACA,SAAS,kBAAA,CAAmB,IAAmB,EAAA,WAAA,EAAsB,gBAAmC,EAAA;AACtG,EAAI,IAAA,IAAA,KAAS,eAAsB,OAAA,qCAAA;AACnC,EAAI,IAAA,IAAA,KAAS,SAAgB,OAAA,gDAAA;AAC7B,EAAA,IAAI,aAAoB,OAAA,kCAAA;AACxB,EAAA,OAAO,mBAAmB,iCAAoC,GAAA,0CAAA;AAChE;AACA,SAAS,mBAAA,CAAoB,MAAmB,WAA8B,EAAA;AAC5E,EAAI,IAAA,IAAA,KAAS,eAAsB,OAAA,sBAAA;AACnC,EAAI,IAAA,IAAA,KAAS,SAAgB,OAAA,iBAAA;AAC7B,EAAA,OAAO,cAAc,uCAAqC,GAAA,6BAAA;AAC5D;AAGA,SAAS,gBAAgB,KAAgD,EAAA;AACvE,EAAA,IAAI,KAAM,CAAA,QAAA,CAAS,MAAM,CAAA,EAAU,OAAA,QAAA;AACnC,EAAA,OAAO,KAAM,CAAA,QAAA,CAAS,KAAK,CAAA,GAAI,KAAQ,GAAA,YAAA;AACzC;AAWA,MAAM,YAAe,GAAA,GAAA;AACrB,MAAM,iBAAoB,GAAAA,cAAA,CAAM,IAAK,CAAA,SAASC,kBAAkB,CAAA;AAAA,EAC9D,MAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA;AAAA,EACA,qBAAA;AAAA,EACA,uBAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAA2B,EAAA;AACzB,EAAM,MAAA,KAAA,GAAQ,mBAAmB,UAAU,CAAA;AAC3C,EAAM,MAAA,QAAA,GAAW,mBAAmB,UAAY,EAAA,OAAA,CAAQ,uBAAuB,CAAG,EAAA,OAAA,CAAQ,qBAAqB,CAAC,CAAA;AAChH,EAAA,uBAAQ,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,MAAA,CAAO,UACjB,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,gBAAkB,EAAA,OAAA,IAAW,OAAO,uBAAyB,EAAA;AAAA,MACxF,KAAO,EAAA;AAAA,KACR,GACY,QACL,EAAA,KAAA,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,aAAe,EAAA,OAAA,IAAW,OAAO,oBAAsB,EAAA;AAAA,MAClF,KAAO,EAAA;AAAA,KACR,GACY,QACL,EAAA,QAAA,EAAA,CAAA;AAAA,IACC,UAAA,KAAe,MAAS,mBAAA,GAAA,CAAC,eAAgB,EAAA,EAAA,MAAA,EAAgB,SAAkB,gBAAoC,EAAA,kBAAA,EAAwC,cAAgC,EAAA,WAAA,EAA0B,CAAK,GAAA;AAAA,GAC3N,EAAA,CAAA;AACR,CAAC,CAAA;AACD,SAAS,iBAAkB,CAAA;AAAA,EACzB,WAAc,GAAA,MAAA;AAAA,EACd,QAAU,EAAA,YAAA;AAAA,EACV,WAAW,aAAgB,GAAA,KAAA;AAAA,EAC3B,QAAW,GAAA;AACb,CAAoB,EAAA;AAxIpB,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AAyIE,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA;AAAA,MACL,mBAAoB,EAAA;AACxB,EAAM,MAAA;AAAA,IACJ;AAAA,MACE,WAAY,EAAA;AAChB,EAAA,MAAM,aAAa,aAA6C,EAAA;AAChE,EAAA,MAAM,QAAQ,QAAyE,EAAA;AACvF,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAM,MAAA,iBAAA,GAAoB,OAAsB,IAAI,CAAA;AACpD,EAAM,MAAA,eAAA,GAAkB,WAAY,CAAA,CAAC,KAQlC,KAAA;AA3JL,IAAA,IAAAC,KAAAC,GAAAC,EAAAA,GAAAA;AA2JQ,IAAA,OAAA,CAAAA,GAAAD,GAAAA,CAAAA,GAAAA,GAAAA,CAAAD,GAAA,GAAA,KAAA,CAAM,MAAN,KAAA,IAAA,GAAA,MAAA,GAAAA,GAAc,CAAA,QAAA,KAAd,IAAAC,GAAAA,MAAAA,GAAAA,GAAAA,CAAwB,YAAxB,KAAA,IAAA,GAAA,MAAA,GAAAC,GAAsC,CAAA,IAAA;AAAA,GAAI,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,EAAE,CAAA;AACrC,EAAM,MAAA,QAAA,GAAW,OAAkB,IAAI,CAAA;AAMvC,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,CAAC,CAAA;AACpD,EAAM,MAAA,uBAAA,GAA0B,OAAO,KAAK,CAAA;AAC5C,EAAM,MAAA,aAAA,GAAgB,YAAY,MAAM;AArK1C,IAAAF,IAAAA,GAAAA;AAsKI,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAiB,gBAAA,CAAA,CAAA,CAAA,KAAK,IAAI,CAAC,CAAA;AAC3B,IAAA,CAAAA,GAAA,GAAA,QAAA,CAAS,OAAT,KAAA,IAAA,GAAA,MAAA,GAAAA,GAAkB,CAAA,KAAA,EAAA;AAAA,GACpB,EAAG,EAAE,CAAA;AACL,EAAA,cAAA,CAAe,YAAY,MAAM;AA1KnC,IAAA,IAAAA,GAAAC,EAAAA,GAAAA;AA2KI,IAAA,iBAAA,CAAkB,UAAU,CAAA;AAC5B,IAAM,MAAA,IAAA,GAAO,kBAAmB,CAAA,oBAAA,CAAqB,MAAM;AACzD,MAAA,iBAAA,CAAkB,UAAU,CAAA;AAAA,KAC7B,CAAA;AACD,IAAA,IAAA,CAAID,GAAA,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,MAAP,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAe,oBAAsB,EAAA;AACvC,MAAA,CAAAC,GAAA,GAAA,UAAA,CAAW,SAAX,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAA,IAAuB,CAAA,UAAA,EAAA;AAAA,QACrB,oBAAsB,EAAA;AAAA,OACxB,CAAA;AAAA;AAEF,IAAA,IAAI,wBAAwB,OAAS,EAAA;AACnC,MAAA,uBAAA,CAAwB,OAAU,GAAA,KAAA;AAClC,MAAc,aAAA,EAAA;AAAA;AAEhB,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,MAAO,EAAA;AACZ,MAAA,oBAAA,CAAqB,YAAY,OAAO,CAAA;AAAA,KAC1C;AAAA,GACF,EAAG,CAAC,UAAY,EAAA,aAAA,EAAA,CAAe,oCAAO,MAAP,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAe,oBAAoB,CAAC,CAAC,CAAA;AACpE,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAsB,WAAW,CAAA;AAMrE,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAS,KAAK,CAAA;AAKhE,EAAA,MAAM,CAAC,qBAAA,EAAuB,wBAAwB,CAAA,GAAI,SAAwB,IAAI,CAAA;AAEtF,EAAA,MAAM,CAAC,qBAAA,EAAuB,wBAAwB,CAAA,GAAI,SAAmC,IAAI,CAAA;AACjG,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAS,KAAK,CAAA;AAChE,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAwB,IAAI,CAAA;AAChE,EAAA,MAAM,sBAAsB,mBAAoB,EAAA;AAChD,EAAM,MAAA;AAAA,IACJ,UAAA;AAAA,IACA,IAAM,EAAA;AAAA,GACR,GAAI,qBAAsB,CAAA,mBAAA,EAAqB,MAAM,CAAA;AACrD,EAAA,MAAM,2BAA2B,mBAAoB,CAAA,KAAA;AACrD,EAAM,MAAA,YAAA,GAAA,CAAe,EAAO,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,MAAA,KAAP,IAAe,GAAA,MAAA,GAAA,EAAA,CAAA,YAAA;AACpC,EAAA,SAAA,CAAU,MAAM;AApNlB,IAAAD,IAAAA,GAAAA;AAqNI,IAAA,IAAI,gBAAgB,IAAM,EAAA;AAC1B,IAAc,aAAA,EAAA;AACd,IAAA,aAAA,CAAc,MAAM,CAAA;AACpB,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,IAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,IAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,IAAA,aAAA,CAAc,IAAI,CAAA;AAClB,IAAyB,wBAAA,EAAA;AACzB,IAAA,CAAAA,GAAA,GAAA,UAAA,CAAW,SAAX,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAA,IAAuB,CAAA,UAAA,EAAA;AAAA,MACrB,YAAc,EAAA;AAAA,KAChB,CAAA;AAAA,KACC,CAAC,YAAA,EAAc,wBAA0B,EAAA,UAAA,EAAY,aAAa,CAAC,CAAA;AACtE,EAAM,MAAA;AAAA,IACJ;AAAA,MACE,gBAAiB,EAAA;AACrB,EAAM,MAAA;AAAA,IACJ,OAAS,EAAA,eAAA;AAAA,IACT,SAAA;AAAA,IACA,KAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,MACE,kBAAmB,EAAA;AACvB,EAAM,MAAA,YAAA,GAAA,CAAA,CAAgB,0CAAO,MAAP,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAe,YAAf,IAAgD,GAAA,EAAA,GAAA,EAAA,EAAI,MAAU,IAAA,IAAA;AACpF,EAAM,MAAA,gBAAA,GAAmB,mBAAmB,YAAgB,IAAA,IAAA;AAC5D,EAAA,MAAM,qBAAqB,SAAa,IAAA,IAAA;AACxC,EAAM,MAAA;AAAA,IACJ,QAAU,EAAA,iBAAA;AAAA,IACV,cAAgB,EAAA;AAAA,GAClB,GAAI,uBAAuB,gBAAgB,CAAA;AAC3C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,KAAK,0BAA2B,EAAA;AAAA,GAClC,EAAG,EAAE,CAAA;AACL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,gBAAA,IAAoB,CAAC,aAAA,IAAiB,CAAC,iBAAmB,EAAA;AAC/D,IAA2B,0BAAA,CAAA,aAAA,EAAe,kBAAkB,iBAAiB,CAAA;AAAA,KAC5E,CAAC,aAAA,EAAe,gBAAkB,EAAA,iBAAA,EAAmB,iBAAiB,CAAC,CAAA;AAC1E,EAAM,MAAA;AAAA,IACJ,MAAQ,EAAA,yBAAA;AAAA,IACR,OAAS,EAAA;AAAA,MACP,4BAA6B,CAAA;AAAA,IAC/B,OAAS,EAAA,gBAAA;AAAA,IACT,OAAS,EAAA;AAAA,GACV,CAAA;AACD,EAAM,MAAA,YAAA,GAAe,MAAM,IAAK,EAAA;AAChC,EAAM,MAAA,mBAAA,GAAsB,uBAAwB,CAAA,IAAA,CAAK,YAAY,CAAA;AACrE,EAAA,MAAM,QAAW,GAAA,YAAA,CAAa,MAAS,GAAA,CAAA,IAAK,CAAC,mBAAA;AAC7C,EAAM,MAAA,cAAA,GAAiB,mBAAoB,CAAA,OAAA,CAAQ,MAAS,GAAA,CAAA;AAI5D,EAAM,MAAA,cAAA,GAAiB,OAAQ,CAAA,YAAA,IAAgB,gBAAgB,CAAA;AAC/D,EAAA,MAAM,YAAY,QAAY,IAAA,cAAA;AAC9B,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA;AACxD,EAAA,MAAM,SAAY,GAAA,aAAA;AAClB,EAAA,MAAM,cAAc,UAAe,KAAA,OAAA;AACnC,EAAA,MAAM,gBAAmB,GAAA,mBAAA,CAAoB,UAAY,EAAA,OAAA,CAAQ,qBAAqB,CAAC,CAAA;AACvF,EAAA,MAAM,SAAS,iBAAkB,EAAA;AACjC,EAAM,MAAA;AAAA,IACJ;AAAA,MACE,uBAAwB,EAAA;AAC5B,EAAM,MAAA,cAAA,GAAiB,OAAmB,IAAI,CAAA;AAC9C,EAAA,SAAA,CAAU,MAAM;AAnRlB,IAAAA,IAAAA,GAAAA;AAoRI,IAAA,IAAI,CAAC,eAAiB,EAAA;AACtB,IAAA,CAAAA,GAAA,GAAA,cAAA,CAAe,OAAf,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAwB,QAAS,CAAA;AAAA,MAC/B,CAAG,EAAA,CAAA;AAAA,MACH,QAAU,EAAA;AAAA,KACZ,CAAA;AAAA,GACF,EAAG,CAAC,eAAe,CAAC,CAAA;AACpB,EAAM,MAAA,gBAAA,GAAmB,WAAY,CAAA,CAAC,IAAsB,KAAA;AAC1D,IAAA,aAAA,CAAc,IAAI,CAAA;AAClB,IAAA,IAAI,SAAS,OAAS,EAAA;AACpB,MAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,MAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,MAAA,wBAAA,CAAyB,IAAI,CAAA;AAAA;AAC/B,GACF,EAAG,EAAE,CAAA;AAQL,EAAA,MAAM,iBAAiB,WAAY,CAAA,CAAC,SAAmB,EAAA,KAAA,EAAe,MAAmB,WAAgD,KAAA;AAzS3I,IAAAA,IAAAA,GAAAA;AA0SI,IAAA,MAAM,MAAkC,GAAA;AAAA,MACtC,SAAA;AAAA,MACA,OAASA,EAAAA,CAAAA,GAAAA,GAAA,gBAAoB,IAAA,IAAA,GAAA,gBAAA,GAAA,YAAA,KAApB,OAAAA,GAAoC,GAAA,MAAA;AAAA,MAC7C,YAAc,EAAA,KAAA;AAAA,MACd,WAAa,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAKf;AACA,IAAI,IAAA,WAAA,IAAe,WAAY,CAAA,MAAA,GAAS,CAAG,EAAA;AACzC,MAAA,MAAA,CAAO,kBAAqB,GAAA,WAAA;AAAA;AAE9B,IAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,MACzC,IAAM,EAAA,gBAAA;AAAA,MACN;AAAA,KACD,CAAC,CAAA;AAAA,GACD,EAAA,CAAC,UAAY,EAAA,gBAAA,EAAkB,YAAY,CAAC,CAAA;AAG/C,EAAA,MAAM,eAAkB,GAAAF,cAAA,CAAM,WAAY,CAAA,CAAC,IAAiB,KAAA;AAC1D,IAAA,oBAAA,CAAqB,YAAY,OAAO,CAAA;AACxC,IAAA,qBAAA,CAAsB,MAAM;AAhUhC,MAAAE,IAAAA,GAAAA;AAiUM,MAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,QACzC,IAAA;AAAA,QACA,MAAQ,EAAA;AAAA,UACN,OAASA,EAAAA,CAAAA,GAAAA,GAAA,gBAAoB,IAAA,IAAA,GAAA,gBAAA,GAAA,YAAA,KAApB,OAAAA,GAAoC,GAAA;AAAA;AAC/C,OACD,CAAC,CAAA;AAAA,KACH,CAAA;AAAA,GACA,EAAA,CAAC,UAAY,EAAA,gBAAA,EAAkB,YAAY,CAAC,CAAA;AAe/C,EAAA,MAAM,oBAAuB,GAAA,WAAA,CAAY,CAAC,SAAA,EAAmB,OAA+B,KAAA;AAvV9F,IAAA,IAAAA,GAAAC,EAAAA,GAAAA;AA2VI,IAAA,MAAM,UAAU,OAAQD,CAAAA,CAAAA,GAAAA,GAAA,QAAQ,UAAR,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAoB,IAAM,EAAA,CAAA;AAClD,IAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,MACzC,IAAM,EAAA,sBAAA;AAAA,MACN,MAAQ,EAAA,cAAA,CAAA,cAAA,CAAA,cAAA,CAAA,cAAA,CAAA,aAAA,CAAA,cAAA,CAAA,cAAA,CAAA;AAAA,QACN,OAASC,EAAAA,CAAAA,GAAAA,GAAA,gBAAoB,IAAA,IAAA,GAAA,gBAAA,GAAA,YAAA,KAApB,OAAAA,GAAoC,GAAA;AAAA,OAAA,EAIzC,CAAC,OAAU,GAAA;AAAA,QACb;AAAA,OACE,GAAA,EACA,CAAA,EAAA,CAAC,WAAW,kBAAqB,GAAA;AAAA,QACnC,SAAW,EAAA;AAAA,OACb,GAAI,EAVE,CAAA,EAAA;AAAA,QAWN,SAAS,OAAQ,CAAA;AAAA,OAAA,CAAA,EACb,QAAQ,UAAa,GAAA;AAAA,QACvB,YAAY,OAAQ,CAAA;AAAA,OAClB,GAAA,EACA,CAAA,EAAA,OAAA,CAAQ,UAAa,GAAA;AAAA,QACvB,YAAY,OAAQ,CAAA;AAAA,OAClB,GAAA,EACA,CAAA,EAAA,OAAA,CAAQ,aAAgB,GAAA;AAAA,QAC1B,eAAe,OAAQ,CAAA;AAAA,OACrB,GAAA,EACA,CAAA,EAAA,OAAA,CAAQ,YAAe,GAAA;AAAA,QACzB,cAAc,OAAQ,CAAA;AAAA,UACpB,EAAC;AAAA,KAER,CAAC,CAAA;AAAA,KACD,CAAC,UAAA,EAAY,gBAAkB,EAAA,YAAA,EAAc,kBAAkB,CAAC,CAAA;AAMnE,EAAM,MAAA,sBAAA,GAAyB,WAAY,CAAA,CAAC,IAA4B,KAAA;AA9X1E,IAAAD,IAAAA,GAAAA;AA+XI,IAAA,MAAM,UAAaA,GAAAA,CAAAA,GAAAA,GAAA,IAAK,CAAA,UAAA,KAAL,gBAAAA,GAAiB,CAAA,IAAA,EAAA;AACpC,IAAA,IAAI,CAAC,UAAY,EAAA;AACf,MAAA,OAAA,CAAQ,KAAK,gFAA2E,CAAA;AAAA;AAE1F,IAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,IAAA,QAAA,CAAS,CAAQ,IAAA,KAAA;AACf,MAAM,MAAA,OAAA,GAAU,KAAK,IAAK,EAAA;AAE1B,MAAA,IAAI,WAAW,CAAC,uBAAA,CAAwB,IAAK,CAAA,OAAO,GAAU,OAAA,IAAA;AAC9D,MAAO,OAAA,YAAA;AAAA,KACR,CAAA;AAAA,GACH,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,yBAAA,GAA4B,WAAY,CAAA,CAAC,OAAoB,KAAA;AACjE,IAAA,wBAAA,CAAyB,OAAO,CAAA;AAChC,IAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAAA,GAC5B,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,wBAAA,GAA2B,YAAY,MAAM;AACjD,IAAA,IAAI,qBAAuB,EAAA;AACzB,MAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,MAAA;AAAA;AAEF,IAAA,wBAAA,CAAyB,IAAI,CAAA;AAAA,GAC/B,EAAG,CAAC,qBAAqB,CAAC,CAAA;AAC1B,EAAM,MAAA,YAAA,GAAe,YAAY,YAAY;AAvZ/C,IAAA,IAAAA,GAAAC,EAAAA,GAAAA;AAwZI,IAAI,IAAA,CAAC,SAAa,IAAA,SAAA,IAAa,QAAU,EAAA;AACzC,IAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,MAAA,gBAAA,CAAiB,IAAI,CAAA;AACrB,MAAA;AAAA;AAEF,IAAM,MAAA,oBAAA,GAAuB,oBAAoB,OAAQ,EAAA;AACzD,IAAA,MAAM,UAA6B,GAAA;AAAA,MACjC,IAAM,EAAA,UAAA;AAAA,MACN,KAAO,EAAA,YAAA;AAAA,MACP,WAAa,EAAA;AAAA,KACf;AACA,IAAA,IAAI,YAAc,EAAA;AAChB,MAAA,YAAA,CAAa,UAAU,CAAA;AAAA;AAEzB,IAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,MAAA,OAAA,CAAQ,KAAK,wDAAmD,CAAA;AAChE,MAAA;AAAA;AAIF,IAAA,MAAM,kBAAkB,kBAAsB,IAAA,sCAAA;AAC9C,IAAA,IAAI,CAAC,kBAAoB,EAAA;AACvB,MAAA,OAAA,CAAQ,KAAK,oFAA+E,CAAA;AAAA;AAE9F,IAAA,MAAM,cAAiB,GAAA,YAAA;AAKvB,IAAI,IAAA,UAAA,KAAe,WAAW,EAACD,CAAAA,GAAAA,GAAA,+DAAuB,UAAvB,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAmC,IAAQ,EAAA,CAAA,EAAA;AACxE,MAAA,uBAAA,CAAwB,OAAU,GAAA,IAAA;AAClC,MAAc,aAAA,EAAA;AACd,MAAA,mBAAA,CAAoB,KAAM,EAAA;AAC1B,MAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,MAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,QACzC,IAAM,EAAA,4BAAA;AAAA,QACN,QAAQ,mBAAoB,CAAA;AAAA,UAC1B,OAAS,EAAA,gBAAA;AAAA,UACT,KAAO,EAAA,cAAA;AAAA,UACP,KAAO,EAAA;AAAA,SACR;AAAA,OACF,CAAC,CAAA;AACF,MAAA;AAAA;AAMF,IAAA,MAAM,qBAAqBG,EAAO,EAAA;AAMlC,IAAM,MAAA,KAAA,GAAQ,iBAAkB,CAAA,UAAA,EAAY,kBAAkB,CAAA;AAC9D,IAAA,uBAAA,CAAwB,OAAU,GAAA,IAAA;AAClC,IAAc,aAAA,EAAA;AACd,IAAA,mBAAA,CAAoB,KAAM,EAAA;AAC1B,IAAA,wBAAA,CAAyB,oBAAoB,oBAAoB,CAAA;AACjE,IAAA,KAAK,aAAc,CAAA;AAAA,MACjB,EAAI,EAAA,kBAAA;AAAA,MACJ,KAAA;AAAA,MACA,QAAU,EAAA,KAAA;AAAA,MACV,UAAY,EAAA,IAAA;AAAA,MACZ,UAAY,EAAA,KAAA;AAAA,MACZ,QAAU,EAAA,KAAA;AAAA,MACV,KAAO,EAAA,IAAA;AAAA,MACP,YAAc,EAAA,IAAA;AAAA,MACd,OAAS,EAAA,gBAAA;AAAA,MACT,SAAW,EAAA;AAAA,KACZ,CAAE,CAAA,KAAA,CAAM,CAAO,GAAA,KAAA;AACd,MAAQ,OAAA,CAAA,KAAA,CAAM,sCAAsC,GAAG,CAAA;AAAA,KACxD,CAAA;AACD,IAAA,IAAI,eAAe,OAAS,EAAA;AAC1B,MAAA,MAAM,GAAM,GAAA,qBAAA;AACZ,MAAA,MAAM,eAAaF,GAAA,GAAA,GAAA,IAAA,IAAA,GAAA,MAAA,GAAA,GAAA,CAAK,UAAL,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAiB,IAAU,EAAA,KAAA,MAAA;AAI9C,MAAA,MAAM,QAAY,GAAA,CAAA,CAAA,GAAA,IAAA,IAAA,GAAA,MAAA,GAAA,GAAA,CAAK,YAAgB,KAAA,EAAA,EAAI,WAAY,EAAA;AACvD,MAAA,MAAM,YAAe,GAAA,UAAA,GAAa,eAAgB,CAAA,QAAQ,CAAI,GAAA,MAAA;AAC9D,MAAA,oBAAA,CAAqB,kBAAoB,EAAA;AAAA,QACvC,OAAS,EAAA,cAAA;AAAA,QACT,UAAA;AAAA,QACA,UAAY,EAAA,GAAA,GAAM,GAAI,CAAA,cAAA,IAAkB,IAAI,EAAK,GAAA,MAAA;AAAA,QACjD,eAAe,GAAK,IAAA,IAAA,GAAA,MAAA,GAAA,GAAA,CAAA,KAAA;AAAA,QACpB;AAAA,OACD,CAAA;AACD,MAAA,wBAAA,CAAyB,IAAI,CAAA;AAC7B,MAAA;AAAA;AAEF,IAAe,cAAA,CAAA,kBAAA,EAAoB,gBAAgB,UAAU,CAAA;AAAA,KAC5D,CAAC,SAAA,EAAW,gBAAgB,SAAW,EAAA,QAAA,EAAU,YAAY,YAAc,EAAA,YAAA,EAAc,gBAAkB,EAAA,kBAAA,EAAoB,eAAe,cAAgB,EAAA,oBAAA,EAAsB,uBAAuB,mBAAqB,EAAA,aAAA,EAAe,UAAU,CAAC,CAAA;AAC7P,EAAA,MAAM,YAAe,GAAA,MAAA,GAAS,SAAY,GAAA,YAAA,CAAa,KAAM,CAAA,OAAA;AAC7D,EAAA,MAAM,gBAAmB,GAAA,MAAA,GAAS,SAAY,GAAA,YAAA,CAAa,KAAM,CAAA,IAAA;AACjE,EAAA,MAAM,kBAAqB,GAAA,MAAA,GAAS,SAAY,GAAA,YAAA,CAAa,KAAM,CAAA,SAAA;AACnE,EAAM,MAAA,eAAA,GAAkB,KAAK,GAAI,CAAA,GAAA,EAAK,KAAK,GAAI,CAAA,GAAA,EAAK,WAAc,GAAA,EAAE,CAAC,CAAA;AAOrE,EAAA,SAAA,CAAU,MAAM;AA/flB,IAAA,IAAAD,KAAAC,GAAAC,EAAAA,GAAAA;AAggBI,IAAM,MAAA,mBAAA,GAAA,CAAA,CAAuBD,GAAAD,GAAAA,CAAAA,GAAAA,GAAA,KAAO,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,MAAA,KAAP,gBAAAA,GAAe,CAAA,OAAA,KAAf,IAAAC,GAAAA,MAAAA,GAAAA,GAAAA,CAA+C,IAAU,EAAA,KAAA,EAAA;AACtF,IAAA,IAAI,mBAAqB,EAAA;AACvB,MAAA,iBAAA,CAAkB,OAAU,GAAA,mBAAA;AAC5B,MAAA;AAAA;AAEF,IAAA,MAAM,UAAa,GAAA,eAAA;AACnB,IAAI,IAAA,CAAC,cAAc,UAAY,EAAA;AAC7B,MAAA;AAAA;AAEF,IAAI,IAAA,iBAAA,CAAkB,YAAY,UAAY,EAAA;AAC5C,MAAA;AAAA;AAEF,IAAA,iBAAA,CAAkB,OAAU,GAAA,UAAA;AAC5B,IAAA,yBAAA,CAA0B,UAAU,UAAY,EAAA;AAAA,MAC9C,MAAQ,EAAA,aAAA;AAAA,MACR,SAAW,EAAA;AAAA,KACZ,CAAA;AACD,IAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,MACzC,IAAMC,EAAAA,CAAAA,GAAAA,GAAA,KAAO,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,IAAA,KAAP,OAAAA,GAAe,GAAA,uBAAA;AAAA,MACrB,MAAQ,EAAA,aAAA,CAAA,cAAA,CAAA,EAAA,EAAA,CACF,KAAO,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,MAAA,KAAU,EADf,CAAA,EAAA;AAAA,QAEN,OAAS,EAAA;AAAA,OACX,CAAA;AAAA,MACA,KAAO,EAAA;AAAA,KACR,CAAC,CAAA;AAAA,KACD,CAAC,QAAA,EAAU,UAAY,EAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,MAAM,KAAO,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,MAAA,EAAA,CAAQ,EAAO,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,MAAA,KAAP,mBAAe,OAAS,EAAA,eAAA,EAAiB,aAAe,EAAA,eAAA,EAAiB,UAAU,CAAC,CAAA;AAC1I,EAAM,MAAA,iBAAA,GAAoB,WAAY,CAAA,CAAC,CAAsD,KAAA;AAC3F,IAAS,QAAA,CAAA,CAAA,CAAE,YAAY,IAAI,CAAA;AAAA,GAC7B,EAAG,EAAE,CAAA;AACL,EAAA,MAAM,kBAAqB,GAAA,WAAA,CAAY,CAAC,MAAA,EAAgB,IAAuB,KAAA;AAC7E,IAAA,QAAA,CAAS,MAAM,CAAA;AACf,IAAI,IAAA,IAAA,gBAAoB,IAAI,CAAA;AAAA,GAC9B,EAAG,EAAE,CAAA;AAuBL,EAAM,MAAA,cAAA,GAAiB,YAAY,MAAM;AACvC,IAAA,IAAI,QAAU,EAAA;AACd,IAAA,aAAA,CAAc,IAAI,CAAA;AAClB,IAAA,QAAA,CAAS,OAAQ,EAAA;AACjB,IAAA,KAAA,CAAM,YAAY;AAChB,MAAM,MAAA;AAAA,QACJ,OAAA;AAAA,QACA;AAAA,OACF,GAAI,MAAM,oBAAqB,EAAA;AAC/B,MAAA,IAAI,CAAC,OAAS,EAAA;AACZ,QAAA,aAAA,CAAc,SAAS,8BAA8B,CAAA;AACrD,QAAA;AAAA;AAEF,MAAA,oBAAA,CAAqB,IAAI,CAAA;AAAA,KACxB,GAAA;AAAA,GACL,EAAG,CAAC,QAAQ,CAAC,CAAA;AACb,EAAM,MAAA,2BAAA,GAA8B,WAAY,CAAA,CAAC,IAAiB,KAAA;AAChE,IAAM,MAAA,OAAA,GAAA,CAAW,IAAQ,IAAA,IAAA,GAAA,IAAA,GAAA,EAAA,EAAI,IAAK,EAAA;AAClC,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,IAAA,IAAI,CAAC,OAAS,EAAA;AAMd,IAAA,QAAA,CAAS,CAAQ,IAAA,KAAA,IAAA,CAAK,IAAK,EAAA,CAAE,MAAS,GAAA,CAAA,GAAI,CAAG,EAAA,IAAA,CAAK,IAAK,EAAC,CAAI,CAAA,EAAA,OAAO,KAAK,OAAO,CAAA;AAAA,GACjF,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,oBAAA,GAAuB,YAAY,MAAM;AAC7C,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAAA,GAC5B,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,mBAAA,GAAsB,WAAY,CAAA,CAAC,KAAkB,KAAA;AAMzD,IAAA,aAAA,CAAc,KAAK,CAAA;AAAA,GACrB,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,SAAA,GAAY,OAAQ,CAAA,MAAM,mBAAoB,CAAA;AAAA,IAClD,MAAQ,EAAA;AAAA,MACN,QAAQ,UAAe,KAAA,MAAA;AAAA,MACvB,OAAA,EAAS,MAAM,gBAAA,CAAiB,MAAM;AAAA,KACxC;AAAA,IACA,GAAK,EAAA;AAAA,MACH,QAAQ,UAAe,KAAA,aAAA;AAAA,MACvB,OAAA,EAAS,MAAM,gBAAA,CAAiB,aAAa;AAAA,KAC/C;AAAA,IACA,SAAW,EAAA;AAAA,MACT,QAAQ,UAAe,KAAA,OAAA;AAAA,MACvB,OAAA,EAAS,MAAM,gBAAA,CAAiB,OAAO;AAAA;AACzC,GACD,CAAA,EAAG,CAAC,UAAA,EAAY,gBAAgB,CAAC,CAAA;AAClC,EAAA,MAAM,kBAAqB,GAAA,OAAA,CAAQ,MAAM,yBAAA,CAA0B,IAAI,CAAU,KAAA,MAAA;AAAA,IAC/E,IAAI,KAAM,CAAA,EAAA;AAAA,IACV,OAAO,KAAM,CAAA,KAAA;AAAA,IACb,aAAa,KAAM,CAAA,WAAA;AAAA,IACnB,UAAU,KAAM,CAAA;AAAA,GAChB,CAAA,CAAA,EAAG,CAAC,yBAAyB,CAAC,CAAA;AAChC,EAAM,MAAA,qBAAA,GAAwB,QAAQ,MAAM;AAjnB9C,IAAA,IAAAF,GAAAC,EAAAA,GAAAA;AAknBI,IAAID,IAAAA,CAAAA,GAAAA,GAAA,+DAAuB,KAAvB,KAAA,IAAA,GAAA,MAAA,GAAAA,IAA8B,IAAQ,EAAA,EAAA,OAAO,qBAAsB,CAAA,KAAA,CAAM,IAAK,EAAA;AAClF,IAAI,IAAA,CAAC,uBAA8B,OAAA,MAAA;AACnC,IAAOC,OAAAA,CAAAA,CAAAA,GAAAA,GAAA,yBAA0B,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA,CAAA,CAAE,OAAO,qBAAqB,CAAA,KAAlE,IAAAA,GAAAA,MAAAA,GAAAA,GAAAA,CAAqE,KAAS,KAAA,qBAAA;AAAA,GACpF,EAAA,CAAC,yBAA2B,EAAA,qBAAA,EAAuB,qBAAqB,CAAC,CAAA;AAC5E,EAAM,MAAA,cAAA,GAAiB,QAAQ,MAAM;AACnC,IAAI,IAAA,CAAC,aAAoB,OAAA,IAAA;AACzB,IAAO,OAAA;AAAA,MACL,KAAO,EAAA,UAAA;AAAA,MACP,OAAO,yBAA0B,CAAA,MAAA;AAAA,MACjC,aAAe,EAAA,qBAAA;AAAA,MACf,OAAA,EAAS,MAAM,oBAAA,CAAqB,IAAI,CAAA;AAAA,MACxC,eAAiB,EAAA,wBAAA;AAAA,MACjB,QAAU,EAAA,SAAA,IAAa,QAAY,IAAA,qBAAA,IAAyB,0BAA0B,MAAW,KAAA;AAAA,KACnG;AAAA,GACF,EAAG,CAAC,WAAA,EAAa,yBAA0B,CAAA,MAAA,EAAQ,uBAAuB,wBAA0B,EAAA,SAAA,EAAW,QAAU,EAAA,qBAAqB,CAAC,CAAA;AAC/I,EAAM,MAAA,mBAAA,GAAsB,QAAQ,MAAM;AACxC,IAAI,IAAA,CAAC,aAAoB,OAAA,IAAA;AACzB,IAAO,OAAA;AAAA,MACL,MAAQ,EAAA,iBAAA;AAAA,MACR,OAAA,EAAS,MAAM,oBAAA,CAAqB,KAAK,CAAA;AAAA,MACzC,SAAW,EAAA,kBAAA;AAAA,MACX,UAAY,EAAA,qBAAA;AAAA,MACZ,QAAU,EAAA,yBAAA;AAAA,MACV,KAAO,EAAA;AAAA,KACT;AAAA,KACC,CAAC,WAAA,EAAa,mBAAmB,kBAAoB,EAAA,qBAAA,EAAuB,yBAAyB,CAAC,CAAA;AACzG,EAAA,MAAM,mBAAsB,GAAA,WAAA,CAAY,CAAC,MAAA,yBAalC,mBAAoB,EAAA,EAAA,MAAA,EAAQ,MAAO,CAAA,MAAA,EAAQ,SAAS,MAAO,CAAA,OAAA,EAAS,SAAW,EAAA,MAAA,CAAO,WAAW,UAAY,EAAA,MAAA,CAAO,UAAY,EAAA,QAAA,EAAU,MAAO,CAAA,QAAA,EAAU,WAAa,EAAA,MAAA,CAAO,aAAa,KAAO,EAAA,MAAA,CAAO,KAAO,EAAA,MAAA,EAAgB,SAAS,qBAAuB,EAAA,CAAA,EAAI,CAAC,MAAA,EAAQ,qBAAqB,CAAC,CAAA;AAI3S,EAAA,SAAA,CAAU,MAAM;AACd,IAAI,IAAA,CAAC,eAAsB,OAAA,MAAA;AAC3B,IAAA,IAAI,CAAC,SAAW,EAAA;AACd,MAAA,gBAAA,CAAiB,KAAK,CAAA;AACtB,MAAO,OAAA,MAAA;AAAA;AAET,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAA,gBAAA,CAAiB,KAAK,CAAA;AACtB,MAAA,KAAK,YAAa,EAAA;AAClB,MAAO,OAAA,MAAA;AAAA;AAET,IAAM,MAAA,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,OAAA,CAAQ,KAAK,mEAAmE,CAAA;AAChF,MAAA,gBAAA,CAAiB,KAAK,CAAA;AAAA,OACrB,YAAY,CAAA;AACf,IAAO,OAAA,MAAM,aAAa,KAAK,CAAA;AAAA,KAC9B,CAAC,aAAA,EAAe,SAAW,EAAA,cAAA,EAAgB,YAAY,CAAC,CAAA;AAC3D,EAAM,MAAA,WAAA,GAAc,QAAQ,OAAO;AAAA,IACjC,KAAA;AAAA,IACA,QAAU,EAAA,iBAAA;AAAA,IACV,WAAa,EAAA,gBAAA;AAAA,IACb,UAAU,SAAa,IAAA,QAAA;AAAA,IACvB,QAAA;AAAA,IACA,aAAe,EAAA,MAAA;AAAA,IACf,YAAc,EAAA,IAAA;AAAA,IACd,iBAAiB,MAAM;AACrB,MAAI,IAAA,SAAA,OAAgB,YAAa,EAAA;AAAA;AACnC,GACF,CAAA,EAAI,CAAC,KAAO,EAAA,iBAAA,EAAmB,kBAAkB,SAAW,EAAA,QAAA,EAAU,SAAW,EAAA,YAAY,CAAC,CAAA;AAC9F,EAAM,MAAA,aAAA,GAAgB,QAAQ,OAAO;AAAA,IACnC,YAAY,QAAY,IAAA,cAAA;AAAA,IACxB,QAAQ,MAAM;AACZ,MAAA,QAAA,CAAS,OAAQ,EAAA;AACjB,MAAA,KAAK,YAAa,EAAA;AAAA,KACpB;AAAA,IACA,KAAO,EAAA,cAAA;AAAA,IACP,UAAU,SAAa,IAAA,QAAA;AAAA,IACvB,WAAW,SAAa,IAAA;AAAA,GAC1B,CAAA,EAAI,CAAC,QAAU,EAAA,cAAA,EAAgB,cAAc,cAAgB,EAAA,SAAA,EAAW,QAAU,EAAA,aAAa,CAAC,CAAA;AAChG,EAAA,4BAAQ,YAAa,EAAA,EAAA,KAAA,EAAO,CAAC,MAAQ,EAAA,OAAO,GAAG,KAAO,EAAA;AAAA,IACpD,IAAM,EAAA,CAAA;AAAA,IACN,eAAiB,EAAA;AAAA,GAGT,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,qBAAkB,OAAS,EAAA,WAAA,EAAa,SAAS,gBAAkB,EAAA,SAAA,EAAW,oBAAoB,KAAc,EAAA,CAAA;AAAA,wBAChH,aAAc,EAAA,EAAA,OAAA,EAAS,gBAAkB,EAAA,SAAA,EAAW,oBAAoB,KAAc,EAAA,CAAA;AAAA,wBACtF,qBAAsB,EAAA,EAAA,CAAA;AAAA,wBACtB,mBACG,EAAA,EAAA,QAAA,kBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,OAAO,IAChB,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,MAAO,CAAA,IAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,UAAA,EAAA,EAAW,GAAK,EAAA,cAAA,EAAgB,KAAO,EAAA,MAAA,CAAO,IAAM,EAAA,qBAAA,EAAuB,CAAC,MAAA,CAAO,WAAa,EAAA,eAAA,GAAkB,MAAO,CAAA,uBAAA,GAA0B,IAAI,CAAA,EAAG,yBAA0B,EAAA,SAAA,EAAU,mBAAqB,EAAA,QAAA,CAAS,EAAO,KAAA,KAAA,GAAQ,aAAgB,GAAA,SAAA,EAAW,mCAAmC,KAAO,EAAA,8BAAA,EAA+B,OAAQ,EAAA,4BAAA,EAA8B,KAClX,EAAA,QAAA,kBAAA,GAAA,CAAC,SAAU,EAAA,EAAA,KAAA,EAAO,MAAO,CAAA,WAAA,EAAa,OAAS,EAAA,eAAA,EAAiB,UAAY,EAAA,KAAA,EACxE,QAAC,kBAAA,GAAA,CAAA,iBAAA,EAAA,EAAkB,QAAgB,kBAAwC,EAAA,gBAAA,EAAoC,UAAwB,EAAA,qBAAA,EAA8C,uBAAyB,EAAA,CAAA,EAAA,GAAA,qBAAA,IAAA,IAAA,GAAA,MAAA,GAAA,qBAAA,CAAuB,EAAvB,KAAA,IAAA,GAAA,EAAA,GAA6B,IAAM,EAAA,OAAA,EAAS,eAAiB,EAAA,cAAA,EAAgB,kBAAoB,EAAA,WAAA,EAAa,eAAiB,EAAA,CAAA,EACjV,GACJ,CACJ,EAAA,CAAA;AAAA,0BACC,oBAAqB,EAAA,EAAA,WAAA,EAAa,MAAO,CAAA,MAAA,EAAQ,WAAW,MAAG;AArtBpF,QAAAD,IAAAA,GAAAA;AAqtBuF,QAAA,OAAA,CAAAA,GAAA,GAAA,QAAA,CAAS,OAAT,KAAA,IAAA,GAAA,MAAA,GAAAA,GAAkB,CAAA,KAAA,EAAA;AAAA,OAAA,EACjF,QAAC,kBAAA,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,aAAe,EAAA;AAAA,QAChD,KAAO,EAAA;AAAA,OACR,CACkB,EAAA,QAAA,EAAA;AAAA,QAAA,UAAA,IAAc,oBAAoB,KAAQ,mBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,gBAAkB,EAAA;AAAA,UAChG,eAAA,EAAiB,SAAS,SAAY,GAAA,SAAA;AAAA,UACtC,WAAA,EAAa,SAAS,SAAY,GAAA;AAAA,SACnC,CACuB,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,cAAgB,EAAA;AAAA,UACzD,KAAA,EAAO,SAAS,SAAY,GAAA;AAAA,SAC7B,CAC0B,EAAA,QAAA,EAAA,UAAA,IAAc,mBAAoB,CAAA,KAAA,EACvC,GACJ,CAAU,GAAA,IAAA;AAAA,QACb,oCAAqB,GAAA,CAAA,gBAAA,EAAA,EAAiB,UAAU,oBAAsB,EAAA,OAAA,EAAS,qBACxE,QAAC,kBAAA,GAAA,CAAA,kBAAA,EAAA,EAAmB,MAAgB,EAAA,uBAAA,EAAyB,6BAA6B,QAAU,EAAA,oBAAA,EAAsB,SAAS,mBAAqB,EAAA,CAAA,EAC5J,oBACI,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,yBAAsB,WAAa,EAAA,mBAAA,CAAoB,SAAS,QAAU,EAAA,mBAAA,CAAoB,QAAQ,MAAgB,EAAA,CAAA;AAAA,0BACvH,GAAA,CAAC,YAAiC,EAAA,EAAA,WAAA,EAA0B,SAAsB,EAAA,UAAA,EAAwB,gBAAgC,mBAA0C,EAAA,mBAAA,EAAqB,mBAAqB,EAAA,aAAA,EAAA,EAA3M,aAAyO;AAAA,SAChQ,EAAA,CAAA;AAAA,QACH,WAAA,uBAAe,qBAAsB,EAAA,EAAA,OAAA,EAAO,MAAC,OAAS,EAAA,eAAA,EAAiB,OAAO,qBAAuB,EAAA,OAAA,EAAS,kBAAkB,MAAgB,EAAA,gBAAA,EAAoC,oBAAwC,kBAAoB,EAAA,CAAA,EAAA,GAAA,qBAAA,IAAA,IAAA,GAAA,MAAA,GAAA,qBAAA,CAAuB,OAAvB,IAA6B,GAAA,EAAA,GAAA,IAAA,EAAM,aAAe,EAAA,sBAAA,EAAwB,CAAK,GAAA;AAAA,OAAA,EACpU,CACJ,EAAA;AAAA,KAAA,EACJ,CACJ,EAAA,CAAA;AAAA,IACC;AAAA,GACL,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,IAAM,EAAA;AAAA,IACJ,IAAM,EAAA;AAAA,GACR;AAAA,EACA,WAAa,EAAA;AAAA,IACX,QAAU,EAAA,CAAA;AAAA,IACV,KAAO,EAAA,MAAA;AAAA,IACP,iBAAmB,EAAA,EAAA;AAAA,IACnB,cAAgB,EAAA,QAAA;AAAA,IAChB,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,uBAAyB,EAAA;AAAA,IACvB,cAAgB,EAAA,YAAA;AAAA,IAChB,UAAY,EAAA,EAAA;AAAA,IACZ,aAAe,EAAA;AAAA,GACjB;AAAA,EACA,UAAY,EAAA;AAAA,IACV,UAAY,EAAA,QAAA;AAAA,IACZ,KAAO,EAAA;AAAA,GACT;AAAA,EACA,WAAa,EAAA;AAAA,IACX,KAAO,EAAA;AAAA,GACT;AAAA,EACA,gBAAkB,EAAA;AAAA,IAChB,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,SAAW,EAAA,QAAA;AAAA,IACX,aAAe,EAAA;AAAA,GACjB;AAAA,EACA,uBAAyB,EAAA;AAAA,IACvB,QAAU,EAAA;AAAA,GACZ;AAAA,EACA,aAAe,EAAA;AAAA,IACb,SAAW,EAAA,CAAA;AAAA,IACX,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,EAAA;AAAA,IACZ,SAAW,EAAA,QAAA;AAAA,IACX,QAAU,EAAA;AAAA,GACZ;AAAA,EACA,oBAAsB,EAAA;AAAA,IACpB,SAAW,EAAA,CAAA;AAAA,IACX,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,aAAe,EAAA;AAAA,IACb,iBAAmB,EAAA,EAAA;AAAA,IACnB,UAAY,EAAA;AAAA,GACd;AAAA,EACA,gBAAkB,EAAA;AAAA,IAChB,YAAc,EAAA,CAAA;AAAA,IACd,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,CAAA;AAAA,IACjB,YAAc,EAAA,EAAA;AAAA,IACd,WAAa,EAAA;AAAA,GACf;AAAA,EACA,cAAgB,EAAA;AAAA,IACd,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA;AAEhB,CAAC,CAAA;AACD,MAAM,UAAkC,GAAA,CAAA,KAAA,qBAAU,GAAA,CAAA,iBAAA,EAAA,cAAA,CAAA,EAAA,EAAsB,KAAO,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React__default,{useEffect}from'react';import {InteractionManager}from'react-native';import AsyncStorage from'@react-native-async-storage/async-storage';import {preloadNativeWebBuilderExperience}from'../../../features/webbuilder/nativeWebBuilderRegistry.js';import {WEBBUILDER_PROJECTS_SNAPSHOT_KEY}from'../../WebBuilderNative/webbuilderSnapshotKey.js';function WebBuilderCodePrewarmImpl() {
|
|
2
|
+
useEffect(() => {
|
|
3
|
+
let cancelled = false;
|
|
4
|
+
const task = InteractionManager.runAfterInteractions(() => {
|
|
5
|
+
AsyncStorage.getAllKeys().then((keys) => {
|
|
6
|
+
if (cancelled) return;
|
|
7
|
+
if (!keys.some((k) => k.startsWith(`${WEBBUILDER_PROJECTS_SNAPSHOT_KEY}:`))) return;
|
|
8
|
+
preloadNativeWebBuilderExperience().catch(() => void 0);
|
|
9
|
+
}).catch(() => void 0);
|
|
10
|
+
});
|
|
11
|
+
return () => {
|
|
12
|
+
cancelled = true;
|
|
13
|
+
task.cancel();
|
|
14
|
+
};
|
|
15
|
+
}, []);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const WebBuilderCodePrewarm = React__default.memo(WebBuilderCodePrewarmImpl);export{WebBuilderCodePrewarm};//# sourceMappingURL=WebBuilderCodePrewarm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebBuilderCodePrewarm.js","sources":["../../../../src/screens/Home/components/WebBuilderCodePrewarm.tsx"],"sourcesContent":["/**\n * Load the native Web Builder's code while the person is on Home, so opening it\n * shows the app at once instead of a spinner while the module loads (in a Metro\n * dev session that is a network fetch of its whole module graph). The session\n * token is WebBuilderPrewarm's job; this is only the code.\n *\n * Same rule as CanvasPrewarm: only for people who use it. A saved Web Builder\n * projects list on this device (`useWebBuilderGallery`'s snapshot, any org) is\n * the evidence; everyone else pays one AsyncStorage key listing.\n */\nimport React, { useEffect } from 'react';\nimport { InteractionManager } from 'react-native';\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { preloadNativeWebBuilderExperience } from '../../../features/webbuilder/nativeWebBuilderRegistry';\nimport { WEBBUILDER_PROJECTS_SNAPSHOT_KEY } from '../../WebBuilderNative/webbuilderSnapshotKey';\n\nfunction WebBuilderCodePrewarmImpl(): null {\n useEffect(() => {\n let cancelled = false;\n // After Home has drawn and settled: the load must not compete with the first paint.\n const task = InteractionManager.runAfterInteractions(() => {\n AsyncStorage.getAllKeys()\n .then((keys) => {\n if (cancelled) return;\n if (!keys.some((k) => k.startsWith(`${WEBBUILDER_PROJECTS_SNAPSHOT_KEY}:`))) return;\n preloadNativeWebBuilderExperience().catch(() => undefined);\n })\n .catch(() => undefined);\n });\n return () => {\n cancelled = true;\n task.cancel();\n };\n }, []);\n return null;\n}\n\nexport const WebBuilderCodePrewarm = React.memo(WebBuilderCodePrewarmImpl);\n"],"names":["React"],"mappings":"uWAeA,SAAS,yBAAkC,GAAA;AACzC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAY,GAAA,KAAA;AAEhB,IAAM,MAAA,IAAA,GAAO,kBAAmB,CAAA,oBAAA,CAAqB,MAAM;AACzD,MAAa,YAAA,CAAA,UAAA,EAAa,CAAA,IAAA,CAAK,CAAQ,IAAA,KAAA;AACrC,QAAA,IAAI,SAAW,EAAA;AACf,QAAI,IAAA,CAAC,IAAK,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA,CAAA,CAAE,WAAW,CAAG,EAAA,gCAAgC,CAAG,CAAA,CAAA,CAAC,CAAG,EAAA;AAC3E,QAAkC,iCAAA,EAAA,CAAE,KAAM,CAAA,MAAM,MAAS,CAAA;AAAA,OAC1D,CAAA,CAAE,KAAM,CAAA,MAAM,MAAS,CAAA;AAAA,KACzB,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAY,SAAA,GAAA,IAAA;AACZ,MAAA,IAAA,CAAK,MAAO,EAAA;AAAA,KACd;AAAA,GACF,EAAG,EAAE,CAAA;AACL,EAAO,OAAA,IAAA;AACT;AACa,MAAA,qBAAA,GAAwBA,cAAM,CAAA,IAAA,CAAK,yBAAyB"}
|
|
@@ -73,7 +73,7 @@ function WebBuilderNativeScreen() {
|
|
|
73
73
|
/* @__PURE__ */ jsx(Text, { style: [styles.detail, isDark && styles.textMuted], children: "This build does not carry the federation host runtime." })
|
|
74
74
|
] }) });
|
|
75
75
|
}
|
|
76
|
-
return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], edges: ["left", "right"], children: /* @__PURE__ */ jsx(Experience, { isDark, onExit, projects: host.projects, projectsLoading: host.projectsLoading, projectsError: host.projectsError, onRefreshProjects: host.refreshProjects, projectsHasMore: host.projectsHasMore, onLoadMoreProjects: host.loadMoreProjects, templates: host.templates, templatesLoading: host.templatesLoading, templatesError: host.templatesError, onReloadTemplates: host.reloadTemplates, startBlocked: host.startBlocked, startNotice: host.startNotice, activeChannelId: host.activeChannelId, onOpenProject: host.openProject, onCloseProject: host.closeProject, onStartProject: host.startProject, builds: host.builds, buildsLoading: host.buildsLoading, building: host.building, publishing: host.publishing, hostChat: host.hostChat, onPublish: host.publish, onResumePreview: host.resumePreview, onOpenCodezen, initialAgentSeed: seed }) });
|
|
76
|
+
return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], edges: ["left", "right"], children: /* @__PURE__ */ jsx(Experience, { isDark, onExit, projects: host.projects, projectsLoading: host.projectsLoading, projectsError: host.projectsError, onRefreshProjects: host.refreshProjects, projectsHasMore: host.projectsHasMore, onLoadMoreProjects: host.loadMoreProjects, templates: host.templates, templatesLoading: host.templatesLoading, templatesError: host.templatesError, onReloadTemplates: host.reloadTemplates, startBlocked: host.startBlocked, startNotice: host.startNotice, activeChannelId: host.activeChannelId, onOpenProject: host.openProject, onCloseProject: host.closeProject, onStartProject: host.startProject, builds: host.builds, buildsLoading: host.buildsLoading, building: host.building, publishing: host.publishing, hostChat: host.hostChat, onPublish: host.publish, onResumePreview: host.resumePreview, onUndo: host.undo, onRedo: host.redo, onDownloadCode: host.downloadCode, onOpenCodezen, initialAgentSeed: seed }) });
|
|
77
77
|
}
|
|
78
78
|
const styles = StyleSheet.create({
|
|
79
79
|
fill: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/screens/WebBuilderNative/index.tsx"],"sourcesContent":["/**\n * Native Web Builder screen - host route for the federated web builder experience.\n *\n * Same delivery contract as Expenses / Movies / Study: the App registers the\n * federated component; this screen reads the registry and hands over what\n * needs the app's data stack - the builds, the templates, the build workflow\n * (the web surface's connector lane), the publish mutation - plus\n * navigation for leaving. A brain-routed hand-off arrives as\n * `initialAgentQuery` and starts a new site with it; a task in the Tasks sheet\n * arrives as `openChannelId` and opens that site. Web Builder draws its own\n * header, so the stack header stays hidden.\n *\n * Not to be confused with `screens/WebBuilder`: that is the shared WebView\n * surface shell (historical name), which still opens the web Web Builder.\n */\nimport React, { useCallback, useEffect, useLayoutEffect, useMemo } from 'react';\nimport { StyleSheet, Text, View } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport {\n useNavigation,\n useRoute,\n type NavigationProp,\n type ParamListBase,\n type RouteProp,\n} from '@react-navigation/native';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { getNativeWebBuilderExperience } from '../../features/webbuilder/nativeWebBuilderRegistry';\nimport { useAppTheme } from '../../theme/AppThemeProvider';\nimport { useWebBuilderHost } from './useWebBuilderHost';\nimport { config } from '../../config/env-config';\nimport { MOBILE_APP_CATALOG } from '../../features/apps/mobileAppCatalog';\nimport { resolveSurfaceUrl } from '../../features/apps/resolveSurfaceUrl';\nimport { CODEZEN_DEV_URL } from '../../features/webbuilder/codezenHandoff';\n\n/** What the launcher and the chat hand-offs may pass. */\ntype WebBuilderRouteParams = {\n orgName?: string | null;\n initialAgentQuery?: string;\n /** Photos or files the ask was typed with; they go to the agent with it. */\n initialAgentAttachments?: MessageAttachment[];\n /** A site to open (its chat), e.g. from its build's task in the Tasks sheet. */\n openChannelId?: string;\n hideNavigationHeader?: boolean;\n};\n\nexport default function WebBuilderNativeScreen() {\n // The in-app light/dark choice (the drawer's Appearance), not only the device setting.\n const { isDark } = useAppTheme();\n const navigation = useNavigation<NavigationProp<ParamListBase>>();\n const route = useRoute<RouteProp<Record<string, WebBuilderRouteParams | undefined>, string>>();\n const routeOrg = typeof route.params?.orgName === 'string' ? route.params.orgName.trim() : '';\n const Experience = getNativeWebBuilderExperience();\n const host = useWebBuilderHost(routeOrg || undefined);\n\n useLayoutEffect(() => {\n if (!route.params?.hideNavigationHeader) navigation.setParams({ hideNavigationHeader: true });\n }, [navigation, route.params?.hideNavigationHeader]);\n\n const seed = useMemo(() => {\n const query = typeof route.params?.initialAgentQuery === 'string' ? route.params.initialAgentQuery.trim() : '';\n const files = Array.isArray(route.params?.initialAgentAttachments)\n ? route.params.initialAgentAttachments\n : undefined;\n if (!query && !files?.length) return null;\n return { text: query, files };\n }, [route.params?.initialAgentQuery, route.params?.initialAgentAttachments]);\n\n // Opened once per hand-off: the param is cleared, so the same task can open it again later.\n const openChannelId = typeof route.params?.openChannelId === 'string' ? route.params.openChannelId.trim() : '';\n const { openProject } = host;\n useEffect(() => {\n if (!openChannelId) return;\n openProject(openChannelId);\n navigation.setParams({ openChannelId: undefined });\n }, [openChannelId, openProject, navigation]);\n\n const onExit = useCallback(() => {\n if (navigation.canGoBack?.()) navigation.goBack();\n else navigation.navigate('MainStack.Layout.Home');\n }, [navigation]);\n\n // \"Demo video\" (web 0.5.0): the Codezen surface, in the app's surface shell, with the handoff fragment.\n const onOpenCodezen = useCallback(\n (fragment: string) => {\n const tile = MOBILE_APP_CATALOG.find((app) => app.key === 'codezen');\n const base = (tile && resolveSurfaceUrl(tile, config)) || CODEZEN_DEV_URL;\n navigation.navigate('MainStack.WebBuilder', {\n url: `${base.split('#')[0]}#${fragment}`,\n appTitle: tile?.label ?? 'Codezen',\n ...(routeOrg ? { orgName: routeOrg } : {}),\n });\n },\n [navigation, routeOrg],\n );\n\n if (!Experience) {\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]}>\n <View style={styles.center}>\n <Text style={[styles.title, isDark && styles.textLight]}>Native web builder unavailable</Text>\n <Text style={[styles.detail, isDark && styles.textMuted]}>\n This build does not carry the federation host runtime.\n </Text>\n </View>\n </SafeAreaView>\n );\n }\n\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]} edges={['left', 'right']}>\n <Experience\n isDark={isDark}\n onExit={onExit}\n projects={host.projects}\n projectsLoading={host.projectsLoading}\n projectsError={host.projectsError}\n onRefreshProjects={host.refreshProjects}\n projectsHasMore={host.projectsHasMore}\n onLoadMoreProjects={host.loadMoreProjects}\n templates={host.templates}\n templatesLoading={host.templatesLoading}\n templatesError={host.templatesError}\n onReloadTemplates={host.reloadTemplates}\n startBlocked={host.startBlocked}\n startNotice={host.startNotice}\n activeChannelId={host.activeChannelId}\n onOpenProject={host.openProject}\n onCloseProject={host.closeProject}\n onStartProject={host.startProject}\n builds={host.builds}\n buildsLoading={host.buildsLoading}\n building={host.building}\n publishing={host.publishing}\n hostChat={host.hostChat}\n onPublish={host.publish}\n onResumePreview={host.resumePreview}\n onOpenCodezen={onOpenCodezen}\n initialAgentSeed={seed}\n />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1, backgroundColor: '#f5f6f8' },\n fillDark: { backgroundColor: '#0c0e14' },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 },\n title: { fontSize: 15, fontWeight: '600', color: '#111827', marginBottom: 6 },\n detail: { fontSize: 13, color: '#5d6575', textAlign: 'center' },\n textLight: { color: '#eceff6' },\n textMuted: { color: '#9ca4b6' },\n});\n"],"names":["_a","_b"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/screens/WebBuilderNative/index.tsx"],"sourcesContent":["/**\n * Native Web Builder screen - host route for the federated web builder experience.\n *\n * Same delivery contract as Expenses / Movies / Study: the App registers the\n * federated component; this screen reads the registry and hands over what\n * needs the app's data stack - the builds, the templates, the build workflow\n * (the web surface's connector lane), the publish mutation - plus\n * navigation for leaving. A brain-routed hand-off arrives as\n * `initialAgentQuery` and starts a new site with it; a task in the Tasks sheet\n * arrives as `openChannelId` and opens that site. Web Builder draws its own\n * header, so the stack header stays hidden.\n *\n * Not to be confused with `screens/WebBuilder`: that is the shared WebView\n * surface shell (historical name), which still opens the web Web Builder.\n */\nimport React, { useCallback, useEffect, useLayoutEffect, useMemo } from 'react';\nimport { StyleSheet, Text, View } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport {\n useNavigation,\n useRoute,\n type NavigationProp,\n type ParamListBase,\n type RouteProp,\n} from '@react-navigation/native';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { getNativeWebBuilderExperience } from '../../features/webbuilder/nativeWebBuilderRegistry';\nimport { useAppTheme } from '../../theme/AppThemeProvider';\nimport { useWebBuilderHost } from './useWebBuilderHost';\nimport { config } from '../../config/env-config';\nimport { MOBILE_APP_CATALOG } from '../../features/apps/mobileAppCatalog';\nimport { resolveSurfaceUrl } from '../../features/apps/resolveSurfaceUrl';\nimport { CODEZEN_DEV_URL } from '../../features/webbuilder/codezenHandoff';\n\n/** What the launcher and the chat hand-offs may pass. */\ntype WebBuilderRouteParams = {\n orgName?: string | null;\n initialAgentQuery?: string;\n /** Photos or files the ask was typed with; they go to the agent with it. */\n initialAgentAttachments?: MessageAttachment[];\n /** A site to open (its chat), e.g. from its build's task in the Tasks sheet. */\n openChannelId?: string;\n hideNavigationHeader?: boolean;\n};\n\nexport default function WebBuilderNativeScreen() {\n // The in-app light/dark choice (the drawer's Appearance), not only the device setting.\n const { isDark } = useAppTheme();\n const navigation = useNavigation<NavigationProp<ParamListBase>>();\n const route = useRoute<RouteProp<Record<string, WebBuilderRouteParams | undefined>, string>>();\n const routeOrg = typeof route.params?.orgName === 'string' ? route.params.orgName.trim() : '';\n const Experience = getNativeWebBuilderExperience();\n const host = useWebBuilderHost(routeOrg || undefined);\n\n useLayoutEffect(() => {\n if (!route.params?.hideNavigationHeader) navigation.setParams({ hideNavigationHeader: true });\n }, [navigation, route.params?.hideNavigationHeader]);\n\n const seed = useMemo(() => {\n const query = typeof route.params?.initialAgentQuery === 'string' ? route.params.initialAgentQuery.trim() : '';\n const files = Array.isArray(route.params?.initialAgentAttachments)\n ? route.params.initialAgentAttachments\n : undefined;\n if (!query && !files?.length) return null;\n return { text: query, files };\n }, [route.params?.initialAgentQuery, route.params?.initialAgentAttachments]);\n\n // Opened once per hand-off: the param is cleared, so the same task can open it again later.\n const openChannelId = typeof route.params?.openChannelId === 'string' ? route.params.openChannelId.trim() : '';\n const { openProject } = host;\n useEffect(() => {\n if (!openChannelId) return;\n openProject(openChannelId);\n navigation.setParams({ openChannelId: undefined });\n }, [openChannelId, openProject, navigation]);\n\n const onExit = useCallback(() => {\n if (navigation.canGoBack?.()) navigation.goBack();\n else navigation.navigate('MainStack.Layout.Home');\n }, [navigation]);\n\n // \"Demo video\" (web 0.5.0): the Codezen surface, in the app's surface shell, with the handoff fragment.\n const onOpenCodezen = useCallback(\n (fragment: string) => {\n const tile = MOBILE_APP_CATALOG.find((app) => app.key === 'codezen');\n const base = (tile && resolveSurfaceUrl(tile, config)) || CODEZEN_DEV_URL;\n navigation.navigate('MainStack.WebBuilder', {\n url: `${base.split('#')[0]}#${fragment}`,\n appTitle: tile?.label ?? 'Codezen',\n ...(routeOrg ? { orgName: routeOrg } : {}),\n });\n },\n [navigation, routeOrg],\n );\n\n if (!Experience) {\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]}>\n <View style={styles.center}>\n <Text style={[styles.title, isDark && styles.textLight]}>Native web builder unavailable</Text>\n <Text style={[styles.detail, isDark && styles.textMuted]}>\n This build does not carry the federation host runtime.\n </Text>\n </View>\n </SafeAreaView>\n );\n }\n\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]} edges={['left', 'right']}>\n <Experience\n isDark={isDark}\n onExit={onExit}\n projects={host.projects}\n projectsLoading={host.projectsLoading}\n projectsError={host.projectsError}\n onRefreshProjects={host.refreshProjects}\n projectsHasMore={host.projectsHasMore}\n onLoadMoreProjects={host.loadMoreProjects}\n templates={host.templates}\n templatesLoading={host.templatesLoading}\n templatesError={host.templatesError}\n onReloadTemplates={host.reloadTemplates}\n startBlocked={host.startBlocked}\n startNotice={host.startNotice}\n activeChannelId={host.activeChannelId}\n onOpenProject={host.openProject}\n onCloseProject={host.closeProject}\n onStartProject={host.startProject}\n builds={host.builds}\n buildsLoading={host.buildsLoading}\n building={host.building}\n publishing={host.publishing}\n hostChat={host.hostChat}\n onPublish={host.publish}\n onResumePreview={host.resumePreview}\n onUndo={host.undo}\n onRedo={host.redo}\n onDownloadCode={host.downloadCode}\n onOpenCodezen={onOpenCodezen}\n initialAgentSeed={seed}\n />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1, backgroundColor: '#f5f6f8' },\n fillDark: { backgroundColor: '#0c0e14' },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 },\n title: { fontSize: 15, fontWeight: '600', color: '#111827', marginBottom: 6 },\n detail: { fontSize: 13, color: '#5d6575', textAlign: 'center' },\n textLight: { color: '#eceff6' },\n textMuted: { color: '#9ca4b6' },\n});\n"],"names":["_a","_b"],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
const KEEPALIVE_INTERVAL_MS = 10 * 6e4;
|
|
5
|
+
const KEEPALIVE_IDLE_MS = 15 * 6e4;
|
|
6
|
+
const KEEPALIVE_EXTEND_MS = 18e5;
|
|
7
|
+
const KEEPALIVE_TICK_MS = 6e4;
|
|
8
|
+
const KEEPALIVE_MAX_FAILURES = 2;
|
|
9
|
+
const WEBBUILDER_EXTEND_ACTION = "WEBBUILDER_EXTEND";
|
|
10
|
+
function keepAliveDecision(i) {
|
|
11
|
+
if (!i.visible || !i.sandboxId || !i.live) return "idle";
|
|
12
|
+
if (i.now - i.lastActivityAt > KEEPALIVE_IDLE_MS) return "idle";
|
|
13
|
+
if (i.lastPingAt !== null && i.now - i.lastPingAt < KEEPALIVE_INTERVAL_MS) return "wait";
|
|
14
|
+
return "ping";
|
|
15
|
+
}
|
|
16
|
+
function isUnsupportedActionError(message) {
|
|
17
|
+
return /unknown (webbuilder |sandbox )?action|unsupported action|not (a )?(known|supported) action|no such action|not mocked|action .*not allowed|invalid action/i.test(String(message || ""));
|
|
18
|
+
}
|
|
19
|
+
const GONE_RE = /sandbox not found|not found \(404\)|no sandbox found|does not exist|sandbox.*expired|sandbox.*killed|not running anymore|cannot be resumed|was (?:killed|deleted|destroyed)/i;
|
|
20
|
+
function extendOutcome(r) {
|
|
21
|
+
if (r.successful) {
|
|
22
|
+
const d = r.data && typeof r.data === "object" ? r.data : {};
|
|
23
|
+
return d.resumed === true ? "resumed" : "alive";
|
|
24
|
+
}
|
|
25
|
+
if (isUnsupportedActionError(r.error)) return "unsupported";
|
|
26
|
+
if (GONE_RE.test(r.error || "")) return "gone";
|
|
27
|
+
return "failed";
|
|
28
|
+
}
|
|
29
|
+
class KeepAliveScheduler {
|
|
30
|
+
constructor(deps) {
|
|
31
|
+
__publicField(this, "visible", true);
|
|
32
|
+
__publicField(this, "sandboxId", "");
|
|
33
|
+
__publicField(this, "live", false);
|
|
34
|
+
__publicField(this, "lastActivityAt");
|
|
35
|
+
__publicField(this, "lastPingAt", /* @__PURE__ */ new Map());
|
|
36
|
+
__publicField(this, "failures", /* @__PURE__ */ new Map());
|
|
37
|
+
__publicField(this, "off", /* @__PURE__ */ new Set());
|
|
38
|
+
__publicField(this, "inflight", false);
|
|
39
|
+
__publicField(this, "deps");
|
|
40
|
+
this.deps = deps;
|
|
41
|
+
this.lastActivityAt = deps.now();
|
|
42
|
+
}
|
|
43
|
+
noteActivity() {
|
|
44
|
+
this.lastActivityAt = this.deps.now();
|
|
45
|
+
}
|
|
46
|
+
setVisible(visible) {
|
|
47
|
+
this.visible = visible;
|
|
48
|
+
}
|
|
49
|
+
setTarget(sandboxId, live) {
|
|
50
|
+
this.sandboxId = String(sandboxId || "").trim();
|
|
51
|
+
this.live = live;
|
|
52
|
+
}
|
|
53
|
+
/** Pinging is off for this sandbox (no EXTEND on this connector, or it kept failing). */
|
|
54
|
+
isOff(sandboxId = this.sandboxId) {
|
|
55
|
+
return this.off.has(sandboxId);
|
|
56
|
+
}
|
|
57
|
+
decision() {
|
|
58
|
+
var _a;
|
|
59
|
+
if (!this.sandboxId || this.off.has(this.sandboxId) || this.inflight) return "idle";
|
|
60
|
+
return keepAliveDecision({
|
|
61
|
+
visible: this.visible,
|
|
62
|
+
sandboxId: this.sandboxId,
|
|
63
|
+
live: this.live,
|
|
64
|
+
now: this.deps.now(),
|
|
65
|
+
lastActivityAt: this.lastActivityAt,
|
|
66
|
+
lastPingAt: (_a = this.lastPingAt.get(this.sandboxId)) != null ? _a : null
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
async tick() {
|
|
70
|
+
var _a, _b, _c, _d, _e;
|
|
71
|
+
const d = this.decision();
|
|
72
|
+
if (d !== "ping") return d;
|
|
73
|
+
const id = this.sandboxId;
|
|
74
|
+
this.inflight = true;
|
|
75
|
+
this.lastPingAt.set(id, this.deps.now());
|
|
76
|
+
let outcome;
|
|
77
|
+
try {
|
|
78
|
+
outcome = extendOutcome(await this.deps.extend(id));
|
|
79
|
+
} catch (e) {
|
|
80
|
+
outcome = extendOutcome({
|
|
81
|
+
successful: false,
|
|
82
|
+
error: e instanceof Error ? e.message : String(e)
|
|
83
|
+
});
|
|
84
|
+
} finally {
|
|
85
|
+
this.inflight = false;
|
|
86
|
+
}
|
|
87
|
+
if (outcome === "resumed" || outcome === "alive") {
|
|
88
|
+
this.failures.delete(id);
|
|
89
|
+
if (outcome === "resumed") (_b = (_a = this.deps).onResumed) == null ? void 0 : _b.call(_a, id);
|
|
90
|
+
return outcome;
|
|
91
|
+
}
|
|
92
|
+
if (outcome === "unsupported") {
|
|
93
|
+
this.off.add(id);
|
|
94
|
+
return outcome;
|
|
95
|
+
}
|
|
96
|
+
const n = ((_c = this.failures.get(id)) != null ? _c : 0) + 1;
|
|
97
|
+
this.failures.set(id, n);
|
|
98
|
+
if (outcome === "gone") {
|
|
99
|
+
this.off.add(id);
|
|
100
|
+
(_e = (_d = this.deps).onGone) == null ? void 0 : _e.call(_d, id);
|
|
101
|
+
} else if (n >= KEEPALIVE_MAX_FAILURES) {
|
|
102
|
+
this.off.add(id);
|
|
103
|
+
}
|
|
104
|
+
return outcome;
|
|
105
|
+
}
|
|
106
|
+
/** A new sandbox came up for this build (wake, restore): try again from scratch. */
|
|
107
|
+
reset(sandboxId) {
|
|
108
|
+
this.off.delete(sandboxId);
|
|
109
|
+
this.failures.delete(sandboxId);
|
|
110
|
+
this.lastPingAt.delete(sandboxId);
|
|
111
|
+
}
|
|
112
|
+
}export{KEEPALIVE_EXTEND_MS,KEEPALIVE_IDLE_MS,KEEPALIVE_INTERVAL_MS,KEEPALIVE_MAX_FAILURES,KEEPALIVE_TICK_MS,KeepAliveScheduler,WEBBUILDER_EXTEND_ACTION,extendOutcome,isUnsupportedActionError,keepAliveDecision};//# sourceMappingURL=keepAlive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keepAlive.js","sources":["../../../src/screens/WebBuilderNative/keepAlive.ts"],"sourcesContent":["/**\n * Keeps an open build's sandbox awake while the app is in front and in use; an idle\n * app lets it pause (web `sandbox/keepAlive.ts`, #438 C1 - ported as is). Pure.\n */\n\nexport const KEEPALIVE_INTERVAL_MS = 10 * 60_000;\nexport const KEEPALIVE_IDLE_MS = 15 * 60_000;\nexport const KEEPALIVE_EXTEND_MS = 1_800_000;\n/** How often the hook asks the scheduler (cheap; the scheduler decides). */\nexport const KEEPALIVE_TICK_MS = 60_000;\n/** Consecutive failures (sandbox gone, network) before pinging stops for that sandbox. */\nexport const KEEPALIVE_MAX_FAILURES = 2;\n\nexport const WEBBUILDER_EXTEND_ACTION = 'WEBBUILDER_EXTEND' as const;\n\nexport type KeepAliveDecision = 'ping' | 'wait' | 'idle';\n\nexport interface KeepAliveInput {\n visible: boolean;\n sandboxId: string;\n /** The build's preview is live (not asleep, not restoring). */\n live: boolean;\n now: number;\n lastActivityAt: number;\n /** When EXTEND last went out for this sandbox; null = never. */\n lastPingAt: number | null;\n}\n\n/** `idle`: nothing should run now (hidden, idle, no live sandbox); `wait`: not due yet. */\nexport function keepAliveDecision(i: KeepAliveInput): KeepAliveDecision {\n if (!i.visible || !i.sandboxId || !i.live) return 'idle';\n if (i.now - i.lastActivityAt > KEEPALIVE_IDLE_MS) return 'idle';\n if (i.lastPingAt !== null && i.now - i.lastPingAt < KEEPALIVE_INTERVAL_MS) return 'wait';\n return 'ping';\n}\n\n/** The connector (or the proxy) does not know the action: an older version, stop asking. */\nexport function isUnsupportedActionError(message: string | null | undefined): boolean {\n return /unknown (webbuilder |sandbox )?action|unsupported action|not (a )?(known|supported) action|no such action|not mocked|action .*not allowed|invalid action/i.test(\n String(message || ''),\n );\n}\n\nexport interface ExtendResult {\n successful: boolean;\n data?: unknown;\n error?: string;\n}\n\nexport type ExtendOutcome = 'resumed' | 'alive' | 'unsupported' | 'gone' | 'failed';\n\nconst GONE_RE =\n /sandbox not found|not found \\(404\\)|no sandbox found|does not exist|sandbox.*expired|sandbox.*killed|not running anymore|cannot be resumed|was (?:killed|deleted|destroyed)/i;\n\n/** What an EXTEND answer means (`{resumed, timeoutMs}` on success). */\nexport function extendOutcome(r: ExtendResult): ExtendOutcome {\n if (r.successful) {\n const d = r.data && typeof r.data === 'object' ? (r.data as Record<string, unknown>) : {};\n return d.resumed === true ? 'resumed' : 'alive';\n }\n if (isUnsupportedActionError(r.error)) return 'unsupported';\n if (GONE_RE.test(r.error || '')) return 'gone';\n return 'failed';\n}\n\nexport interface KeepAliveDeps {\n now: () => number;\n extend: (sandboxId: string) => Promise<ExtendResult>;\n /** EXTEND says the sandbox is gone: the host runs its wake flow. */\n onGone?: (sandboxId: string) => void;\n /** EXTEND woke a paused sandbox: the host reloads the preview. */\n onResumed?: (sandboxId: string) => void;\n}\n\n/** One scheduler per open build; `tick()` runs EXTEND when due, one at a time. */\nexport class KeepAliveScheduler {\n private visible = true;\n\n private sandboxId = '';\n\n private live = false;\n\n private lastActivityAt: number;\n\n private lastPingAt = new Map<string, number>();\n\n private failures = new Map<string, number>();\n\n private off = new Set<string>();\n\n private inflight = false;\n\n private deps: KeepAliveDeps;\n\n constructor(deps: KeepAliveDeps) {\n this.deps = deps;\n this.lastActivityAt = deps.now();\n }\n\n noteActivity(): void {\n this.lastActivityAt = this.deps.now();\n }\n\n setVisible(visible: boolean): void {\n this.visible = visible;\n }\n\n setTarget(sandboxId: string | null | undefined, live: boolean): void {\n this.sandboxId = String(sandboxId || '').trim();\n this.live = live;\n }\n\n /** Pinging is off for this sandbox (no EXTEND on this connector, or it kept failing). */\n isOff(sandboxId = this.sandboxId): boolean {\n return this.off.has(sandboxId);\n }\n\n decision(): KeepAliveDecision {\n if (!this.sandboxId || this.off.has(this.sandboxId) || this.inflight) return 'idle';\n return keepAliveDecision({\n visible: this.visible,\n sandboxId: this.sandboxId,\n live: this.live,\n now: this.deps.now(),\n lastActivityAt: this.lastActivityAt,\n lastPingAt: this.lastPingAt.get(this.sandboxId) ?? null,\n });\n }\n\n async tick(): Promise<KeepAliveDecision | ExtendOutcome> {\n const d = this.decision();\n if (d !== 'ping') return d;\n const id = this.sandboxId;\n this.inflight = true;\n this.lastPingAt.set(id, this.deps.now());\n let outcome: ExtendOutcome;\n try {\n outcome = extendOutcome(await this.deps.extend(id));\n } catch (e) {\n outcome = extendOutcome({ successful: false, error: e instanceof Error ? e.message : String(e) });\n } finally {\n this.inflight = false;\n }\n if (outcome === 'resumed' || outcome === 'alive') {\n this.failures.delete(id);\n if (outcome === 'resumed') this.deps.onResumed?.(id);\n return outcome;\n }\n if (outcome === 'unsupported') {\n this.off.add(id);\n return outcome;\n }\n const n = (this.failures.get(id) ?? 0) + 1;\n this.failures.set(id, n);\n if (outcome === 'gone') {\n this.off.add(id);\n this.deps.onGone?.(id);\n } else if (n >= KEEPALIVE_MAX_FAILURES) {\n this.off.add(id);\n }\n return outcome;\n }\n\n /** A new sandbox came up for this build (wake, restore): try again from scratch. */\n reset(sandboxId: string): void {\n this.off.delete(sandboxId);\n this.failures.delete(sandboxId);\n this.lastPingAt.delete(sandboxId);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {useSyncExternalStore}from'react';import {WEBBUILDER_JOB_BUDGET_MS,WEBBUILDER_JOB_GRACE_MS}from'../../features/webbuilder/buildJob.js';const LIFETIME_MS = WEBBUILDER_JOB_BUDGET_MS + WEBBUILDER_JOB_GRACE_MS;
|
|
2
|
+
let running = /* @__PURE__ */ new Map();
|
|
3
|
+
let snapshot = [];
|
|
4
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
5
|
+
function publish(next) {
|
|
6
|
+
running = next;
|
|
7
|
+
snapshot = [...next.values()].sort((a, b) => b.startedAt - a.startedAt);
|
|
8
|
+
listeners.forEach((listener) => listener());
|
|
9
|
+
}
|
|
10
|
+
function pruned(now = Date.now()) {
|
|
11
|
+
const next = new Map([...running].filter(([, run]) => now - run.startedAt < LIFETIME_MS));
|
|
12
|
+
return next.size === running.size ? running : next;
|
|
13
|
+
}
|
|
14
|
+
function markBuildRunning(run) {
|
|
15
|
+
if (!run.channelId) return;
|
|
16
|
+
const next = new Map(pruned());
|
|
17
|
+
next.set(run.channelId, run);
|
|
18
|
+
publish(next);
|
|
19
|
+
}
|
|
20
|
+
function markBuildDone(channelId, startedBefore = Infinity) {
|
|
21
|
+
const run = channelId ? running.get(channelId) : void 0;
|
|
22
|
+
if (!run || run.startedAt > startedBefore) return;
|
|
23
|
+
const next = new Map(running);
|
|
24
|
+
next.delete(run.channelId);
|
|
25
|
+
publish(next);
|
|
26
|
+
}
|
|
27
|
+
function subscribe(listener) {
|
|
28
|
+
listeners.add(listener);
|
|
29
|
+
const timer = setInterval(() => {
|
|
30
|
+
const next = pruned();
|
|
31
|
+
if (next !== running) publish(next);
|
|
32
|
+
}, 6e4);
|
|
33
|
+
return () => {
|
|
34
|
+
listeners.delete(listener);
|
|
35
|
+
clearInterval(timer);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function useRunningBuilds() {
|
|
39
|
+
return useSyncExternalStore(subscribe, () => snapshot, () => snapshot);
|
|
40
|
+
}export{markBuildDone,markBuildRunning,useRunningBuilds};//# sourceMappingURL=runningBuilds.js.map
|