import { StrictMode, Suspense, lazy } from 'react'; import ReactDOM from 'react-dom/client'; import '@fontsource/mona-sans/400.css'; import '@fontsource/mona-sans/500.css'; import '@fontsource/mona-sans/600.css'; import '@fontsource/mona-sans/700.css'; import '@fontsource/space-grotesk/400.css'; import '@fontsource/space-grotesk/500.css'; import '@fontsource/space-grotesk/600.css'; import '@fontsource/space-grotesk/700.css'; import '@fontsource/jetbrains-mono/400.css'; import '@fontsource/jetbrains-mono/500.css'; import '@fontsource/jetbrains-mono/600.css'; import App from './App'; import { AppLockGate } from './components/AppLockGate'; const LazySettingsPage = lazy(() => import('./components/SettingsPage')); const LazyTrayPanel = lazy(() => import('./components/TrayPanel')); const LazyTerminalPopupPage = lazy(() => import('./components/TerminalPopupPage')); function SettingsWindowFallback() { return (
{Array.from({ length: 7 }).map((_, index) => (
))}
{Array.from({ length: 6 }).map((_, index) => (
))}
); } function TerminalPopupWindowFallback() { return (
); } const rootElement = document.getElementById('root'); if (!rootElement) { throw new Error("Could not find root element to mount to"); } // Simple hash-based routing for separate windows const getRoute = () => { const hash = window.location.hash; if (hash === '#/settings' || hash.startsWith('#/settings')) { return 'settings'; } if (hash === '#/tray' || hash.startsWith('#/tray')) { return 'tray'; } if (hash === '#/terminal-popup' || hash.startsWith('#/terminal-popup')) { return 'terminal-popup'; } if (hash === '#/session-window' || hash.startsWith('#/session-window')) { return 'main'; } return 'main'; }; const root = ReactDOM.createRoot(rootElement); const syncTrayWindowClass = (route: string) => { const rootEl = document.documentElement; if (route === 'tray') { rootEl.classList.add('tray-window'); document.getElementById('splash')?.remove(); } else { rootEl.classList.remove('tray-window'); } }; const renderApp = () => { const route = getRoute(); const isPeerSessionWindow = window.location.hash.startsWith('#/session-window'); // Peer session windows must not drive the main window's settings IPC sync // and must not re-apply OS-level system settings effects (tray, global // shortcuts, …) — they follow the main window through the chrome stores. const settingsOptions = isPeerSessionWindow ? { enableSettingsSync: false, enableSystemEffects: false } : undefined; syncTrayWindowClass(route); if (route === 'settings') { root.render( {({ settings, appLock }) => ( }> )} ); } else if (route === 'tray') { root.render( {({ settings }) => ( }> )} ); } else if (route === 'terminal-popup') { // forceRenderChildren: main sends terminalPopupConfig immediately after // loadURL; the page must mount (and register onTerminalPopupConfig) without // waiting for async app-lock init. notifyRendererReady stays false — this // route is not on the deep-link readiness path. root.render( {({ settings, appLock }) => ( }> {/* forceRenderChildren mounts the page so config IPC registers while locked; defer starting the terminal until unlock (Codex P2). */} )} ); } else { root.render( {({ settings, appLock }) => } ); } }; // Initial render renderApp(); // Listen for hash changes window.addEventListener('hashchange', renderApp);