fix: persist session banner dismissals and add hide-banner setting
- Stop overwriting AI session titles with the "Planning session" fallback during cross-tab broadcasts before initialPlan has hydrated on resume. - Persist SessionNotificationBanner dismissals to localStorage keyed by updatedAt so they survive refresh and auto-re-show on the next event. - Add Settings → Appearance toggle to hide the banner entirely. - Drop the inner scrollbar on the planning question list; let the outer pane handle all scrolling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
45
packages/dashboard/app/hooks/useSessionBannerPref.ts
Normal file
45
packages/dashboard/app/hooks/useSessionBannerPref.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { useSyncExternalStore } from "react";
|
||||
|
||||
const STORAGE_KEY = "fusion:hide-session-banners";
|
||||
const EVENT_NAME = "fusion:session-banner-pref-changed";
|
||||
|
||||
function read(): boolean {
|
||||
if (typeof window === "undefined") return false;
|
||||
try {
|
||||
return window.localStorage.getItem(STORAGE_KEY) === "1";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function subscribe(onChange: () => void): () => void {
|
||||
if (typeof window === "undefined") return () => {};
|
||||
const handleStorage = (e: StorageEvent) => {
|
||||
if (e.key === STORAGE_KEY) onChange();
|
||||
};
|
||||
const handleCustom = () => onChange();
|
||||
window.addEventListener("storage", handleStorage);
|
||||
window.addEventListener(EVENT_NAME, handleCustom);
|
||||
return () => {
|
||||
window.removeEventListener("storage", handleStorage);
|
||||
window.removeEventListener(EVENT_NAME, handleCustom);
|
||||
};
|
||||
}
|
||||
|
||||
export function setSessionBannersHidden(hidden: boolean): void {
|
||||
if (typeof window === "undefined") return;
|
||||
try {
|
||||
if (hidden) {
|
||||
window.localStorage.setItem(STORAGE_KEY, "1");
|
||||
} else {
|
||||
window.localStorage.removeItem(STORAGE_KEY);
|
||||
}
|
||||
window.dispatchEvent(new Event(EVENT_NAME));
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
export function useSessionBannersHidden(): boolean {
|
||||
return useSyncExternalStore(subscribe, read, () => false);
|
||||
}
|
||||
Reference in New Issue
Block a user