@adminide-stack/yantra-mobile 12.0.108-alpha.0 → 12.0.109-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/compute.js +57 -1
- package/lib/compute.js.map +1 -1
- package/lib/config/env-config.js +8 -0
- package/lib/config/env-config.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +10 -0
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/apps/appArt.js +2 -1
- package/lib/features/apps/appArt.js.map +1 -1
- package/lib/features/apps/mobileAppCatalog.js +11 -0
- package/lib/features/apps/mobileAppCatalog.js.map +1 -1
- package/lib/features/apps/nativeAppHandoff.js +2 -1
- package/lib/features/apps/nativeAppHandoff.js.map +1 -1
- package/lib/features/health/healthSyncStore.js +7 -1
- package/lib/features/health/healthSyncStore.js.map +1 -1
- package/lib/features/messaging/NewGroupScreen.js.map +1 -1
- package/lib/features/messaging/useChatViewer.js +3 -2
- package/lib/features/messaging/useChatViewer.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +474 -0
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -0
- package/lib/features/webbuilder/brandKitStorage.js +69 -0
- package/lib/features/webbuilder/brandKitStorage.js.map +1 -0
- package/lib/features/webbuilder/buildFragments.js +360 -0
- package/lib/features/webbuilder/buildFragments.js.map +1 -0
- package/lib/features/webbuilder/components/BottomTabs.js +65 -0
- package/lib/features/webbuilder/components/BottomTabs.js.map +1 -0
- package/lib/features/webbuilder/components/BrandKitSheet.js +197 -0
- package/lib/features/webbuilder/components/BrandKitSheet.js.map +1 -0
- package/lib/features/webbuilder/components/CodeView.js +99 -0
- package/lib/features/webbuilder/components/CodeView.js.map +1 -0
- package/lib/features/webbuilder/components/Composer.js +217 -0
- package/lib/features/webbuilder/components/Composer.js.map +1 -0
- package/lib/features/webbuilder/components/PreviewFrame.js +72 -0
- package/lib/features/webbuilder/components/PreviewFrame.js.map +1 -0
- package/lib/features/webbuilder/components/PreviewPlaceholder.js +107 -0
- package/lib/features/webbuilder/components/PreviewPlaceholder.js.map +1 -0
- package/lib/features/webbuilder/components/PreviewScreen.js +200 -0
- package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -0
- package/lib/features/webbuilder/components/ProjectChat.js +580 -0
- package/lib/features/webbuilder/components/ProjectChat.js.map +1 -0
- package/lib/features/webbuilder/components/ProjectsScreen.js +339 -0
- package/lib/features/webbuilder/components/ProjectsScreen.js.map +1 -0
- package/lib/features/webbuilder/components/PublishSheet.js +143 -0
- package/lib/features/webbuilder/components/PublishSheet.js.map +1 -0
- package/lib/features/webbuilder/components/SiteScoreSheet.js +73 -0
- package/lib/features/webbuilder/components/SiteScoreSheet.js.map +1 -0
- package/lib/features/webbuilder/components/StudioHome.js +367 -0
- package/lib/features/webbuilder/components/StudioHome.js.map +1 -0
- package/lib/features/webbuilder/components/TemplateCard.js +73 -0
- package/lib/features/webbuilder/components/TemplateCard.js.map +1 -0
- package/lib/features/webbuilder/components/TemplatesSheet.js +178 -0
- package/lib/features/webbuilder/components/TemplatesSheet.js.map +1 -0
- package/lib/features/webbuilder/components/VersionsSheet.js +57 -0
- package/lib/features/webbuilder/components/VersionsSheet.js.map +1 -0
- package/lib/features/webbuilder/components/ui.js +291 -0
- package/lib/features/webbuilder/components/ui.js.map +1 -0
- package/lib/features/webbuilder/nativeWebBuilderRegistry.js +15 -0
- package/lib/features/webbuilder/nativeWebBuilderRegistry.js.map +1 -0
- package/lib/features/webbuilder/studioCatalog.js +147 -0
- package/lib/features/webbuilder/studioCatalog.js.map +1 -0
- package/lib/features/webbuilder/webbuilderPrompts.js +42 -0
- package/lib/features/webbuilder/webbuilderPrompts.js.map +1 -0
- package/lib/features/webbuilder/webbuilderTheme.js +63 -0
- package/lib/features/webbuilder/webbuilderTheme.js.map +1 -0
- package/lib/features/webbuilder/workflow.js +540 -0
- package/lib/features/webbuilder/workflow.js.map +1 -0
- package/lib/hooks/useChatApi.js +7 -2
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +1 -1
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/routes.json +106 -0
- package/lib/screens/WebBuilderNative/index.js +71 -0
- package/lib/screens/WebBuilderNative/index.js.map +1 -0
- package/lib/screens/WebBuilderNative/useCodeAssistantCatalog.js +45 -0
- package/lib/screens/WebBuilderNative/useCodeAssistantCatalog.js.map +1 -0
- package/lib/screens/WebBuilderNative/useWebBuilderGallery.js +125 -0
- package/lib/screens/WebBuilderNative/useWebBuilderGallery.js.map +1 -0
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +408 -0
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -0
- package/lib/screens/WebBuilderNative/webbuilderTransport.js +88 -0
- package/lib/screens/WebBuilderNative/webbuilderTransport.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebBuilderExperience.js","sources":["../../../src/features/webbuilder/WebBuilderExperience.tsx"],"sourcesContent":["/**\n * Native Web Builder: describe a site (or start from a template) and the build\n * workflow makes it; watch the live preview, ask for changes, step through\n * versions and publish - on the same builds as the web Web Builder, so a site\n * started on the phone opens on the web and the other way round.\n *\n * Native twin of the web surface (aicode-stack `surfaces/webbuilder`): the\n * studio home and its composer, Templates (the web sidebar, a sheet here),\n * Projects (the web's Your builds, a bottom tab), the open build with Preview / Code /\n * History and Publish, and the Agent pane. The host screen owns what needs\n * the app's data stack (the session, the build workflow, the chats, publish,\n * navigation) and passes it in as props; this component renders.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n ActionSheetIOS,\n Alert,\n BackHandler,\n Keyboard,\n Linking,\n Platform,\n Share,\n StyleSheet,\n Text,\n View,\n} from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { GestureHandlerRootView } from 'react-native-gesture-handler';\nimport { useSafeInsets } from '../canvas/withRemoteSafeArea';\nimport { useAppTheme } from '../../theme/AppThemeProvider';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { DIM, Tap } from '../inbox/components/Tap';\nimport { brandBriefBlock, isBareSeed, siteScoreTurn, studioTurnText } from './studioCatalog';\nimport { useBrandKit } from './brandKitStorage';\nimport { wakePreviewPrompt } from './webbuilderPrompts';\nimport { webbuilderTheme } from './webbuilderTheme';\nimport type { WebBuilderHostChat } from './hostChat';\nimport type {\n WebBuilderBuild,\n WebBuilderBuilding,\n WebBuilderProject,\n WebBuilderPublishResult,\n WebBuilderStartRequest,\n} from './types';\nimport type { WebBuilderTemplate } from './workflow';\nimport { BrandKitSheet } from './components/BrandKitSheet';\nimport { CodeView } from './components/CodeView';\nimport { ProjectChat } from './components/ProjectChat';\nimport { PreviewScreen } from './components/PreviewScreen';\nimport { PublishSheet } from './components/PublishSheet';\nimport { BOTTOM_TABS_SPACE, BottomTabs, type HomeTab } from './components/BottomTabs';\nimport { SiteScoreSheet } from './components/SiteScoreSheet';\nimport { ProjectsScreen } from './components/ProjectsScreen';\nimport { TemplatesSheet } from './components/TemplatesSheet';\nimport { StudioHome, type StudioStart } from './components/StudioHome';\nimport { VersionsSheet } from './components/VersionsSheet';\nimport { IconButton, Toast } from './components/ui';\n\nexport interface WebBuilderExperienceProps {\n /**\n * The app's light/dark choice, from the host. A lazily loaded experience can\n * end up with its own copy of the theme context and miss the in-app setting,\n * so the host's answer wins; the context is only the fallback.\n */\n isDark?: boolean;\n /** Leaves Web Builder. */\n onExit: () => void;\n /** Your builds, newest first. */\n projects: WebBuilderProject[];\n projectsLoading?: boolean;\n projectsError?: string | null;\n onRefreshProjects?: () => void;\n /** More builds exist past the ones loaded (the web gallery pages 10 at a time). */\n projectsHasMore?: boolean;\n onLoadMoreProjects?: () => void;\n /** The workspace's starter templates (marketplace Code Assistant cards). */\n templates: WebBuilderTemplate[];\n templatesLoading?: boolean;\n templatesError?: string | null;\n onReloadTemplates?: () => void;\n /** A connection still coming up: the composer waits (and says so), or null. */\n startBlocked?: string | null;\n /** Why the last Start did not go out, in one sentence, or null. */\n startNotice?: string | null;\n /** The site open on screen (its chat), or null on the home screen. */\n activeChannelId: string | null;\n onOpenProject: (channelId: string) => void;\n onCloseProject: () => void;\n /** Starts a new site; the host runs the build workflow and opens it. */\n onStartProject: (request: WebBuilderStartRequest) => void;\n /** The open site's builds, newest first. */\n builds: WebBuilderBuild[];\n buildsLoading?: boolean;\n /** A turn running on the open site. */\n building?: WebBuilderBuilding | null;\n /** The chat shows a publish still running on the open site. */\n publishing?: boolean;\n /** The open site's agent conversation. */\n hostChat?: WebBuilderHostChat;\n onPublish?: (build: WebBuilderBuild, projectName: string) => Promise<WebBuilderPublishResult>;\n /** Wake a sleeping preview without the agent; 'gone' when the sandbox was reclaimed. */\n onResumePreview?: (build: WebBuilderBuild) => Promise<'ok' | 'gone' | 'failed'>;\n /** A brain-routed hand-off: the person's words, which start a new site. */\n initialAgentSeed?: { text: string; files?: MessageAttachment[] } | null;\n}\n\nconst TOAST_MS = 2_400;\n/** A publish that never reported back stops reading as running after this long. */\nconst PUBLISH_WATCH_MS = 10 * 60 * 1000;\n\nexport function WebBuilderExperience({\n isDark: hostIsDark,\n onExit,\n projects,\n projectsLoading = false,\n projectsError = null,\n onRefreshProjects,\n projectsHasMore = false,\n onLoadMoreProjects,\n templates,\n templatesLoading = false,\n templatesError = null,\n onReloadTemplates,\n startBlocked = null,\n startNotice = null,\n activeChannelId,\n onOpenProject,\n onCloseProject,\n onStartProject,\n builds,\n buildsLoading = false,\n building = null,\n publishing: publishingOnChat = false,\n hostChat,\n onPublish,\n onResumePreview,\n initialAgentSeed = null,\n}: WebBuilderExperienceProps) {\n const appTheme = useAppTheme();\n const isDark = hostIsDark ?? appTheme.isDark;\n const theme = useMemo(() => webbuilderTheme(isDark), [isDark]);\n const insets = useSafeInsets();\n\n const project = useMemo(\n () => projects.find((p) => p.channelId === activeChannelId) ?? null,\n [projects, activeChannelId],\n );\n\n // ── Studio: the composer's draft, template and brand ──────────────────\n const [draft, setDraft] = useState('');\n const [template, setTemplate] = useState<WebBuilderTemplate | null>(null);\n const [templatesOpen, setTemplatesOpen] = useState(false);\n const [scoreOpen, setScoreOpen] = useState(false);\n const [homeTab, setHomeTab] = useState<HomeTab>('create');\n const { brand, saveBrand } = useBrandKit();\n const [brandOpen, setBrandOpen] = useState(false);\n\n const pickTemplate = useCallback((picked: WebBuilderTemplate) => {\n setTemplate(picked);\n setTemplatesOpen(false);\n setHomeTab('create');\n // The web hands a picked card to the composer: its starter prompt when the box is empty.\n setDraft((prev) => (isBareSeed(prev) && picked.chatPrompt ? picked.chatPrompt : prev));\n }, []);\n\n const startSite = useCallback(\n (start: StudioStart, files?: MessageAttachment[]) => {\n const brief =\n start.brief.trim() || (start.template ? start.template.chatPrompt || start.template.title : '');\n if (!brief && !files?.length) return;\n onStartProject({\n text: studioTurnText({ brief, brandBlock: brandBriefBlock(brand), referenceUrl: start.referenceUrl }),\n template: start.template,\n ...(start.referenceUrl ? { referenceUrl: start.referenceUrl } : {}),\n ...(files?.length ? { attachments: files } : {}),\n });\n setDraft('');\n setTemplate(null);\n },\n [onStartProject, brand],\n );\n\n // A hand-off starts its site as soon as a build can start.\n const handedOff = useRef(false);\n useEffect(() => {\n if (handedOff.current || !initialAgentSeed || startBlocked) return;\n handedOff.current = true;\n startSite({ brief: initialAgentSeed.text, template: null }, initialAgentSeed.files);\n }, [initialAgentSeed, startBlocked, startSite]);\n\n // ── The build on screen ────────────────────────────────────────────────\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n useEffect(() => setSelectedKey(null), [activeChannelId]);\n const latest = builds[0] ?? null;\n const build = useMemo(\n () => (selectedKey ? (builds.find((b) => b.key === selectedKey) ?? latest) : latest),\n [builds, selectedKey, latest],\n );\n // The site's resolved name (the web title rules) wins over a build's raw title.\n const siteTitle = project?.title || build?.title || null;\n\n // A new build of the same sandbox (an edit) re-fetches the preview.\n const [previewNonce, setPreviewNonce] = useState(0);\n const seenBuildAt = useRef<{ key: string | null; at: number }>({ key: null, at: 0 });\n useEffect(() => {\n const key = build?.key ?? null;\n const at = build?.updatedAt ?? 0;\n const seen = seenBuildAt.current;\n if (key && key === seen.key && at > seen.at) setPreviewNonce((n) => n + 1);\n seenBuildAt.current = { key, at };\n }, [build?.key, build?.updatedAt]);\n\n // ── Toast ──────────────────────────────────────────────────────────────\n const [toast, setToast] = useState<string | null>(null);\n const toastTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const showToast = useCallback((message: string) => {\n if (toastTimer.current) clearTimeout(toastTimer.current);\n setToast(message);\n toastTimer.current = setTimeout(() => setToast(null), TOAST_MS);\n }, []);\n useEffect(() => () => (toastTimer.current ? clearTimeout(toastTimer.current) : undefined), []);\n\n // ── The project's chat (Manus-style: the conversation leads, the site is a tap away) ──\n const [mode, setMode] = useState<'chat' | 'preview' | 'code'>('chat');\n useEffect(() => setMode('chat'), [activeChannelId]);\n const sendToAgent = useCallback(\n (text: string, files?: MessageAttachment[]) => {\n const words = text.trim();\n if (!words || !hostChat) return;\n // The first ask in a site with nothing built yet is the brief (web `studioTurnText`).\n const turn = build || /^build\\b/i.test(words) ? words : `Build me: ${words}`;\n hostChat.send(turn, files, build);\n setMode('chat');\n },\n [hostChat, build],\n );\n const openChat = useCallback(() => {\n Keyboard.dismiss();\n setMode('chat');\n }, []);\n // A preview that does not answer is woken quietly, the way the web's ensurePreview\n // does it; only a sandbox that is gone needs the agent to rebuild the site.\n const [waking, setWaking] = useState(false);\n const wokenFor = useRef<string | null>(null);\n useEffect(() => {\n wokenFor.current = null;\n }, [build?.key]);\n const wakePreview = useCallback(() => {\n if (!build || waking || wokenFor.current === build.key) return;\n wokenFor.current = build.key;\n setWaking(true);\n const resume = onResumePreview ? onResumePreview(build) : Promise.resolve<'failed'>('failed');\n resume\n .catch(() => 'failed' as const)\n .then((outcome) => {\n if (outcome === 'ok') setPreviewNonce((n) => n + 1);\n // Stay where the person is; the agent's restore shows in the chat.\n else hostChat?.send(wakePreviewPrompt(build), undefined, build);\n })\n .finally(() => setWaking(false));\n }, [build, waking, onResumePreview, hostChat]);\n\n // ── Publish ────────────────────────────────────────────────────────────\n const [publishOpen, setPublishOpen] = useState(false);\n const [versionsOpen, setVersionsOpen] = useState(false);\n const [publishStarted, setPublishStarted] = useState<{ key: string; live: string | null; at: number } | null>(null);\n useEffect(() => setPublishStarted(null), [activeChannelId]);\n useEffect(() => {\n if (!publishStarted) return;\n const target = builds.find((b) => b.key === publishStarted.key);\n if (target?.liveUrl && target.liveUrl !== publishStarted.live) {\n setPublishStarted(null);\n showToast('Your site is live');\n }\n }, [builds, publishStarted, showToast]);\n const publishing = publishingOnChat || Boolean(publishStarted && Date.now() - publishStarted.at < PUBLISH_WATCH_MS);\n const publish = useCallback(\n async (target: WebBuilderBuild, projectName: string): Promise<WebBuilderPublishResult> => {\n if (!onPublish) return { ok: false, message: 'Publishing is not available here.' };\n const result = await onPublish(target, projectName);\n if (result.ok) {\n setPublishStarted({ key: target.key, live: target.liveUrl, at: Date.now() });\n showToast('Publishing started');\n }\n return result;\n },\n [onPublish, showToast],\n );\n\n // ── Back ───────────────────────────────────────────────────────────────\n const back = useCallback(() => {\n if (activeChannelId && mode !== 'chat') {\n setMode('chat');\n return;\n }\n if (activeChannelId) {\n onCloseProject();\n return;\n }\n if (homeTab === 'projects') {\n setHomeTab('create');\n return;\n }\n onExit();\n }, [mode, activeChannelId, homeTab, onCloseProject, onExit]);\n useEffect(() => {\n const sub = BackHandler.addEventListener('hardwareBackPress', () => {\n back();\n return true;\n });\n return () => sub.remove();\n }, [back]);\n\n const live = build?.liveUrl ?? project?.liveUrl ?? null;\n let statusText = 'New';\n let statusTone = theme.muted;\n if (building || hostChat?.busy) {\n statusText = 'Working…';\n statusTone = theme.accent;\n } else if (live) {\n statusText = 'Live';\n statusTone = theme.good;\n } else if (build) {\n statusText = 'Not published';\n }\n const floating = {\n backgroundColor: theme.card,\n borderColor: theme.border,\n shadowColor: theme.isDark ? '#000' : '#1c1917',\n };\n let publishLabel = 'Publish';\n if (publishing) publishLabel = 'Publishing…';\n const shareUrl = live || build?.previewUrl || null;\n const shareSite = () => {\n if (shareUrl) Share.share({ message: shareUrl, url: shareUrl }).catch(() => undefined);\n };\n const openMore = () => {\n const actions: Array<{ label: string; run: () => void; destructive?: boolean }> = [];\n if (mode !== 'chat') actions.push({ label: 'Back to the chat', run: () => setMode('chat') });\n if (build?.previewUrl && mode !== 'preview') {\n actions.push({ label: 'Open preview', run: () => setMode('preview') });\n }\n if (build?.files && mode !== 'code') actions.push({ label: 'View code', run: () => setMode('code') });\n if (builds.length > 1) actions.push({ label: 'Versions', run: () => setVersionsOpen(true) });\n if (build?.sandboxId) {\n actions.push({ label: live ? 'Publish an update' : 'Publish', run: () => setPublishOpen(true) });\n }\n if (build?.previewUrl) {\n const url = live || build.previewUrl;\n actions.push({ label: 'Open in browser', run: () => Linking.openURL(url).catch(() => undefined) });\n }\n if (!actions.length) return;\n if (Platform.OS === 'ios') {\n ActionSheetIOS.showActionSheetWithOptions(\n { options: [...actions.map((a) => a.label), 'Cancel'], cancelButtonIndex: actions.length },\n (index) => actions[index]?.run(),\n );\n return;\n }\n Alert.alert(siteTitle || 'Project', undefined, [\n ...actions.map((a) => ({ text: a.label, onPress: a.run })),\n { text: 'Cancel', style: 'cancel' as const },\n ]);\n };\n\n return (\n <GestureHandlerRootView style={[styles.fill, { backgroundColor: theme.screen }]}>\n {activeChannelId ? (\n <>\n {/* Manus-style: a floating back, the project in a pill, actions on the right. */}\n <View style={[styles.projectHead, { paddingTop: insets.top + 6 }]}>\n <Tap\n onPress={back}\n accessibilityRole=\"button\"\n accessibilityLabel={mode === 'chat' ? 'Back to Web Builder' : 'Back to the chat'}\n style={[styles.roundBtn, floating]}\n pressedStyle={DIM}\n testID=\"webbuilder-back\"\n >\n <MaterialCommunityIcons name=\"chevron-left\" size={28} color={theme.ink} />\n </Tap>\n {mode === 'chat' ? (\n <>\n <View style={[styles.titlePill, floating]}>\n <Text style={[styles.pillTitle, { color: theme.ink }]} numberOfLines={1}>\n {siteTitle || 'New app'}\n </Text>\n <Text style={[styles.pillStatus, { color: statusTone }]} numberOfLines={1}>\n {statusText}\n </Text>\n </View>\n <View style={styles.headSpacer} />\n <View style={[styles.actionPill, floating]}>\n <Tap\n onPress={shareSite}\n disabled={!shareUrl}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Share\"\n style={[styles.pillBtn, !shareUrl && styles.disabled]}\n pressedStyle={DIM}\n >\n <MaterialCommunityIcons name=\"share-outline\" size={24} color={theme.ink} />\n </Tap>\n <Tap\n onPress={openMore}\n accessibilityRole=\"button\"\n accessibilityLabel=\"More\"\n style={styles.pillBtn}\n pressedStyle={DIM}\n testID=\"webbuilder-more\"\n >\n <MaterialCommunityIcons name=\"dots-horizontal\" size={24} color={theme.ink} />\n </Tap>\n </View>\n </>\n ) : (\n <>\n <Text style={[styles.centerTitle, { color: theme.ink }]} numberOfLines={1}>\n {mode === 'code' ? 'Code' : siteTitle || 'Preview'}\n </Text>\n <View style={[styles.actionPill, floating]}>\n <Tap\n onPress={shareSite}\n disabled={!shareUrl}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Share\"\n style={[styles.pillBtn, !shareUrl && styles.disabled]}\n pressedStyle={DIM}\n >\n <MaterialCommunityIcons name=\"share-outline\" size={24} color={theme.ink} />\n </Tap>\n <Tap\n onPress={openMore}\n accessibilityRole=\"button\"\n accessibilityLabel=\"More\"\n style={styles.pillBtn}\n pressedStyle={DIM}\n >\n <MaterialCommunityIcons name=\"dots-horizontal\" size={24} color={theme.ink} />\n </Tap>\n </View>\n </>\n )}\n </View>\n {mode === 'chat' ? (\n <ProjectChat\n messages={hostChat?.messages ?? []}\n streaming={hostChat?.streaming ?? null}\n busy={Boolean(hostChat?.busy)}\n error={hostChat?.error ?? null}\n connected={Boolean(hostChat?.connected)}\n building={building}\n build={build}\n siteTitle={siteTitle || 'Your site'}\n onSend={(text) => sendToAgent(text)}\n onOpenPreview={() => setMode('preview')}\n onPublish={() => setPublishOpen(true)}\n theme={theme}\n bottomInset={insets.bottom}\n />\n ) : null}\n {mode === 'preview' ? (\n <PreviewScreen\n build={build}\n building={building}\n loading={buildsLoading}\n previewNonce={previewNonce}\n onReload={() => setPreviewNonce((n) => n + 1)}\n onHome={() => setPreviewNonce((n) => n + 1)}\n onWake={wakePreview}\n waking={waking || Boolean(hostChat?.busy)}\n onPublish={() => setPublishOpen(true)}\n publishLabel={publishLabel}\n error={hostChat?.error ?? null}\n theme={theme}\n bottomInset={insets.bottom}\n />\n ) : null}\n {mode === 'code' ? (\n <View style={[styles.fill, { backgroundColor: theme.card, paddingBottom: insets.bottom }]}>\n <CodeView files={build?.files ?? null} theme={theme} onAsk={openChat} />\n </View>\n ) : null}\n </>\n ) : (\n <>\n <View\n style={[\n styles.header,\n styles.headerBare,\n { paddingTop: insets.top + 4, borderBottomColor: 'transparent' },\n ]}\n >\n <IconButton\n icon=\"arrow-left\"\n label=\"Leave Web Builder\"\n onPress={back}\n theme={theme}\n testID=\"webbuilder-back\"\n />\n </View>\n <View style={styles.fill}>\n {homeTab === 'create' ? (\n <StudioHome\n draft={draft}\n onDraft={setDraft}\n template={template}\n onClearTemplate={() => setTemplate(null)}\n onBrowseTemplates={() => setTemplatesOpen(true)}\n brand={brand}\n onBrand={() => setBrandOpen(true)}\n onSiteScore={() => setScoreOpen(true)}\n onStart={startSite}\n connecting={startBlocked}\n startNotice={startNotice}\n theme={theme}\n bottomInset={BOTTOM_TABS_SPACE + insets.bottom}\n />\n ) : (\n <ProjectsScreen\n projects={projects}\n loading={projectsLoading}\n error={projectsError}\n hasMore={projectsHasMore}\n onRefresh={onRefreshProjects}\n onLoadMore={onLoadMoreProjects}\n onOpen={(p) => onOpenProject(p.channelId)}\n onNewProject={() => setHomeTab('create')}\n topInset={4}\n bottomInset={BOTTOM_TABS_SPACE + insets.bottom}\n theme={theme}\n />\n )}\n </View>\n <BottomTabs tab={homeTab} onTab={setHomeTab} theme={theme} bottomInset={insets.bottom} />\n </>\n )}\n\n <TemplatesSheet\n visible={templatesOpen}\n onClose={() => setTemplatesOpen(false)}\n templates={templates}\n loading={templatesLoading}\n error={templatesError}\n onReload={onReloadTemplates}\n selectedId={template?.id ?? null}\n onPick={pickTemplate}\n theme={theme}\n />\n <SiteScoreSheet\n visible={scoreOpen}\n onClose={() => setScoreOpen(false)}\n blocked={startBlocked}\n onCheck={(url) => {\n setScoreOpen(false);\n onStartProject({ text: siteScoreTurn(url), template: null, agent: true });\n }}\n theme={theme}\n />\n <BrandKitSheet\n visible={brandOpen}\n brand={brand}\n onSave={saveBrand}\n onClose={() => setBrandOpen(false)}\n theme={theme}\n />\n <PublishSheet\n visible={publishOpen}\n build={build}\n publishing={publishing}\n onPublish={onPublish ? publish : undefined}\n onClose={() => setPublishOpen(false)}\n theme={theme}\n />\n <VersionsSheet\n visible={versionsOpen}\n builds={builds}\n selectedKey={selectedKey}\n onSelect={(picked) => {\n setSelectedKey(picked.key === latest?.key ? null : picked.key);\n setVersionsOpen(false);\n }}\n onClose={() => setVersionsOpen(false)}\n theme={theme}\n />\n\n <Toast message={toast} theme={theme} bottom={insets.bottom + 80} />\n </GestureHandlerRootView>\n );\n}\n\nexport default WebBuilderExperience;\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n header: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n paddingHorizontal: 8,\n paddingBottom: 8,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n headerBare: { paddingBottom: 0 },\n projectHead: { flexDirection: 'row', alignItems: 'center', gap: 10, paddingHorizontal: 14, paddingBottom: 10 },\n roundBtn: {\n width: 52,\n height: 52,\n borderRadius: 26,\n borderWidth: StyleSheet.hairlineWidth,\n alignItems: 'center',\n justifyContent: 'center',\n shadowOpacity: 0.08,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 4 },\n elevation: 3,\n },\n titlePill: {\n flexShrink: 1,\n maxWidth: '58%',\n height: 52,\n paddingHorizontal: 18,\n borderRadius: 26,\n borderWidth: StyleSheet.hairlineWidth,\n justifyContent: 'center',\n shadowOpacity: 0.08,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 4 },\n elevation: 3,\n },\n pillTitle: { fontSize: 16, fontWeight: '700', letterSpacing: -0.2 },\n pillStatus: { fontSize: 12, fontWeight: '600', marginTop: 1 },\n headSpacer: { flex: 1 },\n actionPill: {\n flexDirection: 'row',\n alignItems: 'center',\n height: 52,\n paddingHorizontal: 8,\n borderRadius: 26,\n borderWidth: StyleSheet.hairlineWidth,\n shadowOpacity: 0.08,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 4 },\n elevation: 3,\n },\n pillBtn: { width: 42, height: 42, borderRadius: 21, alignItems: 'center', justifyContent: 'center' },\n centerTitle: { flex: 1, textAlign: 'center', fontSize: 18, fontWeight: '700' },\n headerText: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: 8, minWidth: 0 },\n headerTitle: { flexShrink: 1, fontSize: 17, fontWeight: '700', letterSpacing: -0.2 },\n publish: {\n minHeight: 34,\n paddingHorizontal: 16,\n borderRadius: 17,\n alignItems: 'center',\n justifyContent: 'center',\n marginRight: 4,\n },\n publishLabel: { fontSize: 14, fontWeight: '700' },\n disabled: { opacity: 0.35 },\n});\n"],"names":["_a","_b"],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {useState,useEffect,useCallback}from'react';import {sanitizeBrandKit}from'./studioCatalog.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var _a;
|
|
21
|
+
let AsyncStorage = null;
|
|
22
|
+
try {
|
|
23
|
+
AsyncStorage = (_a = require("@react-native-async-storage/async-storage").default) != null ? _a : null;
|
|
24
|
+
} catch (e) {
|
|
25
|
+
AsyncStorage = null;
|
|
26
|
+
}
|
|
27
|
+
const BRAND_KIT_KEY = "yantra.webbuilder.brandKit.v1";
|
|
28
|
+
async function readBrandKit() {
|
|
29
|
+
try {
|
|
30
|
+
const raw = await (AsyncStorage == null ? void 0 : AsyncStorage.getItem(BRAND_KIT_KEY));
|
|
31
|
+
return raw ? sanitizeBrandKit(JSON.parse(raw)) : null;
|
|
32
|
+
} catch (e) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function writeBrandKit(kit) {
|
|
37
|
+
try {
|
|
38
|
+
if (!AsyncStorage) return false;
|
|
39
|
+
if (kit) await AsyncStorage.setItem(BRAND_KIT_KEY, JSON.stringify(kit));
|
|
40
|
+
else await AsyncStorage.removeItem(BRAND_KIT_KEY);
|
|
41
|
+
return true;
|
|
42
|
+
} catch (e) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function useBrandKit() {
|
|
47
|
+
const [brand, setBrand] = useState(null);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
let alive = true;
|
|
50
|
+
void readBrandKit().then((kit) => {
|
|
51
|
+
if (alive) setBrand(kit);
|
|
52
|
+
});
|
|
53
|
+
return () => {
|
|
54
|
+
alive = false;
|
|
55
|
+
};
|
|
56
|
+
}, []);
|
|
57
|
+
const saveBrand = useCallback(async (kit) => {
|
|
58
|
+
const clean = kit ? sanitizeBrandKit(__spreadProps(__spreadValues({}, kit), {
|
|
59
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
60
|
+
})) : null;
|
|
61
|
+
const ok = await writeBrandKit(clean);
|
|
62
|
+
if (ok) setBrand(clean);
|
|
63
|
+
return ok;
|
|
64
|
+
}, []);
|
|
65
|
+
return {
|
|
66
|
+
brand,
|
|
67
|
+
saveBrand
|
|
68
|
+
};
|
|
69
|
+
}export{BRAND_KIT_KEY,readBrandKit,useBrandKit,writeBrandKit};//# sourceMappingURL=brandKitStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brandKitStorage.js","sources":["../../../src/features/webbuilder/brandKitStorage.ts"],"sourcesContent":["/**\n * The Brand kit on this device. The web keeps it per browser (localStorage)\n * until there is an account-level store; the phone keeps it the same way, in\n * AsyncStorage. Reads and writes never throw: a binary without the module, or\n * a failed write, just means no saved kit.\n */\nimport { useCallback, useEffect, useState } from 'react';\nimport { sanitizeBrandKit, type BrandKit } from './studioCatalog';\n\ntype StorageLike = {\n getItem: (key: string) => Promise<string | null>;\n setItem: (key: string, value: string) => Promise<void>;\n removeItem: (key: string) => Promise<void>;\n};\n\nlet AsyncStorage: StorageLike | null = null;\ntry {\n // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require\n AsyncStorage = require('@react-native-async-storage/async-storage').default ?? null;\n} catch {\n AsyncStorage = null;\n}\n\n/** Same key as the web surface, so the two read alike. */\nexport const BRAND_KIT_KEY = 'yantra.webbuilder.brandKit.v1';\n\nexport async function readBrandKit(): Promise<BrandKit | null> {\n try {\n const raw = await AsyncStorage?.getItem(BRAND_KIT_KEY);\n return raw ? sanitizeBrandKit(JSON.parse(raw)) : null;\n } catch {\n return null;\n }\n}\n\nexport async function writeBrandKit(kit: BrandKit | null): Promise<boolean> {\n try {\n if (!AsyncStorage) return false;\n if (kit) await AsyncStorage.setItem(BRAND_KIT_KEY, JSON.stringify(kit));\n else await AsyncStorage.removeItem(BRAND_KIT_KEY);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function useBrandKit(): { brand: BrandKit | null; saveBrand: (kit: BrandKit | null) => Promise<boolean> } {\n const [brand, setBrand] = useState<BrandKit | null>(null);\n useEffect(() => {\n let alive = true;\n void readBrandKit().then((kit) => {\n if (alive) setBrand(kit);\n });\n return () => {\n alive = false;\n };\n }, []);\n const saveBrand = useCallback(async (kit: BrandKit | null) => {\n const clean = kit ? sanitizeBrandKit({ ...kit, updatedAt: new Date().toISOString() }) : null;\n const ok = await writeBrandKit(clean);\n if (ok) setBrand(clean);\n return ok;\n }, []);\n return { brand, saveBrand };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,IAAA,EAAA;AAaA,IAAI,YAAmC,GAAA,IAAA;AACvC,IAAI;AAEF,EAAA,YAAA,GAAA,CAAe,EAAQ,GAAA,OAAA,CAAA,2CAA2C,CAAE,CAAA,OAAA,KAArD,IAAgE,GAAA,EAAA,GAAA,IAAA;AACjF,CAAQ,CAAA,OAAA,CAAA,EAAA;AACN,EAAe,YAAA,GAAA,IAAA;AACjB;AAGO,MAAM,aAAgB,GAAA;AAC7B,eAAsB,YAAyC,GAAA;AAC7D,EAAI,IAAA;AACF,IAAM,MAAA,GAAA,GAAM,OAAM,YAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,YAAA,CAAc,OAAQ,CAAA,aAAA,CAAA,CAAA;AACxC,IAAA,OAAO,MAAM,gBAAiB,CAAA,IAAA,CAAK,KAAM,CAAA,GAAG,CAAC,CAAI,GAAA,IAAA;AAAA,GAC3C,CAAA,OAAA,CAAA,EAAA;AACN,IAAO,OAAA,IAAA;AAAA;AAEX;AACA,eAAsB,cAAc,GAAwC,EAAA;AAC1E,EAAI,IAAA;AACF,IAAI,IAAA,CAAC,cAAqB,OAAA,KAAA;AAC1B,IAAI,IAAA,GAAA,QAAW,YAAa,CAAA,OAAA,CAAQ,eAAe,IAAK,CAAA,SAAA,CAAU,GAAG,CAAC,CAAA;AAAA,SAAO,MAAM,YAAa,CAAA,UAAA,CAAW,aAAa,CAAA;AACxH,IAAO,OAAA,IAAA;AAAA,GACD,CAAA,OAAA,CAAA,EAAA;AACN,IAAO,OAAA,KAAA;AAAA;AAEX;AACO,SAAS,WAGd,GAAA;AACA,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAA0B,IAAI,CAAA;AACxD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAQ,GAAA,IAAA;AACZ,IAAK,KAAA,YAAA,EAAe,CAAA,IAAA,CAAK,CAAO,GAAA,KAAA;AAC9B,MAAI,IAAA,KAAA,WAAgB,GAAG,CAAA;AAAA,KACxB,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAQ,KAAA,GAAA,KAAA;AAAA,KACV;AAAA,GACF,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,SAAA,GAAY,WAAY,CAAA,OAAO,GAAyB,KAAA;AAC5D,IAAA,MAAM,KAAQ,GAAA,GAAA,GAAM,gBAAiB,CAAA,aAAA,CAAA,cAAA,CAAA,EAAA,EAChC,GADgC,CAAA,EAAA;AAAA,MAEnC,SAAW,EAAA,iBAAA,IAAI,IAAK,EAAA,EAAE,WAAY;AAAA,MACnC,CAAI,GAAA,IAAA;AACL,IAAM,MAAA,EAAA,GAAK,MAAM,aAAA,CAAc,KAAK,CAAA;AACpC,IAAI,IAAA,EAAA,WAAa,KAAK,CAAA;AACtB,IAAO,OAAA,EAAA;AAAA,GACT,EAAG,EAAE,CAAA;AACL,EAAO,OAAA;AAAA,IACL,KAAA;AAAA,IACA;AAAA,GACF;AACF"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
function asObject(value) {
|
|
2
|
+
if (!value) return null;
|
|
3
|
+
if (typeof value === "object") return Array.isArray(value) ? null : value;
|
|
4
|
+
if (typeof value === "string") {
|
|
5
|
+
const trimmed = value.trim();
|
|
6
|
+
if (!trimmed.startsWith("{")) return null;
|
|
7
|
+
try {
|
|
8
|
+
const parsed = JSON.parse(trimmed);
|
|
9
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function str(value) {
|
|
17
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
18
|
+
}
|
|
19
|
+
function accountRecords(record) {
|
|
20
|
+
return Object.values(record).map((v) => asObject(v)).filter((v) => v !== null);
|
|
21
|
+
}
|
|
22
|
+
function pick(records, key) {
|
|
23
|
+
var _a;
|
|
24
|
+
for (const record of records) {
|
|
25
|
+
const value = str(record[key]) || str((_a = asObject(record.fragment)) == null ? void 0 : _a[key]);
|
|
26
|
+
if (value) return value;
|
|
27
|
+
}
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
const LIVE_SANDBOX = /^https?:\/\/\d+-[a-z0-9]+(\.|\/|$)/i;
|
|
31
|
+
function sandboxPreviewUrl(url, sandboxId) {
|
|
32
|
+
const given = str(url);
|
|
33
|
+
if (given) {
|
|
34
|
+
if (/^https?:\/\/\d+-[a-z0-9]+\/?$/i.test(given)) return `${given.replace(/\/$/, "")}.e2b.dev`;
|
|
35
|
+
return given;
|
|
36
|
+
}
|
|
37
|
+
const id = str(sandboxId);
|
|
38
|
+
return id ? `https://3000-${id}.e2b.dev` : null;
|
|
39
|
+
}
|
|
40
|
+
function httpOrigin(value) {
|
|
41
|
+
const match = /^(https?:\/\/[^/?#]+)/i.exec((value != null ? value : "").trim());
|
|
42
|
+
return match && !LIVE_SANDBOX.test(match[1]) ? match[1] : null;
|
|
43
|
+
}
|
|
44
|
+
function coverDisplayUrl(cover, path, cdnOrigin) {
|
|
45
|
+
const raw = str(cover);
|
|
46
|
+
if (!raw || LIVE_SANDBOX.test(raw)) return null;
|
|
47
|
+
if (/^https?:\/\//i.test(raw)) return raw.split("?")[0];
|
|
48
|
+
const key = raw.replace(/^\/+/, "");
|
|
49
|
+
if (!/\/uploads\//i.test(`/${key}`) && !/\.(png|jpe?g|webp|gif|svg)$/i.test(key)) return null;
|
|
50
|
+
const origin = httpOrigin(path) || httpOrigin(cdnOrigin);
|
|
51
|
+
return origin ? `${origin}/${key}` : null;
|
|
52
|
+
}
|
|
53
|
+
function readFragment(post) {
|
|
54
|
+
if (!post || typeof post !== "object") return null;
|
|
55
|
+
const p = post;
|
|
56
|
+
const cfg = p.propsConfiguration || {};
|
|
57
|
+
const contents = asObject(cfg.contents) || asObject(cfg.content) || {};
|
|
58
|
+
const contentsProps = asObject(contents.props) || {};
|
|
59
|
+
const props = asObject(p.props) || {};
|
|
60
|
+
const fragment = asObject(contentsProps.fragment) || asObject(contents.fragment) || asObject(cfg.fragment) || asObject(props.fragment) || asObject(p.fragment) || null;
|
|
61
|
+
const f = fragment || {};
|
|
62
|
+
const sandboxUrl = str(f.sandboxUrl) || str(f.url) || str(p.sandboxUrl) || str(contents.sandboxUrl);
|
|
63
|
+
const sandboxId = str(f.sandboxId) || str(p.sandboxId) || str(contents.sandboxId) || str(cfg.sandboxId);
|
|
64
|
+
const publish = asObject(f.publish);
|
|
65
|
+
const liveUrl = str(f.customDomainUrl) || str(f.cloudflareUrl) || str(f.deployUrl) || str(publish == null ? void 0 : publish.url) || void 0;
|
|
66
|
+
const attachment = asObject(props.attachment) || asObject(contents.attachment) || {};
|
|
67
|
+
const isCreatingSandbox = f.isCreatingSandbox === true || contents.isCreatingSandbox === true || p.isCreatingSandbox === true;
|
|
68
|
+
const isDeploying = attachment.isDeploying === true || f.isDeploying === true;
|
|
69
|
+
if (!sandboxUrl && !sandboxId && !liveUrl && !fragment && !isCreatingSandbox && !isDeploying) return null;
|
|
70
|
+
const files = f.files && typeof f.files === "object" ? f.files : null;
|
|
71
|
+
const coverSources = [f, props, contents, contentsProps, p, ...accountRecords(props), ...accountRecords(contents)];
|
|
72
|
+
const coverImageUrl = [pick(coverSources, "coverImageUrl"), pick(coverSources, "previewImageUrl"), str(f.cover)].find((c) => c && !LIVE_SANDBOX.test(c));
|
|
73
|
+
return {
|
|
74
|
+
sandboxUrl,
|
|
75
|
+
sandboxId,
|
|
76
|
+
liveUrl,
|
|
77
|
+
files,
|
|
78
|
+
title: str(f.title),
|
|
79
|
+
projectId: str(f.projectId) || str(contentsProps.projectId),
|
|
80
|
+
template: str(f.templateId) || str(f.template) || str(contentsProps.template) || str(contents.template),
|
|
81
|
+
coverImageUrl,
|
|
82
|
+
coverImagePath: pick(coverSources, "coverImagePath"),
|
|
83
|
+
isCreatingSandbox,
|
|
84
|
+
isDeploying
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const PREVIEW_LINK = /https?:\/\/\d+-([a-z0-9]+)\.e2b\.(?:dev|app)(?:\/[^\s)\]"'<>]*)?/i;
|
|
88
|
+
function linkFragment(post) {
|
|
89
|
+
const p = post != null ? post : {};
|
|
90
|
+
const text = typeof p.message === "string" ? p.message : "";
|
|
91
|
+
const match = PREVIEW_LINK.exec(text);
|
|
92
|
+
if (!match) return null;
|
|
93
|
+
return {
|
|
94
|
+
sandboxUrl: match[0].replace(/[.,;:!?]+$/, ""),
|
|
95
|
+
sandboxId: match[1],
|
|
96
|
+
isCreatingSandbox: false,
|
|
97
|
+
isDeploying: false
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function postTime(post) {
|
|
101
|
+
const p = post != null ? post : {};
|
|
102
|
+
const raw = p.updatedAt || p.createdAt;
|
|
103
|
+
const ms = typeof raw === "number" ? raw : Date.parse(String(raw != null ? raw : ""));
|
|
104
|
+
return Number.isFinite(ms) ? ms : 0;
|
|
105
|
+
}
|
|
106
|
+
function chronological(posts) {
|
|
107
|
+
return [...posts].sort((a, b) => postTime(a) - postTime(b));
|
|
108
|
+
}
|
|
109
|
+
function isUserPost(post) {
|
|
110
|
+
var _a, _b, _c, _d, _e;
|
|
111
|
+
const p = post != null ? post : {};
|
|
112
|
+
const contents = asObject((_a = p.propsConfiguration) == null ? void 0 : _a.contents) || {};
|
|
113
|
+
const props = asObject(p.props) || {};
|
|
114
|
+
const role = String((_e = (_d = (_b = props.role) != null ? _b : contents.role) != null ? _d : (_c = asObject(contents.props)) == null ? void 0 : _c.role) != null ? _e : "").toUpperCase();
|
|
115
|
+
return role === "USER";
|
|
116
|
+
}
|
|
117
|
+
const DEFAULT_TEMPLATE = "vite-react";
|
|
118
|
+
function buildsFromPosts(posts, fallbackTitle, cdnOrigin) {
|
|
119
|
+
var _a;
|
|
120
|
+
const fallback = fallbackTitle != null ? fallbackTitle : "Web app";
|
|
121
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
122
|
+
let lastKey = null;
|
|
123
|
+
const fragments = chronological(posts).filter((post) => !isUserPost(post)).map((post) => {
|
|
124
|
+
var _a2;
|
|
125
|
+
return {
|
|
126
|
+
post,
|
|
127
|
+
fragment: (_a2 = readFragment(post)) != null ? _a2 : linkFragment(post)
|
|
128
|
+
};
|
|
129
|
+
}).filter((row) => row.fragment !== null && Boolean(row.fragment.sandboxUrl || row.fragment.liveUrl || row.fragment.coverImageUrl));
|
|
130
|
+
for (const {
|
|
131
|
+
post,
|
|
132
|
+
fragment
|
|
133
|
+
} of fragments) {
|
|
134
|
+
const previewUrl = sandboxPreviewUrl(fragment.sandboxUrl, fragment.sandboxId);
|
|
135
|
+
const key = fragment.sandboxId || previewUrl || "";
|
|
136
|
+
const target = key || (fragment.liveUrl || fragment.coverImageUrl ? lastKey : null);
|
|
137
|
+
if (target) {
|
|
138
|
+
const existing = byKey.get(target);
|
|
139
|
+
byKey.set(target, {
|
|
140
|
+
key: target,
|
|
141
|
+
title: fragment.title || (existing == null ? void 0 : existing.title) || fallback,
|
|
142
|
+
previewUrl: previewUrl || (existing == null ? void 0 : existing.previewUrl) || null,
|
|
143
|
+
sandboxId: fragment.sandboxId || (existing == null ? void 0 : existing.sandboxId) || null,
|
|
144
|
+
projectId: fragment.projectId || (existing == null ? void 0 : existing.projectId) || null,
|
|
145
|
+
liveUrl: fragment.liveUrl || (existing == null ? void 0 : existing.liveUrl) || null,
|
|
146
|
+
files: fragment.files || (existing == null ? void 0 : existing.files) || null,
|
|
147
|
+
templateId: fragment.template || (existing == null ? void 0 : existing.templateId) || DEFAULT_TEMPLATE,
|
|
148
|
+
coverUrl: coverDisplayUrl(fragment.coverImageUrl, fragment.coverImagePath, cdnOrigin) || (existing == null ? void 0 : existing.coverUrl) || null,
|
|
149
|
+
updatedAt: Math.max(postTime(post), (_a = existing == null ? void 0 : existing.updatedAt) != null ? _a : 0)
|
|
150
|
+
});
|
|
151
|
+
lastKey = target;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return [...byKey.values()].filter((b) => b.previewUrl || b.liveUrl).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
155
|
+
}
|
|
156
|
+
function pendingWork(posts) {
|
|
157
|
+
const newest = chronological(posts).map((post) => readFragment(post)).filter((f) => f !== null).pop();
|
|
158
|
+
if (!newest) return null;
|
|
159
|
+
if (newest.isCreatingSandbox && !newest.sandboxUrl && !newest.sandboxId) return "creating";
|
|
160
|
+
if (newest.isDeploying && !newest.liveUrl) return "publishing";
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
function isGenericTitle(title) {
|
|
164
|
+
const t = (title || "").trim().toLowerCase();
|
|
165
|
+
return !t || t === "generated page" || t === "generated project" || t === "generated with cdecli" || t === "ai assistant" || t === "web app" || /^build \d+$/.test(t) || /^build\s+me\b/.test(t) || /^remix\s+the\b/.test(t) || /^(build|chat)[- ]channel\b/.test(t) || t.startsWith("selected skill") || /^code[\s_-]?assist/.test(t);
|
|
166
|
+
}
|
|
167
|
+
const TITLE_STOP_WORDS = /* @__PURE__ */ new Set(["a", "an", "the", "create", "build", "make", "please", "me", "my", "for", "with", "simple", "using", "from", "template", "to", "and", "or", "remix", "yantra"]);
|
|
168
|
+
function titleCase(words) {
|
|
169
|
+
return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
170
|
+
}
|
|
171
|
+
function cleanPrompt(text) {
|
|
172
|
+
return text.replace(/^\[webbuilder context:[^\]]*\]\s*/i, "").replace(/^build\s*me\s*:\s*/i, "").replace(/\s+/g, " ").trim();
|
|
173
|
+
}
|
|
174
|
+
function titleFromPrompt(message) {
|
|
175
|
+
var _a, _b;
|
|
176
|
+
const raw = (message || "").replace(/^\[webbuilder context:[^\]]*\]\s*/i, "").trim();
|
|
177
|
+
if (!raw) return null;
|
|
178
|
+
const buildMe = (_b = (_a = raw.match(/^\s*Build me:\s*(.+)$/im)) == null ? void 0 : _a[1]) == null ? void 0 : _b.trim();
|
|
179
|
+
if (!buildMe && /^(change|update|rename|fix|edit|add|remove|delete|improve|make|refactor)\b/i.test(raw)) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
const source = (buildMe || raw.split(/\n+/)[0] || "").replace(/^["']|["']$/g, "");
|
|
183
|
+
const words = source.replace(/[^\w\s-]/g, " ").split(/\s+/).filter((w) => w.length > 1 && !TITLE_STOP_WORDS.has(w.toLowerCase())).slice(0, 3);
|
|
184
|
+
if (!words.length) return null;
|
|
185
|
+
const title = titleCase(words);
|
|
186
|
+
return isGenericTitle(title) ? null : title;
|
|
187
|
+
}
|
|
188
|
+
function titleFromPackageJson(files) {
|
|
189
|
+
var _a;
|
|
190
|
+
if (!files) return null;
|
|
191
|
+
const raw = (_a = Object.entries(files).find(([path]) => /(^|\/)package\.json$/.test(path))) == null ? void 0 : _a[1];
|
|
192
|
+
if (!raw) return null;
|
|
193
|
+
try {
|
|
194
|
+
const name = String(JSON.parse(raw).name || "").trim();
|
|
195
|
+
if (!name || name === "vite-react" || name === "project") return null;
|
|
196
|
+
return name.replace(/^@[^/]+\//, "").replace(/[-_]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
197
|
+
} catch (e) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function resolveSiteTitle(opts) {
|
|
202
|
+
const candidates = [opts.fragmentTitle, titleFromPrompt(opts.userPrompt), opts.channelTitle, titleFromPackageJson(opts.files)];
|
|
203
|
+
const found = candidates.find((c) => c && !isGenericTitle(c));
|
|
204
|
+
return (found || "Generated Page").trim();
|
|
205
|
+
}
|
|
206
|
+
function lastMessageHasCover(channel) {
|
|
207
|
+
var _a;
|
|
208
|
+
return Boolean((_a = readFragment(channel.lastMessage)) == null ? void 0 : _a.coverImageUrl);
|
|
209
|
+
}
|
|
210
|
+
function projectFromPosts(channel, posts, cdnOrigin) {
|
|
211
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
212
|
+
const channelId = str(channel.id);
|
|
213
|
+
if (!channelId) return null;
|
|
214
|
+
const builds = buildsFromPosts(posts, "", cdnOrigin);
|
|
215
|
+
const latest = builds[0];
|
|
216
|
+
if (!latest) return null;
|
|
217
|
+
const userPrompts = chronological(posts).filter((post) => isUserPost(post) && str(post.message)).map((post) => String(post.message));
|
|
218
|
+
const brief = (_a = userPrompts.find((m) => /build\s*me\s*:/i.test(m))) != null ? _a : userPrompts[0];
|
|
219
|
+
const channelTitle = [channel.displayName, channel.title].map((t) => str(t)).find((t) => t && !isGenericTitle(t));
|
|
220
|
+
const title = resolveSiteTitle({
|
|
221
|
+
fragmentTitle: latest.title,
|
|
222
|
+
channelTitle,
|
|
223
|
+
userPrompt: brief,
|
|
224
|
+
files: latest.files
|
|
225
|
+
});
|
|
226
|
+
const updated = Date.parse(String((_c = (_b = channel.updatedAt) != null ? _b : channel.createdAt) != null ? _c : ""));
|
|
227
|
+
return {
|
|
228
|
+
channelId,
|
|
229
|
+
title,
|
|
230
|
+
updatedAt: Math.max(Number.isFinite(updated) ? updated : 0, latest.updatedAt),
|
|
231
|
+
previewUrl: latest.previewUrl,
|
|
232
|
+
liveUrl: (_e = (_d = builds.find((b) => b.liveUrl)) == null ? void 0 : _d.liveUrl) != null ? _e : null,
|
|
233
|
+
coverUrl: (_g = (_f = builds.find((b) => b.coverUrl)) == null ? void 0 : _f.coverUrl) != null ? _g : null,
|
|
234
|
+
templateId: latest.templateId
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function cacheBustedUrl(url, nonce) {
|
|
238
|
+
const [base, hash = ""] = url.split("#");
|
|
239
|
+
const clean = base.replace(/([?&])wb=[^&]*(&|$)/, "$1").replace(/[?&]$/, "");
|
|
240
|
+
const sep = clean.includes("?") ? "&" : "?";
|
|
241
|
+
return `${clean}${sep}wb=${nonce}${hash ? `#${hash}` : ""}`;
|
|
242
|
+
}
|
|
243
|
+
function publishSlug(title) {
|
|
244
|
+
const slug = title.toLowerCase().normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 58).replace(/-+$/, "");
|
|
245
|
+
return slug || "my-site";
|
|
246
|
+
}
|
|
247
|
+
function isValidPublishSlug(value) {
|
|
248
|
+
return /^[a-z0-9](?:[a-z0-9-]{0,56}[a-z0-9])?$/.test(value);
|
|
249
|
+
}
|
|
250
|
+
function displayHost(url) {
|
|
251
|
+
const match = /^https?:\/\/([^/?#]+)/i.exec((url != null ? url : "").trim());
|
|
252
|
+
return match ? match[1] : (url != null ? url : "").trim();
|
|
253
|
+
}
|
|
254
|
+
function relativeTime(ms, now = Date.now()) {
|
|
255
|
+
if (!ms) return "";
|
|
256
|
+
const diff = Math.max(0, now - ms);
|
|
257
|
+
const min = Math.floor(diff / 6e4);
|
|
258
|
+
if (min < 1) return "just now";
|
|
259
|
+
if (min < 60) return `${min} min ago`;
|
|
260
|
+
const hours = Math.floor(min / 60);
|
|
261
|
+
if (hours < 24) return `${hours} h ago`;
|
|
262
|
+
if (hours < 48) return "Yesterday";
|
|
263
|
+
const d = new Date(ms);
|
|
264
|
+
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
265
|
+
return `${d.getDate()} ${months[d.getMonth()]}`;
|
|
266
|
+
}
|
|
267
|
+
function isThinkingPost(post) {
|
|
268
|
+
var _a, _b, _c;
|
|
269
|
+
const p = post != null ? post : {};
|
|
270
|
+
const props = asObject(p.props) || {};
|
|
271
|
+
const attachment = asObject(props.attachment) || {};
|
|
272
|
+
const msg = String((_a = p.message) != null ? _a : "").trim().toLowerCase();
|
|
273
|
+
return String((_b = p.type) != null ? _b : "").toUpperCase() === "THINKING" || Boolean((_c = props.thinking) != null ? _c : props.isThinking) || props.kind === "thinking" || Boolean(attachment.isThinking) || msg === "thinking..." || msg === "initializing..." || msg === "initializing\u2026";
|
|
274
|
+
}
|
|
275
|
+
function readFragmentStatus(p) {
|
|
276
|
+
var _a, _b, _c, _d;
|
|
277
|
+
const contents = asObject((_a = p.propsConfiguration) == null ? void 0 : _a.contents) || {};
|
|
278
|
+
return str((_c = asObject((_b = asObject(contents.props)) == null ? void 0 : _b.fragment)) == null ? void 0 : _c.statusText) || str((_d = asObject(contents.fragment)) == null ? void 0 : _d.statusText);
|
|
279
|
+
}
|
|
280
|
+
function progressText(post) {
|
|
281
|
+
var _a, _b, _c;
|
|
282
|
+
const p = post != null ? post : {};
|
|
283
|
+
const props = asObject(p.props) || {};
|
|
284
|
+
const thought = str((_a = asObject(props.attachment)) == null ? void 0 : _a.thought);
|
|
285
|
+
if (thought) return thought;
|
|
286
|
+
const status = str((_b = asObject(props.fragment)) == null ? void 0 : _b.statusText) || str(readFragmentStatus(p));
|
|
287
|
+
if (status) return status;
|
|
288
|
+
return isThinkingPost(post) ? (_c = str(p.message)) != null ? _c : null : null;
|
|
289
|
+
}
|
|
290
|
+
function isErrorPost(post) {
|
|
291
|
+
var _a, _b;
|
|
292
|
+
const p = post != null ? post : {};
|
|
293
|
+
const props = asObject(p.props) || {};
|
|
294
|
+
const contents = asObject((_a = p.propsConfiguration) == null ? void 0 : _a.contents) || {};
|
|
295
|
+
const f = asObject(props.fragment) || asObject((_b = asObject(contents.props)) == null ? void 0 : _b.fragment) || asObject(contents.fragment) || {};
|
|
296
|
+
return f.isError === true || f.type === "error";
|
|
297
|
+
}
|
|
298
|
+
function transcriptFromPosts(posts) {
|
|
299
|
+
var _a;
|
|
300
|
+
const out = [];
|
|
301
|
+
for (const post of chronological(posts)) {
|
|
302
|
+
const p = post;
|
|
303
|
+
const text = str(p.message);
|
|
304
|
+
if (text && !isThinkingPost(post)) {
|
|
305
|
+
const user = isUserPost(post);
|
|
306
|
+
out.push({
|
|
307
|
+
id: String((_a = p.id) != null ? _a : `${user ? "u" : "a"}-${out.length}`),
|
|
308
|
+
role: user ? "user" : "assistant",
|
|
309
|
+
content: user ? cleanPrompt(text) || text : text,
|
|
310
|
+
createdAt: postTime(post)
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return out;
|
|
315
|
+
}
|
|
316
|
+
function turnState(posts, since) {
|
|
317
|
+
var _a, _b;
|
|
318
|
+
const after = chronological(posts).filter((post) => postTime(post) >= since - 2e3);
|
|
319
|
+
let progress = null;
|
|
320
|
+
for (const post of after) {
|
|
321
|
+
if (!isUserPost(post)) {
|
|
322
|
+
if (isErrorPost(post)) {
|
|
323
|
+
const p = post;
|
|
324
|
+
return {
|
|
325
|
+
status: "failed",
|
|
326
|
+
progress: null,
|
|
327
|
+
error: (_a = str(p.message)) != null ? _a : "The build failed."
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
const fragment = readFragment(post);
|
|
331
|
+
if (fragment && (fragment.sandboxUrl || fragment.liveUrl) && !isThinkingPost(post)) {
|
|
332
|
+
return {
|
|
333
|
+
status: "done",
|
|
334
|
+
progress: null,
|
|
335
|
+
error: null
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
progress = (_b = progressText(post)) != null ? _b : progress;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const newest = after.filter((post) => !isUserPost(post)).pop();
|
|
342
|
+
if (newest && !isThinkingPost(newest) && !progressText(newest) && str(newest.message)) {
|
|
343
|
+
return {
|
|
344
|
+
status: "done",
|
|
345
|
+
progress: null,
|
|
346
|
+
error: null
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
status: "running",
|
|
351
|
+
progress,
|
|
352
|
+
error: null
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function hasWorkflowPosts(posts) {
|
|
356
|
+
return posts.some((post) => readFragment(post) !== null);
|
|
357
|
+
}
|
|
358
|
+
function stripAgentNote(content) {
|
|
359
|
+
return content.replace(/\n*\[Template\][\s\S]*$/, "").trim();
|
|
360
|
+
}export{DEFAULT_TEMPLATE,buildsFromPosts,cacheBustedUrl,cleanPrompt,coverDisplayUrl,displayHost,hasWorkflowPosts,isErrorPost,isGenericTitle,isThinkingPost,isValidPublishSlug,lastMessageHasCover,pendingWork,progressText,projectFromPosts,publishSlug,readFragment,relativeTime,resolveSiteTitle,sandboxPreviewUrl,stripAgentNote,titleFromPrompt,transcriptFromPosts,turnState};//# sourceMappingURL=buildFragments.js.map
|