import type { UploadedEditorImage } from "./im-editor-image" export type MessageEditorDraft = { html: string revision: number objectUrls: Set uploadedImages: Map } type PendingDraftSend = { key: string draft: MessageEditorDraft revision: number } /** In-memory only: neither messages nor temporary image URLs belong in storage. */ export function createMessageEditorDraftStore() { const drafts = new Map() let pendingSend: PendingDraftSend | null = null let scope: string | undefined const sendingListeners = new Set<() => void>() const notifySending = () => { for (const listener of sendingListeners) listener() } const listeners = new Set<(draft: MessageEditorDraft) => void>() const notify = (draft: MessageEditorDraft) => { for (const listener of listeners) listener(draft) } function release(draft: MessageEditorDraft) { for (const url of draft.objectUrls) URL.revokeObjectURL(url) draft.objectUrls.clear() draft.uploadedImages.clear() } function clear() { for (const draft of drafts.values()) release(draft) drafts.clear() pendingSend = null notifySending() } return { clear, notify, subscribe(listener: (draft: MessageEditorDraft) => void) { listeners.add(listener) return () => { listeners.delete(listener) } }, isSending() { return pendingSend !== null }, subscribeSending(listener: () => void) { sendingListeners.add(listener) return () => { sendingListeners.delete(listener) } }, setScope(nextScope: string) { if (scope !== nextScope) { clear() scope = nextScope } }, get(key: string): MessageEditorDraft { let draft = drafts.get(key) if (!draft) { draft = { html: "", revision: 0, objectUrls: new Set(), uploadedImages: new Map() } drafts.set(key, draft) } return draft }, contains(key: string, draft: MessageEditorDraft) { return drafts.get(key) === draft }, update(draft: MessageEditorDraft, html: string) { draft.html = html draft.revision += 1 }, beginSend(key: string): PendingDraftSend | null { const draft = drafts.get(key) if (!draft || pendingSend) return null pendingSend = { key, draft, revision: draft.revision } notifySending() return pendingSend }, finishSend(sent: PendingDraftSend, succeeded: boolean) { if (pendingSend !== sent) return false pendingSend = null notifySending() if (!succeeded || drafts.get(sent.key) !== sent.draft || sent.draft.revision !== sent.revision) { return false } sent.draft.html = "" sent.draft.revision += 1 release(sent.draft) notify(sent.draft) return true }, } } export type MessageEditorDraftStore = ReturnType