// Per-user customization of the filter sidebar: order of the widget cards, which are // collapsed, and which are hidden. Persisted to localStorage and the server-side // `preferences` blob so it follows the account. // `show`, `sort` and `content` moved to the feed toolbar (above the cards); they are no // longer sidebar widgets. normalizeLayout drops them from any persisted layout automatically. export type WidgetId = "date" | "language" | "topic" | "tags"; export const ALL_WIDGETS: WidgetId[] = ["date", "language", "topic", "tags"]; export const WIDGET_TITLES: Record = { date: "Upload date", language: "Language", topic: "Topic", tags: "Tags", }; export interface SidebarLayout { order: WidgetId[]; collapsed: Partial>; hidden: Partial>; } export const DEFAULT_LAYOUT: SidebarLayout = { order: [...ALL_WIDGETS], collapsed: {}, hidden: {}, }; const KEY = "subfeed.sidebarLayout"; // Tolerate stale/partial data: keep only known widgets and append any that are missing // (e.g. a widget added in a later version) so nothing silently disappears. export function normalizeLayout(raw: unknown): SidebarLayout { const r = (raw ?? {}) as Partial; const order: WidgetId[] = Array.isArray(r.order) ? (r.order.filter((x) => ALL_WIDGETS.includes(x as WidgetId)) as WidgetId[]) : []; for (const w of ALL_WIDGETS) if (!order.includes(w)) order.push(w); return { order, collapsed: { ...(r.collapsed ?? {}) }, hidden: { ...(r.hidden ?? {}) }, }; } export function loadLayout(): SidebarLayout { try { return normalizeLayout(JSON.parse(localStorage.getItem(KEY) || "{}")); } catch { return DEFAULT_LAYOUT; } } export function saveLayoutLocal(l: SidebarLayout): void { localStorage.setItem(KEY, JSON.stringify(l)); }