86 lines
3.3 KiB
TypeScript
86 lines
3.3 KiB
TypeScript
/**
|
|
* Shell entry point — loaded on every page.
|
|
*
|
|
* Registers the three header web components:
|
|
* <rstack-app-switcher>
|
|
* <rstack-space-switcher>
|
|
* <rstack-identity>
|
|
*/
|
|
|
|
import { RStackIdentity } from "../shared/components/rstack-identity";
|
|
import { RStackNotificationBell } from "../shared/components/rstack-notification-bell";
|
|
import { RStackAppSwitcher } from "../shared/components/rstack-app-switcher";
|
|
import { RStackSpaceSwitcher } from "../shared/components/rstack-space-switcher";
|
|
import { RStackTabBar } from "../shared/components/rstack-tab-bar";
|
|
import { RStackMi } from "../shared/components/rstack-mi";
|
|
|
|
import { RStackModuleSetup } from "../shared/components/rstack-module-setup";
|
|
import { RStackOfflineIndicator } from "../shared/components/rstack-offline-indicator";
|
|
import { RStackSharePanel } from "../shared/components/rstack-share-panel";
|
|
import { RStackCommentBell } from "../shared/components/rstack-comment-bell";
|
|
import { RStackCollabOverlay } from "../shared/components/rstack-collab-overlay";
|
|
import { RStackUserDashboard } from "../shared/components/rstack-user-dashboard";
|
|
import { rspaceNavUrl } from "../shared/url-helpers";
|
|
import { TabCache } from "../shared/tab-cache";
|
|
|
|
// Expose URL helper globally (used by shell inline scripts + components)
|
|
(window as any).__rspaceNavUrl = rspaceNavUrl;
|
|
|
|
// Expose TabCache for inline shell script to instantiate
|
|
(window as any).__RSpaceTabCache = TabCache;
|
|
|
|
// Register all header components
|
|
RStackIdentity.define();
|
|
RStackNotificationBell.define();
|
|
RStackAppSwitcher.define();
|
|
RStackSpaceSwitcher.define();
|
|
RStackTabBar.define();
|
|
RStackMi.define();
|
|
|
|
RStackModuleSetup.define();
|
|
RStackOfflineIndicator.define();
|
|
RStackSharePanel.define();
|
|
RStackCommentBell.define();
|
|
RStackCollabOverlay.define();
|
|
RStackUserDashboard.define();
|
|
|
|
// ── Offline Runtime (lazy-loaded) ──
|
|
// Automerge + WASM (~2.5MB) loaded in a separate chunk to avoid blocking first paint.
|
|
// Components that depend on window.__rspaceOfflineRuntime already handle late init.
|
|
const spaceSlug = document.body?.getAttribute("data-space-slug");
|
|
if (spaceSlug) {
|
|
import('./shell-offline').then(m => m.initOffline(spaceSlug)).catch(e => {
|
|
console.warn("[shell] Failed to load offline chunk:", e);
|
|
});
|
|
}
|
|
|
|
// ── Track space visits for dashboard recency sorting ──
|
|
if (spaceSlug) {
|
|
try {
|
|
const RECENT_KEY = "rspace_recent_spaces";
|
|
const visits = JSON.parse(localStorage.getItem(RECENT_KEY) || "{}");
|
|
visits[spaceSlug] = Date.now();
|
|
localStorage.setItem(RECENT_KEY, JSON.stringify(visits));
|
|
} catch { /* localStorage unavailable */ }
|
|
}
|
|
|
|
// Reload space list when user signs in/out (to show/hide private spaces)
|
|
document.addEventListener("auth-change", (e) => {
|
|
const reason = (e as CustomEvent).detail?.reason;
|
|
|
|
// Token refreshes are invisible — no UI side-effects needed
|
|
if (reason === "refresh") return;
|
|
|
|
// Reload space switcher on state-changing events
|
|
const spaceSwitcher = document.querySelector("rstack-space-switcher") as any;
|
|
spaceSwitcher?.reload?.();
|
|
|
|
// Only redirect to homepage on genuine sign-out or server revocation
|
|
if (reason === "signout" || reason === "revoked") {
|
|
window.location.href = "/";
|
|
}
|
|
});
|
|
|
|
// SW update banner is handled by the inline script in server/shell.ts
|
|
// (single #pwa-update-banner element, no duplicate)
|