Persist sidebar collapsed preference to localStorage

This commit is contained in:
2026-04-21 19:17:00 +02:00
parent b3eb5dc6ec
commit 4f91e8fdd3
3 changed files with 53 additions and 7 deletions

View File

@@ -40,6 +40,7 @@ import { useBlocklistStatus } from "../hooks/useBlocklist";
const SIDEBAR_FULL = "240px";
const SIDEBAR_COLLAPSED = "48px";
const SIDEBAR_COLLAPSED_STORAGE_KEY = "bangui_sidebar_collapsed";
const useStyles = makeStyles({
root: {
@@ -220,23 +221,52 @@ export function MainLayout(): React.JSX.Element {
const styles = useStyles();
const { logout } = useAuth();
const navigate = useNavigate();
// Initialise collapsed based on screen width so narrow viewports start
// with the icon-only sidebar rather than the full-width one.
const [collapsed, setCollapsed] = useState(() => window.innerWidth < 640);
const readSavedCollapsed = (): boolean => {
try {
const savedValue = localStorage.getItem(SIDEBAR_COLLAPSED_STORAGE_KEY);
if (savedValue === "true") {
return true;
}
if (savedValue === "false") {
return false;
}
} catch {
// Ignore storage errors and fall back to viewport heuristics.
}
return window.innerWidth < 640;
};
const [collapsed, setCollapsed] = useState<boolean>(readSavedCollapsed);
const { status } = useServerStatus();
const { hasErrors: blocklistHasErrors } = useBlocklistStatus();
/** True only after the first successful poll and fail2ban is unreachable. */
const serverOffline = status !== null && !status.online;
// Auto-collapse / auto-expand when the viewport crosses the 640 px breakpoint.
useEffect(() => {
try {
localStorage.setItem(SIDEBAR_COLLAPSED_STORAGE_KEY, String(collapsed));
} catch {
// Local storage may be unavailable in some environments.
}
}, [collapsed]);
useEffect(() => {
const savedValue = localStorage.getItem(SIDEBAR_COLLAPSED_STORAGE_KEY);
if (savedValue !== null) {
return undefined;
}
const mq = window.matchMedia("(max-width: 639px)");
const handler = (e: MediaQueryListEvent): void => {
setCollapsed(e.matches);
};
mq.addEventListener("change", handler);
return (): void => { mq.removeEventListener("change", handler); };
return (): void => {
mq.removeEventListener("change", handler);
};
}, []);
const toggleCollapse = useCallback(() => {