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:
gsxdsm
2026-05-01 13:08:07 -07:00
parent 1c0a5dfd6d
commit 139b552036
7 changed files with 141 additions and 28 deletions

View 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);
}