/** * Lazy-loaded offline runtime chunk. * * Contains Automerge + WASM (~2.5MB) — split from shell.ts so the main * shell bundle stays small and doesn't block first paint. */ import { RStackHistoryPanel } from "../shared/components/rstack-history-panel"; import { RSpaceOfflineRuntime } from "../shared/local-first/runtime"; import { CommunitySync } from "../lib/community-sync"; import { OfflineStore } from "../lib/offline-store"; // Define the history panel component (depends on Automerge) RStackHistoryPanel.define(); export function initOffline(spaceSlug: string) { const runtime = new RSpaceOfflineRuntime(spaceSlug); (window as any).__rspaceOfflineRuntime = runtime; // Configure module scope resolution from server-rendered data try { const scopeJson = document.body?.getAttribute("data-scope-overrides"); const overrides: Record = scopeJson ? JSON.parse(scopeJson) : {}; const moduleList: Array<{ id: string; scoping?: { defaultScope: string } }> = (window as any).__rspaceModuleList || []; const scopes: Array<{ id: string; scope: 'global' | 'space' }> = moduleList.map(m => ({ id: m.id, scope: (overrides[m.id] || m.scoping?.defaultScope || 'space') as 'global' | 'space', })); runtime.setModuleScopes(scopes); } catch { /* scope config unavailable — defaults to space-scoped */ } runtime.init().catch((e: unknown) => { console.warn("[shell] Offline runtime init failed — REST fallback only:", e); }); // Flush pending writes before the page unloads window.addEventListener("beforeunload", () => { runtime.flush(); }); // ── CommunitySync (tab list Automerge sync) ── const offlineStore = new OfflineStore(); const communitySync = new CommunitySync(spaceSlug, offlineStore); (window as any).__communitySync = communitySync; (async () => { try { await offlineStore.open(); await communitySync.initFromCache(); } catch (e) { console.warn("[shell] CommunitySync cache init failed:", e); } document.dispatchEvent(new CustomEvent("community-sync-ready", { detail: { sync: communitySync, communitySlug: spaceSlug }, })); const proto = location.protocol === "https:" ? "wss:" : "ws:"; const wsUrl = `${proto}//${location.host}/ws/${spaceSlug}`; communitySync.connect(wsUrl); })(); window.addEventListener("beforeunload", () => { communitySync.saveBeforeUnload(); }); }