import { useCallback, useMemo, useState } from "react"; import { initialSprints, initialWho } from "./analysis/facets.ts"; import type { LayoutStore } from "./components/BoardCanvas.tsx"; import * as st from "./storage.ts"; import type { BoardModel, Filters, JsonImport } from "./types.ts"; export interface BoardPrefsApi { filters: Filters; snap: boolean; table: boolean; problems: boolean; store: LayoutStore; toggle(name: st.FlagName | "snap" | "table" | "problems"): void; setSprints(s: Set): void; setWho(s: Set): void; toggleHidden(what: "kind" | "edge", value: string): void; toggleLane(name: string): void; moveLane(current: string[], name: string, to: number): void; setColWidth(date: string, w: number | null): void; resetLayout(): void; applyJson(r: JsonImport): void; } const readStore = (version: number): LayoutStore => ({ laneOrder: st.laneOrder(), folded: st.foldedSet(), colWidths: st.colWidths(), version }); const pick = (model: BoardModel, f: Filters) => ({ model, sprints: initialSprints(model, f, st.rememberedSprints()), who: initialWho(model, f, st.rememberedWho()) }); // настройки доски из хранилища links.html: флаги, скрытые виды и типы, выбор спринтов и исполнителей, раскладка export function useBoardPrefs(model: BoardModel): BoardPrefsApi { const [prefs, setPrefs] = useState(() => { st.migrateMode(); st.migrateStore(); return st.readPrefs(); }); const [store, setStore] = useState(() => readStore(0)); const [sel, setSel] = useState(() => pick(model, prefs.filters)); if (sel.model !== model) setSel(pick(model, prefs.filters)); // новая модель — выбор заново, как fillSprints/fillWho const bump = useCallback(() => setStore((s) => readStore(s.version + 1)), []); const filters = useMemo(() => ({ ...prefs.filters, sprints: sel.sprints, who: sel.who }), [prefs.filters, sel]); const toggle = useCallback((name: st.FlagName | "snap" | "table" | "problems") => { setPrefs((p) => { if (name === "snap" || name === "table" || name === "problems") { st.writeFlag(name, !p[name]); return { ...p, [name]: !p[name] }; } st.writeFlag(name, !p.filters[name]); return { ...p, filters: { ...p.filters, [name]: !p.filters[name] } }; }); }, []); const setSprints = useCallback((s: Set) => { st.writeSprints(s); setSel((x) => ({ ...x, sprints: new Set(s) })); }, []); const setWho = useCallback((s: Set) => { st.writeWho(s); setSel((x) => ({ ...x, who: new Set(s) })); }, []); const toggleHidden = useCallback((what: "kind" | "edge", value: string) => { setPrefs((p) => { const key = what === "kind" ? "hideKind" : "hideEdge"; const next = new Set(p.filters[key]); if (next.has(value)) next.delete(value); else next.add(value); const filters = { ...p.filters, [key]: next }; st.writeHidden(filters.hideKind, filters.hideEdge); return { ...p, filters }; }); }, []); const toggleLane = useCallback((name: string) => { st.toggleLane(name); bump(); }, [bump]); const moveLane = useCallback((current: string[], name: string, to: number) => { if (st.moveLane(current, name, to)) bump(); }, [bump]); const setColWidth = useCallback((date: string, w: number | null) => { st.setColWidth(date, w); bump(); }, [bump]); const resetLayout = useCallback(() => { st.resetLayout(prefs.filters.byDate); bump(); }, [prefs.filters.byDate, bump]); const applyJson = useCallback((r: JsonImport) => { const patch = st.applyJsonSettings(r); setPrefs((p) => ({ ...p, filters: { ...p.filters, ...patch } })); setSel(pick(model, { ...prefs.filters, ...patch })); bump(); }, [model, prefs.filters, bump]); return { filters, snap: prefs.snap, table: prefs.table, problems: prefs.problems, store, toggle, setSprints, setWho, toggleHidden, toggleLane, moveLane, setColWidth, resetLayout, applyJson }; }