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);