import { useCallback, useEffect, useRef, useState } from "react"; import type { Message } from "../types"; const STORAGE_KEY_PREFIX = "storykit-chat-history:"; function storageKey(projectPath: string): string { return `${STORAGE_KEY_PREFIX}${projectPath}`; } function loadMessages(projectPath: string): Message[] { try { const raw = localStorage.getItem(storageKey(projectPath)); if (!raw) return []; const parsed: unknown = JSON.parse(raw); if (!Array.isArray(parsed)) return []; return parsed as Message[]; } catch { return []; } } function saveMessages(projectPath: string, messages: Message[]): void { try { if (messages.length === 0) { localStorage.removeItem(storageKey(projectPath)); } else { localStorage.setItem(storageKey(projectPath), JSON.stringify(messages)); } } catch (e) { console.warn("Failed to persist chat history to localStorage:", e); } } export function useChatHistory(projectPath: string) { const [messages, setMessagesState] = useState(() => loadMessages(projectPath), ); const projectPathRef = useRef(projectPath); // Keep the ref in sync so the effect closure always has the latest path. projectPathRef.current = projectPath; // Persist whenever messages change. useEffect(() => { saveMessages(projectPathRef.current, messages); }, [messages]); const setMessages = useCallback( (update: Message[] | ((prev: Message[]) => Message[])) => { setMessagesState(update); }, [], ); const clearMessages = useCallback(() => { setMessagesState([]); // Eagerly remove from storage so clearSession doesn't depend on the // effect firing before the component unmounts or re-renders. try { localStorage.removeItem(storageKey(projectPathRef.current)); } catch { // Ignore — quota or security errors. } }, []); return { messages, setMessages, clearMessages } as const; }