import { create } from 'zustand'; import { devtools, persist, createJSONStorage } from 'zustand/middleware'; import { getSafeStorage } from './utils/safeStorage'; export type InlineCommentSource = 'diff' | 'plan' | 'file'; export interface InlineCommentDraft { id: string; sessionKey: string; // sessionId or 'draft' for new sessions source: InlineCommentSource; fileLabel: string; // filename or 'plan' startLine: number; endLine: number; side?: 'original' | 'modified'; // diff only code: string; language: string; text: string; createdAt: number; } interface InlineCommentDraftState { drafts: Record; // sessionKey -> drafts } interface InlineCommentDraftActions { addDraft: (draft: Omit) => void; updateDraft: (sessionKey: string, draftId: string, updates: Partial>) => void; removeDraft: (sessionKey: string, draftId: string) => void; clearDrafts: (sessionKey: string) => void; getDrafts: (sessionKey: string) => InlineCommentDraft[]; consumeDrafts: (sessionKey: string) => InlineCommentDraft[]; getDraftCount: (sessionKey: string) => number; hasDrafts: (sessionKey: string) => boolean; } type InlineCommentDraftStore = InlineCommentDraftState & InlineCommentDraftActions; export const useInlineCommentDraftStore = create()( devtools( persist( (set, get) => ({ drafts: {}, addDraft: (draft) => { const id = `icd-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`; const newDraft: InlineCommentDraft = { ...draft, id, createdAt: Date.now(), }; set((state) => { const currentDrafts = state.drafts[draft.sessionKey] ?? []; return { drafts: { ...state.drafts, [draft.sessionKey]: [...currentDrafts, newDraft], }, }; }); return id; }, updateDraft: (sessionKey, draftId, updates) => { set((state) => { const currentDrafts = state.drafts[sessionKey] ?? []; const newDrafts = currentDrafts.map((draft) => { if (draft.id !== draftId) { return draft; } return { ...draft, ...updates, }; }); return { drafts: { ...state.drafts, [sessionKey]: newDrafts, }, }; }); }, removeDraft: (sessionKey, draftId) => { set((state) => { const currentDrafts = state.drafts[sessionKey] ?? []; const newDrafts = currentDrafts.filter((d) => d.id !== draftId); if (newDrafts.length === 0) { const { [sessionKey]: _removed, ...rest } = state.drafts; void _removed; return { drafts: rest }; } return { drafts: { ...state.drafts, [sessionKey]: newDrafts, }, }; }); }, clearDrafts: (sessionKey) => { set((state) => { const { [sessionKey]: _removed, ...rest } = state.drafts; void _removed; return { drafts: rest }; }); }, getDrafts: (sessionKey) => { return get().drafts[sessionKey] ?? []; }, consumeDrafts: (sessionKey) => { const drafts = get().drafts[sessionKey] ?? []; if (drafts.length === 0) return []; // Sort by creation time to maintain order const sortedDrafts = [...drafts].sort((a, b) => a.createdAt - b.createdAt); // Clear drafts after consuming set((state) => { const { [sessionKey]: _removed, ...rest } = state.drafts; void _removed; return { drafts: rest }; }); return sortedDrafts; }, getDraftCount: (sessionKey) => { return (get().drafts[sessionKey] ?? []).length; }, hasDrafts: (sessionKey) => { return (get().drafts[sessionKey] ?? []).length > 0; }, }), { name: 'openchamber-inline-comment-drafts', storage: createJSONStorage(() => getSafeStorage()), } ), { name: 'inline-comment-draft-store' } ) ); export default useInlineCommentDraftStore;