import { type ArkmeTextFormat } from '../markdown.js'; import type { ArkmeMarkdownDraft } from './markdown-editor.js'; import { type ArkmeComposerExtensionTarget } from './composer-extension-target.js'; import type { ArkmeTimelineItem, ArkmeSourceItem, ArkmeUploadedAsset } from '../types.js'; import type { ArkmeLocalFile } from '../file-transfer-contract.js'; import { type ArkmeEmoji } from './arkme-emoji.js'; export interface ArkmeAttachmentPreparation extends Omit { id: string; state: 'queued' | 'preparing' | 'failed'; error?: string; retry(): void; cancel(): void; } export type ArkmeComposerAttachment = ({ asset: ArkmeUploadedAsset; localFile?: never; preparation?: never; } | { localFile: ArkmeLocalFile; asset?: never; preparation?: never; } | { preparation: ArkmeAttachmentPreparation; asset?: never; localFile?: never; }) & { previewUrl?: string; clientId?: string; }; export declare function arkmeAttachmentId(item: ArkmeComposerAttachment): string; export declare function arkmeAttachmentMetadata(item: ArkmeComposerAttachment): Omit; export declare function arkmeAttachmentsPending(attachments: readonly ArkmeComposerAttachment[]): boolean; export interface ArkmeComposerMention { originalIndex?: number; mentionRef?: string; botRef?: string; all?: boolean; displayName: string; startIndex: number; length: number; } export interface ArkmeComposerEmoji { emojiId: string; startIndex: number; } export interface ArkmeComposerDraftSnapshot { /** Last content edit, preserved when hydrating, replicating or restoring a failed send. */ editedAtMillis?: number; /** Last departure after editing. Zero means this draft has not left its conversation yet. */ leftAtMillis?: number; extensionTarget?: ArkmeComposerExtensionTarget; markdown?: ArkmeMarkdownDraft; text: string; attachments: readonly ArkmeComposerAttachment[]; mentions: readonly ArkmeComposerMention[]; emojis: readonly ArkmeComposerEmoji[]; fileSendIdentity?: { recordUid: string; relationUid: string; fingerprint: string; sendAtMillis?: number; }; } export type ArkmeComposerDeleteDirection = 'backward' | 'forward'; export interface ArkmeComposerAtomicDeletion { text: string; caretIndex: number; } export interface ArkmeComposerMentionInsertion { text: string; mentions: ArkmeComposerMention[]; emojis: ArkmeComposerEmoji[]; caretIndex: number; } export declare function arkmeDraftEditedAtMillis(draft: ArkmeComposerDraftSnapshot): number; export declare function arkmeDraftActivityAtMillis(draft: ArkmeComposerDraftSnapshot): number; export declare const ARKME_COMPOSER_EMOJI_PLACEHOLDER = "\uFFFC"; /** Decode the persisted wire text without sharing any conversation's draft owner. */ export declare function arkmeComposerDraftFromText(value: string): ArkmeComposerDraftSnapshot; /** Pure edit used by both the Chat draft store and independently owned composers. */ export declare function insertArkmeComposerEmoji(current: ArkmeComposerDraftSnapshot, emoji: Pick, selectionStart: number, selectionEnd?: number, maxSerializedLength?: number): { snapshot: ArkmeComposerDraftSnapshot; caretIndex: number; } | undefined; export declare function reconcileArkmeComposerMentions(previousText: string, nextText: string, mentions: readonly ArkmeComposerMention[], textFormat?: ArkmeTextFormat): ArkmeComposerMention[]; /** Preserve atom identity when the editor provides an exact replacement range. */ export declare function replaceArkmeComposerEmojiSelection(emojis: readonly ArkmeComposerEmoji[], start: number, end: number, insertedLength: number): ArkmeComposerEmoji[]; export declare function reconcileArkmeComposerEmojis(previousText: string, nextText: string, emojis: readonly ArkmeComposerEmoji[]): ArkmeComposerEmoji[]; export interface ArkmeSerializedComposerDraft { textFormat?: 'plain' | 'markdown'; text: string; mentions: readonly ArkmeComposerMention[]; } export declare function serializeArkmeComposerDraft(snapshot: ArkmeComposerDraftSnapshot): ArkmeSerializedComposerDraft; /** Expands a native text deletion to complete mention ranges so mentions behave as atomic inline objects. */ export declare function arkmeComposerAtomicDeletion(text: string, mentions: readonly ArkmeComposerMention[], selectionStart: number, selectionEnd: number, direction: ArkmeComposerDeleteDirection): ArkmeComposerAtomicDeletion | undefined; export declare function insertArkmeComposerMentionToken(snapshot: Pick, mention: Pick, displayName: string, selectionStart: number, selectionEnd?: number, textFormat?: ArkmeTextFormat): ArkmeComposerMentionInsertion | undefined; export declare function arkmeComposerCanSend(text: string, attachmentCount: number, busy: boolean): boolean; export declare function arkmeSourceComposerDraftKey(userId: number | undefined, source: Pick | undefined): string | undefined; export declare function arkmeArkoComposerDraftKey(userId: number | undefined): string | undefined; export declare function releaseArkmeComposerAttachment(attachment: ArkmeComposerAttachment): void; export declare function releaseArkmeComposerDraft(snapshot: ArkmeComposerDraftSnapshot): void; export declare class ArkmeComposerDraftStore { private readonly storage?; private readonly drafts; private readonly listeners; private readonly persisted; private nativePersistence; private lastPersisted; private pendingPersisted; private revision; private readonly changeRevisions; private readonly contentEditRevisions; private readonly departures; private contentEditRevision; private readonly restoredKeys; isRestored(key: string | undefined): boolean; beginFileSend(key: string, submissionScope?: string): { recordUid: string; relationUid: string; sendAtMillis?: number; }; private static readonly storageKey; constructor(storage?: Pick | undefined); /** Native files become the authority; browser data is read only for migration. */ useNativePersistence(): void; confirmNativeSave(key: string): void; /** A per-key snapshot for desktop replication; includes ordinary text drafts. */ entries(): ReadonlyMap; applyRemote(key: string, value: unknown): void; readonly getRevision: () => number; /** Session-local edit order for aggregate previews; restored drafts do not become new activity. */ getChangeRevision(key: string | undefined): number; getContentEditRevision(key: string): number; markConversationLeft(key: string, atMillis: number): void; readonly subscribe: (listener: (key?: string, reason?: "evict") => void) => (() => void); get(key: string | undefined): ArkmeComposerDraftSnapshot; setExtensionTarget(key: string | undefined, item: ArkmeTimelineItem | undefined, quote?: import('../message-quote.js').ArkmeMessageQuote): void; setMarkdown(key: string | undefined, markdown: ArkmeMarkdownDraft, text: string, mentions: readonly ArkmeComposerMention[], emojis: readonly ArkmeComposerEmoji[]): void; setText(key: string | undefined, text: string, emojis?: readonly ArkmeComposerEmoji[]): void; /** Atomic text-editor projection, including emoji restored by undo/redo. */ setRichText(key: string | undefined, text: string, emojis: readonly ArkmeComposerEmoji[]): void; insertEmoji(key: string | undefined, emoji: Pick, selectionStart: number, selectionEnd?: number, maxSerializedLength?: number): number | undefined; private insertMentionToken; insertMention(key: string | undefined, mentionRef: string, displayName: string, selectionStart: number, selectionEnd?: number): number | undefined; insertHashTag(key: string | undefined, tagName: string, selectionStart: number, selectionEnd?: number): number | undefined; insertAllMention(key: string | undefined, selectionStart: number, selectionEnd?: number): number | undefined; insertBotMention(key: string | undefined, botRef: string, displayName: string, selectionStart: number, selectionEnd?: number): number | undefined; deleteMentionAtSelection(key: string | undefined, selectionStart: number, selectionEnd: number, direction: ArkmeComposerDeleteDirection): number | undefined; appendAttachments(key: string | undefined, incoming: readonly ArkmeComposerAttachment[], maxAttachments?: number): void; /** Preparation updates the existing tile without changing its selection order. */ updateAttachments(key: string, update: (items: readonly ArkmeComposerAttachment[]) => readonly ArkmeComposerAttachment[]): void; removeAttachment(key: string | undefined, fileAssetUid: string): void; moveAttachment(key: string | undefined, index: number, destination: number): void; /** Removes a draft without releasing its attachments so an in-flight send can own the snapshot. */ take(key: string | undefined): ArkmeComposerDraftSnapshot; restore(key: string | undefined, snapshot: ArkmeComposerDraftSnapshot): void; clear(key: string | undefined): void; clearAccount(userId: number): void; private storeOrDelete; private store; private refreshPersisted; private persistedPayload; private publish; } export declare const arkmeComposerDraftStore: ArkmeComposerDraftStore; //# sourceMappingURL=composer-draft-store.d.ts.map