()
| 29 | import { HubView } from './views/HubView'; |
| 30 | |
| 31 | export function App() { |
| 32 | const t = useT(); |
| 33 | const config = useCodesignStore((s) => s.config); |
| 34 | const configLoaded = useCodesignStore((s) => s.configLoaded); |
| 35 | const loadConfig = useCodesignStore((s) => s.loadConfig); |
| 36 | const loadDesigns = useCodesignStore((s) => s.loadDesigns); |
| 37 | const syncGenerationStatus = useCodesignStore((s) => s.syncGenerationStatus); |
| 38 | const switchDesign = useCodesignStore((s) => s.switchDesign); |
| 39 | const setView = useCodesignStore((s) => s.setView); |
| 40 | const view = useCodesignStore((s) => s.view); |
| 41 | const previousView = useCodesignStore((s) => s.previousView); |
| 42 | const designsViewOpen = useCodesignStore((s) => s.designsViewOpen); |
| 43 | const closeDesignsView = useCodesignStore((s) => s.closeDesignsView); |
| 44 | const createNewDesign = useCodesignStore((s) => s.createNewDesign); |
| 45 | const designToDelete = useCodesignStore((s) => s.designToDelete); |
| 46 | const designToRename = useCodesignStore((s) => s.designToRename); |
| 47 | const requestDeleteDesign = useCodesignStore((s) => s.requestDeleteDesign); |
| 48 | const requestRenameDesign = useCodesignStore((s) => s.requestRenameDesign); |
| 49 | const interactionMode = useCodesignStore((s) => s.interactionMode); |
| 50 | const setInteractionMode = useCodesignStore((s) => s.setInteractionMode); |
| 51 | const _sidebarCollapsed = useCodesignStore((s) => s.sidebarCollapsed); |
| 52 | const activeReportLocalId = useCodesignStore((s) => s.activeReportLocalId); |
| 53 | const closeReportDialog = useCodesignStore((s) => s.closeReportDialog); |
| 54 | |
| 55 | const [prefillPrompt, setPrefillPrompt] = useState<{ id: number; text: string } | null>(null); |
| 56 | const [sidebarWidth, setSidebarWidth] = useState(() => |
| 57 | Math.max(320, Math.round(window.innerWidth * 0.25)), |
| 58 | ); |
| 59 | const [isResizing, setIsResizing] = useState(false); |
| 60 | |
| 61 | const [updateStore] = useState(() => createUpdateStore({ dismissedVersion: '' })); |
| 62 | useUpdateWiring(updateStore); |
| 63 | useAgentStream(); |
| 64 | |
| 65 | useEffect(() => { |
| 66 | if (!window.codesign) { |
| 67 | updateStore.getState().markDismissedVersionReady(''); |
| 68 | return; |
| 69 | } |
| 70 | window.codesign.preferences |
| 71 | .get() |
| 72 | .then((prefs) => { |
| 73 | updateStore.getState().markDismissedVersionReady(prefs.dismissedUpdateVersion ?? ''); |
| 74 | }) |
| 75 | .catch((err) => { |
| 76 | console.warn('[App] failed to seed dismissedUpdateVersion', err); |
| 77 | updateStore.getState().markDismissedVersionReady(''); |
| 78 | }); |
| 79 | }, [updateStore]); |
| 80 | // Once the user has visited Hub we keep HubView mounted (toggled via |
| 81 | // `hidden`) so going Workspace → Hub doesn't tear down the design-card |
| 82 | // iframes and pay the srcDoc parse cost again. |
| 83 | const [hubMounted, setHubMounted] = useState(view === 'hub'); |
| 84 | useEffect(() => { |
| 85 | if (view === 'hub') setHubMounted(true); |
| 86 | }, [view]); |
| 87 | // Same trick for workspace — once visited, keep PreviewPane mounted so the |
| 88 | // iframe pool survives Workspace ↔ Hub round trips. Without this, the pool |
nothing calls this directly
no test coverage detected