"use client"; import { useEffect, useId, useSyncExternalStore } from "react"; import { Sun } from "lucide-react"; import { toast } from "sonner"; import { useAppearance } from "@/lib/appearance/appearance"; import { Button } from "@/components/ui/button"; /** Remembered per device (spec 15.4): the notice is shown until it is closed or tried once. */ export const SUN_NOTICE_KEY = "apicore.notice.sun"; const SEEN = "seen"; const CHANGE_EVENT = "apicore:notice"; /** Closed in this visit; covers blocked storage (private mode). */ let seenThisVisit = false; function isSeen(): boolean { if (seenThisVisit) return true; try { return window.localStorage.getItem(SUN_NOTICE_KEY) === SEEN; } catch { return false; } } function markSeen(): void { seenThisVisit = true; try { window.localStorage.setItem(SUN_NOTICE_KEY, SEEN); } catch { // Not persisted - gone for this visit only. } window.dispatchEvent(new Event(CHANGE_EVENT)); } function subscribe(onChange: () => void): () => void { window.addEventListener(CHANGE_EVENT, onChange); window.addEventListener("storage", onChange); return () => { window.removeEventListener(CHANGE_EVENT, onChange); window.removeEventListener("storage", onChange); }; } /** * The notice unmounts on close; focus inside it would drop to (WCAG 2.4.3). It goes to * the page heading (h1 with tabIndex -1) instead. */ function keepFocus(): void { const heading = document.querySelector("main h1, h1"); heading?.focus(); } const TEXT = "Neu: Sonnenmodus für draußen – im Benutzermenü."; /** One-time hint on the start page: try the sun mode or close the hint. */ export function AppearanceNotice() { const textId = useId(); const { sunActive, setContrast } = useAppearance(); // The server never shows it, so a device that has seen it gets no flash after hydration. const seen = useSyncExternalStore(subscribe, isSeen, () => true); // Sun switched on elsewhere (user menu, device setting) means the hint has done its job. useEffect(() => { if (sunActive && !seen) markSeen(); }, [sunActive, seen]); if (seen || sunActive) return null; return ( ); }