import { useState, useCallback, useEffect, useRef } from "react"; const STORAGE_KEY = "forge-editor-state"; interface PersistedState { openTabs: string[]; activeTab: string | null; } function loadPersistedState(): PersistedState { try { const raw = localStorage.getItem(STORAGE_KEY); if (raw) { const parsed = JSON.parse(raw); return { openTabs: Array.isArray(parsed.openTabs) ? parsed.openTabs : [], activeTab: typeof parsed.activeTab === "string" ? parsed.activeTab : null, }; } } catch { // corrupted storage — start fresh } return { openTabs: [], activeTab: null }; } function persistState(state: PersistedState) { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } catch { // quota exceeded — silently ignore } } export function useEditorState() { const [openTabs, setOpenTabs] = useState( () => loadPersistedState().openTabs, ); const [activeTab, setActiveTab] = useState( () => loadPersistedState().activeTab, ); const [dirtyFiles, setDirtyFiles] = useState>(new Set()); const fileContents = useRef>(new Map()); useEffect(() => { persistState({ openTabs, activeTab }); }, [openTabs, activeTab]); const openFile = useCallback( (path: string, content?: string) => { if (content !== undefined) { fileContents.current.set(path, content); } setOpenTabs((prev) => { if (prev.includes(path)) return prev; return [...prev, path]; }); setActiveTab(path); }, [], ); const closeFile = useCallback( (path: string) => { setOpenTabs((prev) => { const next = prev.filter((p) => p !== path); setActiveTab((current) => { if (current !== path) return current; const idx = prev.indexOf(path); return next[Math.min(idx, next.length - 1)] ?? null; }); return next; }); setDirtyFiles((prev) => { const next = new Set(prev); next.delete(path); return next; }); fileContents.current.delete(path); }, [], ); const selectTab = useCallback((path: string) => { setActiveTab(path); }, []); const markDirty = useCallback((path: string) => { setDirtyFiles((prev) => { if (prev.has(path)) return prev; return new Set(prev).add(path); }); }, []); const markClean = useCallback((path: string) => { setDirtyFiles((prev) => { if (!prev.has(path)) return prev; const next = new Set(prev); next.delete(path); return next; }); }, []); const updateContent = useCallback( (path: string, content: string) => { fileContents.current.set(path, content); markDirty(path); }, [markDirty], ); const getContent = useCallback((path: string): string | undefined => { return fileContents.current.get(path); }, []); return { openTabs, activeTab, dirtyFiles, openFile, closeFile, selectTab, markDirty, markClean, updateContent, getContent, }; }