52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import type { WorkbenchAlert } from "../types";
|
|
|
|
function readDismissed(key: string): string[] {
|
|
try {
|
|
const value: unknown = JSON.parse(localStorage.getItem(key) ?? "[]");
|
|
return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
function alertKey(alert: WorkbenchAlert): string {
|
|
return JSON.stringify([alert.id, alert.notificationVersion ?? null]);
|
|
}
|
|
|
|
export function useDismissedWorkbenchAlerts(
|
|
alerts: WorkbenchAlert[], projectId: string | null, username: string
|
|
) {
|
|
const storageKey = `tjwater.dismissed-alerts@1:${JSON.stringify([projectId, username])}`;
|
|
const [stored, setStored] = useState(() => ({ key: storageKey, ids: readDismissed(storageKey) }));
|
|
// Switch scopes synchronously so another user's or project's rows never flash hidden.
|
|
if (stored.key !== storageKey) {
|
|
setStored({ key: storageKey, ids: readDismissed(storageKey) });
|
|
}
|
|
|
|
useEffect(() => {
|
|
const sync = (event: StorageEvent) => {
|
|
if (event.storageArea === localStorage && (event.key === storageKey || event.key === null)) {
|
|
setStored({ key: storageKey, ids: readDismissed(storageKey) });
|
|
}
|
|
};
|
|
window.addEventListener("storage", sync);
|
|
return () => window.removeEventListener("storage", sync);
|
|
}, [storageKey]);
|
|
|
|
const dismissAlert = useCallback((alert: WorkbenchAlert) => {
|
|
if (!projectId) return false;
|
|
const ids = [...new Set([...readDismissed(storageKey), alertKey(alert)])];
|
|
try {
|
|
localStorage.setItem(storageKey, JSON.stringify(ids));
|
|
} catch {
|
|
return false;
|
|
}
|
|
setStored({ key: storageKey, ids });
|
|
return true;
|
|
}, [projectId, storageKey]);
|
|
|
|
const dismissed = new Set(stored.key === storageKey ? stored.ids : readDismissed(storageKey));
|
|
return { alerts: alerts.filter((alert) => !dismissed.has(alertKey(alert))), dismissAlert };
|
|
}
|