diff --git a/apps/client-standalone/src/main.ts b/apps/client-standalone/src/main.ts index 22c7eb279..9be9186d8 100644 --- a/apps/client-standalone/src/main.ts +++ b/apps/client-standalone/src/main.ts @@ -15,7 +15,7 @@ async function waitForServiceWorkerControl(): Promise { // Register service worker const registration = await navigator.serviceWorker.register("./sw.js", { scope: "/" }); - + // Wait for it to be ready (installed + activated) await navigator.serviceWorker.ready; @@ -28,40 +28,40 @@ async function waitForServiceWorkerControl(): Promise { // If not controlling yet, we need to reload the page for SW to take control // This is standard PWA behavior on first install console.log("[Bootstrap] Service worker installed but not controlling yet - reloading page"); - + // Wait a tiny bit for SW to fully activate await new Promise(resolve => setTimeout(resolve, 100)); - + // Reload to let SW take control window.location.reload(); - + // Throw to stop execution (page will reload) throw new Error("Reloading for service worker activation"); } async function fetchWithRetry(url: string, maxRetries = 3, delayMs = 500): Promise { let lastError: Error | null = null; - + for (let attempt = 0; attempt < maxRetries; attempt++) { try { console.log(`[Bootstrap] Fetching ${url} (attempt ${attempt + 1}/${maxRetries})`); const response = await fetch(url); - + if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } - + // Check if response has content const contentType = response.headers.get("content-type"); if (!contentType || !contentType.includes("application/json")) { throw new Error(`Invalid content-type: ${contentType || "none"}`); } - + return response; } catch (err) { lastError = err as Error; console.warn(`[Bootstrap] Fetch attempt ${attempt + 1} failed:`, err); - + if (attempt < maxRetries - 1) { // Exponential backoff const delay = delayMs * Math.pow(2, attempt); @@ -70,7 +70,7 @@ async function fetchWithRetry(url: string, maxRetries = 3, delayMs = 500): Promi } } } - + throw new Error(`Failed to fetch ${url} after ${maxRetries} attempts: ${lastError?.message}`); } @@ -88,12 +88,6 @@ async function bootstrap() { // 3) Wait for service worker to control the page (may reload on first install) await waitForServiceWorkerControl(); - // 4) Now fetch bootstrap - SW is guaranteed to intercept this - await setupGlob(); - - loadStylesheets(); - loadIcons(); - setBodyAttributes(); await loadScripts(); } catch (err) { // If error is from reload, it will stop here (page reloads) @@ -102,7 +96,7 @@ async function bootstrap() { // Page is reloading, do nothing return; } - + console.error("[Bootstrap] Fatal error:", err); document.body.innerHTML = `
@@ -118,72 +112,8 @@ async function bootstrap() { } } -async function setupGlob() { - const response = await fetchWithRetry("/bootstrap"); - console.log("Service worker state", navigator.serviceWorker.controller); - console.log("Resp", response); - const json = await response.json(); - console.log("Bootstrap", json); - - window.glob = { - ...json, - activeDialog: null - }; -} - -function loadStylesheets() { - const { assetPath, themeCssUrl, themeUseNextAsBase } = window.glob; - const cssToLoad = []; - cssToLoad.push(`${assetPath}/stylesheets/theme-light.css`); - if (themeCssUrl) { - cssToLoad.push(themeCssUrl); - } - if (themeUseNextAsBase === "next") { - cssToLoad.push(`${assetPath}/stylesheets/theme-next.css`) - } else if (themeUseNextAsBase === "next-dark") { - cssToLoad.push(`${assetPath}/stylesheets/theme-next-dark.css`) - } else if (themeUseNextAsBase === "next-light") { - cssToLoad.push(`${assetPath}/stylesheets/theme-next-light.css`) - } - cssToLoad.push(`${assetPath}/stylesheets/style.css`); - - for (const href of cssToLoad) { - const linkEl = document.createElement("link"); - linkEl.href = href; - linkEl.rel = "stylesheet"; - document.body.appendChild(linkEl); - } -} - -function loadIcons() { - const styleEl = document.createElement("style"); - styleEl.innerText = window.glob.iconPackCss; - document.head.appendChild(styleEl); -} - -function setBodyAttributes() { - const { device, headingStyle, layoutOrientation, platform, isElectron, hasNativeTitleBar, hasBackgroundEffects, currentLocale } = window.glob; - const classesToSet = [ - device, - `heading-style-${headingStyle}`, - `layout-${layoutOrientation}`, - `platform-${platform}`, - isElectron && "isElectron", - hasNativeTitleBar && "native-titlebar", - hasBackgroundEffects && "background-effects" - ].filter(Boolean); - - for (const classToSet of classesToSet) { - document.body.classList.add(classToSet); - } - - document.body.lang = currentLocale.id; - document.body.dir = currentLocale.rtl ? "rtl" : "ltr"; -} - async function loadScripts() { - await import("./runtime.js"); - await import("./desktop.js"); + await import("../../client/src/index.js"); } bootstrap(); diff --git a/apps/client-standalone/src/runtime.ts b/apps/client-standalone/src/runtime.ts deleted file mode 100644 index d2a2dfe77..000000000 --- a/apps/client-standalone/src/runtime.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Re-export runtime from client -export * from "../../client/src/runtime";