rspace-online/website/shell-offline.ts

67 lines
2.3 KiB
TypeScript

/**
* 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<string, string> = 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();
});
}