siftlode/frontend/src/lib/sidebarLayout.ts
npeter83 c2a2c98f16 chore: Phase 1 hygiene — drop unused imports/exports/types (behavior-neutral)
Machine-baseline harvest (ruff + knip), all tsc/parse-green, no runtime change:
- backend: remove 3 unused imports (channels/playlists/youtube) via ruff; drop the
  unused `job` binding in unshare_download (keep the _own_job ownership guard call).
- frontend: remove `export` from 23 internally-used-only symbols (knip "unused
  exports") to shrink the public surface; delete 2 genuinely-dead declarations
  (PlexBrowseResult — leftover from the removed /browse route; WIDGET_TITLES —
  hardcoded English titles superseded by i18n).

Held back for a decision (unused here = possibly-unwired, NOT dead — flagged, not
removed): e2ee.lock()/clearDevice() (security primitives never wired to logout / a
"forget device" feature) and loadDefaultViewFilters (App reimplements it inline — a
DRY issue). See siftlode-ops/CODE-HYGIENE.md.
2026-07-11 04:47:08 +02:00

46 lines
1.7 KiB
TypeScript

// 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.
import { LS, readAccount, writeAccount } from "./storage";
export type WidgetId = "savedviews" | "date" | "language" | "topic" | "tags";
const ALL_WIDGETS: WidgetId[] = ["savedviews", "date", "tags", "language", "topic"];
export interface SidebarLayout {
order: WidgetId[];
collapsed: Partial<Record<WidgetId, boolean>>;
hidden: Partial<Record<WidgetId, boolean>>;
}
export const DEFAULT_LAYOUT: SidebarLayout = {
order: [...ALL_WIDGETS],
collapsed: {},
hidden: {},
};
// 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<SidebarLayout>;
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 {
return normalizeLayout(readAccount<unknown>(LS.sidebarLayout, {}));
}
export function saveLayoutLocal(l: SidebarLayout): void {
writeAccount(LS.sidebarLayout, l);
}