const authChannelName = "makers3d-auth"; const authTabIdKey = "makers3d-auth-tab"; export type AuthEventType = "login" | "logout"; function getTabId() { let tabId = window.sessionStorage.getItem(authTabIdKey); if (!tabId) { tabId = crypto.randomUUID(); window.sessionStorage.setItem(authTabIdKey, tabId); } return tabId; } export function notifyAuthChanged(type: AuthEventType) { if (typeof window === "undefined") { return; } const payload = JSON.stringify({ type, source: getTabId(), at: Date.now() }); if ("BroadcastChannel" in window) { const channel = new BroadcastChannel(authChannelName); channel.postMessage(payload); channel.close(); } window.localStorage.setItem(authChannelName, payload); } export function listenAuthChanged(callback: (type: AuthEventType) => void) { if (typeof window === "undefined") { return () => {}; } function handlePayload(payload: unknown) { if (typeof payload !== "string") { return; } try { const event = JSON.parse(payload) as { type?: AuthEventType; source?: string }; if (event.source === getTabId()) { return; } if (event.type === "login" || event.type === "logout") { callback(event.type); } } catch { // Ignore malformed cross-tab payloads. } } const channel = "BroadcastChannel" in window ? new BroadcastChannel(authChannelName) : null; channel?.addEventListener("message", (event) => handlePayload(event.data)); const storageListener = (event: StorageEvent) => { if (event.key === authChannelName) { handlePayload(event.newValue); } }; window.addEventListener("storage", storageListener); return () => { channel?.close(); window.removeEventListener("storage", storageListener); }; }