Addresses "the floating Sasquatch flashing is annoying": - Pulse is now state-driven: the animate-ping halo shows only when there's an unread tip (message), never perpetually; the unread dot matches. - Honors prefers-reduced-motion (motion-reduce:hidden). - Map-aware: Layout passes isFullBleed, so on the map the bubble runs compact (smaller, no glow, no pulse) instead of competing with map controls. - Hideable: a ✕ on the FAB hides it (useSasquatchHidden, localStorage sasquatch-hidden, same-tab synced via an event), with a "Show Sasquatch assistant" toggle in Settings → Appearance to bring it back.
31 lines
1 KiB
TypeScript
31 lines
1 KiB
TypeScript
import { useCallback, useEffect } from 'react';
|
|
import { useLocalStorage } from '@/hooks/useLocalStorage';
|
|
|
|
const KEY = 'sasquatch-hidden';
|
|
const EVENT = 'sasquatch:hiddenchange';
|
|
|
|
/**
|
|
* Whether the floating Sasquatch assistant is hidden. Device-local (like the
|
|
* other visibility prefs) and synced **within the same tab** via a custom event
|
|
* — `useLocalStorage` only syncs across tabs, so the Settings toggle and the
|
|
* guide itself need this bridge to stay in step.
|
|
*/
|
|
export function useSasquatchHidden(): [boolean, (value: boolean) => void] {
|
|
const [hidden, setHiddenRaw] = useLocalStorage(KEY, false);
|
|
|
|
useEffect(() => {
|
|
const handler = (e: Event) => setHiddenRaw(!!(e as CustomEvent<boolean>).detail);
|
|
window.addEventListener(EVENT, handler);
|
|
return () => window.removeEventListener(EVENT, handler);
|
|
}, [setHiddenRaw]);
|
|
|
|
const setHidden = useCallback(
|
|
(value: boolean) => {
|
|
setHiddenRaw(value);
|
|
window.dispatchEvent(new CustomEvent(EVENT, { detail: value }));
|
|
},
|
|
[setHiddenRaw],
|
|
);
|
|
|
|
return [hidden, setHidden];
|
|
}
|