@convokitapp/vue-ui 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +125 -0
- package/PARITY.md +9 -0
- package/README.md +126 -1
- package/dist/index.cjs +838 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +79 -5
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +463 -7
- package/dist/index.d.ts +463 -7
- package/dist/index.js +840 -29
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/components/avatar.ts","../src/utils.ts","../src/components/conversation.ts","../src/composables/use-conversation.ts","../src/conversation-store.ts","../src/components/message-list.ts","../src/components/conversation-list.ts","../src/composables/use-conversation-list.ts","../src/conversation-list-store.ts","../src/theme.ts"],"sourcesContent":["import type { ConvoKitClient } from '@convokitapp/sdk'\nimport type { ConvoKitUiClient } from './types'\n\n/** Adapts a connected `@convokitapp/sdk` client to the replaceable UI boundary. */\nexport function createConvoKitUiClient(client: ConvoKitClient): ConvoKitUiClient {\n return {\n get sessionIdentity() { return client.connected ? client.realtime : null },\n onConnectionEvent: (handlers) => client.realtime.onConnectionEvent(handlers),\n onInboxChanged: (handler, onError) => client.realtime.onInboxChanged(client.clientId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onInboxActivity: (handler, onError) => client.realtime.onInboxActivity(client.clientId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onMessageDeleted: (conversationId, handler, onError) => client.realtime.onMessageDeleted(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n get currentUserId() { return client.connected ? client.currentUserId : '' },\n getConversations: (options) => client.getConversations(options),\n listInbox: (options) => client.listInbox(options),\n getConversation: (conversationId) => client.getConversation(conversationId),\n getMessages: (options) => client.getMessages(options),\n getMessage: (id) => client.getMessage(id),\n sendMessage: (input) => client.sendMessage(input),\n editMessage: (messageId, input) => client.editMessage(messageId, input),\n deleteMessage: (messageId) => client.deleteMessage(messageId),\n markConversationRead: (conversationId, options) => client.markConversationRead(conversationId, options),\n markConversationUnread: (conversationId) => client.markConversationUnread(conversationId),\n clearConversationUnread: (conversationId, options) => client.clearConversationUnread(conversationId, options),\n sendTyping: (input) => client.sendTyping(input),\n onMessage: (conversationId, handler, onError) => client.realtime.onMessage(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onReadReceipt: (conversationId, handler, onError) => client.realtime.onReadReceipt(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onTyping: (conversationId, handler, onError) => client.realtime.onTyping(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n }\n}\n","import { AvatarFallback, AvatarImage, AvatarRoot } from 'reka-ui'\nimport { defineComponent, h, type PropType } from 'vue'\nimport { cx, initials } from '../utils'\n\n/** Accessible avatar built on Reka UI, the primitive layer used by shadcn-vue. */\nexport const ConvoKitAvatar = defineComponent({\n name: 'ConvoKitAvatar',\n inheritAttrs: false,\n props: {\n name: { type: String, required: true },\n src: { type: String as PropType<string | null>, default: null },\n },\n setup(props, { attrs }) {\n return () => h(AvatarRoot, {\n ...attrs,\n class: cx('ckui-avatar', attrs.class),\n }, {\n default: () => [\n props.src ? h(AvatarImage, { class: 'ckui-avatar__image', src: props.src, alt: '' }) : null,\n h(AvatarFallback, {\n class: 'ckui-avatar__fallback',\n ...(props.src ? { delayMs: 300 } : {}),\n }, () => initials(props.name)),\n ],\n })\n },\n})\n","import type { Conversation, InboxEntry, InboxSummary, Message, ReadPosition } from '@convokitapp/sdk'\nimport { readThrough } from '@convokitapp/sdk'\nimport { clsx } from 'clsx'\nimport { normalizeClass } from 'vue'\nimport type { CSSProperties } from 'vue'\nimport type { ConversationFilter, ConvoKitAppearanceProps, ConvoKitUiPart } from './types'\n\nconst pendingMessageIdPrefix = 'convokit-pending-'\n\n/** Message cursor order: createdAt, then id by UTF-16 code units (the server's TEXT order for its lowercase UUIDs). */\nexport function compareMessageOrder(left: Pick<Message, 'createdAt' | 'id'>, right: Pick<Message, 'createdAt' | 'id'>): number {\n return left.createdAt.getTime() - right.createdAt.getTime()\n || (left.id < right.id ? -1 : left.id > right.id ? 1 : 0)\n}\n\n/** Whether a message is an optimistic row awaiting server acknowledgement. */\nexport function isConvoKitPendingMessage(message: Message): boolean {\n return message.id.startsWith(pendingMessageIdPrefix)\n}\n\n/** Vue class attributes accept nested arrays/objects, including unknown attrs on Vue 3.4. */\nexport function cx(...values: unknown[]): string { return clsx(values.map(normalizeClass)) }\n\nfunction requestedParticipantIds(filter: ConversationFilter): ReadonlySet<string> {\n const values = filter.participantIds ?? []\n return values instanceof Set ? values : new Set(values)\n}\n\nexport function matchesConversation(conversation: Conversation, filter: ConversationFilter): boolean {\n const query = filter.query?.trim().toLocaleLowerCase() ?? ''\n if (query) {\n const haystack = [\n conversation.id,\n conversation.displayTitle,\n conversation.title ?? '',\n conversation.description ?? '',\n ...conversation.participants.flatMap((participant) => [participant.id, participant.appUserId, participant.name]),\n ].join(' ').toLocaleLowerCase()\n if (!haystack.includes(query)) return false\n }\n const requested = requestedParticipantIds(filter)\n if (requested.size > 0) {\n const available = new Set(conversation.participants.flatMap((participant) => [participant.id, participant.appUserId]))\n const values = [...requested]\n const matches = filter.requireAllParticipants\n ? values.every((id) => available.has(id))\n : values.some((id) => available.has(id))\n if (!matches) return false\n }\n return filter.predicate?.(conversation) ?? true\n}\n\nexport function applyConversationFilter(conversations: readonly Conversation[], filter: ConversationFilter): Conversation[] {\n const result = conversations.filter((conversation) => matchesConversation(conversation, filter))\n if (filter.comparator) result.sort(filter.comparator)\n return result\n}\n\nexport function mergeConversations(current: readonly Conversation[], incoming: readonly Conversation[]): Conversation[] {\n const byId = new Map(current.map((conversation) => [conversation.id, conversation]))\n for (const conversation of incoming) byId.set(conversation.id, conversation)\n return [...byId.values()]\n}\n\n/** Inbox order: newest activity first, ties by id descending in UTF-16 code units (the server's TEXT order). */\nexport function compareInboxOrder(left: InboxEntry, right: InboxEntry): number {\n return right.activityAt.getTime() - left.activityAt.getTime()\n || (left.conversation.id < right.conversation.id ? 1 : left.conversation.id > right.conversation.id ? -1 : 0)\n}\n\n/** Merge inbox pages by conversation ID: a later entry replaces an earlier one (its room moved), and the result is\n * re-ordered by `(activityAt desc, id desc)`. Server order is authoritative within a page; this is the rule applied\n * whenever pages are combined (load more, refresh).\n */\nexport function mergeInboxEntries(current: readonly InboxEntry[], incoming: readonly InboxEntry[]): InboxEntry[] {\n const byId = new Map(current.map((entry) => [entry.conversation.id, entry]))\n for (const entry of incoming) byId.set(entry.conversation.id, entry)\n return [...byId.values()].sort(compareInboxOrder)\n}\n\n/** The default row's one-line preview, or `''` when the row should keep its participants/description line. */\nexport function inboxPreview(conversation: Conversation, summary: InboxSummary | undefined, currentUserId: string | undefined): string {\n const message = summary?.latestMessage\n if (!message) return ''\n const first = message.media[0]\n const body = message.text?.trim() || (!first ? ''\n : first.type === 'image' ? 'Photo'\n : first.type === 'file' ? first.name?.trim() || 'File'\n : first.type === 'location' ? 'Location'\n : first.type === 'contact' ? 'Contact' : '')\n if (!body) return ''\n if (currentUserId !== undefined && message.senderId === currentUserId) return `You: ${body}`\n if (conversation.participants.length > 2) {\n const sender = conversation.participants.find((participant) => participant.appUserId === message.senderId || participant.id === message.senderId)\n const name = sender?.name.trim()\n if (name) return `${name}: ${body}`\n }\n return body\n}\n\n/** Device-zone clock time, shared by message rows and inbox rows. */\nexport function formatMessageTime(date: Date): string {\n return new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: '2-digit' }).format(date)\n}\n\nexport function mergeMessages(current: readonly Message[], incoming: readonly Message[]): Message[] {\n const byId = new Map(current.map((message) => [message.id, message]))\n for (const message of incoming) byId.set(message.id, message)\n return [...byId.values()].sort((left, right) => {\n const leftPending = isConvoKitPendingMessage(left)\n const rightPending = isConvoKitPendingMessage(right)\n if (leftPending !== rightPending) return leftPending ? 1 : -1\n return compareMessageOrder(left, right)\n })\n}\n\n/** Readers of a message under the unified rule: a user's read position (createdAt, id) wins when present,\n * otherwise the acknowledgement time is compared with createdAt (legacy participants, empty-room acknowledgements).\n * The sender and pending rows never have readers.\n */\nexport function readerIdsFor(\n message: Message,\n readAtByUserId: ReadonlyMap<string, Date>,\n readPositionByUserId: ReadonlyMap<string, ReadPosition> = new Map(),\n): ReadonlySet<string> {\n if (isConvoKitPendingMessage(message)) return new Set()\n const userIds = new Set([...readAtByUserId.keys(), ...readPositionByUserId.keys()])\n return new Set([...userIds].filter((userId) => userId !== message.senderId && readThrough({\n readPosition: readPositionByUserId.get(userId) ?? null, lastReadAt: readAtByUserId.get(userId) ?? null,\n }, message)))\n}\n\nexport function partClass(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps, defaultClass: string): string {\n return cx(!appearance.unstyled && defaultClass, appearance.classNames?.[part])\n}\n\nexport function partStyle(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps): CSSProperties | undefined {\n return appearance.styles?.[part]\n}\n\nexport function errorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error) }\n\nexport function formatFileSize(size: number | undefined): string | null {\n if (size === undefined || !Number.isFinite(size) || size < 0) return null\n if (size < 1024) return `${Math.round(size)} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(size < 10 * 1024 ? 1 : 0)} KB`\n return `${(size / (1024 * 1024)).toFixed(size < 10 * 1024 * 1024 ? 1 : 0)} MB`\n}\n\nexport function initials(value: string): string {\n const words = value.trim().split(/\\s+/).filter(Boolean)\n return (words.length > 1 ? `${words[0]?.[0] ?? ''}${words.at(-1)?.[0] ?? ''}` : value[0] ?? '?').toLocaleUpperCase()\n}\n","import type { Conversation as ConversationModel, Message, MessageMedia, ReadPosition } from '@convokitapp/sdk'\nimport { ArrowLeft, Check, LoaderCircle, Paperclip, Pencil, RefreshCw, Send } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n onBeforeUnmount,\n ref,\n watch,\n watchEffect,\n type CSSProperties,\n type PropType,\n type TextareaHTMLAttributes,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationController, UseConversationOptions } from '../composables/use-conversation'\nimport { useConversation } from '../composables/use-conversation'\nimport type {\n ComposerSlotProps,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n TypingSlotProps,\n} from '../types'\nimport { cx, errorMessage, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\nimport { MessageListView } from './message-list'\n\nexport interface ConversationViewProps extends ConvoKitAppearanceProps {\n conversation: ConversationModel\n messages: readonly Message[]\n currentUserId: string\n onSendMessage: (text: string) => boolean | void | Promise<boolean | void>\n typingUserIds?: ReadonlySet<string>\n readAtByUserId?: ReadonlyMap<string, Date>\n readPositionByUserId?: ReadonlyMap<string, ReadPosition>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onBack?: () => void\n onRefresh?: () => void | Promise<void>\n onLoadOlder?: () => void | Promise<void>\n onTypingChange?: (isTyping: boolean) => void | Promise<void>\n onAddAttachment?: () => void\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n /** The message being edited (0.8.0), or null. Entering edit mode stashes the unsent draft and prefills the field\n * with the message text without a typing update; the composer then saves instead of sending.\n */\n editingMessage?: Message | null\n /** Start editing a message (0.8.0): set `editingMessage` in response. Without it rows offer no edit action. */\n onEditMessage?: (message: Message) => void\n /** Save the edit in progress (0.8.0); the composer's submit calls it instead of `onSendMessage` while\n * `editingMessage` is set. `false` keeps edit mode and the draft (like `onSendMessage`); any other result\n * restores the stashed unsent draft. Clear `editingMessage` when the edit is done.\n */\n onSaveEdit?: (message: Message, text: string) => boolean | void | Promise<boolean | void>\n /** Leave edit mode (0.8.0): clear `editingMessage` in response; the view restores the unsent draft. */\n onCancelEdit?: () => void\n /** Delete a message after confirmation (0.8.0); `false` means it was not accepted. Without it rows offer no\n * delete action.\n */\n onDeleteMessage?: (message: Message) => boolean | void | Promise<boolean | void>\n /** Replaces the default row eligibility (own confirmed rows while the viewer's role is not `READ`). */\n canEditMessage?: (message: Message) => boolean\n /** Replaces the inline \"Delete this message?\" prompt (and confirms `remove()` from custom rows). */\n confirmDelete?: (message: Message) => boolean | Promise<boolean>\n isInitialLoading?: boolean\n isLoadingOlder?: boolean\n isSending?: boolean\n hasOlderMessages?: boolean\n error?: unknown\n messageError?: unknown\n displayNameForUser?: (userId: string) => string | null | undefined\n reverseMessages?: boolean\n stickToBottom?: boolean\n paginationThreshold?: number\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n composerPlaceholder?: string\n composerAriaLabel?: string\n composerProps?: Omit<TextareaHTMLAttributes, 'value' | 'disabled'>\n modelValue?: string\n defaultDraft?: string\n onDraftChange?: (value: string) => void\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst viewProps = {\n ...appearanceProps,\n conversation: { type: Object as PropType<ConversationModel>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, required: true },\n typingUserIds: { type: Object as PropType<ReadonlySet<string>>, default: () => new Set() },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readPositionByUserId: { type: Object as PropType<ReadonlyMap<string, ReadPosition>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onBack: { type: Function as PropType<() => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onTypingChange: { type: Function as PropType<(isTyping: boolean) => void | Promise<void>>, default: undefined },\n onAddAttachment: { type: Function as PropType<() => void>, default: undefined },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n editingMessage: { type: Object as PropType<Message | null>, default: null },\n onEditMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onSaveEdit: { type: Function as PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n onCancelEdit: { type: Function as PropType<() => void>, default: undefined },\n onDeleteMessage: { type: Function as PropType<(message: Message) => boolean | void | Promise<boolean | void>>, default: undefined },\n canEditMessage: { type: Function as PropType<(message: Message) => boolean>, default: undefined },\n confirmDelete: { type: Function as PropType<(message: Message) => boolean | Promise<boolean>>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n isSending: { type: Boolean, default: false },\n hasOlderMessages: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n messageError: { type: null as unknown as PropType<unknown>, required: false },\n displayNameForUser: { type: Function as PropType<(userId: string) => string | null | undefined>, default: undefined },\n reverseMessages: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n paginationThreshold: { type: Number, default: 240 },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: undefined },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n composerPlaceholder: { type: String, default: 'Write a message' },\n composerAriaLabel: { type: String, default: 'Message' },\n composerProps: { type: Object as PropType<Omit<TextareaHTMLAttributes, 'value' | 'disabled'>>, default: undefined },\n modelValue: { type: String, default: undefined },\n defaultDraft: { type: String, default: '' },\n onDraftChange: { type: Function as PropType<(value: string) => void>, default: undefined },\n} as const\n\n/** The edit banner's summary of the message: its text, or its attachments when the caption is empty. */\nfunction editingSummary(message: Message): string {\n return message.text?.trim() || (message.media.length === 1 ? '1 attachment' : `${message.media.length} attachments`)\n}\n\nfunction typingLabel(userIds: ReadonlySet<string>, displayNameForUser: (userId: string) => string): string {\n const names = [...userIds].map(displayNameForUser)\n if (names.length === 0) return ''\n if (names.length === 1) return `${names[0]} is typing…`\n if (names.length === 2) return `${names[0]} and ${names[1]} are typing…`\n return `${names[0]} and ${names.length - 1} others are typing…`\n}\n\n/** Controlled, complete selected-conversation surface. */\nexport const ConversationView = defineComponent({\n name: 'ConversationView',\n inheritAttrs: false,\n props: viewProps,\n emits: [\n 'send-message', 'typing-change', 'back', 'refresh', 'load-older',\n 'add-attachment', 'attachment-click', 'update:modelValue',\n 'edit-message', 'save-edit', 'cancel-edit', 'delete-message',\n ],\n setup(props, { attrs, emit, slots }) {\n const internalDraft = ref(props.defaultDraft)\n const submitting = ref(false)\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n const draft = () => props.modelValue ?? internalDraft.value\n let latestDraft = draft()\n // Edit mode (0.8.0) is the host's/store's (`editingMessage`); the view owns the draft: the unsent draft is\n // stashed on entry and the field prefilled silently (no typing update). Cancel and a successful save restore\n // the stash; an external end (the row removed) keeps text the user changed and restores the stash otherwise.\n /** The unsent draft stashed on entering edit mode; undefined while not editing. */\n let stash: string | undefined\n /** A save request is in flight: its continuation, not the `editingMessage` watcher, settles the draft. */\n let saving = false\n const setDraft = (value: string, typing = true) => {\n latestDraft = value\n if (props.modelValue === undefined) internalDraft.value = value\n props.onDraftChange?.(value)\n emit('update:modelValue', value)\n if (typing) void props.onTypingChange?.(value.trim().length > 0)\n }\n const enterEdit = (message: Message) => {\n if (stash === undefined) stash = draft()\n setDraft(message.text ?? '', false)\n }\n /** Leave edit mode in the view: restore the stash always, or only when the field is empty or still the snapshot's text. */\n const leaveEdit = (message: Message, restore: 'always' | 'unchanged') => {\n if (stash === undefined) return\n const saved = stash\n stash = undefined\n const current = draft()\n if (restore === 'always' || current.trim() === '' || current === (message.text ?? '')) setDraft(saved)\n }\n watch(() => props.editingMessage, (next, previous) => {\n if (next && (!previous || previous.id !== next.id)) enterEdit(next)\n else if (!next && previous && !saving) leaveEdit(previous, 'unchanged')\n }, { immediate: true })\n const cancelEdit = () => {\n const editing = props.editingMessage\n if (!editing) return\n leaveEdit(editing, 'always')\n props.onCancelEdit?.()\n }\n /** Save is possible while the field has text or the edited row has attachments (an empty caption). */\n const canSave = (editing: Message) => draft().trim().length > 0 || editing.media.length > 0\n const submit = async () => {\n const editing = props.editingMessage\n if (editing) {\n const text = draft().trim()\n if (!canSave(editing) || props.isSending || submitting.value) return\n submitting.value = true\n saving = true\n try {\n // The field keeps the edited text during the request; a failure or a conflict leaves it in place.\n const saved = await props.onSaveEdit?.(editing, text)\n if (saved === false) {\n if (props.editingMessage === null) leaveEdit(editing, 'unchanged')\n return\n }\n leaveEdit(editing, 'always')\n } finally {\n saving = false\n submitting.value = false\n }\n return\n }\n const originalDraft = draft()\n const text = originalDraft.trim()\n if (!text || props.isSending || submitting.value) return\n submitting.value = true\n setDraft('')\n try {\n const shouldClear = await props.onSendMessage(text)\n if (shouldClear === false && latestDraft.length === 0) setDraft(originalDraft)\n } finally {\n submitting.value = false\n }\n }\n const nameForUser = (userId: string) => {\n const custom = props.displayNameForUser?.(userId)?.trim()\n if (custom) return custom\n const participant = props.conversation.participants.find((value) => value.id === userId || value.appUserId === userId)\n return participant?.name.trim() || userId\n }\n const goBack = () => { props.onBack?.() }\n const refresh = () => props.onRefresh?.()\n const loadOlder = () => props.onLoadOlder?.()\n const addAttachment = () => { props.onAddAttachment?.() }\n\n const renderHeader = (): VNodeChild => {\n const slotProps = {\n conversation: props.conversation,\n ...(props.onBack ? { onBack: goBack } : {}),\n ...(props.onRefresh ? { onRefresh: refresh } : {}),\n }\n return slots.header?.(slotProps) ?? h('header', {\n class: partClass('header', appearance(), 'ckui-conversation-header'),\n style: partStyle('header', appearance()),\n }, [\n props.onBack ? h('button', {\n type: 'button', 'aria-label': 'Back', onClick: goBack,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(ArrowLeft, { size: 20, 'aria-hidden': 'true' })]) : null,\n h(ConvoKitAvatar, { name: props.conversation.displayTitle, src: props.conversation.imageUrl }),\n h('div', { class: 'ckui-conversation-header__body' }, [\n h('strong', props.conversation.displayTitle),\n h('span', `${props.conversation.participants.length} participant${props.conversation.participants.length === 1 ? '' : 's'}`),\n ]),\n props.onRefresh ? h('button', {\n type: 'button', 'aria-label': 'Refresh conversation', onClick: () => { void refresh() },\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(RefreshCw, { size: 18, 'aria-hidden': 'true' })]) : null,\n ])\n }\n\n const renderTyping = (): VNodeChild => {\n const slotProps: TypingSlotProps = { userIds: props.typingUserIds, displayNameForUser: nameForUser }\n return slots['typing-indicator']?.(slotProps) ?? h('div', {\n class: partClass('typing', appearance(), 'ckui-typing'),\n style: partStyle('typing', appearance()),\n 'aria-live': 'polite',\n }, typingLabel(props.typingUserIds, nameForUser))\n }\n\n const renderComposer = (): VNodeChild => {\n const editing = props.editingMessage\n const slotProps: ComposerSlotProps = {\n value: draft(), setValue: setDraft, isSending: props.isSending || submitting.value,\n send: () => { void submit() },\n ...(props.onAddAttachment ? { addAttachment } : {}),\n ...(editing ? { editing, cancelEdit } : {}),\n }\n const busy = props.isSending || submitting.value\n return slots.composer?.(slotProps) ?? h('form', {\n class: cx(partClass('composer', appearance(), 'ckui-composer'), editing && !props.unstyled && 'ckui-composer--editing'),\n style: partStyle('composer', appearance()),\n onSubmit: (event: Event) => { event.preventDefault(); void submit() },\n }, [\n // Spread, not null: outside edit mode the composer markup stays byte-identical to 0.7.\n ...(editing ? [h('div', { class: 'ckui-composer__editing', role: 'status' }, [\n h(Pencil, { size: 14, 'aria-hidden': 'true' }),\n h('span', { class: 'ckui-composer__editing-body' }, [\n h('strong', 'Editing message'),\n h('span', editingSummary(editing)),\n ]),\n h('button', { type: 'button', class: 'ckui-link-button', 'aria-label': 'Cancel editing', onClick: cancelEdit }, 'Cancel'),\n ])] : []),\n props.onAddAttachment ? h('button', {\n type: 'button', 'aria-label': 'Add attachment', onClick: addAttachment,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(Paperclip, { size: 20, 'aria-hidden': 'true' })]) : null,\n h('textarea', {\n ...props.composerProps,\n rows: props.composerProps?.rows ?? 1,\n placeholder: props.composerPlaceholder,\n 'aria-label': props.composerAriaLabel,\n class: cx(!props.unstyled && 'ckui-composer__input', props.classNames?.input, props.composerProps?.class),\n style: [props.styles?.input, props.composerProps?.style],\n value: draft(),\n onInput: (event: InputEvent) => {\n const handler = props.composerProps?.onInput\n if (typeof handler === 'function') handler(event)\n if (!event.defaultPrevented) setDraft((event.currentTarget as HTMLTextAreaElement).value)\n },\n onKeydown: (event: KeyboardEvent) => {\n const handler = props.composerProps?.onKeydown\n if (typeof handler === 'function') handler(event)\n if (event.defaultPrevented) return\n if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); void submit() }\n if (event.key === 'Escape' && props.editingMessage) { event.preventDefault(); cancelEdit() }\n },\n }),\n h('button', {\n type: 'submit', 'aria-label': editing ? 'Save message' : 'Send message',\n disabled: (editing ? !canSave(editing) : !draft().trim()) || busy,\n class: partClass('button', appearance(), 'ckui-send-button'),\n style: partStyle('button', appearance()),\n }, [busy\n ? h(LoaderCircle, { class: 'ckui-spin', size: 18, 'aria-hidden': 'true' })\n : h(editing ? Check : Send, { size: 18, 'aria-hidden': 'true' })]),\n ])\n }\n\n return () => {\n if (props.isInitialLoading && props.messages.length === 0) {\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, slots.loading?.() ?? h('div', {\n class: partClass('loading', appearance(), 'ckui-state'), style: partStyle('loading', appearance()), role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…']))\n }\n const children: VNodeChild[] = [renderHeader()]\n if (props.error) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', appearance(), 'ckui-conversation-error'),\n style: partStyle('error', appearance()), role: 'alert',\n }, [h('span', errorMessage(props.error)), retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null]))\n }\n const messageSlots = {\n ...(slots.message ? { message: slots.message } : {}),\n ...(slots.media ? { media: slots.media } : {}),\n ...(slots['read-receipt'] ? { 'read-receipt': slots['read-receipt'] } : {}),\n ...(slots.empty ? { empty: slots.empty } : {}),\n ...(slots['loading-older'] ? { 'loading-older': slots['loading-older'] } : {}),\n ...(slots['message-error'] ? { error: slots['message-error'] } : {}),\n }\n children.push(h(MessageListView, {\n conversation: props.conversation,\n messages: props.messages,\n currentUserId: props.currentUserId,\n readAtByUserId: props.readAtByUserId,\n readPositionByUserId: props.readPositionByUserId,\n ...(props.readersResolver ? { readersResolver: props.readersResolver } : {}),\n ...(props.onLoadOlder ? { onLoadOlder: loadOlder } : {}),\n hasOlderMessages: props.hasOlderMessages,\n isLoadingOlder: props.isLoadingOlder,\n ...(props.messageError == null ? {} : { error: props.messageError }),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n } } : {}),\n ...(props.onEditMessage ? { onEditMessage: (message: Message) => { props.onEditMessage?.(message) } } : {}),\n ...(props.onDeleteMessage ? { onDeleteMessage: (message: Message) => props.onDeleteMessage?.(message) } : {}),\n ...(props.canEditMessage ? { canEditMessage: props.canEditMessage } : {}),\n ...(props.confirmDelete ? { confirmDelete: props.confirmDelete } : {}),\n reverse: props.reverseMessages,\n stickToBottom: props.stickToBottom,\n paginationThreshold: props.paginationThreshold,\n ...(props.formatTime ? { formatTime: props.formatTime } : {}),\n imageLoading: props.imageLoading,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n density: props.density,\n unstyled: props.unstyled,\n }, messageSlots))\n children.push(renderTyping(), renderComposer())\n return h('section', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n 'aria-label': props.conversation.displayTitle,\n }, children)\n }\n },\n})\n\nexport interface ConversationProps extends Omit<ConversationViewProps,\n 'conversation' | 'messages' | 'currentUserId' | 'onSendMessage' | 'typingUserIds' |\n 'readAtByUserId' | 'readPositionByUserId' | 'onRefresh' | 'onLoadOlder' | 'onTypingChange' |\n 'isInitialLoading' | 'isLoadingOlder' | 'isSending' | 'hasOlderMessages' | 'error' |\n 'editingMessage' | 'onEditMessage' | 'onSaveEdit' | 'onCancelEdit' | 'onDeleteMessage'>,\n Omit<UseConversationOptions, 'client' | 'conversationId'> {\n client: ConvoKitUiClient\n conversationId: string\n onControllerChange?: (controller: ConversationController) => void\n}\n\n/** Plug-and-play SDK-backed UI for one conversation. */\nexport const Conversation = defineComponent({\n name: 'Conversation',\n inheritAttrs: false,\n props: {\n ...viewProps,\n conversation: { type: Object as PropType<ConversationModel>, default: undefined },\n messages: { type: Array as PropType<readonly Message[]>, default: () => [] },\n currentUserId: { type: String, default: '' },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n editingMessage: { type: Object as PropType<Message | null>, default: undefined },\n onEditMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onSaveEdit: { type: Function as PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n onCancelEdit: { type: Function as PropType<() => void>, default: undefined },\n onDeleteMessage: { type: Function as PropType<(message: Message) => boolean | void | Promise<boolean | void>>, default: undefined },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n conversationId: { type: String, required: true },\n messagePageSize: { type: Number, default: 30 },\n markReadOnLoad: { type: Boolean, default: true },\n markReadOnReceive: { type: Boolean, default: true },\n typingTimeoutMs: { type: Number, default: 3000 },\n autoLoad: { type: Boolean, default: true },\n onControllerChange: { type: Function as PropType<(controller: ConversationController) => void>, default: undefined },\n },\n emits: [\n 'controller-change', 'send-message', 'typing-change', 'back', 'refresh', 'load-older', 'add-attachment', 'attachment-click', 'update:modelValue',\n 'edit-message', 'save-edit', 'cancel-edit', 'delete-message',\n ],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversation({\n client: () => props.client,\n conversationId: () => props.conversationId,\n messagePageSize: props.messagePageSize,\n markReadOnLoad: props.markReadOnLoad,\n markReadOnReceive: props.markReadOnReceive,\n typingTimeoutMs: props.typingTimeoutMs,\n autoLoad: props.autoLoad,\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n // Automatic acknowledgements only while the document is visible; prerender/unknown/no document count as visible.\n if (typeof document !== 'undefined') {\n const syncVisibility = () => controller.setVisible(document.visibilityState !== 'hidden')\n syncVisibility()\n document.addEventListener('visibilitychange', syncVisibility)\n onBeforeUnmount(() => document.removeEventListener('visibilitychange', syncVisibility))\n }\n return () => {\n const loadedConversation = controller.conversation.value\n if (!loadedConversation) {\n const retry = () => { void controller.refresh() }\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, controller.error.value\n ? slots.error?.({ error: controller.error.value, retry }) ?? h('div', { class: 'ckui-state ckui-state--error', role: 'alert' }, [\n h('span', errorMessage(controller.error.value)),\n h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again'),\n ])\n : slots.loading?.() ?? h('div', { class: 'ckui-state', role: 'status' }, [\n h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…',\n ]))\n }\n const {\n client: _client,\n conversationId: _conversationId,\n messagePageSize: _messagePageSize,\n markReadOnLoad: _markReadOnLoad,\n markReadOnReceive: _markReadOnReceive,\n typingTimeoutMs: _typingTimeoutMs,\n autoLoad: _autoLoad,\n onControllerChange: _onControllerChange,\n conversation: _conversation,\n messages: _messages,\n currentUserId: _currentUserId,\n onSendMessage: _onSendMessage,\n typingUserIds: _typingUserIds,\n readAtByUserId: _readAtByUserId,\n readPositionByUserId: _readPositionByUserId,\n onRefresh: _onRefresh,\n onLoadOlder: _onLoadOlder,\n onTypingChange: _onTypingChange,\n isInitialLoading: _isInitialLoading,\n isLoadingOlder: _isLoadingOlder,\n isSending: _isSending,\n hasOlderMessages: _hasOlderMessages,\n error: _error,\n editingMessage: _editingMessage,\n onEditMessage: _onEditMessage,\n onSaveEdit: _onSaveEdit,\n onCancelEdit: _onCancelEdit,\n onDeleteMessage: _onDeleteMessage,\n ...forwarded\n } = props\n return h(ConversationView, {\n ...attrs,\n ...forwarded,\n conversation: loadedConversation,\n messages: controller.messages.value,\n currentUserId: controller.currentUserId.value,\n onSendMessage: async (text: string) => {\n emit('send-message', text)\n return (await controller.sendMessage({ text })) !== null\n },\n typingUserIds: controller.typingUserIds.value,\n readAtByUserId: controller.readAtByUserId.value,\n readPositionByUserId: controller.readPositionByUserId.value,\n onRefresh: controller.refresh,\n onLoadOlder: controller.loadOlderMessages,\n onTypingChange: controller.updateTyping,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingOlder: controller.isLoadingOlder.value,\n isSending: controller.isSending.value,\n hasOlderMessages: controller.hasOlderMessages.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n // Edit mode is the store's; the actions render only while the adapter supports them (0.8.0).\n editingMessage: controller.editingMessage.value,\n ...(controller.canEditMessages.value ? {\n onEditMessage: (message: Message) => { emit('edit-message', message); controller.startEditing(message.id) },\n onSaveEdit: async (message: Message, text: string) => { emit('save-edit', message, text); return controller.saveEdit(text) },\n onCancelEdit: () => { emit('cancel-edit'); controller.cancelEditing() },\n } : {}),\n ...(controller.canDeleteMessages.value ? {\n onDeleteMessage: async (message: Message) => { emit('delete-message', message); return controller.deleteMessage(message.id) },\n } : {}),\n 'onUpdate:modelValue': (value: string) => emit('update:modelValue', value),\n ...(props.onBack ? { onBack: () => { props.onBack?.(); emit('back') } } : {}),\n ...(props.onAddAttachment ? { onAddAttachment: () => { props.onAddAttachment?.(); emit('add-attachment') } } : {}),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n emit('attachment-click', media, message)\n } } : {}),\n } as never, slots)\n }\n },\n})\n","import type { Message, MessageMedia } from '@convokitapp/sdk'\nimport { computed, getCurrentScope, onScopeDispose, shallowRef, toValue, watch, type MaybeRefOrGetter } from 'vue'\nimport type { ConversationState, ConvoKitUiClient } from '../types'\nimport { ConversationStore, type ConversationSnapshot } from '../conversation-store'\n\nexport interface UseConversationOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n conversationId: MaybeRefOrGetter<string>\n messagePageSize?: number\n markReadOnLoad?: boolean\n markReadOnReceive?: boolean\n typingTimeoutMs?: number\n autoLoad?: boolean\n}\nexport interface ConversationController extends ConversationState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadOlderMessages(): Promise<void>\n sendMessage(input: { text?: string; media?: MessageMedia[] }): Promise<Message | null>\n /** Enter edit mode on one of the caller's own confirmed messages (0.8.0); a no-op for other rows, for a `READ`\n * role and for adapters without `editMessage`. Sends nothing (no typing update either).\n */\n startEditing(messageId: string): void\n /** Leave edit mode without a request. */\n cancelEditing(): void\n /** Save the edit in progress with the snapshot's revision; resolves true when the server accepted it. A stale\n * revision reloads the row, refreshes `editingMessage` and reports `REVISION_CONFLICT` through `error` (edit mode\n * and draft kept); see the README for the other outcomes. Rejects when the adapter lacks `editMessage`.\n */\n saveEdit(text: string): Promise<boolean>\n /** Delete one of the caller's own confirmed messages; resolves true once the row is gone (accepted, or already\n * unknown to the server). No optimistic removal. Rejects when the adapter lacks `deleteMessage`.\n */\n deleteMessage(messageId: string): Promise<boolean>\n /** Acknowledge through the newest rendered message now; no request is sent while nothing is rendered. */\n markRead(): Promise<void>\n /** Automatic acknowledgements pause while hidden and resume when the view becomes visible again. */\n setVisible(visible: boolean): void\n updateTyping(isTyping: boolean): Promise<void>\n dispose(): Promise<void>\n}\n\n/** Each room/login gets an independent owner; disposal also stops reactive reloads. */\nexport function useConversation(options: UseConversationOptions): ConversationController {\n const createStore = () => new ConversationStore({\n ...options, client: toValue(options.client), conversationId: toValue(options.conversationId),\n })\n let store = createStore()\n const snapshot = shallowRef(store.getSnapshot())\n let unsubscribe: (() => void) | undefined\n let visible = true\n const stop = watch(\n () => [toValue(options.client), toValue(options.client).sessionIdentity, toValue(options.conversationId)] as const,\n () => {\n store.dispose()\n unsubscribe?.()\n store = createStore()\n snapshot.value = store.getSnapshot()\n unsubscribe = store.subscribe(() => { snapshot.value = store.getSnapshot() })\n store.setVisible(visible)\n store.start(options.autoLoad ?? true)\n },\n { immediate: true, flush: 'sync' },\n )\n const field = <K extends keyof ConversationSnapshot>(key: K) => computed(() => snapshot.value[key])\n const dispose = async () => {\n stop()\n store.dispose()\n unsubscribe?.()\n unsubscribe = undefined\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n return {\n conversation: field('conversation'), messages: field('messages'),\n typingUserIds: field('typingUserIds'), readAtByUserId: field('readAtByUserId'),\n readPositionByUserId: field('readPositionByUserId'),\n isInitialLoading: field('isInitialLoading'), isLoadingOlder: field('isLoadingOlder'),\n isReconciling: field('isReconciling'), isSending: field('isSending'),\n hasOlderMessages: field('hasOlderMessages'), hasLoaded: field('hasLoaded'),\n error: field('error'), currentUserId: field('currentUserId'),\n editingMessage: field('editingMessage'), canEditMessages: field('canEditMessages'), canDeleteMessages: field('canDeleteMessages'),\n readerIdsFor: (message) => store.readerIdsFor(message),\n loadInitial: () => store.loadInitial(), refresh: () => store.refresh(),\n loadOlderMessages: () => store.loadOlderMessages(), sendMessage: (input) => store.sendMessage(input),\n startEditing: (messageId) => store.startEditing(messageId), cancelEditing: () => store.cancelEditing(),\n saveEdit: (text) => store.saveEdit(text), deleteMessage: (messageId) => store.deleteMessage(messageId),\n markRead: () => store.markRead(), updateTyping: (isTyping) => store.updateTyping(isTyping),\n setVisible: (value) => { visible = value; store.setVisible(value) },\n dispose,\n }\n}\n","import type { Conversation, Message, MessageEvent, MessageMedia, Participant, ReadPosition, RealtimeSubscription } from '@convokitapp/sdk'\nimport { createClientMessageId } from '@convokitapp/sdk'\nimport type { ConvoKitUiClient } from './ui-client'\nimport { compareMessageOrder, isConvoKitPendingMessage, mergeMessages, readerIdsFor } from './utils'\n\nexport interface ConversationSnapshot {\n conversation: Conversation | null\n messages: Message[]\n typingUserIds: ReadonlySet<string>\n /** Last acknowledgement time per user; kept for custom renderers. */\n readAtByUserId: ReadonlyMap<string, Date>\n /** Monotonic read-through position per user; wins over `readAtByUserId` where present. */\n readPositionByUserId: ReadonlyMap<string, ReadPosition>\n isInitialLoading: boolean\n isLoadingOlder: boolean\n isReconciling: boolean\n isSending: boolean\n hasOlderMessages: boolean\n hasLoaded: boolean\n error: unknown\n currentUserId: string\n /** The row being edited, as the user saw it when editing started (0.8.0): its `revision` is what `saveEdit`\n * sends. Replaced by the current row when a conflict is detected; null when not editing.\n */\n editingMessage: Message | null\n /** Whether the adapter implements `editMessage` / `deleteMessage` (0.8.0); computed once at construction. */\n canEditMessages: boolean\n canDeleteMessages: boolean\n}\n\ninterface Options {\n client: ConvoKitUiClient\n conversationId: string\n messagePageSize?: number\n markReadOnLoad?: boolean\n markReadOnReceive?: boolean\n typingTimeoutMs?: number\n}\n\ntype Cursor = Pick<Message, 'createdAt' | 'id'>\n// `revision` on changes, hydrations and the store is the store's own change counter (`this.revision`), unrelated to\n// `Message.revision`, the server's content revision that `revisionOrder` compares.\ntype Change = { revision: number; message: Message; insert: boolean; complete: boolean }\ntype Hydration = { revision: number; generation: number; message: Message; insert: boolean }\ntype Support = { edit: boolean; delete: boolean }\ntype HydrationPool = { running: Set<string>; queued: Map<string, Hydration> }\ntype ReadEntry = { userId: string; readAt: Date | null; readPosition: ReadPosition | null | undefined }\n/** One acknowledgement pipeline per load: a single request in flight, one boolean follow-up resolved at send time. */\ntype Acknowledgement = {\n inFlight: Promise<void> | undefined\n followUp: boolean\n /** An automatic acknowledgement was wanted while hidden or before this open's DTO (and so its version) was in\n * hand; re-issued once the view becomes visible or the open captures.\n */\n suppressed: boolean\n /** Target of the request in flight. */\n target: string | undefined\n /** Last target the server accepted; older or equal targets are never re-sent. */\n acknowledged: Cursor | undefined\n /** Targets the server does not know (or that were removed): never targeted again. */\n unacknowledgeable: Set<string>\n}\n/** The caller's private state captured once per open, the first time `conversation` goes from null to a DTO.\n * `version` stays undefined until then and for a DTO without `membership` (0.6 backend: acknowledgements send no\n * version); `clearPending` is set when the opened membership carried an unread marker and consumed by the single\n * empty-room clear of that open.\n */\ntype Capture = { version: number | undefined; clearPending: boolean }\n\nfunction version(message: Message): number { return message.updatedAt?.getTime() ?? message.createdAt.getTime() }\nfunction hasContent(message: Message): boolean { return !!message.text?.trim() || message.media.length > 0 }\n/** Row precedence (0.8.0): when both rows carry a usable content revision (both present, at least one above 0)\n * the higher `Message.revision` decides (negative: `left` is older, positive: newer); equal revisions and rows\n * without a usable one (pending rows, 0.7 backends where every row is 0) answer undefined and fall back to the\n * `updatedAt ?? createdAt` rule.\n */\nfunction revisionOrder(left: Message, right: Message): number | undefined {\n const a = left.revision, b = right.revision\n if (typeof a !== 'number' || typeof b !== 'number' || (a <= 0 && b <= 0)) return undefined\n return a === b ? undefined : a - b\n}\n/** Whether `candidate` is strictly older than `reference`: by revision when usable, else by timestamp. */\nfunction older(candidate: Message, reference: Message): boolean {\n const byRevision = revisionOrder(candidate, reference)\n return byRevision === undefined ? version(candidate) < version(reference) : byRevision < 0\n}\nfunction newest(current: Message, incoming: Message, incomingComplete = true): Message {\n const byRevision = revisionOrder(current, incoming)\n if (byRevision !== undefined) return byRevision > 0 ? current : incoming\n return version(current) > version(incoming) || (!incomingComplete && version(current) === version(incoming)) ? current : incoming\n}\n/** A stale expected revision, as the backend reports it (409 `REVISION_CONFLICT`); a bare 409 counts only for\n * adapters that expose no code at all, like `isTargetMiss`.\n */\nfunction isRevisionConflict(cause: unknown): boolean {\n if (typeof cause !== 'object' || cause === null) return false\n const { code, status } = cause as { code?: unknown; status?: unknown }\n return code === 'REVISION_CONFLICT' || (code === undefined && status === 409)\n}\n/** An author mutation rejected because the message is gone: only the coded 404. An uncoded 404 (a 0.7 backend's\n * unmatched `/own` route, a proxy, a custom adapter) is reported as an error and never evicts the row.\n */\nfunction isMessageMissing(cause: unknown): boolean {\n return typeof cause === 'object' && cause !== null && (cause as { code?: unknown }).code === 'MESSAGE_NOT_FOUND'\n}\n/** The local conflict signal: a newer row for the edited message reached the store without a request. */\nfunction localConflict(): Error {\n return Object.assign(new Error('Message was changed since it was loaded'), { code: 'REVISION_CONFLICT' })\n}\n\nconst compare = compareMessageOrder\nfunction positionCursor(position: ReadPosition): Cursor { return { createdAt: position.createdAt, id: position.messageId } }\nfunction readEntry(participant: Participant): ReadEntry {\n return { userId: participant.appUserId, readAt: participant.lastReadAt, readPosition: participant.readPosition }\n}\nfunction acknowledgement(): Acknowledgement {\n return { inFlight: undefined, followUp: false, suppressed: false, target: undefined, acknowledged: undefined, unacknowledgeable: new Set() }\n}\nfunction capture(conversation?: Conversation): Capture {\n const membership = conversation?.membership\n return { version: membership?.privateStateVersion, clearPending: membership?.unreadMarkedAt != null }\n}\n/** A targeted read the server rejected because the target is unknown to it (deleted or foreign). Membership\n * failures carry no `MESSAGE_NOT_FOUND` code (the core SDK reports `HTTP_ERROR`), so they remain errors; a\n * bare 404 counts as a miss only for adapters that expose no code at all.\n */\nfunction isTargetMiss(cause: unknown): boolean {\n if (typeof cause !== 'object' || cause === null) return false\n const { code, status } = cause as { code?: unknown; status?: unknown }\n return code === 'MESSAGE_NOT_FOUND' || (code === undefined && status === 404)\n}\n\nfunction blank(currentUserId = '', support: Support = { edit: false, delete: false }): ConversationSnapshot {\n return {\n conversation: null, messages: [], typingUserIds: new Set(), readAtByUserId: new Map(), readPositionByUserId: new Map(),\n isInitialLoading: false, isLoadingOlder: false, isReconciling: false, isSending: false,\n hasOlderMessages: true, hasLoaded: false, error: null, currentUserId,\n editingMessage: null, canEditMessages: support.edit, canDeleteMessages: support.delete,\n }\n}\n\n/** Internal, framework-independent room lifecycle. Never shared across client sessions. */\nexport class ConversationStore {\n private readonly client: ConvoKitUiClient\n private readonly room: string\n private readonly owner: object | null\n private readonly user: string\n private readonly pageSize: number\n private readonly typingTimeout: number\n private state: ConversationSnapshot\n private listeners = new Set<() => void>()\n private subscriptions: RealtimeSubscription[] = []\n private disposed = true\n private generation = 0\n private cursor: Cursor | undefined\n private revision = 0\n private changes = new Map<string, Change>()\n private hydrations = new Map<string, Hydration>()\n private hydrationPool: HydrationPool = { running: new Set(), queued: new Map() }\n // Keep tombstones until an explicit reload/session change, including across refreshes.\n private deleted = new Set<string>()\n private ack = acknowledgement()\n private captured = capture()\n // Visible until the platform reports otherwise; unknown/prerender/no document count as visible.\n private visible = true\n private sendRevision: number | undefined\n private activeSend: { pending: Message; confirmed?: Message } | undefined\n /** Adapter support for author edits/deletes, decided once like `listInbox`. */\n private readonly support: Support\n /** The id whose `saveEdit` request is in flight: its outcome (success or 409) decides the edit, so newer rows for\n * it arriving meanwhile (its own UPDATE image, typically) are not reported as a local conflict while it lasts;\n * `settleEditing` re-evaluates them once the request has settled any other way.\n */\n private activeEdit: string | undefined\n private refreshQueued = false\n private typingTimers = new Map<string, ReturnType<typeof setTimeout>>()\n private ownTypingTimer: ReturnType<typeof setTimeout> | undefined\n private sentTyping = false\n private typingRevision = 0\n private lastTypingSentAt = -Infinity\n\n constructor(private readonly options: Options) {\n this.client = options.client\n this.room = options.conversationId.trim()\n this.pageSize = options.messagePageSize ?? 30\n this.typingTimeout = options.typingTimeoutMs ?? 3000\n if (!this.room) throw new TypeError('conversationId is required')\n if (!Number.isInteger(this.pageSize) || this.pageSize < 1 || this.pageSize > 100) {\n throw new RangeError('messagePageSize must be an integer between 1 and 100')\n }\n if (!Number.isFinite(this.typingTimeout) || this.typingTimeout < 0) {\n throw new RangeError('typingTimeoutMs must be non-negative')\n }\n this.owner = this.client.sessionIdentity\n this.user = this.owner ? this.client.currentUserId : ''\n this.support = { edit: typeof this.client.editMessage === 'function', delete: typeof this.client.deleteMessage === 'function' }\n this.state = blank(this.user, this.support)\n }\n\n getSnapshot = (): ConversationSnapshot => this.state\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n private patch(patch: Partial<ConversationSnapshot>): void {\n if (patch.messages && this.activeSend) {\n for (const message of patch.messages) this.confirmSend(message)\n if (this.activeSend.confirmed) patch.messages = patch.messages.filter(message => message.id !== this.activeSend!.pending.id)\n }\n if (patch.messages) patch = this.trackEditing(patch)\n this.state = { ...this.state, ...patch }\n for (const listener of this.listeners) listener()\n }\n /** Edit mode follows the edited row wherever a message list reaches the state: the row leaving the list (deletion,\n * reconcile tombstone, eviction) ends it, and a row for it with a higher revision than the snapshot (UPDATE image,\n * hydration, reconcile, refresh) is the local conflict: the snapshot is replaced and `error` carries the conflict\n * code, without a request. A save in flight owns its own outcome (`activeEdit`) and re-checks when it settles\n * (`settleEditing`).\n */\n private trackEditing(patch: Partial<ConversationSnapshot>): Partial<ConversationSnapshot> {\n const editing = patch.editingMessage === undefined ? this.state.editingMessage : patch.editingMessage\n if (!editing || !patch.messages) return patch\n const live = patch.messages.find((message) => message.id === editing.id)\n if (!live) return { ...patch, editingMessage: null }\n if (this.activeEdit === editing.id || !(live.revision > editing.revision)) return patch\n return { ...patch, editingMessage: live, error: localConflict() }\n }\n /** After a save for `id` has settled without deciding the edit (a failure, or a 409 whose reload failed), a newer\n * row for it that arrived during the request is the local conflict after all: the snapshot is replaced and\n * `error` carries the conflict code, so the next save carries the fresh revision without another round trip.\n */\n private settleEditing(id: string): void {\n const editing = this.state.editingMessage\n const live = editing?.id === id ? this.state.messages.find((message) => message.id === id) : undefined\n if (editing && live && live.revision > editing.revision) this.patch({ editingMessage: live, error: localConflict() })\n }\n private alive(generation = this.generation): boolean {\n return !this.disposed && generation === this.generation\n && this.owner !== null && this.client.sessionIdentity === this.owner\n }\n\n start = (autoLoad = true): void => {\n if (this.owner === null || this.client.sessionIdentity !== this.owner) return\n this.disposed = false\n this.patch({ currentUserId: this.user })\n if (autoLoad) void this.loadInitial()\n else {\n try { this.attach(this.generation, false) } catch { /* attach reports adapter failures */ }\n }\n }\n\n private detach(): void {\n const active = this.subscriptions\n this.subscriptions = []\n for (const subscription of active) void subscription.unsubscribe().catch(() => undefined)\n }\n\n private clearTyping(): void {\n for (const timer of this.typingTimers.values()) clearTimeout(timer)\n this.typingTimers.clear()\n clearTimeout(this.ownTypingTimer)\n this.ownTypingTimer = undefined\n this.sentTyping = false\n this.typingRevision++\n this.lastTypingSentAt = -Infinity\n this.patch({ typingUserIds: new Set() })\n }\n\n private clear(): void {\n this.generation++\n this.detach()\n this.clearTyping()\n this.cursor = undefined\n this.changes.clear()\n this.hydrations.clear()\n this.hydrationPool.queued.clear()\n // In-flight adapter promises cannot be aborted through this interface.\n // Keep their slots across reloads so repeated loads cannot exceed the cap.\n this.deleted.clear()\n // A retired pipeline's response settles against the old generation and is ignored.\n this.ack = acknowledgement()\n // Every open captures the caller's private state afresh; nothing captured survives `conversation` going null.\n this.captured = capture()\n this.sendRevision = undefined\n this.activeSend = undefined\n this.activeEdit = undefined\n this.refreshQueued = false\n }\n\n dispose = (): void => {\n // A retired session must never send a typing update using a replacement login.\n if (this.alive() && this.sentTyping) {\n void this.client.sendTyping({ conversationId: this.room, isTyping: false }).catch(() => undefined)\n }\n this.disposed = true\n this.clear()\n this.patch(blank('', this.support))\n }\n\n private fail(cause: unknown, generation: number, history = false): void {\n if (!this.alive(generation)) return\n const status = typeof cause === 'object' && cause !== null && 'status' in cause ? cause.status : undefined\n if (history && (status === 401 || status === 403 || status === 404)) {\n this.clear()\n this.patch({ ...blank(this.user, this.support), error: cause, hasLoaded: true, hasOlderMessages: false })\n } else this.patch({ error: cause })\n }\n\n private attach(generation: number, data = true): void {\n const report = (cause: Error) => this.fail(cause, generation)\n const add = (create: () => RealtimeSubscription) => {\n if (!this.alive(generation)) return\n const subscription = create()\n if (this.alive(generation)) this.subscriptions.push(subscription)\n else void subscription.unsubscribe().catch(() => undefined)\n }\n try {\n // Install lifecycle ownership before providers can synchronously report a join.\n add(() => this.client.onConnectionEvent({\n onEvent: ({ topic, status }) => {\n if (!data || !this.alive(generation) || (topic !== `messages:${this.room}` && topic !== `conversation:${this.room}`)) return\n if (status === 'SUBSCRIBED') this.queueRefresh()\n else this.clearTyping()\n },\n onSessionEnded: () => {\n if (this.disposed || generation !== this.generation) return\n this.dispose()\n },\n onError: report,\n }))\n if (!data) return\n add(() => this.client.onInboxChanged(() => {\n if (this.alive(generation)) this.queueRefresh()\n }, cause => {\n if (this.alive(generation)) { report(cause); this.queueRefresh() }\n }))\n add(() => this.client.onMessage(this.room, (event) => this.onMessage(event, generation), report))\n add(() => this.client.onMessageDeleted(this.room, ({ id, conversationId }) => {\n if (!this.alive(generation) || conversationId !== this.room || !id.trim()) return\n this.removeMessage(id)\n }, report))\n add(() => this.client.onReadReceipt(this.room, ({ userId, readAt, readPosition }) => {\n if (this.alive(generation)) this.mergeReads([{ userId, readAt, readPosition }])\n }, report))\n add(() => this.client.onTyping(this.room, ({ userId, isTyping }) => {\n if (!this.alive(generation) || !userId.trim() || userId === this.user) return\n clearTimeout(this.typingTimers.get(userId))\n this.typingTimers.delete(userId)\n const next = new Set(this.state.typingUserIds)\n if (isTyping) {\n next.add(userId)\n this.typingTimers.set(userId, setTimeout(() => {\n this.typingTimers.delete(userId)\n if (!this.alive(generation)) return\n const remaining = new Set(this.state.typingUserIds)\n remaining.delete(userId)\n this.patch({ typingUserIds: remaining })\n }, this.typingTimeout))\n } else next.delete(userId)\n this.patch({ typingUserIds: next })\n }, report))\n } catch (cause) {\n this.detach()\n this.fail(cause, generation)\n throw cause\n }\n }\n\n private validMessage(message: Message): boolean {\n return message.conversationId === this.room && !!message.id.trim()\n && !!message.senderId.trim() && !isConvoKitPendingMessage(message)\n && Number.isFinite(message.createdAt.getTime()) && Number.isFinite(version(message))\n }\n\n private onMessage(event: MessageEvent, generation: number): void {\n const { message, type } = event\n if (!this.alive(generation) || (type !== 'insert' && type !== 'update')\n || !this.validMessage(message) || this.deleted.has(message.id)) return\n const existing = this.state.messages.find((item) => item.id === message.id)\n const known = existing ?? this.changes.get(message.id)?.message\n if (known && older(message, known)) return\n const insert = type === 'insert' || this.changes.get(message.id)?.insert === true\n if (!existing && !insert && type === 'update' && !this.state.isInitialLoading && !this.state.isLoadingOlder && !this.state.isReconciling) return\n const revision = ++this.revision\n // A raw Message row has no related Media; absence is not authoritative removal.\n const provisional = existing && !message.media.length ? { ...message, media: existing.media } : message\n this.record(provisional, insert, revision, false)\n const job: Hydration = { revision, generation, message, insert }\n this.hydrations.set(message.id, job)\n this.hydrationPool.queued.set(message.id, job)\n this.drainHydration()\n }\n\n private record(message: Message, insert: boolean, revision: number, complete: boolean): void {\n const existing = this.state.messages.find((item) => item.id === message.id)\n if (existing && older(message, existing)) return\n // The exact server-echoed send ID also confirms media-only rows before hydration.\n // Keep that send's local media until the complete authorized response arrives.\n if (this.confirmSend(message) && !complete && !message.media.length) {\n message = { ...message, media: this.activeSend!.pending.media }\n this.confirmSend(message)\n }\n this.changes.set(message.id, { revision, message, insert, complete })\n if (!existing && !(insert && hasContent(message))) return\n this.patch({ messages: mergeMessages(this.state.messages, [message]) })\n // A foreign row entering the rendered list is the receive trigger, so a withheld\n // media-only row is acknowledged once its hydration renders it, never before.\n if (!existing && message.senderId !== this.user && (this.options.markReadOnReceive ?? true)) void this.acknowledge(true)\n }\n\n private confirmSend(message: Message): boolean {\n const send = this.activeSend\n if (!send || !this.validMessage(message) || message.senderId !== this.user\n || message.clientMessageId !== send.pending.clientMessageId) return false\n send.confirmed = send.confirmed ? newest(send.confirmed, message) : message\n return true\n }\n\n private currentHydration(job: Hydration): boolean {\n return this.alive(job.generation) && !this.deleted.has(job.message.id) && this.hydrations.get(job.message.id) === job\n }\n\n private removeMessage(id: string): void {\n this.forget(id)\n this.patch({ messages: this.state.messages.filter((message) => message.id !== id) })\n }\n\n /** Tombstone a row learned to be gone; a removed acknowledgement target is re-resolved from what remains. */\n private forget(id: string): void {\n this.deleted.add(id)\n this.changes.delete(id)\n this.hydrations.delete(id)\n this.hydrationPool.queued.delete(id)\n const ack = this.ack\n if (ack.target !== id && ack.acknowledged?.id !== id) return\n ack.unacknowledgeable.add(id)\n if (ack.target === id) ack.followUp = true\n }\n\n private drainHydration(): void {\n const pool = this.hydrationPool\n for (const [id, job] of pool.queued) {\n if (pool.running.size >= 8) break\n if (pool.running.has(id)) continue\n pool.queued.delete(id)\n if (!this.currentHydration(job)) continue\n pool.running.add(id)\n void this.hydrate(job, pool)\n }\n }\n\n private async hydrate(job: Hydration, pool: HydrationPool): Promise<void> {\n const id = job.message.id\n try {\n if (!this.currentHydration(job)) return\n const full = await this.client.getMessage(id)\n if (!this.currentHydration(job)) return\n if (!this.validMessage(full) || full.id !== id || full.senderId !== job.message.senderId || older(full, job.message)) {\n throw new Error('Complete message response does not match the observed resource/revision')\n }\n // Completion is not a fresh change: a later snapshot outranks the originating event.\n this.record(full, job.insert, job.revision, true)\n } catch (cause) {\n if (!this.currentHydration(job)) return\n const status = typeof cause === 'object' && cause !== null && 'status' in cause ? cause.status : undefined\n if (status === 404) this.removeMessage(id)\n this.fail(cause, job.generation)\n this.queueRefresh()\n } finally {\n if (this.hydrations.get(id) === job) this.hydrations.delete(id)\n pool.running.delete(id)\n queueMicrotask(() => { if (this.hydrationPool === pool) this.drainHydration() })\n }\n }\n\n /** Both maps only ever advance: acknowledgement times by time, positions by (createdAt, id). Participants and\n * read events are the only sources; the local user's own read is never written from the device clock.\n */\n private mergeReads(entries: Iterable<ReadEntry>): void {\n const readAt = new Map(this.state.readAtByUserId)\n const positions = new Map(this.state.readPositionByUserId)\n for (const entry of entries) {\n const { userId, readPosition } = entry\n if (!userId.trim()) continue\n if (entry.readAt && Number.isFinite(entry.readAt.getTime()) && entry.readAt.getTime() > (readAt.get(userId)?.getTime() ?? -Infinity)) {\n readAt.set(userId, entry.readAt)\n }\n if (!readPosition || typeof readPosition.messageId !== 'string' || !readPosition.messageId.trim()\n || !(readPosition.createdAt instanceof Date) || !Number.isFinite(readPosition.createdAt.getTime())) continue\n const current = positions.get(userId)\n if (!current || compare(positionCursor(readPosition), positionCursor(current)) > 0) positions.set(userId, readPosition)\n }\n this.patch({ readAtByUserId: readAt, readPositionByUserId: positions })\n }\n\n private validatePage(page: Message[], before?: Cursor): void {\n if (page.length > this.pageSize) throw new Error('Message page exceeds the requested limit')\n let previous = before\n for (const message of page) {\n if (!this.validMessage(message) || (previous && compare(message, previous) >= 0)) {\n throw new Error('Message history must contain distinct, room-scoped rows in newest-first cursor order')\n }\n previous = message\n }\n }\n\n private fetchPage(before?: Cursor): Promise<Message[]> {\n return this.client.getMessages({\n conversationId: this.room, limit: this.pageSize,\n ...(before ? { beforeCreatedAt: before.createdAt, beforeId: before.id } : {}),\n })\n }\n\n private overlay(rows: Message[], revision: number): Message[] {\n const byId = new Map(rows.filter((message) => !this.deleted.has(message.id)).map((message) => [message.id, message]))\n for (const [id, change] of this.changes) {\n if (change.revision > revision && !this.deleted.has(id) && (change.insert || byId.has(id))) {\n const current = byId.get(id)\n if (current || change.complete || hasContent(change.message)) {\n byId.set(id, current ? newest(current, change.message, change.complete) : change.message)\n }\n }\n }\n for (const message of this.state.messages) {\n if (isConvoKitPendingMessage(message)) byId.set(message.id, message)\n }\n return mergeMessages([], [...byId.values()])\n }\n\n private prune(revision: number): void {\n const safeRevision = Math.min(revision, this.sendRevision ?? Infinity)\n for (const [id, change] of this.changes) if (change.revision <= safeRevision) this.changes.delete(id)\n for (const [id, job] of this.hydrations) if (job.revision <= revision) {\n this.hydrations.delete(id)\n this.hydrationPool.queued.delete(id)\n }\n }\n\n loadInitial = async (): Promise<void> => {\n if (!this.alive()) return\n this.clear()\n const generation = this.generation\n this.patch({ ...blank(this.user, this.support), isInitialLoading: true })\n const revision = this.revision\n try {\n this.attach(generation)\n if (!this.alive(generation)) return\n const [conversation, page] = await Promise.all([this.client.getConversation(this.room), this.fetchPage()])\n if (!this.alive(generation)) return\n if (conversation.id !== this.room) throw new Error('Conversation response belongs to a different room')\n this.validatePage(page)\n this.cursor = page.at(-1)\n this.patch({ conversation, messages: this.overlay(page, revision), hasOlderMessages: page.length === this.pageSize })\n // The DTO is in hand before this open's first acknowledgement: capture its private state now.\n this.captured = capture(conversation)\n this.mergeReads(conversation.participants.map(readEntry))\n this.prune(revision)\n // The load acknowledgement also covers an automatic one that waited for the DTO (a row inserted during the load).\n if ((this.options.markReadOnLoad ?? true) || this.ack.suppressed) {\n this.ack.suppressed = false\n await this.acknowledge(true)\n }\n } catch (cause) {\n this.fail(cause, generation, true)\n } finally {\n if (this.alive(generation)) {\n this.patch({ isInitialLoading: false, hasLoaded: true })\n this.flushRefresh()\n }\n }\n }\n\n private queueRefresh(): void {\n this.refreshQueued = true\n this.flushRefresh()\n }\n private flushRefresh(): void {\n const generation = this.generation\n void Promise.resolve().then(() => {\n if (!this.alive(generation) || !this.refreshQueued || this.state.isInitialLoading\n || this.state.isLoadingOlder || this.state.isReconciling) return\n this.refreshQueued = false\n void this.refresh()\n })\n }\n\n /** Re-fetch the entire viewed range atomically; a first-page-only refresh loses history. */\n refresh = async (): Promise<void> => {\n if (!this.alive()) return\n if (this.state.isInitialLoading || this.state.isLoadingOlder || this.state.isReconciling) {\n this.refreshQueued = true\n return\n }\n if (!this.state.hasLoaded || !this.subscriptions.length) return this.loadInitial()\n const generation = this.generation\n const revision = this.revision\n const observed = this.state.messages.filter((message) => !isConvoKitPendingMessage(message))\n .concat([...this.changes.values()].filter((change) => change.insert).map((change) => change.message))\n const boundary = observed.reduce<Cursor | undefined>((oldest, message) =>\n !oldest || compare(message, oldest) < 0 ? message : oldest, this.cursor)\n const previouslyExhausted = !this.state.hasOlderMessages\n this.patch({ isReconciling: true, error: null })\n try {\n const conversation = await this.client.getConversation(this.room)\n if (!this.alive(generation)) return\n if (conversation.id !== this.room) throw new Error('Conversation response belongs to a different room')\n const rows: Message[] = []\n let before: Cursor | undefined\n let hasOlder = true\n while (this.alive(generation)) {\n const page = await this.fetchPage(before)\n if (!this.alive(generation)) return\n this.validatePage(page, before)\n rows.push(...page)\n before = page.at(-1) ?? before\n hasOlder = page.length === this.pageSize\n // An empty previous view has no history range to recover: keep its first\n // returning page bounded even if many messages arrived while offline.\n if (!hasOlder || !boundary || (!previouslyExhausted && before && compare(before, boundary) < 0)) break\n }\n this.cursor = before\n const reconciled = this.overlay(rows, revision)\n const survivingIds = new Set(reconciled.map((message) => message.id))\n const known = this.state.messages.filter((message) => !isConvoKitPendingMessage(message)).map((message) => message.id)\n .concat([...this.changes].filter(([, change]) => change.insert && change.revision <= revision).map(([id]) => id))\n // A missed deletion learned from the full viewed range also defeats late acks/replays.\n for (const id of known) if (!survivingIds.has(id)) this.forget(id)\n // A reconcile after a transient first-load failure is this open's first DTO; replacing one never recaptures.\n const opening = this.state.conversation === null\n this.patch({ conversation, messages: reconciled, hasOlderMessages: hasOlder })\n if (opening) this.captured = capture(conversation)\n this.mergeReads(conversation.participants.map(readEntry))\n this.prune(revision)\n // Rows received while the DTO was missing waited for its version; this open's first DTO issues them.\n if (opening) void this.resumeAcknowledgement()\n } catch (cause) {\n this.fail(cause, generation, true)\n } finally {\n if (this.alive(generation)) {\n this.patch({ isReconciling: false })\n this.flushRefresh()\n }\n }\n }\n\n loadOlderMessages = async (): Promise<void> => {\n if (!this.alive() || !this.state.hasLoaded || this.state.isInitialLoading || this.state.isLoadingOlder\n || this.state.isReconciling || !this.state.hasOlderMessages) return\n const generation = this.generation\n const revision = this.revision\n const cursor = this.cursor\n this.patch({ isLoadingOlder: true, error: null })\n try {\n const page = await this.fetchPage(cursor)\n if (!this.alive(generation)) return\n this.validatePage(page, cursor)\n this.cursor = page.at(-1) ?? cursor\n // Existing live edits always win over an older-page duplicate.\n this.patch({\n messages: this.overlay(mergeMessages(page, this.state.messages), revision),\n hasOlderMessages: page.length === this.pageSize,\n })\n } catch (cause) {\n this.fail(cause, generation, true)\n } finally {\n if (this.alive(generation)) {\n this.patch({ isLoadingOlder: false })\n this.flushRefresh()\n }\n }\n }\n\n /** Acknowledge through the newest rendered row now, regardless of visibility; no acknowledgement without a\n * target (a room opened with a marker that renders nothing clears the marker instead, once).\n */\n markRead = (): Promise<void> => this.alive() ? this.acknowledge(false) : Promise.resolve()\n\n /** Automatic acknowledgements wait while hidden and are re-issued (once) on becoming visible. */\n setVisible = (visible: boolean): void => {\n this.visible = visible\n if (!visible || !this.alive()) return\n void this.resumeAcknowledgement()\n }\n\n /** Re-issue (once) the automatic acknowledgement that waited while hidden or before this open's DTO, if any. */\n private resumeAcknowledgement(): Promise<void> {\n if (!this.ack.suppressed) return Promise.resolve()\n this.ack.suppressed = false\n return this.acknowledge(true)\n }\n\n /** The newest non-pending rendered row by (createdAt, id), never by list index and never a raw realtime\n * row; rows the server does not know are skipped, and nothing at or before the accepted target is re-sent.\n */\n private ackTarget(ack: Acknowledgement): Cursor | undefined {\n let target: Cursor | undefined\n for (const message of this.state.messages) {\n if (isConvoKitPendingMessage(message) || ack.unacknowledgeable.has(message.id)) continue\n if (!target || compare(message, target) > 0) target = { createdAt: message.createdAt, id: message.id }\n }\n return target && (!ack.acknowledged || compare(target, ack.acknowledged) > 0) ? target : undefined\n }\n\n /** Resolves when the request this call issued or joined settles; a follow-up is issued, not awaited. */\n private acknowledge(automatic: boolean): Promise<void> {\n const ack = this.ack\n // Before this open's DTO is in hand there is no captured version to send: a row inserted during the load (or\n // while a transient first-load failure stands) waits for the capture, like it waits while hidden.\n if (automatic && (!this.visible || this.state.conversation === null)) {\n ack.suppressed = true\n return Promise.resolve()\n }\n if (ack.inFlight) {\n ack.followUp = true\n return ack.inFlight\n }\n return this.issue(ack, this.generation) ?? Promise.resolve()\n }\n\n private issue(ack: Acknowledgement, generation: number): Promise<void> | undefined {\n ack.followUp = false\n const target = this.ackTarget(ack)\n // An empty marked room clears its marker in the acknowledgement's slot; nothing else is sent without a target.\n const request = target ? this.send(ack, generation, target) : this.clearMarker(ack, generation)\n if (!request) return undefined\n ack.target = target?.id\n ack.inFlight = request.finally(() => {\n ack.inFlight = undefined\n ack.target = undefined\n if (!this.alive(generation) || !ack.followUp) return\n if (!this.visible) {\n ack.followUp = false\n ack.suppressed = true\n } else this.issue(ack, generation)\n })\n return ack.inFlight\n }\n\n /** A room opened with the caller's unread marker that renders no non-pending, acknowledgeable row cannot clear\n * it through a targeted acknowledgement, so it asks the adapter to clear the marker conditionally on the captured\n * version, once per open, under the acknowledgement triggers and visibility gating. Rows rendered later clear it\n * through their acknowledgements; adapters without the member leave it; `cleared: false` is not an error.\n */\n private clearMarker(ack: Acknowledgement, generation: number): Promise<void> | undefined {\n const captured = this.captured\n if (!captured.clearPending || captured.version === undefined || typeof this.client.clearConversationUnread !== 'function'\n || this.state.messages.some((message) => !isConvoKitPendingMessage(message) && !ack.unacknowledgeable.has(message.id))) return undefined\n captured.clearPending = false\n return this.clearUnread(captured.version, generation)\n }\n\n private async clearUnread(version: number, generation: number): Promise<void> {\n try {\n await this.client.clearConversationUnread!(this.room, { ifVersion: version })\n } catch (cause) {\n if (this.alive(generation)) this.fail(cause, generation)\n }\n }\n\n private async send(ack: Acknowledgement, generation: number, target: Cursor): Promise<void> {\n try {\n // Every targeted acknowledgement of this open carries the version captured when it opened (none on 0.6).\n const version = this.captured.version\n await this.client.markConversationRead(this.room, {\n throughMessageId: target.id, ...(version === undefined ? {} : { privateStateVersion: version }),\n })\n if (!this.alive(generation)) return\n // Only persisted participant positions / server read events advance receipts.\n if (!ack.acknowledged || compare(target, ack.acknowledged) > 0) ack.acknowledged = target\n } catch (cause) {\n if (!this.alive(generation)) return\n if (isTargetMiss(cause)) {\n // The server does not know this target (deleted meanwhile): re-issue once with the next newest row.\n ack.unacknowledgeable.add(target.id)\n ack.followUp = true\n } else this.fail(cause, generation)\n }\n }\n\n updateTyping = async (isTyping: boolean): Promise<void> => {\n if (!this.alive()) return\n const generation = this.generation\n clearTimeout(this.ownTypingTimer)\n if (isTyping) this.ownTypingTimer = setTimeout(() => {\n if (this.alive(generation)) void this.updateTyping(false)\n }, this.typingTimeout)\n const now = performance.now()\n // Renew while keystrokes continue, so the receiver's expiry does not hide\n // someone who is still typing. Idle input never generates a keepalive.\n const renew = isTyping && now - this.lastTypingSentAt >= Math.max(1, this.typingTimeout / 2)\n if (this.sentTyping === isTyping && !renew) return\n const revision = ++this.typingRevision\n this.sentTyping = isTyping\n this.lastTypingSentAt = isTyping ? now : -Infinity\n try {\n await this.client.sendTyping({ conversationId: this.room, isTyping })\n } catch (cause) {\n if (this.alive(generation) && revision === this.typingRevision) {\n this.sentTyping = false\n this.fail(cause, generation)\n }\n }\n }\n\n sendMessage = async ({ text, media }: { text?: string; media?: MessageMedia[] }): Promise<Message | null> => {\n const normalized = text?.trim()\n if (!this.alive() || this.state.isSending || (!normalized && !media?.length)) return null\n const generation = this.generation\n const revision = this.revision\n this.sendRevision = revision\n const clientMessageId = createClientMessageId()\n const pendingId = `convokit-pending-${clientMessageId}`\n const pending: Message = {\n id: pendingId, clientMessageId, conversationId: this.room, senderId: this.user, text: normalized || null,\n media: media ?? [], createdAt: new Date(), updatedAt: null, revision: 0,\n }\n const send = { pending } as { pending: Message; confirmed?: Message }\n this.activeSend = send\n this.patch({ messages: mergeMessages(this.state.messages, [pending]), isSending: true, error: null })\n try {\n const message = await this.client.sendMessage({\n conversationId: this.room, clientMessageId, ...(normalized ? { text: normalized } : {}), ...(media?.length ? { media } : {}),\n })\n if (!this.alive(generation)) return null\n if (!this.validMessage(message) || message.senderId !== this.user) throw new Error('Send response belongs to a different room or sender')\n if (message.clientMessageId && message.clientMessageId !== clientMessageId) throw new Error('Send response belongs to a different send')\n const live = this.changes.get(message.id)\n const existing = this.state.messages.find((item) => item.id === message.id)\n let latest = existing ? newest(message, existing, live?.complete !== false) : message\n if (live && live.revision > revision) latest = newest(latest, live.message, live.complete)\n if (!this.deleted.has(message.id)) this.changes.set(message.id, { revision: ++this.revision, message: latest, insert: true, complete: true })\n this.patch({ messages: mergeMessages(\n this.state.messages.filter((item) => item.id !== pendingId),\n this.deleted.has(message.id) ? [] : [latest],\n ) })\n void this.updateTyping(false)\n return this.alive(generation) ? latest : null\n } catch (cause) {\n if (this.alive(generation)) {\n this.patch({ messages: this.state.messages.filter((item) => item.id !== pendingId) })\n // A live/history confirmation is authoritative even if its HTTP acknowledgement was lost.\n // Returning success clears the composer; deleted confirmations are never reinserted.\n if (send.confirmed) {\n void this.updateTyping(false)\n return send.confirmed\n }\n this.fail(cause, generation)\n }\n return null\n } finally {\n if (this.alive(generation)) {\n this.sendRevision = undefined\n this.activeSend = undefined\n this.patch({ isSending: false })\n }\n }\n }\n\n /** The caller's role in the open room when known (0.7 `membership`, else the caller's participant row). */\n private ownRole(): string | undefined {\n const conversation = this.state.conversation\n return conversation?.membership?.role\n ?? conversation?.participants.find((participant) => participant.appUserId === this.user || participant.id === this.user)?.role\n }\n\n /** A rendered, confirmed row of the caller's own that is not known to be gone. */\n private ownRow(messageId: string): Message | undefined {\n const row = this.state.messages.find((message) => message.id === messageId)\n return row && row.senderId === this.user && !isConvoKitPendingMessage(row) && !this.deleted.has(messageId) ? row : undefined\n }\n\n /** Enter edit mode on one of the caller's own confirmed messages (0.8.0): the row as it stands now becomes the\n * snapshot whose `revision` every save sends. A no-op unless the adapter implements `editMessage`, the row is\n * rendered, own, confirmed, not tombstoned and the caller's role (when known) is not `READ`. Sends nothing.\n */\n startEditing = (messageId: string): void => {\n if (!this.alive() || !this.support.edit || this.ownRole() === 'READ') return\n const row = this.ownRow(messageId)\n if (row) this.patch({ editingMessage: row })\n }\n\n /** Leave edit mode without a request; the draft is the view's to restore. */\n cancelEditing = (): void => {\n if (this.state.editingMessage) this.patch({ editingMessage: null })\n }\n\n /** Save the edit in progress with the snapshot's revision (never the live row's), trimming the text and sending\n * `null` for an empty caption. Resolves true when the server accepted the edit (the response is merged through the\n * tombstone and precedence guards and edit mode ends); false when nothing was saved: a stale revision (409\n * `REVISION_CONFLICT`) reloads the row once through `getMessage`, replaces the snapshot with it (the next save\n * carries the fresh revision) and reports the conflict through `error`, keeping edit mode; a coded 404\n * (`MESSAGE_NOT_FOUND`, on the save or on that reload) removes the row and ends edit mode; any other failure\n * (403, 500, network, an uncoded 404 from a 0.7 backend) is reported through `error` without evicting anything and\n * keeps edit mode; if a newer row for the message arrived during such a request, that row is then the local\n * conflict (`settleEditing`). A text-only message cannot be saved empty (no request). Rejects when the adapter\n * lacks `editMessage`.\n */\n saveEdit = async (text: string): Promise<boolean> => {\n const client = this.client\n if (typeof client.editMessage !== 'function') {\n throw new TypeError('This ConvoKitUiClient adapter does not implement editMessage (0.8)')\n }\n const snapshot = this.state.editingMessage\n if (!this.alive() || !snapshot || this.activeEdit !== undefined) return false\n const trimmed = text.trim()\n const normalized = trimmed === '' ? null : trimmed\n if (normalized === null && snapshot.media.length === 0) return false\n const generation = this.generation\n const id = snapshot.id\n this.activeEdit = id\n this.patch({ error: null })\n try {\n const message = await client.editMessage(id, { text: normalized, revision: snapshot.revision })\n if (!this.alive(generation)) return false\n if (!this.validMessage(message) || message.id !== id || message.senderId !== this.user) {\n throw new Error('Edit response belongs to a different message or sender')\n }\n // Edit mode ends before the merge so the accepted row is not mistaken for a local conflict.\n if (this.state.editingMessage?.id === id) this.patch({ editingMessage: null })\n this.applyRow(message)\n return true\n } catch (cause) {\n if (!this.alive(generation)) return false\n if (isRevisionConflict(cause)) await this.reloadConflict(id, cause, generation)\n else if (isMessageMissing(cause)) {\n this.removeMessage(id)\n this.patch({ error: cause })\n } else this.fail(cause, generation)\n return false\n } finally {\n if (this.alive(generation)) {\n this.activeEdit = undefined\n this.settleEditing(id)\n }\n }\n }\n\n /** Merge a complete REST row for a known id through the live-row guards: a tombstoned id is dropped, and an older\n * revision (or timestamp) never overwrites the newer row already recorded. Recorded as a non-insert change, so a\n * reconcile keeps it only while the row is still in the fetched range.\n */\n private applyRow(message: Message): void {\n if (this.deleted.has(message.id)) return\n this.record(message, this.changes.get(message.id)?.insert === true, ++this.revision, true)\n }\n\n /** The 409 path: one `getMessage` shows the conflicting content. Its row is merged through the guards and becomes\n * the new snapshot; a `MESSAGE_NOT_FOUND` answer removes the row and ends edit mode; another failure keeps the\n * snapshot. `error` carries the conflict (or the reload failure).\n */\n private async reloadConflict(id: string, conflict: unknown, generation: number): Promise<void> {\n try {\n const current = await this.client.getMessage(id)\n if (!this.alive(generation)) return\n if (!this.validMessage(current) || current.id !== id) throw new Error('Complete message response does not match the edited message')\n this.applyRow(current)\n const row = this.state.messages.find((message) => message.id === id)\n const editing = this.state.editingMessage?.id === id && row ? { editingMessage: row } : {}\n this.patch({ ...editing, error: conflict })\n } catch (cause) {\n if (!this.alive(generation)) return\n if (isTargetMiss(cause)) this.removeMessage(id)\n this.patch({ error: cause })\n }\n }\n\n /** Delete one of the caller's own confirmed messages (0.8.0). The row stays until the server answers: on success,\n * or when the server no longer knows it (`MESSAGE_NOT_FOUND`), it is tombstoned and removed (late responses, row\n * images and hydrations for it are dropped, the acknowledgement target is re-resolved and edit mode on it ends)\n * and the call resolves true; any other failure keeps the row, reports through `error` and resolves false. Rejects\n * when the adapter lacks `deleteMessage`.\n */\n deleteMessage = async (messageId: string): Promise<boolean> => {\n const client = this.client\n if (typeof client.deleteMessage !== 'function') {\n throw new TypeError('This ConvoKitUiClient adapter does not implement deleteMessage (0.8)')\n }\n if (!this.alive() || !this.ownRow(messageId)) return false\n const generation = this.generation\n this.patch({ error: null })\n try {\n await client.deleteMessage(messageId)\n } catch (cause) {\n if (!this.alive(generation)) return false\n if (!isMessageMissing(cause)) {\n this.fail(cause, generation)\n return false\n }\n }\n if (!this.alive(generation)) return false\n this.removeMessage(messageId)\n return true\n }\n\n readerIdsFor = (message: Message): ReadonlySet<string> =>\n readerIdsFor(message, this.state.readAtByUserId, this.state.readPositionByUserId)\n}\n","import type { Conversation, Message, MessageMedia, ReadPosition } from '@convokitapp/sdk'\nimport { isEditedMessage } from '@convokitapp/sdk'\nimport {\n Check,\n CheckCheck,\n ContactRound,\n Download,\n FileText,\n ImageOff,\n LoaderCircle,\n MapPin,\n MessageCircle,\n Pencil,\n Trash2,\n} from '@lucide/vue'\nimport {\n computed,\n defineComponent,\n h,\n nextTick,\n ref,\n watch,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type {\n ConvoKitAppearanceProps,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n MediaSlotProps,\n MessageSlotProps,\n ReadReceiptSlotProps,\n} from '../types'\nimport { cx, errorMessage, formatFileSize, formatMessageTime, isConvoKitPendingMessage, partClass, partStyle, readerIdsFor } from '../utils'\n\nexport interface MessageListViewProps extends ConvoKitAppearanceProps {\n conversation: Conversation\n messages: readonly Message[]\n currentUserId: string\n /** Acknowledgement times; the fallback for users without a read position. */\n readAtByUserId?: ReadonlyMap<string, Date>\n /** Read-through positions; a user's position decides their receipts whenever one is present. */\n readPositionByUserId?: ReadonlyMap<string, ReadPosition>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onLoadOlder?: () => void | Promise<void>\n hasOlderMessages?: boolean\n isLoadingOlder?: boolean\n error?: unknown\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n /** Start editing a message (0.8.0). Without it no row offers an edit action and the markup is unchanged. */\n onEditMessage?: (message: Message) => void\n /** Delete a message after confirmation (0.8.0); `false` means the deletion was not accepted. Without it no row\n * offers a delete action.\n */\n onDeleteMessage?: (message: Message) => boolean | void | Promise<boolean | void>\n /** Replaces the default eligibility (the viewer's own confirmed rows while the viewer's role is not `READ`) for\n * both actions; pending rows are never eligible.\n */\n canEditMessage?: (message: Message) => boolean\n /** Replaces the row's inline \"Delete this message?\" prompt (and confirms `remove()` from custom rows). */\n confirmDelete?: (message: Message) => boolean | Promise<boolean>\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n reverse?: boolean\n stickToBottom?: boolean\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nfunction defaultMedia(\n media: MessageMedia,\n open: (() => void) | undefined,\n imageLoading: 'eager' | 'lazy',\n): VNodeChild {\n const tag = open ? 'button' : 'div'\n const interactive = open ? { type: 'button', onClick: open } : {}\n if (media.type === 'image') {\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--image' }, [\n media.url\n ? h('img', { src: media.url, alt: media.name ?? 'Shared image', loading: imageLoading })\n : h('span', { class: 'ckui-media-placeholder' }, [h(ImageOff, { 'aria-hidden': 'true' }), ' Image unavailable']),\n media.name ? h('span', { class: 'ckui-media-name' }, media.name) : null,\n ])\n }\n if (media.type === 'file') {\n const size = formatFileSize(media.size)\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--file' }, [\n h(FileText, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Attachment'), size ? h('small', size) : null]),\n open ? h(Download, { size: 18, 'aria-hidden': 'true' }) : null,\n ])\n }\n if (media.type === 'location') {\n const label = media.name || `${media.metadata.lat}, ${media.metadata.lng}`\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--location' }, [\n h(MapPin, { 'aria-hidden': 'true' }),\n h('span', [h('strong', label), h('small', `${media.metadata.lat}, ${media.metadata.lng}`)]),\n ])\n }\n const contact = media.metadata.email || media.metadata.phone || 'Contact details'\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--contact' }, [\n h(ContactRound, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Shared contact'), h('small', String(contact))]),\n ])\n}\n\n/** Controlled message history with read receipts, structured media, and older-page loading. */\nexport const MessageListView = defineComponent({\n name: 'MessageListView',\n inheritAttrs: false,\n props: {\n ...appearanceProps,\n conversation: { type: Object as PropType<Conversation>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readPositionByUserId: { type: Object as PropType<ReadonlyMap<string, ReadPosition>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n hasOlderMessages: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n onEditMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onDeleteMessage: { type: Function as PropType<(message: Message) => boolean | void | Promise<boolean | void>>, default: undefined },\n canEditMessage: { type: Function as PropType<(message: Message) => boolean>, default: undefined },\n confirmDelete: { type: Function as PropType<(message: Message) => boolean | Promise<boolean>>, default: undefined },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n reverse: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: formatMessageTime },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n },\n emits: ['load-older', 'attachment-click', 'edit-message', 'delete-message'],\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n /** The row whose inline \"Delete this message?\" prompt is open. */\n const confirming = ref<string | null>(null)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n let previousMessageCount = 0\n const participants = computed(() => new Map(props.conversation.participants.flatMap((participant) => [\n [participant.id, participant] as const,\n [participant.appUserId, participant] as const,\n ])))\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestOlder = async () => {\n if (requestInFlight || lastRequestedLength === props.messages.length || props.isLoadingOlder || !props.hasOlderMessages || !props.onLoadOlder) return\n requestInFlight = true\n lastRequestedLength = props.messages.length\n try { await props.onLoadOlder() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n watch(() => [props.messages.length, props.hasOlderMessages] as const, async ([count, hasOlder]) => {\n const previous = previousMessageCount\n if (count !== previousMessageCount || !hasOlder) lastRequestedLength = null\n const appended = count > previous\n const element = internalElement.value\n previousMessageCount = count\n if (element && props.reverse && props.stickToBottom && appended) {\n const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight\n if (previous === 0 || distanceFromBottom < 320) {\n await nextTick()\n element.scrollTop = element.scrollHeight\n }\n }\n }, { flush: 'post', immediate: true })\n\n /** The viewer's role when the room knows it: the 0.7 `membership` sibling, else the viewer's participant row. */\n const viewerRole = computed(() => props.conversation.membership?.role\n ?? props.conversation.participants.find((participant) => participant.appUserId === props.currentUserId || participant.id === props.currentUserId)?.role)\n /** Delete after confirmation: `confirmDelete` when the view has one, otherwise at once (custom rows own their\n * prompt; the default row opens its inline prompt instead of calling this without one).\n */\n const remove = async (message: Message): Promise<boolean> => {\n if (props.confirmDelete && !(await props.confirmDelete(message))) return false\n return (await props.onDeleteMessage?.(message)) !== false\n }\n\n const renderMessage = (message: Message, index: number): VNodeChild => {\n const isCurrentUser = message.senderId === props.currentUserId\n const sender = participants.value.get(message.senderId)\n const isPending = isConvoKitPendingMessage(message)\n const readerIds = isPending\n ? new Set<string>()\n : props.readersResolver ? props.readersResolver(message) : readerIdsFor(message, props.readAtByUserId, props.readPositionByUserId)\n const isEdited = !isPending && isEditedMessage(message)\n const eligible = !isPending && (props.canEditMessage ? props.canEditMessage(message) : isCurrentUser && viewerRole.value !== 'READ')\n const canEdit = eligible && !!props.onEditMessage\n const canDelete = eligible && !!props.onDeleteMessage\n const edit = () => { props.onEditMessage?.(message) }\n const slotProps: MessageSlotProps = {\n message, chronologicalIndex: index, isCurrentUser, sender, readerIds, isEdited, canEdit, canDelete,\n ...(canEdit ? { edit } : {}),\n ...(canDelete ? { remove: () => remove(message) } : {}),\n }\n const custom = slots.message?.(slotProps)\n if (custom) return h('div', { key: message.id, role: 'listitem' }, custom)\n const currentAppearance = appearance()\n const messagePart = isCurrentUser ? 'outgoingMessage' : 'incomingMessage'\n const iconButton = (label: string, onClick: () => void, icon: VNodeChild) => h('button', {\n type: 'button', 'aria-label': label, onClick,\n class: partClass('button', currentAppearance, 'ckui-icon-button'),\n style: partStyle('button', currentAppearance),\n }, [icon])\n const actions = canEdit || canDelete ? h('div', { class: 'ckui-message-actions' }, [\n ...(canEdit ? [iconButton('Edit message', edit, h(Pencil, { size: 16, 'aria-hidden': 'true' }))] : []),\n ...(canDelete ? [iconButton('Delete message', () => {\n if (props.confirmDelete) void remove(message)\n else confirming.value = message.id\n }, h(Trash2, { size: 16, 'aria-hidden': 'true' }))] : []),\n ]) : null\n const confirm = canDelete && confirming.value === message.id ? h('div', {\n class: 'ckui-message-confirm', role: 'group', 'aria-label': 'Delete this message?',\n }, [\n h('span', 'Delete this message?'),\n h('button', {\n type: 'button', class: 'ckui-link-button', 'aria-label': 'Confirm delete',\n onClick: () => { confirming.value = null; void props.onDeleteMessage?.(message) },\n }, 'Delete'),\n h('button', {\n type: 'button', class: 'ckui-link-button', 'aria-label': 'Cancel delete',\n onClick: () => { confirming.value = null },\n }, 'Cancel'),\n ]) : null\n const mediaNodes = message.media.map((media, mediaIndex) => {\n const open = props.onAttachmentClick\n ? () => {\n props.onAttachmentClick?.(media, message)\n }\n : undefined\n const mediaSlotProps: MediaSlotProps = { media, message, isCurrentUser, ...(open ? { open } : {}) }\n return h('div', {\n key: media.id ?? `${media.type}-${mediaIndex}`,\n class: partClass('media', currentAppearance, 'ckui-media'),\n style: partStyle('media', currentAppearance),\n }, slots.media?.(mediaSlotProps) ?? [defaultMedia(media, open, props.imageLoading)])\n })\n const receiptSlotProps: ReadReceiptSlotProps = { message, readerIds }\n return h('div', { key: message.id, role: 'listitem' }, [\n h('article', {\n class: cx(\n !props.unstyled && 'ckui-message-row',\n isCurrentUser && !props.unstyled && 'ckui-message-row--outgoing',\n props.classNames?.message,\n props.classNames?.[messagePart],\n ),\n style: [props.styles?.message, props.styles?.[messagePart]],\n 'data-message-id': message.id,\n }, [\n // Spread, not null: an absent action/label/prompt must not leave a comment node (0.7 markup stays byte-identical).\n ...(actions ? [actions] : []),\n h('div', { class: 'ckui-message-bubble' }, [\n !isCurrentUser ? h('strong', { class: 'ckui-message-sender' }, sender?.name || message.senderId) : null,\n message.text ? h('div', { class: 'ckui-message-text' }, message.text) : null,\n ...mediaNodes,\n h('span', { class: 'ckui-message-time' }, [\n isPending ? 'Sending…' : props.formatTime(message.createdAt),\n ...(isEdited ? [h('span', { class: 'ckui-message-edited', 'aria-label': 'Edited' }, 'Edited')] : []),\n isCurrentUser && !isPending\n ? readerIds.size > 0\n ? h(CheckCheck, { size: 14, 'aria-label': 'Read' })\n : h(Check, { size: 14, 'aria-label': 'Sent' })\n : null,\n ]),\n ]),\n ...(confirm ? [confirm] : []),\n isCurrentUser && !isPending\n ? slots['read-receipt']?.(receiptSlotProps) ?? h('div', {\n class: partClass('receipt', currentAppearance, 'ckui-read-receipt'),\n style: partStyle('receipt', currentAppearance),\n }, readerIds.size > 0 ? `Read by ${readerIds.size}` : 'Sent')\n : null,\n ]),\n ])\n }\n\n return () => {\n const currentAppearance = appearance()\n const children: VNodeChild[] = []\n if (props.isLoadingOlder) {\n children.push(slots['loading-older']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading older messages…']))\n }\n if (props.error) {\n const retry = props.onLoadOlder ? () => { void requestOlder() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null,\n ]))\n }\n if (props.messages.length === 0 && !props.isLoadingOlder) {\n children.push(slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(MessageCircle, { 'aria-hidden': 'true' }), ' No messages yet']))\n } else {\n children.push(...props.messages.map(renderMessage))\n }\n return h('div', {\n ...attrs,\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui ckui-message-list', props.classNames?.messages, attrs.class),\n style: [props.styles?.messages, attrs.style],\n 'data-density': props.density,\n role: 'log',\n 'aria-live': 'polite',\n 'aria-label': `Messages in ${props.conversation.displayTitle}`,\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n const element = event.currentTarget as HTMLElement\n const distanceFromOldest = props.reverse\n ? element.scrollTop\n : element.scrollHeight - element.scrollTop - element.clientHeight\n if (distanceFromOldest <= props.paginationThreshold) void requestOlder()\n },\n }, children)\n }\n },\n})\n\nexport function defaultReadersResolver(\n readAtByUserId: ReadonlyMap<string, Date>,\n readPositionByUserId: ReadonlyMap<string, ReadPosition> = new Map(),\n): (message: Message) => ReadonlySet<string> {\n return (message) => readerIdsFor(message, readAtByUserId, readPositionByUserId)\n}\n","import type { Conversation, InboxSummary } from '@convokitapp/sdk'\nimport { ChevronRight, Inbox, LoaderCircle, RefreshCw } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n ref,\n watchEffect,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationListController, UseConversationListOptions } from '../composables/use-conversation-list'\nimport { useConversationList } from '../composables/use-conversation-list'\nimport type {\n ConversationFilter,\n ConversationItemSlotProps,\n ConversationPageLoader,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n} from '../types'\nimport { cx, errorMessage, formatMessageTime, inboxPreview, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\n\nexport interface ConversationListViewProps extends ConvoKitAppearanceProps {\n conversations: readonly Conversation[]\n /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge: the count, or\n * a numberless dot when `isUnread` is set without one (0.7.0).\n */\n summaries?: ReadonlyMap<string, InboxSummary>\n /** The viewer; a preview from them reads `You: …`. Absent → no prefix. */\n currentUserId?: string\n selectedConversationId?: string\n onConversationSelect?: (conversation: Conversation) => void\n onRefresh?: () => void | Promise<void>\n onLoadMore?: () => void | Promise<void>\n isInitialLoading?: boolean\n isLoadingMore?: boolean\n hasMore?: boolean\n error?: unknown\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n ariaLabel?: string\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst listViewProps = {\n ...appearanceProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, required: true },\n summaries: { type: Object as PropType<ReadonlyMap<string, InboxSummary>>, default: undefined },\n currentUserId: { type: String, default: undefined },\n selectedConversationId: { type: String, default: undefined },\n onConversationSelect: { type: Function as PropType<(conversation: Conversation) => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadMore: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingMore: { type: Boolean, default: false },\n hasMore: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n ariaLabel: { type: String, default: 'Conversations' },\n} as const\n\n/** Controlled conversation list. It can be used with any state-management layer. */\nexport const ConversationListView = defineComponent({\n name: 'ConversationListView',\n inheritAttrs: false,\n props: listViewProps,\n emits: {\n 'conversation-select': (_conversation: Conversation) => true,\n refresh: () => true,\n 'load-more': () => true,\n },\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestMore = async () => {\n if (requestInFlight || lastRequestedLength === props.conversations.length || props.isInitialLoading || props.isLoadingMore || !props.hasMore || !props.onLoadMore) return\n requestInFlight = true\n lastRequestedLength = props.conversations.length\n try { await props.onLoadMore() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n const selectConversation = (conversation: Conversation) => {\n props.onConversationSelect?.(conversation)\n }\n\n const refresh = () => {\n return props.onRefresh?.()\n }\n\n /** Inline errors retry the next page when one is pending (past the duplicate guard), otherwise refresh. */\n const inlineRetry = (): (() => void) | undefined => {\n if (props.hasMore && props.onLoadMore) return () => { lastRequestedLength = null; void requestMore() }\n if (props.onRefresh) return () => { void refresh() }\n return undefined\n }\n\n /** A count (or a capped count) keeps the numeric badge; a marker without one is a numberless dot named\n * `Unread` (never `0 unread`). Returned as a spread so an absent badge adds no child.\n */\n const unreadBadge = (summary: InboxSummary): VNodeChild[] => {\n if (summary.unreadCount > 0 || summary.unreadCountCapped) {\n const capped = summary.unreadCountCapped || summary.unreadCount > 99\n return [h('span', {\n class: 'ckui-unread-badge',\n role: 'img',\n 'aria-label': `${summary.unreadCountCapped ? '99+' : summary.unreadCount} unread`,\n }, [h('span', { 'aria-hidden': 'true' }, capped ? '99+' : String(summary.unreadCount))])]\n }\n if (summary.isUnread) return [h('span', { class: 'ckui-unread-badge ckui-unread-badge--dot', role: 'img', 'aria-label': 'Unread' })]\n return []\n }\n\n const renderContent = () => {\n const currentAppearance = appearance()\n if (props.isInitialLoading && props.conversations.length === 0) {\n return slots['initial-loading']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversations…'])\n }\n if (props.error && props.conversations.length === 0) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n return slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again') : null,\n ])\n }\n if (props.conversations.length === 0) {\n return slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(Inbox, { 'aria-hidden': 'true' }), ' No conversations yet'])\n }\n const children: VNodeChild[] = props.conversations.flatMap((conversation, index) => {\n const selected = props.selectedConversationId === conversation.id\n const select = () => selectConversation(conversation)\n const summary = props.summaries?.get(conversation.id)\n const slotProps: ConversationItemSlotProps = {\n conversation, index, selected, select,\n ...(summary ? { summary } : {}),\n ...(props.currentUserId === undefined ? {} : { currentUserId: props.currentUserId }),\n }\n const preview = inboxPreview(conversation, summary, props.currentUserId)\n // Consumer-built summaries that omit `isUnread` keep their count-driven badges.\n const unread = summary !== undefined && (summary.isUnread || summary.unreadCount > 0 || summary.unreadCountCapped)\n const item = slots['conversation-item']?.(slotProps) ?? h('button', {\n type: 'button',\n 'data-selected': selected || undefined,\n 'data-unread': unread || undefined,\n 'aria-current': selected ? 'true' : undefined,\n onClick: select,\n class: partClass('listItem', currentAppearance, 'ckui-conversation-item'),\n style: partStyle('listItem', currentAppearance),\n }, [\n h(ConvoKitAvatar, {\n name: conversation.displayTitle,\n src: conversation.imageUrl,\n class: partClass('avatar', currentAppearance, ''),\n style: partStyle('avatar', currentAppearance),\n } as never),\n h('span', { class: 'ckui-conversation-item__body' }, [\n h('strong', conversation.displayTitle),\n h('span', preview || conversation.participants.map((participant) => participant.name).join(', ') || conversation.description || 'No participants'),\n ]),\n // Spread rather than emit `null`: a null child renders a `<!---->` comment, and rows without a\n // summary must keep 0.5's exact markup.\n ...(summary ? [h('span', { class: 'ckui-conversation-item__meta' }, [\n h('time', { class: 'ckui-conversation-item__time', datetime: summary.activityAt.toISOString() }, formatMessageTime(summary.activityAt)),\n ...unreadBadge(summary),\n ])] : []),\n h(ChevronRight, { size: 18, 'aria-hidden': 'true' }),\n ])\n const nodes = [h('div', { key: conversation.id, role: 'listitem' }, [item])]\n if (index < props.conversations.length - 1) {\n nodes.push(h('div', { key: `${conversation.id}-separator` }, slots.separator?.({ index }) ?? h('div', { class: 'ckui-separator' })))\n }\n return nodes\n })\n if (props.error) {\n const retry = inlineRetry()\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n ...(retry ? [h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry')] : []),\n ]))\n } else if (props.isLoadingMore) {\n children.push(slots['load-more']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading more…']))\n }\n return h('div', {\n role: 'list',\n class: partClass('list', currentAppearance, 'ckui-conversation-list__items'),\n style: partStyle('list', currentAppearance),\n }, children)\n }\n\n return () => h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation-list', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, [\n props.onRefresh ? h('div', { class: 'ckui-conversation-list__toolbar' }, [\n h('span', props.ariaLabel),\n h('button', {\n type: 'button',\n 'aria-label': 'Refresh conversations',\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n onClick: () => { void refresh() },\n }, [h(RefreshCw, { size: 17, 'aria-hidden': 'true' })]),\n ]) : null,\n h('div', {\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui-scroll-area', props.classNames?.list),\n style: props.styles?.list,\n 'aria-label': props.ariaLabel,\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n const element = event.currentTarget as HTMLElement\n if (element.scrollHeight - element.scrollTop - element.clientHeight <= props.paginationThreshold) void requestMore()\n },\n }, [renderContent()]),\n ])\n },\n})\n\nexport interface ConversationListProps extends Omit<ConversationListViewProps,\n 'conversations' | 'onRefresh' | 'onLoadMore' | 'isInitialLoading' | 'isLoadingMore' | 'hasMore' | 'error'>,\n Omit<UseConversationListOptions, 'client'> {\n client: ConvoKitUiClient\n onControllerChange?: (controller: ConversationListController) => void\n}\n\n/** Plug-and-play SDK-backed conversation list. */\nexport const ConversationList = defineComponent({\n name: 'ConversationList',\n inheritAttrs: false,\n props: {\n ...listViewProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, default: () => [] },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n pageLoader: { type: Function as PropType<ConversationPageLoader>, default: undefined },\n initialFilter: { type: Object as PropType<ConversationFilter>, default: undefined },\n pageSize: { type: Number, default: 30 },\n autoLoad: { type: Boolean, default: true },\n activityRefreshWindowMs: { type: Number, default: undefined },\n onControllerChange: { type: Function as PropType<(controller: ConversationListController) => void>, default: undefined },\n },\n emits: ['conversation-select', 'controller-change'],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversationList({\n client: () => props.client,\n ...(props.pageLoader ? { pageLoader: props.pageLoader } : {}),\n ...(props.initialFilter ? { initialFilter: props.initialFilter } : {}),\n pageSize: props.pageSize,\n autoLoad: props.autoLoad,\n ...(props.activityRefreshWindowMs === undefined ? {} : { activityRefreshWindowMs: props.activityRefreshWindowMs }),\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n return () => {\n const {\n client: _client,\n pageLoader: _pageLoader,\n initialFilter: _initialFilter,\n pageSize: _pageSize,\n autoLoad: _autoLoad,\n activityRefreshWindowMs: _activityRefreshWindowMs,\n onControllerChange: _onControllerChange,\n conversations: _conversations,\n summaries: _summaries,\n currentUserId: _currentUserId,\n onRefresh: _onRefresh,\n onLoadMore: _onLoadMore,\n isInitialLoading: _isInitialLoading,\n isLoadingMore: _isLoadingMore,\n hasMore: _hasMore,\n error: _error,\n ...forwarded\n } = props\n return h(ConversationListView, {\n ...attrs,\n ...forwarded,\n conversations: controller.conversations.value,\n summaries: controller.summaries.value,\n currentUserId: controller.currentUserId.value,\n onRefresh: controller.refresh,\n onLoadMore: controller.loadMore,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingMore: controller.isLoadingMore.value,\n hasMore: controller.hasMore.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n onConversationSelect: (conversation: Conversation) => {\n emit('conversation-select', conversation)\n },\n } as never, slots)\n }\n },\n})\n","import type { ClearConversationUnreadOptions } from '@convokitapp/sdk'\nimport { computed, getCurrentScope, onScopeDispose, shallowRef, toValue, watch, type MaybeRefOrGetter } from 'vue'\nimport type { ConversationFilter, ConversationListState, ConversationPageLoader, ConvoKitUiClient } from '../types'\nimport { ConversationListStore, type ConversationListSnapshot } from '../conversation-list-store'\n\nexport interface UseConversationListOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n pageLoader?: ConversationPageLoader\n initialFilter?: ConversationFilter\n pageSize?: number\n autoLoad?: boolean\n /** Max-wait window (ms) that coalesces `inbox_activity` signals into one refresh; default 500, 0 = immediate. */\n activityRefreshWindowMs?: number\n}\nexport interface ConversationListController extends ConversationListState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadMore(): Promise<void>\n setFilter(filter: ConversationFilter): Promise<void>\n setQuery(query: string): Promise<void>\n /** Mark a room unread for the viewer only (0.7.0); its summary shows the marker at once. Rejects when the adapter\n * lacks `markConversationUnread`.\n */\n markUnread(conversationId: string): Promise<void>\n /** Remove the viewer's marker, only while it still has `options.ifVersion` when given; resolves to whether this\n * request removed it. Rejects when the adapter lacks `clearConversationUnread`.\n */\n clearUnread(conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean>\n dispose(): Promise<void>\n}\n\nexport function useConversationList(options: UseConversationListOptions): ConversationListController {\n const createStore = () => new ConversationListStore({ ...options, client: toValue(options.client) })\n let store = createStore()\n const snapshot = shallowRef(store.getSnapshot())\n let unsubscribe: (() => void) | undefined\n const stop = watch(\n () => [toValue(options.client), toValue(options.client).sessionIdentity] as const,\n () => {\n store.dispose()\n unsubscribe?.()\n store = createStore()\n snapshot.value = store.getSnapshot()\n unsubscribe = store.subscribe(() => { snapshot.value = store.getSnapshot() })\n store.start(options.autoLoad ?? true)\n },\n { immediate: true, flush: 'sync' },\n )\n const field = <K extends keyof ConversationListSnapshot>(key: K) => computed(() => snapshot.value[key])\n const dispose = async () => {\n stop()\n store.dispose()\n unsubscribe?.()\n unsubscribe = undefined\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n return {\n conversations: field('conversations'), summaries: field('summaries'), currentUserId: field('currentUserId'),\n filter: field('filter'),\n isInitialLoading: field('isInitialLoading'), isLoadingMore: field('isLoadingMore'),\n hasMore: field('hasMore'), hasLoaded: field('hasLoaded'), error: field('error'),\n loadInitial: () => store.loadInitial(), refresh: () => store.refresh(),\n loadMore: () => store.loadMore(), setFilter: (filter) => store.setFilter(filter),\n setQuery: (query) => store.setQuery(query),\n markUnread: (conversationId) => store.markUnread(conversationId),\n clearUnread: (conversationId, options) => store.clearUnread(conversationId, options),\n dispose,\n }\n}\n","import type {\n ClearConversationUnreadOptions, Conversation, ConversationPrivateState, InboxEntry, InboxPage, InboxSummary, RealtimeSubscription,\n} from '@convokitapp/sdk'\nimport type { ConversationFilter, ConversationPageLoader, ConvoKitUiClient } from './types'\nimport { applyConversationFilter, mergeConversations, mergeInboxEntries } from './utils'\n\nexport interface ConversationListSnapshot {\n conversations: Conversation[]\n summaries: ReadonlyMap<string, InboxSummary>\n currentUserId: string\n filter: ConversationFilter\n isInitialLoading: boolean\n isLoadingMore: boolean\n hasMore: boolean\n hasLoaded: boolean\n error: unknown\n}\ninterface Options {\n client: ConvoKitUiClient\n pageLoader?: ConversationPageLoader\n initialFilter?: ConversationFilter\n pageSize?: number\n /** Max-wait window for coalescing `inbox_activity` signals into one refresh; 0 refreshes immediately. */\n activityRefreshWindowMs?: number\n}\nconst defaultActivityRefreshWindowMs = 500\nfunction blank(filter: ConversationFilter): ConversationListSnapshot {\n return {\n conversations: [], summaries: new Map(), currentUserId: '', filter,\n isInitialLoading: false, isLoadingMore: false, hasMore: true, hasLoaded: false, error: null,\n }\n}\nfunction statusOf(cause: unknown): unknown {\n return typeof cause === 'object' && cause !== null && 'status' in cause ? cause.status : undefined\n}\nfunction summaryOf(entry: InboxEntry): InboxSummary {\n const { conversation: _conversation, ...summary } = entry\n return summary\n}\nfunction ids(entries: readonly InboxEntry[]): Conversation[] { return entries.map((entry) => entry.conversation) }\n\n/** Session-owned inbox paging. A page loader must belong to the same authenticated app.\n *\n * Inbox mode (an adapter with `listInbox`, no custom page loader, endpoint available) pages by opaque cursor in\n * activity order and carries per-room summaries; every other configuration is the legacy offset path over\n * `getConversations`, unchanged from 0.5 and without summaries.\n */\nexport class ConversationListStore {\n private readonly owner: object | null\n private readonly user: string\n private readonly pageSize: number\n private readonly activityRefreshWindowMs: number\n private state: ConversationListSnapshot\n private source: Conversation[] = []\n private entries: InboxEntry[] = []\n private offset = 0\n private cursor: string | null = null\n private inboxUnavailable = false\n private inboxWarned = false\n private generation = 0\n private lifecycleGeneration = 0\n private disposed = true\n private lifecycle: RealtimeSubscription | undefined\n private inbox: RealtimeSubscription | undefined\n private activity: RealtimeSubscription | undefined\n private activityTimer: ReturnType<typeof setTimeout> | undefined\n private refreshQueued = false\n private refreshing = false\n private listeners = new Set<() => void>()\n\n constructor(private readonly options: Options) {\n this.owner = options.client.sessionIdentity\n this.user = this.owner ? options.client.currentUserId : ''\n this.pageSize = options.pageSize ?? 30\n if (!Number.isInteger(this.pageSize) || this.pageSize < 1 || this.pageSize > 100) {\n throw new RangeError('pageSize must be an integer between 1 and 100')\n }\n this.activityRefreshWindowMs = options.activityRefreshWindowMs ?? defaultActivityRefreshWindowMs\n if (!Number.isFinite(this.activityRefreshWindowMs) || this.activityRefreshWindowMs < 0) {\n throw new RangeError('activityRefreshWindowMs must be a non-negative number')\n }\n this.state = blank(options.initialFilter ?? {})\n }\n getSnapshot = (): ConversationListSnapshot => this.state\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n private patch(patch: Partial<ConversationListSnapshot>): void {\n this.state = { ...this.state, ...patch }\n for (const listener of this.listeners) listener()\n }\n private alive(generation = this.generation): boolean {\n return !this.disposed && generation === this.generation && this.owner !== null\n && this.options.client.sessionIdentity === this.owner\n }\n private get inboxMode(): boolean {\n return !this.options.pageLoader && typeof this.options.client.listInbox === 'function' && !this.inboxUnavailable\n }\n private currentUserId(): string { return this.inboxMode ? this.user : '' }\n start = (autoLoad = true): void => {\n if (!this.owner || this.options.client.sessionIdentity !== this.owner) return\n if (!this.disposed) return\n this.disposed = false\n this.inboxUnavailable = false\n const lifecycleGeneration = ++this.lifecycleGeneration\n const current = () => this.alive() && lifecycleGeneration === this.lifecycleGeneration\n const reconcile = (cause: Error) => {\n if (current()) {\n this.patch({ error: cause })\n // Reconcile authoritative REST after terminal topic denial as well.\n this.queueRefresh()\n }\n }\n try {\n this.patch({ currentUserId: this.currentUserId() })\n const subscription = this.options.client.onConnectionEvent({\n onEvent: () => {},\n onSessionEnded: () => {\n if (!this.disposed && lifecycleGeneration === this.lifecycleGeneration) this.dispose()\n },\n })\n if (this.alive()) this.lifecycle = subscription\n else void subscription.unsubscribe().catch(() => undefined)\n if (!this.alive()) return\n const inbox = this.options.client.onInboxChanged(() => {\n if (!current()) return\n // Structural changes are immediate and supersede a pending activity window.\n this.clearActivityTimer()\n this.queueRefresh()\n }, reconcile)\n if (this.alive()) this.inbox = inbox\n else void inbox.unsubscribe().catch(() => undefined)\n if (!this.alive()) return\n if (this.inboxMode && typeof this.options.client.onInboxActivity === 'function') {\n const activity = this.options.client.onInboxActivity(() => {\n if (current()) this.scheduleActivityRefresh(lifecycleGeneration)\n }, reconcile)\n if (this.alive()) this.activity = activity\n else void activity.unsubscribe().catch(() => undefined)\n }\n if (autoLoad) void this.loadInitial()\n } catch (cause) { if (this.alive()) this.patch({ error: cause }) }\n }\n dispose = (): void => {\n this.disposed = true\n this.generation++\n this.lifecycleGeneration++\n this.clearActivityTimer()\n const subscription = this.lifecycle\n this.lifecycle = undefined\n if (subscription) void subscription.unsubscribe().catch(() => undefined)\n if (this.inbox) void this.inbox.unsubscribe().catch(() => undefined)\n this.inbox = undefined\n this.stopActivity()\n this.refreshQueued = false\n this.refreshing = false\n this.source = []\n this.entries = []\n this.offset = 0\n this.cursor = null\n this.patch(blank(this.state.filter))\n }\n private stopActivity(): void {\n if (this.activity) void this.activity.unsubscribe().catch(() => undefined)\n this.activity = undefined\n }\n private clearActivityTimer(): void {\n if (this.activityTimer !== undefined) clearTimeout(this.activityTimer)\n this.activityTimer = undefined\n }\n /** Max-wait throttle: the first signal opens a window; later signals wait for it; one refresh runs when it closes. */\n private scheduleActivityRefresh(lifecycleGeneration: number): void {\n if (this.activityRefreshWindowMs === 0) return this.queueRefresh()\n if (this.activityTimer !== undefined) return\n const timer = setTimeout(() => {\n this.activityTimer = undefined\n if (this.alive() && lifecycleGeneration === this.lifecycleGeneration) this.queueRefresh()\n }, this.activityRefreshWindowMs)\n ;(timer as { unref?: () => void }).unref?.()\n this.activityTimer = timer\n }\n private fail(cause: unknown, generation: number): void {\n if (!this.alive(generation)) return\n const status = statusOf(cause)\n if (status === 401 || status === 403 || status === 404) {\n this.source = []\n this.entries = []\n this.offset = 0\n this.cursor = null\n this.patch({ conversations: [], summaries: new Map(), hasMore: false })\n }\n this.patch({ error: cause })\n }\n /** Run an operation in inbox mode, falling back to the legacy path for the rest of this store's life when the\n * inbox route is absent (404: rollback, staging). Loaded rows are kept and the same operation continues.\n */\n private async withFallback(generation: number, inbox: () => Promise<void>, legacy: () => Promise<void>): Promise<void> {\n if (!this.inboxMode) return legacy()\n try { await inbox() }\n catch (cause) {\n if (!this.alive(generation) || statusOf(cause) !== 404) throw cause\n this.inboxUnavailable = true\n this.clearActivityTimer()\n this.stopActivity()\n this.entries = []\n this.cursor = null\n this.offset = this.source.length\n if (!this.inboxWarned) {\n this.inboxWarned = true\n console.warn('ConvoKit inbox endpoint unavailable (404); using getConversations without previews or unread counts.')\n }\n this.patch({ summaries: new Map(), currentUserId: '' })\n await legacy()\n }\n }\n private validateInboxPage(page: InboxPage, limit: number, requestedCursor: string | null): void {\n const seen = new Set<string>()\n for (const entry of page.entries) {\n const id = entry.conversation.id\n if (!id.trim() || seen.has(id)) throw new Error('Invalid conversation page')\n seen.add(id)\n }\n if (page.entries.length > limit) throw new Error('Invalid conversation page')\n if (page.nextCursor !== null && (page.nextCursor === requestedCursor || page.entries.length === 0)) {\n throw new Error('Inbox pagination did not advance')\n }\n }\n /** Swap rows, summaries, cursor and hasMore together, filtered by the filter current at commit time. */\n private commitInbox(entries: InboxEntry[], cursor: string | null): void {\n this.entries = entries\n this.source = ids(entries)\n this.cursor = cursor\n this.patch({\n conversations: applyConversationFilter(this.source, this.state.filter),\n summaries: new Map(entries.map((entry) => [entry.conversation.id, summaryOf(entry)])),\n hasMore: cursor !== null,\n })\n }\n private async loadInboxUntilVisible(generation: number, filter: ConversationFilter): Promise<void> {\n const visibleBefore = applyConversationFilter(this.source, filter).length\n while (this.alive(generation)) {\n const requested = this.cursor\n const page = await this.options.client.listInbox!({ limit: this.pageSize, cursor: requested, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n this.validateInboxPage(page, this.pageSize, requested)\n this.commitInbox(mergeInboxEntries(this.entries, page.entries), page.nextCursor)\n if (page.nextCursor === null || this.state.conversations.length > visibleBefore) return\n }\n }\n private async loadUntilVisible(generation: number, filter: ConversationFilter): Promise<void> {\n const visibleBefore = applyConversationFilter(this.source, filter).length\n while (this.alive(generation)) {\n const request = { limit: this.pageSize, offset: this.offset, filter }\n const page = this.options.pageLoader\n ? await this.options.pageLoader(request)\n : await this.options.client.getConversations({ limit: this.pageSize, offset: this.offset, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n if (page.length > this.pageSize || page.some((conversation) => !conversation.id.trim())) {\n throw new Error('Invalid conversation page')\n }\n const merged = mergeConversations(this.source, page)\n if (page.length === this.pageSize && merged.length === this.source.length) {\n throw new Error('Conversation pagination did not advance')\n }\n this.offset += page.length\n this.source = merged\n const visible = applyConversationFilter(merged, filter)\n const hasMore = page.length === this.pageSize\n this.patch({ conversations: visible, hasMore })\n if (!hasMore || visible.length > visibleBefore) return\n }\n }\n loadInitial = async (): Promise<void> => {\n if (!this.alive()) return\n const generation = ++this.generation\n this.refreshing = false\n this.source = []\n this.entries = []\n this.offset = 0\n this.cursor = null\n this.patch({ ...blank(this.state.filter), currentUserId: this.currentUserId(), isInitialLoading: true })\n const filter = this.state.filter\n try {\n await this.withFallback(generation,\n () => this.loadInboxUntilVisible(generation, filter),\n () => this.loadUntilVisible(generation, filter))\n } catch (cause) { this.fail(cause, generation) }\n finally {\n if (this.alive(generation)) {\n this.patch({ isInitialLoading: false, hasLoaded: true })\n this.flushRefresh()\n }\n }\n }\n private queueRefresh(): void {\n this.refreshQueued = true\n this.flushRefresh()\n }\n private flushRefresh(): void {\n const lifecycle = this.lifecycleGeneration\n void Promise.resolve().then(() => {\n if (!this.alive() || lifecycle !== this.lifecycleGeneration || !this.refreshQueued\n || this.refreshing || this.state.isInitialLoading || this.state.isLoadingMore) return\n this.refreshQueued = false\n void this.refresh()\n })\n }\n /** Re-walk the inbox from the head until the loaded window is covered and something is visible, or the inbox\n * ends. Rooms that moved are re-positioned by the merge; an exhausted inbox publishes what it found.\n */\n private async refreshInbox(generation: number, filter: ConversationFilter): Promise<void> {\n const target = Math.max(this.pageSize, this.entries.length)\n let rows: InboxEntry[] = [], consumed = 0, cursor: string | null = null\n while (this.alive(generation)) {\n const remaining = target - consumed\n // Past the covered window (still nothing visible) continue in page-size steps.\n const limit = remaining >= 1 ? Math.min(100, remaining) : this.pageSize\n const page = await this.options.client.listInbox!({ limit, cursor, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n this.validateInboxPage(page, limit, cursor)\n rows = mergeInboxEntries(rows, page.entries)\n consumed += page.entries.length\n cursor = page.nextCursor\n if (cursor === null || (consumed >= target && applyConversationFilter(ids(rows), this.state.filter).length > 0)) break\n }\n if (!this.alive(generation)) return\n this.commitInbox(rows, cursor)\n }\n private async refreshLegacy(generation: number, filter: ConversationFilter): Promise<void> {\n const target = Math.max(this.pageSize, this.offset)\n // Default REST order is immutable creation time/ID, independent of UI sorting.\n const compare = (a: Conversation, b: Conversation) => a.createdAt.getTime() - b.createdAt.getTime()\n || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)\n const boundary = this.options.pageLoader ? undefined\n : this.source.reduce<Conversation | undefined>((oldest, row) => !oldest || compare(row, oldest) < 0 ? row : oldest, undefined)\n let rows: Conversation[] = [], offset = 0, hasMore = true\n while (this.alive(generation)) {\n const page = this.options.pageLoader\n ? await this.options.pageLoader({ limit: this.pageSize, offset, filter })\n : await this.options.client.getConversations({ limit: this.pageSize, offset, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n if (page.length > this.pageSize || page.some(row => !row.id.trim())) throw new Error('Invalid conversation page')\n const merged = mergeConversations(rows, page)\n if (page.length === this.pageSize && merged.length === rows.length) throw new Error('Conversation pagination did not advance')\n rows = merged\n offset += page.length\n hasMore = page.length === this.pageSize\n if (!hasMore || (offset >= target && applyConversationFilter(rows, this.state.filter).length > 0\n && (!boundary || page.some(row => compare(row, boundary) <= 0)))) break\n }\n if (!this.alive(generation)) return\n this.source = rows\n this.offset = offset\n this.patch({ conversations: applyConversationFilter(rows, this.state.filter), hasMore })\n }\n /** Replace the loaded window atomically, retaining filters and rows during transient failures. */\n refresh = async (): Promise<void> => {\n if (!this.alive()) return\n if (this.refreshing || this.state.isInitialLoading || this.state.isLoadingMore) {\n this.refreshQueued = true\n return\n }\n if (!this.state.hasLoaded) return this.loadInitial()\n const generation = this.generation\n const filter = this.state.filter\n this.refreshing = true\n this.patch({ error: null })\n try {\n await this.withFallback(generation,\n () => this.refreshInbox(generation, filter),\n () => this.refreshLegacy(generation, filter))\n } catch (cause) { this.fail(cause, generation) }\n finally {\n if (this.alive(generation)) {\n this.refreshing = false\n this.flushRefresh()\n }\n }\n }\n loadMore = async (): Promise<void> => {\n if (!this.alive() || this.refreshing || this.state.isInitialLoading || this.state.isLoadingMore || !this.state.hasMore) return\n const generation = this.generation\n const filter = this.state.filter\n this.patch({ isLoadingMore: true, error: null })\n try {\n await this.withFallback(generation,\n () => this.loadInboxUntilVisible(generation, filter),\n () => this.loadUntilVisible(generation, filter))\n } catch (cause) { this.fail(cause, generation) }\n finally {\n if (this.alive(generation)) {\n this.patch({ isLoadingMore: false })\n this.flushRefresh()\n }\n }\n }\n setFilter = async (filter: ConversationFilter): Promise<void> => {\n if (!this.alive()) return\n const reload = this.options.pageLoader || !this.state.hasLoaded || this.state.isInitialLoading\n || this.state.isLoadingMore || (filter.archived ?? false) !== (this.state.filter.archived ?? false)\n this.patch({ filter, conversations: applyConversationFilter(this.source, filter), error: null })\n if (reload) await this.loadInitial()\n else if (!this.state.conversations.length && this.state.hasMore) await this.loadMore()\n }\n setQuery = (query: string): Promise<void> => this.setFilter({ ...this.state.filter, query })\n /** Mark a room unread for the viewer only; the row's summary takes the response (D10). Rejects when the adapter\n * lacks `markConversationUnread` or the store is not active; a request failure is reported through `error`\n * without evicting rows and rejects.\n */\n markUnread = async (conversationId: string): Promise<void> => {\n const client = this.options.client\n if (typeof client.markConversationUnread !== 'function') {\n throw new TypeError('markUnread requires a ConvoKitUiClient adapter with markConversationUnread (core SDK 0.7)')\n }\n this.assertActive()\n this.applyPrivateState(conversationId, await this.mutate(client.markConversationUnread(conversationId)))\n }\n /** Remove the viewer's marker (conditionally on `options.ifVersion`); resolves to the response's `cleared` (\"this\n * request removed the marker\", not \"the room is read\") and patches the summary on true and false alike (D10).\n * Rejects when the adapter lacks `clearConversationUnread` or the store is not active; failures are reported like\n * `markUnread`.\n */\n clearUnread = async (conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean> => {\n const client = this.options.client\n if (typeof client.clearConversationUnread !== 'function') {\n throw new TypeError('clearUnread requires a ConvoKitUiClient adapter with clearConversationUnread (core SDK 0.7)')\n }\n this.assertActive()\n const result = await this.mutate(client.clearConversationUnread(conversationId, options))\n this.applyPrivateState(conversationId, result)\n return result.cleared\n }\n /** A disposed or session-evicted store never sends a private-state mutation: on a shared client it could go out\n * under a replacement login. Rejected without touching `error` (there is no live snapshot to report into).\n */\n private assertActive(): void {\n if (!this.alive()) throw new Error('ConversationListStore is not active')\n }\n private async mutate<T>(request: Promise<T>): Promise<T> {\n try { return await request }\n catch (cause) {\n if (this.alive()) this.patch({ error: cause })\n throw cause\n }\n }\n /** Apply a mark/clear response to the row's CURRENT summary (a refresh may have swapped it) as one unit, only while\n * the store is alive and the response is not older than the stored version: a delayed response never resurrects a\n * marker a newer action removed (equal versions are an idempotent no-op). `isUnread` is recomputed from the stored\n * counts and the response marker. Other devices learn of the change through `inbox_activity`.\n */\n private applyPrivateState(conversationId: string, state: ConversationPrivateState): void {\n if (!this.alive()) return\n const current = this.entries.find((entry) => entry.conversation.id === conversationId)\n if (!current || state.privateStateVersion < current.privateStateVersion) return\n const { unreadMarkedAt, privateStateVersion } = state\n const patched: InboxEntry = {\n ...current, unreadMarkedAt, privateStateVersion,\n isUnread: current.unreadCount > 0 || current.unreadCountCapped || unreadMarkedAt !== null,\n }\n this.entries = this.entries.map((entry) => entry === current ? patched : entry)\n this.patch({ summaries: new Map(this.entries.map((entry) => [entry.conversation.id, summaryOf(entry)])) })\n }\n}\n","import {\n computed,\n defineComponent,\n h,\n inject,\n provide,\n type CSSProperties,\n type InjectionKey,\n type PropType,\n type Ref,\n} from 'vue'\nimport { cx } from './utils'\n\nexport interface ConvoKitTheme {\n background: string\n surface: string\n primary: string\n text: string\n mutedText: string\n border: string\n error: string\n incomingBubble: string\n outgoingBubble: string\n outgoingText: string\n /** Unread badge and dot background (0.6.0); the badge label uses `outgoingText`. Defaults to the primary color. */\n badge: string\n radius: string\n avatarSize: string\n fontFamily: string\n}\n\nexport const defaultConvoKitTheme: ConvoKitTheme = {\n background: '#fafafa',\n surface: '#ffffff',\n primary: '#18181b',\n text: '#09090b',\n mutedText: '#71717a',\n border: '#e4e4e7',\n error: '#dc2626',\n incomingBubble: '#f4f4f5',\n outgoingBubble: '#18181b',\n outgoingText: '#fafafa',\n badge: '#18181b',\n radius: '10px',\n avatarSize: '40px',\n fontFamily: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n}\n\nconst themeKey: InjectionKey<Readonly<Ref<ConvoKitTheme>>> = Symbol('ConvoKitTheme')\nconst defaultThemeRef = computed(() => defaultConvoKitTheme)\n\nexport const ConvoKitThemeProvider = defineComponent({\n name: 'ConvoKitThemeProvider',\n inheritAttrs: false,\n props: {\n theme: { type: Object as PropType<Partial<ConvoKitTheme>>, default: () => ({}) },\n class: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n style: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n },\n setup(props, { attrs, slots }) {\n const parent = inject(themeKey, defaultThemeRef)\n const value = computed(() => ({ ...parent.value, ...props.theme }))\n provide(themeKey, value)\n return () => {\n const theme = value.value\n const variables = {\n '--ckui-background': theme.background,\n '--ckui-surface': theme.surface,\n '--ckui-primary': theme.primary,\n '--ckui-text': theme.text,\n '--ckui-muted': theme.mutedText,\n '--ckui-border': theme.border,\n '--ckui-error': theme.error,\n '--ckui-incoming': theme.incomingBubble,\n '--ckui-outgoing': theme.outgoingBubble,\n '--ckui-outgoing-text': theme.outgoingText,\n '--ckui-badge': theme.badge,\n '--ckui-radius': theme.radius,\n '--ckui-avatar-size': theme.avatarSize,\n '--ckui-font': theme.fontFamily,\n } as CSSProperties\n return h('div', {\n ...attrs,\n class: cx('ckui-theme', props.class, attrs.class),\n style: [variables, props.style, attrs.style],\n }, slots.default?.())\n }\n },\n})\n\nexport function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>> {\n return inject(themeKey, defaultThemeRef)\n}\n"],"mappings":"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","names":["Check","LoaderCircle","Pencil","defineComponent","h","ref","watch","version","computed","defineComponent","h","watch","h","defineComponent","computed","watch","appearanceProps","defineComponent","ref","watch","text","h","Pencil","LoaderCircle","Check","LoaderCircle","RefreshCw","defineComponent","h","ref","watchEffect","computed","getCurrentScope","onScopeDispose","shallowRef","toValue","watch","blank","compare","toValue","shallowRef","watch","computed","getCurrentScope","onScopeDispose","options","appearanceProps","defineComponent","ref","h","LoaderCircle","RefreshCw","watchEffect","computed","defineComponent","h","computed","defineComponent","h"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/components/avatar.ts","../src/utils.ts","../src/components/conversation.ts","../src/composables/use-conversation.ts","../src/conversation-store.ts","../src/components/message-list.ts","../src/components/conversation-list.ts","../src/composables/use-conversation-list.ts","../src/conversation-list-store.ts","../src/theme.ts"],"sourcesContent":["import type { ConvoKitClient } from '@convokitapp/sdk'\nimport type { ConvoKitUiClient } from './types'\n\n/** Adapts a connected `@convokitapp/sdk` client to the replaceable UI boundary. */\nexport function createConvoKitUiClient(client: ConvoKitClient): ConvoKitUiClient {\n return {\n get sessionIdentity() { return client.connected ? client.realtime : null },\n onConnectionEvent: (handlers) => client.realtime.onConnectionEvent(handlers),\n onInboxChanged: (handler, onError) => client.realtime.onInboxChanged(client.clientId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onInboxActivity: (handler, onError) => client.realtime.onInboxActivity(client.clientId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onMessageDeleted: (conversationId, handler, onError) => client.realtime.onMessageDeleted(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n get currentUserId() { return client.connected ? client.currentUserId : '' },\n getConversations: (options) => client.getConversations(options),\n listInbox: (options) => client.listInbox(options),\n getConversation: (conversationId) => client.getConversation(conversationId),\n getMessages: (options) => client.getMessages(options),\n getMessage: (id) => client.getMessage(id),\n sendMessage: (input) => client.sendMessage(input),\n editMessage: (messageId, input) => client.editMessage(messageId, input),\n deleteMessage: (messageId) => client.deleteMessage(messageId),\n getReplyPreviews: (conversationId, messageIds) => client.getReplyPreviews(conversationId, messageIds),\n getMessageContext: (conversationId, options) => client.getMessageContext(conversationId, options),\n markConversationRead: (conversationId, options) => client.markConversationRead(conversationId, options),\n markConversationUnread: (conversationId) => client.markConversationUnread(conversationId),\n clearConversationUnread: (conversationId, options) => client.clearConversationUnread(conversationId, options),\n sendTyping: (input) => client.sendTyping(input),\n onMessage: (conversationId, handler, onError) => client.realtime.onMessage(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onReadReceipt: (conversationId, handler, onError) => client.realtime.onReadReceipt(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onTyping: (conversationId, handler, onError) => client.realtime.onTyping(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n }\n}\n","import { AvatarFallback, AvatarImage, AvatarRoot } from 'reka-ui'\nimport { defineComponent, h, type PropType } from 'vue'\nimport { cx, initials } from '../utils'\n\n/** Accessible avatar built on Reka UI, the primitive layer used by shadcn-vue. */\nexport const ConvoKitAvatar = defineComponent({\n name: 'ConvoKitAvatar',\n inheritAttrs: false,\n props: {\n name: { type: String, required: true },\n src: { type: String as PropType<string | null>, default: null },\n },\n setup(props, { attrs }) {\n return () => h(AvatarRoot, {\n ...attrs,\n class: cx('ckui-avatar', attrs.class),\n }, {\n default: () => [\n props.src ? h(AvatarImage, { class: 'ckui-avatar__image', src: props.src, alt: '' }) : null,\n h(AvatarFallback, {\n class: 'ckui-avatar__fallback',\n ...(props.src ? { delayMs: 300 } : {}),\n }, () => initials(props.name)),\n ],\n })\n },\n})\n","import type { Conversation, InboxEntry, InboxSummary, Message, ReadPosition } from '@convokitapp/sdk'\nimport { readThrough } from '@convokitapp/sdk'\nimport { clsx } from 'clsx'\nimport { normalizeClass } from 'vue'\nimport type { CSSProperties } from 'vue'\nimport type { ConversationFilter, ConvoKitAppearanceProps, ConvoKitUiPart } from './types'\n\nconst pendingMessageIdPrefix = 'convokit-pending-'\n\n/** Message cursor order: createdAt, then id by UTF-16 code units (the server's TEXT order for its lowercase UUIDs). */\nexport function compareMessageOrder(left: Pick<Message, 'createdAt' | 'id'>, right: Pick<Message, 'createdAt' | 'id'>): number {\n return left.createdAt.getTime() - right.createdAt.getTime()\n || (left.id < right.id ? -1 : left.id > right.id ? 1 : 0)\n}\n\n/** Whether a message is an optimistic row awaiting server acknowledgement. */\nexport function isConvoKitPendingMessage(message: Message): boolean {\n return message.id.startsWith(pendingMessageIdPrefix)\n}\n\n/** Vue class attributes accept nested arrays/objects, including unknown attrs on Vue 3.4. */\nexport function cx(...values: unknown[]): string { return clsx(values.map(normalizeClass)) }\n\nfunction requestedParticipantIds(filter: ConversationFilter): ReadonlySet<string> {\n const values = filter.participantIds ?? []\n return values instanceof Set ? values : new Set(values)\n}\n\nexport function matchesConversation(conversation: Conversation, filter: ConversationFilter): boolean {\n const query = filter.query?.trim().toLocaleLowerCase() ?? ''\n if (query) {\n const haystack = [\n conversation.id,\n conversation.displayTitle,\n conversation.title ?? '',\n conversation.description ?? '',\n ...conversation.participants.flatMap((participant) => [participant.id, participant.appUserId, participant.name]),\n ].join(' ').toLocaleLowerCase()\n if (!haystack.includes(query)) return false\n }\n const requested = requestedParticipantIds(filter)\n if (requested.size > 0) {\n const available = new Set(conversation.participants.flatMap((participant) => [participant.id, participant.appUserId]))\n const values = [...requested]\n const matches = filter.requireAllParticipants\n ? values.every((id) => available.has(id))\n : values.some((id) => available.has(id))\n if (!matches) return false\n }\n return filter.predicate?.(conversation) ?? true\n}\n\nexport function applyConversationFilter(conversations: readonly Conversation[], filter: ConversationFilter): Conversation[] {\n const result = conversations.filter((conversation) => matchesConversation(conversation, filter))\n if (filter.comparator) result.sort(filter.comparator)\n return result\n}\n\nexport function mergeConversations(current: readonly Conversation[], incoming: readonly Conversation[]): Conversation[] {\n const byId = new Map(current.map((conversation) => [conversation.id, conversation]))\n for (const conversation of incoming) byId.set(conversation.id, conversation)\n return [...byId.values()]\n}\n\n/** Inbox order: newest activity first, ties by id descending in UTF-16 code units (the server's TEXT order). */\nexport function compareInboxOrder(left: InboxEntry, right: InboxEntry): number {\n return right.activityAt.getTime() - left.activityAt.getTime()\n || (left.conversation.id < right.conversation.id ? 1 : left.conversation.id > right.conversation.id ? -1 : 0)\n}\n\n/** Merge inbox pages by conversation ID: a later entry replaces an earlier one (its room moved), and the result is\n * re-ordered by `(activityAt desc, id desc)`. Server order is authoritative within a page; this is the rule applied\n * whenever pages are combined (load more, refresh).\n */\nexport function mergeInboxEntries(current: readonly InboxEntry[], incoming: readonly InboxEntry[]): InboxEntry[] {\n const byId = new Map(current.map((entry) => [entry.conversation.id, entry]))\n for (const entry of incoming) byId.set(entry.conversation.id, entry)\n return [...byId.values()].sort(compareInboxOrder)\n}\n\n/** The default row's one-line preview, or `''` when the row should keep its participants/description line. */\nexport function inboxPreview(conversation: Conversation, summary: InboxSummary | undefined, currentUserId: string | undefined): string {\n const message = summary?.latestMessage\n if (!message) return ''\n const first = message.media[0]\n const body = message.text?.trim() || (!first ? ''\n : first.type === 'image' ? 'Photo'\n : first.type === 'file' ? first.name?.trim() || 'File'\n : first.type === 'location' ? 'Location'\n : first.type === 'contact' ? 'Contact' : '')\n if (!body) return ''\n if (currentUserId !== undefined && message.senderId === currentUserId) return `You: ${body}`\n if (conversation.participants.length > 2) {\n const sender = conversation.participants.find((participant) => participant.appUserId === message.senderId || participant.id === message.senderId)\n const name = sender?.name.trim()\n if (name) return `${name}: ${body}`\n }\n return body\n}\n\n/** Device-zone clock time, shared by message rows and inbox rows. */\nexport function formatMessageTime(date: Date): string {\n return new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: '2-digit' }).format(date)\n}\n\nexport function mergeMessages(current: readonly Message[], incoming: readonly Message[]): Message[] {\n const byId = new Map(current.map((message) => [message.id, message]))\n for (const message of incoming) byId.set(message.id, message)\n return [...byId.values()].sort((left, right) => {\n const leftPending = isConvoKitPendingMessage(left)\n const rightPending = isConvoKitPendingMessage(right)\n if (leftPending !== rightPending) return leftPending ? 1 : -1\n return compareMessageOrder(left, right)\n })\n}\n\n/** Readers of a message under the unified rule: a user's read position (createdAt, id) wins when present,\n * otherwise the acknowledgement time is compared with createdAt (legacy participants, empty-room acknowledgements).\n * The sender and pending rows never have readers.\n */\nexport function readerIdsFor(\n message: Message,\n readAtByUserId: ReadonlyMap<string, Date>,\n readPositionByUserId: ReadonlyMap<string, ReadPosition> = new Map(),\n): ReadonlySet<string> {\n if (isConvoKitPendingMessage(message)) return new Set()\n const userIds = new Set([...readAtByUserId.keys(), ...readPositionByUserId.keys()])\n return new Set([...userIds].filter((userId) => userId !== message.senderId && readThrough({\n readPosition: readPositionByUserId.get(userId) ?? null, lastReadAt: readAtByUserId.get(userId) ?? null,\n }, message)))\n}\n\nexport function partClass(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps, defaultClass: string): string {\n return cx(!appearance.unstyled && defaultClass, appearance.classNames?.[part])\n}\n\nexport function partStyle(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps): CSSProperties | undefined {\n return appearance.styles?.[part]\n}\n\nexport function errorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error) }\n\nexport function formatFileSize(size: number | undefined): string | null {\n if (size === undefined || !Number.isFinite(size) || size < 0) return null\n if (size < 1024) return `${Math.round(size)} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(size < 10 * 1024 ? 1 : 0)} KB`\n return `${(size / (1024 * 1024)).toFixed(size < 10 * 1024 * 1024 ? 1 : 0)} MB`\n}\n\nexport function initials(value: string): string {\n const words = value.trim().split(/\\s+/).filter(Boolean)\n return (words.length > 1 ? `${words[0]?.[0] ?? ''}${words.at(-1)?.[0] ?? ''}` : value[0] ?? '?').toLocaleUpperCase()\n}\n","import type { Conversation as ConversationModel, Message, MessageMedia, ReadPosition } from '@convokitapp/sdk'\nimport { ArrowDown, ArrowLeft, Check, LoaderCircle, Paperclip, Pencil, Reply, RefreshCw, Send } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n onBeforeUnmount,\n ref,\n watch,\n watchEffect,\n type CSSProperties,\n type PropType,\n type TextareaHTMLAttributes,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationController, UseConversationOptions } from '../composables/use-conversation'\nimport { useConversation } from '../composables/use-conversation'\nimport type {\n ComposerSlotProps,\n JumpToLatestSlotProps,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n ReplyPreviewEntry,\n TypingSlotProps,\n} from '../types'\nimport { cx, errorMessage, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\nimport { MessageListView } from './message-list'\n\nexport interface ConversationViewProps extends ConvoKitAppearanceProps {\n conversation: ConversationModel\n messages: readonly Message[]\n currentUserId: string\n onSendMessage: (text: string) => boolean | void | Promise<boolean | void>\n typingUserIds?: ReadonlySet<string>\n readAtByUserId?: ReadonlyMap<string, Date>\n readPositionByUserId?: ReadonlyMap<string, ReadPosition>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onBack?: () => void\n onRefresh?: () => void | Promise<void>\n onLoadOlder?: () => void | Promise<void>\n onTypingChange?: (isTyping: boolean) => void | Promise<void>\n onAddAttachment?: () => void\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n /** The message being edited (0.8.0), or null. Entering edit mode stashes the unsent draft and prefills the field\n * with the message text without a typing update; the composer then saves instead of sending.\n */\n editingMessage?: Message | null\n /** Start editing a message (0.8.0): set `editingMessage` in response. Without it rows offer no edit action. */\n onEditMessage?: (message: Message) => void\n /** Save the edit in progress (0.8.0); the composer's submit calls it instead of `onSendMessage` while\n * `editingMessage` is set. `false` keeps edit mode and the draft (like `onSendMessage`); any other result\n * restores the stashed unsent draft. Clear `editingMessage` when the edit is done.\n */\n onSaveEdit?: (message: Message, text: string) => boolean | void | Promise<boolean | void>\n /** Leave edit mode (0.8.0): clear `editingMessage` in response; the view restores the unsent draft. */\n onCancelEdit?: () => void\n /** Delete a message after confirmation (0.8.0); `false` means it was not accepted. Without it rows offer no\n * delete action.\n */\n onDeleteMessage?: (message: Message) => boolean | void | Promise<boolean | void>\n /** Replaces the default row eligibility (own confirmed rows while the viewer's role is not `READ`). */\n canEditMessage?: (message: Message) => boolean\n /** Replaces the inline \"Delete this message?\" prompt (and confirms `remove()` from custom rows). */\n confirmDelete?: (message: Message) => boolean | Promise<boolean>\n /** The message being quoted (0.9.0), or null. The composer shows a cancellable strip and keeps the draft —\n * replying never replaces it, unlike edit mode. Editing wins while both are set.\n */\n replyTarget?: Message | null\n /** Quote a message (0.9.0): set `replyTarget` in response. Without it rows offer no reply action. */\n onReplyToMessage?: (message: Message) => void\n /** Drop the reply target (0.9.0): clear `replyTarget` in response. */\n onCancelReply?: () => void\n /** Replaces the default reply eligibility (any confirmed row while the viewer's role is not `READ`, 0.9.0). */\n canReplyToMessage?: (message: Message) => boolean\n /** Quoted parents by `Message.replyToMessageId` (0.9.0); a missing key renders the reference with no quoted\n * text, `'unavailable'` the deleted-parent copy.\n */\n replyPreviewByMessageId?: ReadonlyMap<string, ReplyPreviewEntry>\n /** Bring a message into view (0.9.0). Without it quoted blocks are inert and no row is focusable. */\n onJumpToMessage?: (messageId: string) => void\n /** The row a jump landed on (0.9.0); it is centred, focused and highlighted. */\n highlightedMessageId?: string | null\n /** Set while a jump lands (0.9.0): the list is `aria-busy` and suspends stick-to-bottom and pagination. */\n jumpInFlight?: boolean\n /** Whether newer messages exist past the window (0.9.0); only ever true in a jumped window. */\n hasNewerMessages?: boolean\n isLoadingNewer?: boolean\n /** Load the page immediately newer than a jumped window (0.9.0); the newer-edge scroll trigger. */\n onLoadNewer?: () => void | Promise<void>\n /** Leave a jumped window for the live tail (0.9.0). Present only while the window IS jumped: it is what\n * renders the \"Jump to latest\" control.\n */\n onReturnToLatest?: () => void | Promise<void>\n isInitialLoading?: boolean\n isLoadingOlder?: boolean\n isSending?: boolean\n hasOlderMessages?: boolean\n error?: unknown\n messageError?: unknown\n displayNameForUser?: (userId: string) => string | null | undefined\n reverseMessages?: boolean\n stickToBottom?: boolean\n paginationThreshold?: number\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n composerPlaceholder?: string\n composerAriaLabel?: string\n composerProps?: Omit<TextareaHTMLAttributes, 'value' | 'disabled'>\n modelValue?: string\n defaultDraft?: string\n onDraftChange?: (value: string) => void\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst viewProps = {\n ...appearanceProps,\n conversation: { type: Object as PropType<ConversationModel>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, required: true },\n typingUserIds: { type: Object as PropType<ReadonlySet<string>>, default: () => new Set() },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readPositionByUserId: { type: Object as PropType<ReadonlyMap<string, ReadPosition>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onBack: { type: Function as PropType<() => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onTypingChange: { type: Function as PropType<(isTyping: boolean) => void | Promise<void>>, default: undefined },\n onAddAttachment: { type: Function as PropType<() => void>, default: undefined },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n editingMessage: { type: Object as PropType<Message | null>, default: null },\n onEditMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onSaveEdit: { type: Function as PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n onCancelEdit: { type: Function as PropType<() => void>, default: undefined },\n onDeleteMessage: { type: Function as PropType<(message: Message) => boolean | void | Promise<boolean | void>>, default: undefined },\n canEditMessage: { type: Function as PropType<(message: Message) => boolean>, default: undefined },\n confirmDelete: { type: Function as PropType<(message: Message) => boolean | Promise<boolean>>, default: undefined },\n replyTarget: { type: Object as PropType<Message | null>, default: null },\n onReplyToMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onCancelReply: { type: Function as PropType<() => void>, default: undefined },\n canReplyToMessage: { type: Function as PropType<(message: Message) => boolean>, default: undefined },\n replyPreviewByMessageId: { type: Object as PropType<ReadonlyMap<string, ReplyPreviewEntry>>, default: undefined },\n onJumpToMessage: { type: Function as PropType<(messageId: string) => void>, default: undefined },\n highlightedMessageId: { type: String as PropType<string | null>, default: null },\n jumpInFlight: { type: Boolean, default: false },\n hasNewerMessages: { type: Boolean, default: false },\n isLoadingNewer: { type: Boolean, default: false },\n onLoadNewer: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onReturnToLatest: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n isSending: { type: Boolean, default: false },\n hasOlderMessages: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n messageError: { type: null as unknown as PropType<unknown>, required: false },\n displayNameForUser: { type: Function as PropType<(userId: string) => string | null | undefined>, default: undefined },\n reverseMessages: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n paginationThreshold: { type: Number, default: 240 },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: undefined },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n composerPlaceholder: { type: String, default: 'Write a message' },\n composerAriaLabel: { type: String, default: 'Message' },\n composerProps: { type: Object as PropType<Omit<TextareaHTMLAttributes, 'value' | 'disabled'>>, default: undefined },\n modelValue: { type: String, default: undefined },\n defaultDraft: { type: String, default: '' },\n onDraftChange: { type: Function as PropType<(value: string) => void>, default: undefined },\n} as const\n\n/** The composer banner's summary of a message: its text, or its attachments when the caption is empty. Shared by\n * the 0.8 edit banner and the 0.9 reply strip.\n */\nfunction messageSummary(message: Message): string {\n return message.text?.trim() || (message.media.length === 1 ? '1 attachment' : `${message.media.length} attachments`)\n}\n\nfunction typingLabel(userIds: ReadonlySet<string>, displayNameForUser: (userId: string) => string): string {\n const names = [...userIds].map(displayNameForUser)\n if (names.length === 0) return ''\n if (names.length === 1) return `${names[0]} is typing…`\n if (names.length === 2) return `${names[0]} and ${names[1]} are typing…`\n return `${names[0]} and ${names.length - 1} others are typing…`\n}\n\n/** Controlled, complete selected-conversation surface. */\nexport const ConversationView = defineComponent({\n name: 'ConversationView',\n inheritAttrs: false,\n props: viewProps,\n emits: [\n 'send-message', 'typing-change', 'back', 'refresh', 'load-older',\n 'add-attachment', 'attachment-click', 'update:modelValue',\n 'edit-message', 'save-edit', 'cancel-edit', 'delete-message',\n 'reply-to-message', 'cancel-reply', 'jump-to-message', 'load-newer', 'return-to-latest',\n ],\n setup(props, { attrs, emit, slots }) {\n const internalDraft = ref(props.defaultDraft)\n const submitting = ref(false)\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n const draft = () => props.modelValue ?? internalDraft.value\n let latestDraft = draft()\n // Edit mode (0.8.0) is the host's/store's (`editingMessage`); the view owns the draft: the unsent draft is\n // stashed on entry and the field prefilled silently (no typing update). Cancel and a successful save restore\n // the stash; an external end (the row removed) keeps text the user changed and restores the stash otherwise.\n /** The unsent draft stashed on entering edit mode; undefined while not editing. */\n let stash: string | undefined\n /** A save request is in flight: its continuation, not the `editingMessage` watcher, settles the draft. */\n let saving = false\n const setDraft = (value: string, typing = true) => {\n latestDraft = value\n if (props.modelValue === undefined) internalDraft.value = value\n props.onDraftChange?.(value)\n emit('update:modelValue', value)\n if (typing) void props.onTypingChange?.(value.trim().length > 0)\n }\n const enterEdit = (message: Message) => {\n if (stash === undefined) stash = draft()\n setDraft(message.text ?? '', false)\n }\n /** Leave edit mode in the view: restore the stash always, or only when the field is empty or still the snapshot's text. */\n const leaveEdit = (message: Message, restore: 'always' | 'unchanged') => {\n if (stash === undefined) return\n const saved = stash\n stash = undefined\n const current = draft()\n if (restore === 'always' || current.trim() === '' || current === (message.text ?? '')) setDraft(saved)\n }\n watch(() => props.editingMessage, (next, previous) => {\n if (next && (!previous || previous.id !== next.id)) enterEdit(next)\n else if (!next && previous && !saving) leaveEdit(previous, 'unchanged')\n }, { immediate: true })\n const cancelEdit = () => {\n const editing = props.editingMessage\n if (!editing) return\n leaveEdit(editing, 'always')\n props.onCancelEdit?.()\n }\n // Replying never touches the draft, so it has no stash: cancelling only drops the target (0.9.0).\n const cancelReply = () => { props.onCancelReply?.() }\n const returnToLatest = () => props.onReturnToLatest?.()\n /** Save is possible while the field has text or the edited row has attachments (an empty caption). */\n const canSave = (editing: Message) => draft().trim().length > 0 || editing.media.length > 0\n const submit = async () => {\n const editing = props.editingMessage\n if (editing) {\n const text = draft().trim()\n if (!canSave(editing) || props.isSending || submitting.value) return\n submitting.value = true\n saving = true\n try {\n // The field keeps the edited text during the request; a failure or a conflict leaves it in place.\n const saved = await props.onSaveEdit?.(editing, text)\n if (saved === false) {\n if (props.editingMessage === null) leaveEdit(editing, 'unchanged')\n return\n }\n leaveEdit(editing, 'always')\n } finally {\n saving = false\n submitting.value = false\n }\n return\n }\n const originalDraft = draft()\n const text = originalDraft.trim()\n if (!text || props.isSending || submitting.value) return\n submitting.value = true\n setDraft('')\n try {\n const shouldClear = await props.onSendMessage(text)\n if (shouldClear === false && latestDraft.length === 0) setDraft(originalDraft)\n } finally {\n submitting.value = false\n }\n }\n const nameForUser = (userId: string) => {\n const custom = props.displayNameForUser?.(userId)?.trim()\n if (custom) return custom\n const participant = props.conversation.participants.find((value) => value.id === userId || value.appUserId === userId)\n return participant?.name.trim() || userId\n }\n const goBack = () => { props.onBack?.() }\n const refresh = () => props.onRefresh?.()\n const loadOlder = () => props.onLoadOlder?.()\n const loadNewer = () => props.onLoadNewer?.()\n const addAttachment = () => { props.onAddAttachment?.() }\n\n const renderHeader = (): VNodeChild => {\n const slotProps = {\n conversation: props.conversation,\n ...(props.onBack ? { onBack: goBack } : {}),\n ...(props.onRefresh ? { onRefresh: refresh } : {}),\n }\n return slots.header?.(slotProps) ?? h('header', {\n class: partClass('header', appearance(), 'ckui-conversation-header'),\n style: partStyle('header', appearance()),\n }, [\n props.onBack ? h('button', {\n type: 'button', 'aria-label': 'Back', onClick: goBack,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(ArrowLeft, { size: 20, 'aria-hidden': 'true' })]) : null,\n h(ConvoKitAvatar, { name: props.conversation.displayTitle, src: props.conversation.imageUrl }),\n h('div', { class: 'ckui-conversation-header__body' }, [\n h('strong', props.conversation.displayTitle),\n h('span', `${props.conversation.participants.length} participant${props.conversation.participants.length === 1 ? '' : 's'}`),\n ]),\n props.onRefresh ? h('button', {\n type: 'button', 'aria-label': 'Refresh conversation', onClick: () => { void refresh() },\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(RefreshCw, { size: 18, 'aria-hidden': 'true' })]) : null,\n ])\n }\n\n const renderTyping = (): VNodeChild => {\n const slotProps: TypingSlotProps = { userIds: props.typingUserIds, displayNameForUser: nameForUser }\n return slots['typing-indicator']?.(slotProps) ?? h('div', {\n class: partClass('typing', appearance(), 'ckui-typing'),\n style: partStyle('typing', appearance()),\n 'aria-live': 'polite',\n }, typingLabel(props.typingUserIds, nameForUser))\n }\n\n const renderComposer = (): VNodeChild => {\n const editing = props.editingMessage\n // Editing and replying are mutually exclusive; the store enforces it, and a host that sets both sees the\n // edit, which owns the draft.\n const replying = editing ? null : props.replyTarget\n const slotProps: ComposerSlotProps = {\n value: draft(), setValue: setDraft, isSending: props.isSending || submitting.value,\n send: () => { void submit() },\n ...(props.onAddAttachment ? { addAttachment } : {}),\n ...(editing ? { editing, cancelEdit } : {}),\n ...(replying ? { replying, cancelReply } : {}),\n }\n const busy = props.isSending || submitting.value\n return slots.composer?.(slotProps) ?? h('form', {\n class: cx(\n partClass('composer', appearance(), 'ckui-composer'),\n editing && !props.unstyled && 'ckui-composer--editing',\n replying && !props.unstyled && 'ckui-composer--replying',\n ),\n style: partStyle('composer', appearance()),\n onSubmit: (event: Event) => { event.preventDefault(); void submit() },\n }, [\n // Spread, not null: outside edit mode the composer markup stays byte-identical to 0.7.\n ...(editing ? [h('div', { class: 'ckui-composer__editing', role: 'status' }, [\n h(Pencil, { size: 14, 'aria-hidden': 'true' }),\n h('span', { class: 'ckui-composer__editing-body' }, [\n h('strong', 'Editing message'),\n h('span', messageSummary(editing)),\n ]),\n h('button', { type: 'button', class: 'ckui-link-button', 'aria-label': 'Cancel editing', onClick: cancelEdit }, 'Cancel'),\n ])] : []),\n ...(replying ? [h('div', { class: 'ckui-composer__replying', role: 'status' }, [\n h(Reply, { size: 14, 'aria-hidden': 'true' }),\n h('span', { class: 'ckui-composer__replying-body' }, [\n h('strong', `Replying to ${nameForUser(replying.senderId)}`),\n h('span', messageSummary(replying)),\n ]),\n h('button', { type: 'button', class: 'ckui-link-button', 'aria-label': 'Cancel reply', onClick: cancelReply }, 'Cancel'),\n ])] : []),\n props.onAddAttachment ? h('button', {\n type: 'button', 'aria-label': 'Add attachment', onClick: addAttachment,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(Paperclip, { size: 20, 'aria-hidden': 'true' })]) : null,\n h('textarea', {\n ...props.composerProps,\n rows: props.composerProps?.rows ?? 1,\n placeholder: props.composerPlaceholder,\n 'aria-label': props.composerAriaLabel,\n class: cx(!props.unstyled && 'ckui-composer__input', props.classNames?.input, props.composerProps?.class),\n style: [props.styles?.input, props.composerProps?.style],\n value: draft(),\n onInput: (event: InputEvent) => {\n const handler = props.composerProps?.onInput\n if (typeof handler === 'function') handler(event)\n if (!event.defaultPrevented) setDraft((event.currentTarget as HTMLTextAreaElement).value)\n },\n onKeydown: (event: KeyboardEvent) => {\n const handler = props.composerProps?.onKeydown\n if (typeof handler === 'function') handler(event)\n if (event.defaultPrevented) return\n if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); void submit() }\n if (event.key === 'Escape' && props.editingMessage) { event.preventDefault(); cancelEdit() }\n else if (event.key === 'Escape' && props.replyTarget) { event.preventDefault(); cancelReply() }\n },\n }),\n h('button', {\n type: 'submit', 'aria-label': editing ? 'Save message' : 'Send message',\n disabled: (editing ? !canSave(editing) : !draft().trim()) || busy,\n class: partClass('button', appearance(), 'ckui-send-button'),\n style: partStyle('button', appearance()),\n }, [busy\n ? h(LoaderCircle, { class: 'ckui-spin', size: 18, 'aria-hidden': 'true' })\n : h(editing ? Check : Send, { size: 18, 'aria-hidden': 'true' })]),\n ])\n }\n\n return () => {\n if (props.isInitialLoading && props.messages.length === 0) {\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, slots.loading?.() ?? h('div', {\n class: partClass('loading', appearance(), 'ckui-state'), style: partStyle('loading', appearance()), role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…']))\n }\n const children: VNodeChild[] = [renderHeader()]\n if (props.error) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', appearance(), 'ckui-conversation-error'),\n style: partStyle('error', appearance()), role: 'alert',\n }, [h('span', errorMessage(props.error)), retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null]))\n }\n const messageSlots = {\n ...(slots.message ? { message: slots.message } : {}),\n ...(slots.media ? { media: slots.media } : {}),\n ...(slots['read-receipt'] ? { 'read-receipt': slots['read-receipt'] } : {}),\n ...(slots.empty ? { empty: slots.empty } : {}),\n ...(slots['loading-older'] ? { 'loading-older': slots['loading-older'] } : {}),\n ...(slots['loading-newer'] ? { 'loading-newer': slots['loading-newer'] } : {}),\n ...(slots['message-error'] ? { error: slots['message-error'] } : {}),\n }\n children.push(h(MessageListView, {\n conversation: props.conversation,\n messages: props.messages,\n currentUserId: props.currentUserId,\n readAtByUserId: props.readAtByUserId,\n readPositionByUserId: props.readPositionByUserId,\n ...(props.readersResolver ? { readersResolver: props.readersResolver } : {}),\n ...(props.onLoadOlder ? { onLoadOlder: loadOlder } : {}),\n hasOlderMessages: props.hasOlderMessages,\n isLoadingOlder: props.isLoadingOlder,\n ...(props.messageError == null ? {} : { error: props.messageError }),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n } } : {}),\n ...(props.onEditMessage ? { onEditMessage: (message: Message) => { props.onEditMessage?.(message) } } : {}),\n ...(props.onDeleteMessage ? { onDeleteMessage: (message: Message) => props.onDeleteMessage?.(message) } : {}),\n ...(props.canEditMessage ? { canEditMessage: props.canEditMessage } : {}),\n ...(props.confirmDelete ? { confirmDelete: props.confirmDelete } : {}),\n ...(props.onReplyToMessage ? { onReplyToMessage: (message: Message) => { props.onReplyToMessage?.(message) } } : {}),\n ...(props.canReplyToMessage ? { canReplyToMessage: props.canReplyToMessage } : {}),\n ...(props.replyPreviewByMessageId ? { replyPreviewByMessageId: props.replyPreviewByMessageId } : {}),\n ...(props.onJumpToMessage ? { onJumpToMessage: (messageId: string) => { props.onJumpToMessage?.(messageId) } } : {}),\n highlightedMessageId: props.highlightedMessageId,\n jumpInFlight: props.jumpInFlight,\n hasNewerMessages: props.hasNewerMessages,\n isLoadingNewer: props.isLoadingNewer,\n ...(props.onLoadNewer ? { onLoadNewer: loadNewer } : {}),\n reverse: props.reverseMessages,\n stickToBottom: props.stickToBottom,\n paginationThreshold: props.paginationThreshold,\n ...(props.formatTime ? { formatTime: props.formatTime } : {}),\n imageLoading: props.imageLoading,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n density: props.density,\n unstyled: props.unstyled,\n }, messageSlots))\n // Spread, not null: a live window renders nothing here and stays byte-identical to 0.8.\n if (props.onReturnToLatest) {\n const jumpSlotProps: JumpToLatestSlotProps = { returnToLatest }\n children.push(slots['jump-to-latest']?.(jumpSlotProps) ?? h('div', { class: 'ckui-conversation-jump' }, [\n h('button', {\n type: 'button', class: 'ckui-link-button', 'aria-label': 'Jump to latest messages',\n onClick: () => { void returnToLatest() },\n }, [h(ArrowDown, { size: 14, 'aria-hidden': 'true' }), ' Jump to latest']),\n ]))\n }\n children.push(renderTyping(), renderComposer())\n return h('section', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n 'aria-label': props.conversation.displayTitle,\n }, children)\n }\n },\n})\n\nexport interface ConversationProps extends Omit<ConversationViewProps,\n 'conversation' | 'messages' | 'currentUserId' | 'onSendMessage' | 'typingUserIds' |\n 'readAtByUserId' | 'readPositionByUserId' | 'onRefresh' | 'onLoadOlder' | 'onTypingChange' |\n 'isInitialLoading' | 'isLoadingOlder' | 'isSending' | 'hasOlderMessages' | 'error' |\n 'editingMessage' | 'onEditMessage' | 'onSaveEdit' | 'onCancelEdit' | 'onDeleteMessage' |\n 'replyTarget' | 'onReplyToMessage' | 'onCancelReply' | 'replyPreviewByMessageId' | 'onJumpToMessage' |\n 'highlightedMessageId' | 'jumpInFlight' | 'hasNewerMessages' | 'isLoadingNewer' | 'onLoadNewer' | 'onReturnToLatest'>,\n Omit<UseConversationOptions, 'client' | 'conversationId'> {\n client: ConvoKitUiClient\n conversationId: string\n onControllerChange?: (controller: ConversationController) => void\n}\n\n/** Plug-and-play SDK-backed UI for one conversation. */\nexport const Conversation = defineComponent({\n name: 'Conversation',\n inheritAttrs: false,\n props: {\n ...viewProps,\n conversation: { type: Object as PropType<ConversationModel>, default: undefined },\n messages: { type: Array as PropType<readonly Message[]>, default: () => [] },\n currentUserId: { type: String, default: '' },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n editingMessage: { type: Object as PropType<Message | null>, default: undefined },\n onEditMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onSaveEdit: { type: Function as PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n onCancelEdit: { type: Function as PropType<() => void>, default: undefined },\n onDeleteMessage: { type: Function as PropType<(message: Message) => boolean | void | Promise<boolean | void>>, default: undefined },\n replyTarget: { type: Object as PropType<Message | null>, default: undefined },\n onReplyToMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onCancelReply: { type: Function as PropType<() => void>, default: undefined },\n onJumpToMessage: { type: Function as PropType<(messageId: string) => void>, default: undefined },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n conversationId: { type: String, required: true },\n messagePageSize: { type: Number, default: 30 },\n markReadOnLoad: { type: Boolean, default: true },\n markReadOnReceive: { type: Boolean, default: true },\n typingTimeoutMs: { type: Number, default: 3000 },\n autoLoad: { type: Boolean, default: true },\n onControllerChange: { type: Function as PropType<(controller: ConversationController) => void>, default: undefined },\n },\n emits: [\n 'controller-change', 'send-message', 'typing-change', 'back', 'refresh', 'load-older', 'add-attachment', 'attachment-click', 'update:modelValue',\n 'edit-message', 'save-edit', 'cancel-edit', 'delete-message',\n 'reply-to-message', 'cancel-reply', 'jump-to-message', 'load-newer', 'return-to-latest',\n ],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversation({\n client: () => props.client,\n conversationId: () => props.conversationId,\n messagePageSize: props.messagePageSize,\n markReadOnLoad: props.markReadOnLoad,\n markReadOnReceive: props.markReadOnReceive,\n typingTimeoutMs: props.typingTimeoutMs,\n autoLoad: props.autoLoad,\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n // Automatic acknowledgements only while the document is visible; prerender/unknown/no document count as visible.\n if (typeof document !== 'undefined') {\n const syncVisibility = () => controller.setVisible(document.visibilityState !== 'hidden')\n syncVisibility()\n document.addEventListener('visibilitychange', syncVisibility)\n onBeforeUnmount(() => document.removeEventListener('visibilitychange', syncVisibility))\n }\n return () => {\n const loadedConversation = controller.conversation.value\n if (!loadedConversation) {\n const retry = () => { void controller.refresh() }\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, controller.error.value\n ? slots.error?.({ error: controller.error.value, retry }) ?? h('div', { class: 'ckui-state ckui-state--error', role: 'alert' }, [\n h('span', errorMessage(controller.error.value)),\n h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again'),\n ])\n : slots.loading?.() ?? h('div', { class: 'ckui-state', role: 'status' }, [\n h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…',\n ]))\n }\n const {\n client: _client,\n conversationId: _conversationId,\n messagePageSize: _messagePageSize,\n markReadOnLoad: _markReadOnLoad,\n markReadOnReceive: _markReadOnReceive,\n typingTimeoutMs: _typingTimeoutMs,\n autoLoad: _autoLoad,\n onControllerChange: _onControllerChange,\n conversation: _conversation,\n messages: _messages,\n currentUserId: _currentUserId,\n onSendMessage: _onSendMessage,\n typingUserIds: _typingUserIds,\n readAtByUserId: _readAtByUserId,\n readPositionByUserId: _readPositionByUserId,\n onRefresh: _onRefresh,\n onLoadOlder: _onLoadOlder,\n onTypingChange: _onTypingChange,\n isInitialLoading: _isInitialLoading,\n isLoadingOlder: _isLoadingOlder,\n isSending: _isSending,\n hasOlderMessages: _hasOlderMessages,\n error: _error,\n editingMessage: _editingMessage,\n onEditMessage: _onEditMessage,\n onSaveEdit: _onSaveEdit,\n onCancelEdit: _onCancelEdit,\n onDeleteMessage: _onDeleteMessage,\n replyTarget: _replyTarget,\n onReplyToMessage: _onReplyToMessage,\n onCancelReply: _onCancelReply,\n replyPreviewByMessageId: _replyPreviewByMessageId,\n onJumpToMessage: _onJumpToMessage,\n highlightedMessageId: _highlightedMessageId,\n jumpInFlight: _jumpInFlight,\n hasNewerMessages: _hasNewerMessages,\n isLoadingNewer: _isLoadingNewer,\n onLoadNewer: _onLoadNewer,\n onReturnToLatest: _onReturnToLatest,\n ...forwarded\n } = props\n return h(ConversationView, {\n ...attrs,\n ...forwarded,\n conversation: loadedConversation,\n messages: controller.messages.value,\n currentUserId: controller.currentUserId.value,\n onSendMessage: async (text: string) => {\n emit('send-message', text)\n return (await controller.sendMessage({ text })) !== null\n },\n typingUserIds: controller.typingUserIds.value,\n readAtByUserId: controller.readAtByUserId.value,\n readPositionByUserId: controller.readPositionByUserId.value,\n onRefresh: controller.refresh,\n onLoadOlder: controller.loadOlderMessages,\n onTypingChange: controller.updateTyping,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingOlder: controller.isLoadingOlder.value,\n isSending: controller.isSending.value,\n hasOlderMessages: controller.hasOlderMessages.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n // Edit mode is the store's; the actions render only while the adapter supports them (0.8.0).\n editingMessage: controller.editingMessage.value,\n ...(controller.canEditMessages.value ? {\n onEditMessage: (message: Message) => { emit('edit-message', message); controller.startEditing(message.id) },\n onSaveEdit: async (message: Message, text: string) => { emit('save-edit', message, text); return controller.saveEdit(text) },\n onCancelEdit: () => { emit('cancel-edit'); controller.cancelEditing() },\n } : {}),\n ...(controller.canDeleteMessages.value ? {\n onDeleteMessage: async (message: Message) => { emit('delete-message', message); return controller.deleteMessage(message.id) },\n } : {}),\n // Quoted replies and jump windows are the store's (0.9.0). Replying needs no adapter member; the jump\n // affordances appear only while the adapter can fetch a context window, and disappear for the store's\n // life against a backend that does not serve the route.\n replyTarget: controller.replyTarget.value,\n onReplyToMessage: (message: Message) => { emit('reply-to-message', message); controller.startReply(message.id) },\n onCancelReply: () => { emit('cancel-reply'); controller.cancelReply() },\n replyPreviewByMessageId: controller.replyPreviews.value,\n highlightedMessageId: controller.highlightedMessageId.value,\n jumpInFlight: controller.jumpInFlight.value,\n hasNewerMessages: controller.hasNewerMessages.value,\n isLoadingNewer: controller.isLoadingNewer.value,\n ...(controller.canJumpToMessage.value ? {\n onJumpToMessage: (messageId: string) => { emit('jump-to-message', messageId); void controller.jumpToMessage(messageId) },\n } : {}),\n ...(controller.windowMode.value === 'jumped' ? {\n onLoadNewer: () => { emit('load-newer'); return controller.loadNewerMessages() },\n onReturnToLatest: () => { emit('return-to-latest'); return controller.returnToLatest() },\n } : {}),\n 'onUpdate:modelValue': (value: string) => emit('update:modelValue', value),\n ...(props.onBack ? { onBack: () => { props.onBack?.(); emit('back') } } : {}),\n ...(props.onAddAttachment ? { onAddAttachment: () => { props.onAddAttachment?.(); emit('add-attachment') } } : {}),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n emit('attachment-click', media, message)\n } } : {}),\n } as never, slots)\n }\n },\n})\n","import type { Message, MessageMedia } from '@convokitapp/sdk'\nimport { computed, getCurrentScope, onScopeDispose, shallowRef, toValue, watch, type MaybeRefOrGetter } from 'vue'\nimport type { ConversationState, ConvoKitUiClient } from '../types'\nimport { ConversationStore, type ConversationSnapshot } from '../conversation-store'\n\nexport interface UseConversationOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n conversationId: MaybeRefOrGetter<string>\n messagePageSize?: number\n markReadOnLoad?: boolean\n markReadOnReceive?: boolean\n typingTimeoutMs?: number\n autoLoad?: boolean\n}\nexport interface ConversationController extends ConversationState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadOlderMessages(): Promise<void>\n sendMessage(input: { text?: string; media?: MessageMedia[] }): Promise<Message | null>\n /** Enter edit mode on one of the caller's own confirmed messages (0.8.0); a no-op for other rows, for a `READ`\n * role and for adapters without `editMessage`. Sends nothing (no typing update either).\n */\n startEditing(messageId: string): void\n /** Leave edit mode without a request. */\n cancelEditing(): void\n /** Save the edit in progress with the snapshot's revision; resolves true when the server accepted it. A stale\n * revision reloads the row, refreshes `editingMessage` and reports `REVISION_CONFLICT` through `error` (edit mode\n * and draft kept); see the README for the other outcomes. Rejects when the adapter lacks `editMessage`.\n */\n saveEdit(text: string): Promise<boolean>\n /** Delete one of the caller's own confirmed messages; resolves true once the row is gone (accepted, or already\n * unknown to the server). No optimistic removal. Rejects when the adapter lacks `deleteMessage`.\n */\n deleteMessage(messageId: string): Promise<boolean>\n /** Quote a rendered, confirmed message in the composer (0.9.0); a no-op for pending, tombstoned and unknown\n * rows and for a `READ` role. Any member may quote any row, own or not. Leaves edit mode. Sends nothing.\n */\n startReply(messageId: string): void\n /** Drop the reply target without a request; the draft is untouched. */\n cancelReply(): void\n /** Bring a message into view (0.9.0): a rendered row is only highlighted, otherwise the window is replaced by\n * a context window centred on it (`windowMode` becomes `jumped`). Resolves true once the target is\n * highlighted; false when the quoted message is gone (its preview becomes `'unavailable'`), when a send is in\n * flight, or when the adapter cannot fetch a context window.\n */\n jumpToMessage(messageId: string): Promise<boolean>\n /** Page a jumped window towards the newest messages; a no-op while `live` or already at the end. */\n loadNewerMessages(): Promise<void>\n /** Leave a jumped window and render the live tail again; resolves true once it is rendered. */\n returnToLatest(): Promise<boolean>\n /** Acknowledge through the newest rendered message now; no request is sent while nothing is rendered, and a\n * jumped window acknowledges nothing at all (0.9.0).\n */\n markRead(): Promise<void>\n /** Automatic acknowledgements pause while hidden and resume when the view becomes visible again. */\n setVisible(visible: boolean): void\n updateTyping(isTyping: boolean): Promise<void>\n dispose(): Promise<void>\n}\n\n/** Each room/login gets an independent owner; disposal also stops reactive reloads. */\nexport function useConversation(options: UseConversationOptions): ConversationController {\n const createStore = () => new ConversationStore({\n ...options, client: toValue(options.client), conversationId: toValue(options.conversationId),\n })\n let store = createStore()\n const snapshot = shallowRef(store.getSnapshot())\n let unsubscribe: (() => void) | undefined\n let visible = true\n const stop = watch(\n () => [toValue(options.client), toValue(options.client).sessionIdentity, toValue(options.conversationId)] as const,\n () => {\n store.dispose()\n unsubscribe?.()\n store = createStore()\n snapshot.value = store.getSnapshot()\n unsubscribe = store.subscribe(() => { snapshot.value = store.getSnapshot() })\n store.setVisible(visible)\n store.start(options.autoLoad ?? true)\n },\n { immediate: true, flush: 'sync' },\n )\n const field = <K extends keyof ConversationSnapshot>(key: K) => computed(() => snapshot.value[key])\n const dispose = async () => {\n stop()\n store.dispose()\n unsubscribe?.()\n unsubscribe = undefined\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n return {\n conversation: field('conversation'), messages: field('messages'),\n typingUserIds: field('typingUserIds'), readAtByUserId: field('readAtByUserId'),\n readPositionByUserId: field('readPositionByUserId'),\n isInitialLoading: field('isInitialLoading'), isLoadingOlder: field('isLoadingOlder'),\n isReconciling: field('isReconciling'), isSending: field('isSending'),\n hasOlderMessages: field('hasOlderMessages'), hasLoaded: field('hasLoaded'),\n error: field('error'), currentUserId: field('currentUserId'),\n editingMessage: field('editingMessage'), canEditMessages: field('canEditMessages'), canDeleteMessages: field('canDeleteMessages'),\n replyTarget: field('replyTarget'), replyPreviews: field('replyPreviews'),\n highlightedMessageId: field('highlightedMessageId'), jumpInFlight: field('jumpInFlight'),\n windowMode: field('windowMode'), hasNewerMessages: field('hasNewerMessages'), isLoadingNewer: field('isLoadingNewer'),\n canJumpToMessage: field('canJumpToMessage'), canResolveReplyPreviews: field('canResolveReplyPreviews'),\n readerIdsFor: (message) => store.readerIdsFor(message),\n loadInitial: () => store.loadInitial(), refresh: () => store.refresh(),\n loadOlderMessages: () => store.loadOlderMessages(), sendMessage: (input) => store.sendMessage(input),\n startEditing: (messageId) => store.startEditing(messageId), cancelEditing: () => store.cancelEditing(),\n saveEdit: (text) => store.saveEdit(text), deleteMessage: (messageId) => store.deleteMessage(messageId),\n startReply: (messageId) => store.startReply(messageId), cancelReply: () => store.cancelReply(),\n jumpToMessage: (messageId) => store.jumpToMessage(messageId),\n loadNewerMessages: () => store.loadNewerMessages(), returnToLatest: () => store.returnToLatest(),\n markRead: () => store.markRead(), updateTyping: (isTyping) => store.updateTyping(isTyping),\n setVisible: (value) => { visible = value; store.setVisible(value) },\n dispose,\n }\n}\n","import type {\n Conversation, Message, MessageEvent, MessageMedia, Participant, ReadPosition, RealtimeSubscription, ReplyPreview,\n} from '@convokitapp/sdk'\nimport { createClientMessageId } from '@convokitapp/sdk'\nimport type { ConvoKitWindowMode, ReplyPreviewEntry } from './types'\nimport type { ConvoKitUiClient } from './ui-client'\nimport { compareMessageOrder, isConvoKitPendingMessage, mergeMessages, readerIdsFor } from './utils'\n\nexport interface ConversationSnapshot {\n conversation: Conversation | null\n messages: Message[]\n typingUserIds: ReadonlySet<string>\n /** Last acknowledgement time per user; kept for custom renderers. */\n readAtByUserId: ReadonlyMap<string, Date>\n /** Monotonic read-through position per user; wins over `readAtByUserId` where present. */\n readPositionByUserId: ReadonlyMap<string, ReadPosition>\n isInitialLoading: boolean\n isLoadingOlder: boolean\n isReconciling: boolean\n isSending: boolean\n hasOlderMessages: boolean\n hasLoaded: boolean\n error: unknown\n currentUserId: string\n /** The row being edited, as the user saw it when editing started (0.8.0): its `revision` is what `saveEdit`\n * sends. Replaced by the current row when a conflict is detected; null when not editing.\n */\n editingMessage: Message | null\n /** Whether the adapter implements `editMessage` / `deleteMessage` (0.8.0); computed once at construction. */\n canEditMessages: boolean\n canDeleteMessages: boolean\n /** The message the composer is quoting (0.9.0), or null; replying and editing are mutually exclusive. */\n replyTarget: Message | null\n /** Quoted parents by `Message.replyToMessageId` (0.9.0). `'unavailable'` is terminal (the quoted message is\n * gone); a MISSING key is the distinct third state, \"not resolved yet\".\n */\n replyPreviews: ReadonlyMap<string, ReplyPreviewEntry>\n /** The row the last jump landed on (0.9.0); cleared by the highlight timeout. */\n highlightedMessageId: string | null\n /** Set from the moment a jump starts until shortly after the window has been replaced and scrolled (0.9.0).\n * The views read it to suspend stick-to-bottom, the highlight clear and pagination while a jump is landing.\n */\n jumpInFlight: boolean\n /** `live` (the tail) or `jumped` (a historical window a jump loaded, 0.9.0). */\n windowMode: ConvoKitWindowMode\n /** Whether a jumped window has newer messages beyond it; always false while `live` (0.9.0). */\n hasNewerMessages: boolean\n isLoadingNewer: boolean\n /** Whether the adapter implements `getMessageContext` / `getReplyPreviews` (0.9.0); decided once at\n * construction and turned off for the store's life by the uncoded 404 a 0.8 backend answers.\n */\n canJumpToMessage: boolean\n canResolveReplyPreviews: boolean\n}\n\ninterface Options {\n client: ConvoKitUiClient\n conversationId: string\n messagePageSize?: number\n markReadOnLoad?: boolean\n markReadOnReceive?: boolean\n typingTimeoutMs?: number\n}\n\ntype Cursor = Pick<Message, 'createdAt' | 'id'>\n// `revision` on changes, hydrations and the store is the store's own change counter (`this.revision`), unrelated to\n// `Message.revision`, the server's content revision that `revisionOrder` compares.\ntype Change = { revision: number; message: Message; insert: boolean; complete: boolean }\ntype Hydration = { revision: number; generation: number; message: Message; insert: boolean }\n/** Adapter support, decided once at construction. `jump` / `previews` (0.9.0) are also turned off for the store's\n * life by the uncoded 404 a 0.8 backend answers for the two new routes (E9b).\n */\ntype Support = { edit: boolean; delete: boolean; jump: boolean; previews: boolean }\ntype HydrationPool = { running: Set<string>; queued: Map<string, Hydration> }\ntype ReadEntry = { userId: string; readAt: Date | null; readPosition: ReadPosition | null | undefined }\n/** One acknowledgement pipeline per load: a single request in flight, one boolean follow-up resolved at send time. */\ntype Acknowledgement = {\n inFlight: Promise<void> | undefined\n followUp: boolean\n /** An automatic acknowledgement was wanted while hidden or before this open's DTO (and so its version) was in\n * hand; re-issued once the view becomes visible or the open captures.\n */\n suppressed: boolean\n /** Target of the request in flight. */\n target: string | undefined\n /** Last target the server accepted; older or equal targets are never re-sent. */\n acknowledged: Cursor | undefined\n /** Targets the server does not know (or that were removed): never targeted again. */\n unacknowledgeable: Set<string>\n}\n/** The caller's private state captured once per open, the first time `conversation` goes from null to a DTO.\n * `version` stays undefined until then and for a DTO without `membership` (0.6 backend: acknowledgements send no\n * version); `clearPending` is set when the opened membership carried an unread marker and consumed by the single\n * empty-room clear of that open.\n */\ntype Capture = { version: number | undefined; clearPending: boolean }\n\nfunction version(message: Message): number { return message.updatedAt?.getTime() ?? message.createdAt.getTime() }\nfunction hasContent(message: Message): boolean { return !!message.text?.trim() || message.media.length > 0 }\n/** Row precedence (0.8.0): when both rows carry a usable content revision (both present, at least one above 0)\n * the higher `Message.revision` decides (negative: `left` is older, positive: newer); equal revisions and rows\n * without a usable one (pending rows, 0.7 backends where every row is 0) answer undefined and fall back to the\n * `updatedAt ?? createdAt` rule.\n */\nfunction revisionOrder(left: Message, right: Message): number | undefined {\n const a = left.revision, b = right.revision\n if (typeof a !== 'number' || typeof b !== 'number' || (a <= 0 && b <= 0)) return undefined\n return a === b ? undefined : a - b\n}\n/** Whether `candidate` is strictly older than `reference`: by revision when usable, else by timestamp. */\nfunction older(candidate: Message, reference: Message): boolean {\n const byRevision = revisionOrder(candidate, reference)\n return byRevision === undefined ? version(candidate) < version(reference) : byRevision < 0\n}\nfunction newest(current: Message, incoming: Message, incomingComplete = true): Message {\n const byRevision = revisionOrder(current, incoming)\n if (byRevision !== undefined) return byRevision > 0 ? current : incoming\n return version(current) > version(incoming) || (!incomingComplete && version(current) === version(incoming)) ? current : incoming\n}\n/** A stale expected revision, as the backend reports it (409 `REVISION_CONFLICT`); a bare 409 counts only for\n * adapters that expose no code at all, like `isTargetMiss`.\n */\nfunction isRevisionConflict(cause: unknown): boolean {\n if (typeof cause !== 'object' || cause === null) return false\n const { code, status } = cause as { code?: unknown; status?: unknown }\n return code === 'REVISION_CONFLICT' || (code === undefined && status === 409)\n}\n/** An author mutation rejected because the message is gone: only the coded 404. An uncoded 404 (a 0.7 backend's\n * unmatched `/own` route, a proxy, a custom adapter) is reported as an error and never evicts the row.\n */\nfunction isMessageMissing(cause: unknown): boolean {\n return typeof cause === 'object' && cause !== null && (cause as { code?: unknown }).code === 'MESSAGE_NOT_FOUND'\n}\n/** The local conflict signal: a newer row for the edited message reached the store without a request. */\nfunction localConflict(): Error {\n return Object.assign(new Error('Message was changed since it was loaded'), { code: 'REVISION_CONFLICT' })\n}\n\n/** How long the jump guard holds after the window is in place: about two animation frames, long enough for the\n * view's programmatic scroll and focus move and the scroll events they emit.\n */\nconst JUMP_GUARD_MS = 150\n/** How long the jumped-to row stays highlighted once the guard clears. */\nconst HIGHLIGHT_MS = 2000\n\nconst compare = compareMessageOrder\nfunction positionCursor(position: ReadPosition): Cursor { return { createdAt: position.createdAt, id: position.messageId } }\nfunction readEntry(participant: Participant): ReadEntry {\n return { userId: participant.appUserId, readAt: participant.lastReadAt, readPosition: participant.readPosition }\n}\nfunction acknowledgement(): Acknowledgement {\n return { inFlight: undefined, followUp: false, suppressed: false, target: undefined, acknowledged: undefined, unacknowledgeable: new Set() }\n}\nfunction capture(conversation?: Conversation): Capture {\n const membership = conversation?.membership\n return { version: membership?.privateStateVersion, clearPending: membership?.unreadMarkedAt != null }\n}\n/** A targeted read the server rejected because the target is unknown to it (deleted or foreign). Membership\n * failures carry no `MESSAGE_NOT_FOUND` code (the core SDK reports `HTTP_ERROR`), so they remain errors; a\n * bare 404 counts as a miss only for adapters that expose no code at all.\n */\nfunction isTargetMiss(cause: unknown): boolean {\n if (typeof cause !== 'object' || cause === null) return false\n const { code, status } = cause as { code?: unknown; status?: unknown }\n return code === 'MESSAGE_NOT_FOUND' || (code === undefined && status === 404)\n}\n/** The 404 a 0.8 backend answers for a route it does not serve: Express's unmatched-route HTML, which the core\n * SDK reports without a body code (`HTTP_ERROR`). Never `MESSAGE_NOT_FOUND`, which is a real missing target and\n * must not retire the affordance (E9b).\n */\nfunction isRouteMissing(cause: unknown): boolean {\n if (typeof cause !== 'object' || cause === null) return false\n const { code, status } = cause as { code?: unknown; status?: unknown }\n return status === 404 && code !== 'MESSAGE_NOT_FOUND'\n}\n\n/** The preview a quoted parent inside the loaded window derives to (0.9.0): the same shape the backend returns,\n * so a rendered quote never costs a request for a row the store already has. Text is cut at the backend's 500\n * characters and `mediaCount` counts the hydrated attachments.\n */\nconst REPLY_PREVIEW_TEXT_LIMIT = 500\nfunction previewOf(message: Message): ReplyPreview {\n const text = message.text\n return {\n id: message.id, conversationId: message.conversationId, senderId: message.senderId,\n text: text === null ? null : text.slice(0, REPLY_PREVIEW_TEXT_LIMIT),\n textTruncated: (text?.length ?? 0) > REPLY_PREVIEW_TEXT_LIMIT,\n createdAt: message.createdAt, revision: message.revision, mediaCount: message.media.length,\n }\n}\n\nfunction blank(currentUserId = '', support: Support = { edit: false, delete: false, jump: false, previews: false }): ConversationSnapshot {\n return {\n conversation: null, messages: [], typingUserIds: new Set(), readAtByUserId: new Map(), readPositionByUserId: new Map(),\n isInitialLoading: false, isLoadingOlder: false, isReconciling: false, isSending: false,\n hasOlderMessages: true, hasLoaded: false, error: null, currentUserId,\n editingMessage: null, canEditMessages: support.edit, canDeleteMessages: support.delete,\n replyTarget: null, replyPreviews: new Map(), highlightedMessageId: null, jumpInFlight: false,\n windowMode: 'live', hasNewerMessages: false, isLoadingNewer: false,\n canJumpToMessage: support.jump, canResolveReplyPreviews: support.previews,\n }\n}\n\n/** Internal, framework-independent room lifecycle. Never shared across client sessions. */\nexport class ConversationStore {\n private readonly client: ConvoKitUiClient\n private readonly room: string\n private readonly owner: object | null\n private readonly user: string\n private readonly pageSize: number\n private readonly typingTimeout: number\n private state: ConversationSnapshot\n private listeners = new Set<() => void>()\n private subscriptions: RealtimeSubscription[] = []\n private disposed = true\n private generation = 0\n private cursor: Cursor | undefined\n private revision = 0\n private changes = new Map<string, Change>()\n private hydrations = new Map<string, Hydration>()\n private hydrationPool: HydrationPool = { running: new Set(), queued: new Map() }\n // Keep tombstones until an explicit reload/session change, including across refreshes.\n private deleted = new Set<string>()\n private ack = acknowledgement()\n private captured = capture()\n // Visible until the platform reports otherwise; unknown/prerender/no document count as visible.\n private visible = true\n private sendRevision: number | undefined\n private activeSend: { pending: Message; confirmed?: Message } | undefined\n /** Adapter support for author edits/deletes, decided once like `listInbox`. */\n private readonly support: Support\n /** The id whose `saveEdit` request is in flight: its outcome (success or 409) decides the edit, so newer rows for\n * it arriving meanwhile (its own UPDATE image, typically) are not reported as a local conflict while it lasts;\n * `settleEditing` re-evaluates them once the request has settled any other way.\n */\n private activeEdit: string | undefined\n private refreshQueued = false\n /** A reconcile owed to the JUMPED window (0.9.0). `refreshQueued` stays owed across a jump so the tail-anchored\n * reconcile still runs on the return to `live`; this flag is the one a jumped window consumes.\n */\n private jumpedRefreshQueued = false\n /** The jumped window's paging cursors (0.9.0), opaque and server-minted; null at that end of the history. */\n private olderContextCursor: string | null = null\n private newerContextCursor: string | null = null\n /** Preview entries that must be re-read on the next batch: a quoted parent changed outside the window, or the\n * subscription reconnected (0.9.0). `'unavailable'` is terminal and never enters this set.\n */\n private stalePreviews = new Set<string>()\n /** Ids a batch is already asking for (0.9.0): two triggers that overlap share one request instead of racing. */\n private requestedPreviews = new Set<string>()\n /** Live inserts recorded but not rendered while jumped (0.9.0); drained — and acknowledged — by the return. */\n private deferred = new Set<string>()\n /** The message the current jumped window was centred on, until the window is paged (0.9.0). */\n private jumpAnchor: string | undefined\n private previewTimer: ReturnType<typeof setTimeout> | undefined\n private jumpTimer: ReturnType<typeof setTimeout> | undefined\n private highlightTimer: ReturnType<typeof setTimeout> | undefined\n private typingTimers = new Map<string, ReturnType<typeof setTimeout>>()\n private ownTypingTimer: ReturnType<typeof setTimeout> | undefined\n private sentTyping = false\n private typingRevision = 0\n private lastTypingSentAt = -Infinity\n\n constructor(private readonly options: Options) {\n this.client = options.client\n this.room = options.conversationId.trim()\n this.pageSize = options.messagePageSize ?? 30\n this.typingTimeout = options.typingTimeoutMs ?? 3000\n if (!this.room) throw new TypeError('conversationId is required')\n if (!Number.isInteger(this.pageSize) || this.pageSize < 1 || this.pageSize > 100) {\n throw new RangeError('messagePageSize must be an integer between 1 and 100')\n }\n if (!Number.isFinite(this.typingTimeout) || this.typingTimeout < 0) {\n throw new RangeError('typingTimeoutMs must be non-negative')\n }\n this.owner = this.client.sessionIdentity\n this.user = this.owner ? this.client.currentUserId : ''\n this.support = {\n edit: typeof this.client.editMessage === 'function', delete: typeof this.client.deleteMessage === 'function',\n jump: typeof this.client.getMessageContext === 'function', previews: typeof this.client.getReplyPreviews === 'function',\n }\n this.state = blank(this.user, this.support)\n }\n\n getSnapshot = (): ConversationSnapshot => this.state\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n private patch(patch: Partial<ConversationSnapshot>): void {\n if (patch.messages && this.activeSend) {\n for (const message of patch.messages) this.confirmSend(message)\n if (this.activeSend.confirmed) patch.messages = patch.messages.filter(message => message.id !== this.activeSend!.pending.id)\n }\n if (patch.messages) patch = this.trackEditing(patch)\n this.state = { ...this.state, ...patch }\n for (const listener of this.listeners) listener()\n }\n /** Edit mode follows the edited row wherever a message list reaches the state: the row leaving the list (deletion,\n * reconcile tombstone, eviction) ends it, and a row for it with a higher revision than the snapshot (UPDATE image,\n * hydration, reconcile, refresh) is the local conflict: the snapshot is replaced and `error` carries the conflict\n * code, without a request. A save in flight owns its own outcome (`activeEdit`) and re-checks when it settles\n * (`settleEditing`).\n */\n private trackEditing(patch: Partial<ConversationSnapshot>): Partial<ConversationSnapshot> {\n const editing = patch.editingMessage === undefined ? this.state.editingMessage : patch.editingMessage\n if (!editing || !patch.messages) return patch\n const live = patch.messages.find((message) => message.id === editing.id)\n if (!live) return { ...patch, editingMessage: null }\n if (this.activeEdit === editing.id || !(live.revision > editing.revision)) return patch\n return { ...patch, editingMessage: live, error: localConflict() }\n }\n /** After a save for `id` has settled without deciding the edit (a failure, or a 409 whose reload failed), a newer\n * row for it that arrived during the request is the local conflict after all: the snapshot is replaced and\n * `error` carries the conflict code, so the next save carries the fresh revision without another round trip.\n */\n private settleEditing(id: string): void {\n const editing = this.state.editingMessage\n const live = editing?.id === id ? this.state.messages.find((message) => message.id === id) : undefined\n if (editing && live && live.revision > editing.revision) this.patch({ editingMessage: live, error: localConflict() })\n }\n private alive(generation = this.generation): boolean {\n return !this.disposed && generation === this.generation\n && this.owner !== null && this.client.sessionIdentity === this.owner\n }\n\n start = (autoLoad = true): void => {\n if (this.owner === null || this.client.sessionIdentity !== this.owner) return\n this.disposed = false\n this.patch({ currentUserId: this.user })\n if (autoLoad) void this.loadInitial()\n else {\n try { this.attach(this.generation, false) } catch { /* attach reports adapter failures */ }\n }\n }\n\n private detach(): void {\n const active = this.subscriptions\n this.subscriptions = []\n for (const subscription of active) void subscription.unsubscribe().catch(() => undefined)\n }\n\n private clearTyping(): void {\n for (const timer of this.typingTimers.values()) clearTimeout(timer)\n this.typingTimers.clear()\n clearTimeout(this.ownTypingTimer)\n this.ownTypingTimer = undefined\n this.sentTyping = false\n this.typingRevision++\n this.lastTypingSentAt = -Infinity\n this.patch({ typingUserIds: new Set() })\n }\n\n private clear(): void {\n this.generation++\n this.detach()\n this.clearTyping()\n this.cursor = undefined\n this.changes.clear()\n this.hydrations.clear()\n this.hydrationPool.queued.clear()\n // In-flight adapter promises cannot be aborted through this interface.\n // Keep their slots across reloads so repeated loads cannot exceed the cap.\n this.deleted.clear()\n // A retired pipeline's response settles against the old generation and is ignored.\n this.ack = acknowledgement()\n // Every open captures the caller's private state afresh; nothing captured survives `conversation` going null.\n this.captured = capture()\n this.sendRevision = undefined\n this.activeSend = undefined\n this.activeEdit = undefined\n this.refreshQueued = false\n // Quoted replies and jump windows (0.9.0) are per-open state like the rest; a JUMP never resets any of it.\n this.jumpedRefreshQueued = false\n this.olderContextCursor = null\n this.newerContextCursor = null\n this.jumpAnchor = undefined\n this.stalePreviews.clear()\n this.requestedPreviews.clear()\n this.deferred.clear()\n clearTimeout(this.previewTimer)\n this.previewTimer = undefined\n clearTimeout(this.jumpTimer)\n this.jumpTimer = undefined\n clearTimeout(this.highlightTimer)\n this.highlightTimer = undefined\n }\n\n dispose = (): void => {\n // A retired session must never send a typing update using a replacement login.\n if (this.alive() && this.sentTyping) {\n void this.client.sendTyping({ conversationId: this.room, isTyping: false }).catch(() => undefined)\n }\n this.disposed = true\n this.clear()\n this.patch(blank('', this.support))\n }\n\n private fail(cause: unknown, generation: number, history = false): void {\n if (!this.alive(generation)) return\n const status = typeof cause === 'object' && cause !== null && 'status' in cause ? cause.status : undefined\n if (history && (status === 401 || status === 403 || status === 404)) {\n this.clear()\n this.patch({ ...blank(this.user, this.support), error: cause, hasLoaded: true, hasOlderMessages: false })\n } else this.patch({ error: cause })\n }\n\n private attach(generation: number, data = true): void {\n const report = (cause: Error) => this.fail(cause, generation)\n const add = (create: () => RealtimeSubscription) => {\n if (!this.alive(generation)) return\n const subscription = create()\n if (this.alive(generation)) this.subscriptions.push(subscription)\n else void subscription.unsubscribe().catch(() => undefined)\n }\n try {\n // Install lifecycle ownership before providers can synchronously report a join.\n add(() => this.client.onConnectionEvent({\n onEvent: ({ topic, status }) => {\n if (!data || !this.alive(generation) || (topic !== `messages:${this.room}` && topic !== `conversation:${this.room}`)) return\n if (status === 'SUBSCRIBED') {\n // Anything could have changed while the socket was down, including the quoted parents the window\n // references, so every non-terminal preview is re-read with the reconcile (0.9.0).\n this.markPreviewsStale()\n this.queueRefresh()\n } else this.clearTyping()\n },\n onSessionEnded: () => {\n if (this.disposed || generation !== this.generation) return\n this.dispose()\n },\n onError: report,\n }))\n if (!data) return\n add(() => this.client.onInboxChanged(() => {\n if (this.alive(generation)) this.queueRefresh()\n }, cause => {\n if (this.alive(generation)) { report(cause); this.queueRefresh() }\n }))\n add(() => this.client.onMessage(this.room, (event) => this.onMessage(event, generation), report))\n add(() => this.client.onMessageDeleted(this.room, ({ id, conversationId }) => {\n if (!this.alive(generation) || conversationId !== this.room || !id.trim()) return\n this.removeMessage(id)\n }, report))\n add(() => this.client.onReadReceipt(this.room, ({ userId, readAt, readPosition }) => {\n if (this.alive(generation)) this.mergeReads([{ userId, readAt, readPosition }])\n }, report))\n add(() => this.client.onTyping(this.room, ({ userId, isTyping }) => {\n if (!this.alive(generation) || !userId.trim() || userId === this.user) return\n clearTimeout(this.typingTimers.get(userId))\n this.typingTimers.delete(userId)\n const next = new Set(this.state.typingUserIds)\n if (isTyping) {\n next.add(userId)\n this.typingTimers.set(userId, setTimeout(() => {\n this.typingTimers.delete(userId)\n if (!this.alive(generation)) return\n const remaining = new Set(this.state.typingUserIds)\n remaining.delete(userId)\n this.patch({ typingUserIds: remaining })\n }, this.typingTimeout))\n } else next.delete(userId)\n this.patch({ typingUserIds: next })\n }, report))\n } catch (cause) {\n this.detach()\n this.fail(cause, generation)\n throw cause\n }\n }\n\n private validMessage(message: Message): boolean {\n return message.conversationId === this.room && !!message.id.trim()\n && !!message.senderId.trim() && !isConvoKitPendingMessage(message)\n && Number.isFinite(message.createdAt.getTime()) && Number.isFinite(version(message))\n }\n\n private onMessage(event: MessageEvent, generation: number): void {\n const { message, type } = event\n if (!this.alive(generation) || (type !== 'insert' && type !== 'update')\n || !this.validMessage(message) || this.deleted.has(message.id)) return\n const existing = this.state.messages.find((item) => item.id === message.id)\n const known = existing ?? this.changes.get(message.id)?.message\n if (known && older(message, known)) return\n const insert = type === 'insert' || this.changes.get(message.id)?.insert === true\n if (!existing && !insert && type === 'update') {\n // The row is outside the loaded window, so it is not history this store keeps — but it may be a quoted\n // parent a rendered reply points at, and a preview is re-read, never copied (0.9.0). The invalidation is\n // unconditional: while a load is in flight the event still falls through to `record()` so the page in\n // flight sees the newer image, and `record()` returns before the preview calls for a row the window does\n // not hold.\n this.notePreviewSource(message.id)\n if (!this.state.isInitialLoading && !this.state.isLoadingOlder && !this.state.isReconciling) return\n }\n const revision = ++this.revision\n // A raw Message row has no related Media; absence is not authoritative removal.\n const provisional = existing && !message.media.length ? { ...message, media: existing.media } : message\n this.record(provisional, insert, revision, false)\n const job: Hydration = { revision, generation, message, insert }\n this.hydrations.set(message.id, job)\n this.hydrationPool.queued.set(message.id, job)\n this.drainHydration()\n }\n\n private record(message: Message, insert: boolean, revision: number, complete: boolean): void {\n const existing = this.state.messages.find((item) => item.id === message.id)\n if (existing && older(message, existing)) return\n // The exact server-echoed send ID also confirms media-only rows before hydration.\n // Keep that send's local media until the complete authorized response arrives.\n if (this.confirmSend(message) && !complete && !message.media.length) {\n message = { ...message, media: this.activeSend!.pending.media }\n this.confirmSend(message)\n }\n this.changes.set(message.id, { revision, message, insert, complete })\n if (!existing && !(insert && hasContent(message))) return\n // A historical window never gains a live-tail row (0.9.0): ingestion ran to completion (the change is\n // recorded, so hydration, media completion, send confirmation and tombstones keep working) but the row is\n // not rendered and therefore not acknowledged until the return to `live` drains it.\n if (!existing && this.state.windowMode === 'jumped') {\n this.deferred.add(message.id)\n if (!this.state.hasNewerMessages) this.patch({ hasNewerMessages: true })\n return\n }\n this.patch({ messages: mergeMessages(this.state.messages, [message]) })\n this.notePreviewSource(message.id)\n if (message.replyToMessageId) this.schedulePreviews()\n // A foreign row entering the rendered list is the receive trigger, so a withheld\n // media-only row is acknowledged once its hydration renders it, never before.\n if (!existing && message.senderId !== this.user && (this.options.markReadOnReceive ?? true)) void this.acknowledge(true)\n }\n\n private confirmSend(message: Message): boolean {\n const send = this.activeSend\n if (!send || !this.validMessage(message) || message.senderId !== this.user\n || message.clientMessageId !== send.pending.clientMessageId) return false\n send.confirmed = send.confirmed ? newest(send.confirmed, message) : message\n return true\n }\n\n private currentHydration(job: Hydration): boolean {\n return this.alive(job.generation) && !this.deleted.has(job.message.id) && this.hydrations.get(job.message.id) === job\n }\n\n private removeMessage(id: string): void {\n this.forget(id)\n this.patch({ messages: this.state.messages.filter((message) => message.id !== id) })\n }\n\n /** Tombstone a row learned to be gone; a removed acknowledgement target is re-resolved from what remains. */\n private forget(id: string): void {\n this.deleted.add(id)\n this.changes.delete(id)\n this.hydrations.delete(id)\n this.hydrationPool.queued.delete(id)\n this.deferred.delete(id)\n // A deleted message is a terminal answer for every reply quoting it, inside the window or outside (0.9.0):\n // the reference and the jump affordance stay, the quoted text becomes \"Original message unavailable\".\n this.markUnavailable(id)\n // A quote survives a window change, but not the disappearance of the message it quotes.\n if (this.state.replyTarget?.id === id) this.patch({ replyTarget: null })\n const ack = this.ack\n if (ack.target !== id && ack.acknowledged?.id !== id) return\n ack.unacknowledgeable.add(id)\n if (ack.target === id) ack.followUp = true\n }\n\n private drainHydration(): void {\n const pool = this.hydrationPool\n for (const [id, job] of pool.queued) {\n if (pool.running.size >= 8) break\n if (pool.running.has(id)) continue\n pool.queued.delete(id)\n if (!this.currentHydration(job)) continue\n pool.running.add(id)\n void this.hydrate(job, pool)\n }\n }\n\n private async hydrate(job: Hydration, pool: HydrationPool): Promise<void> {\n const id = job.message.id\n try {\n if (!this.currentHydration(job)) return\n const full = await this.client.getMessage(id)\n if (!this.currentHydration(job)) return\n if (!this.validMessage(full) || full.id !== id || full.senderId !== job.message.senderId || older(full, job.message)) {\n throw new Error('Complete message response does not match the observed resource/revision')\n }\n // Completion is not a fresh change: a later snapshot outranks the originating event.\n this.record(full, job.insert, job.revision, true)\n } catch (cause) {\n if (!this.currentHydration(job)) return\n const status = typeof cause === 'object' && cause !== null && 'status' in cause ? cause.status : undefined\n if (status === 404) this.removeMessage(id)\n this.fail(cause, job.generation)\n this.queueRefresh()\n } finally {\n if (this.hydrations.get(id) === job) this.hydrations.delete(id)\n pool.running.delete(id)\n queueMicrotask(() => { if (this.hydrationPool === pool) this.drainHydration() })\n }\n }\n\n /** Both maps only ever advance: acknowledgement times by time, positions by (createdAt, id). Participants and\n * read events are the only sources; the local user's own read is never written from the device clock.\n */\n private mergeReads(entries: Iterable<ReadEntry>): void {\n const readAt = new Map(this.state.readAtByUserId)\n const positions = new Map(this.state.readPositionByUserId)\n for (const entry of entries) {\n const { userId, readPosition } = entry\n if (!userId.trim()) continue\n if (entry.readAt && Number.isFinite(entry.readAt.getTime()) && entry.readAt.getTime() > (readAt.get(userId)?.getTime() ?? -Infinity)) {\n readAt.set(userId, entry.readAt)\n }\n if (!readPosition || typeof readPosition.messageId !== 'string' || !readPosition.messageId.trim()\n || !(readPosition.createdAt instanceof Date) || !Number.isFinite(readPosition.createdAt.getTime())) continue\n const current = positions.get(userId)\n if (!current || compare(positionCursor(readPosition), positionCursor(current)) > 0) positions.set(userId, readPosition)\n }\n this.patch({ readAtByUserId: readAt, readPositionByUserId: positions })\n }\n\n private validatePage(page: Message[], before?: Cursor): void {\n if (page.length > this.pageSize) throw new Error('Message page exceeds the requested limit')\n let previous = before\n for (const message of page) {\n if (!this.validMessage(message) || (previous && compare(message, previous) >= 0)) {\n throw new Error('Message history must contain distinct, room-scoped rows in newest-first cursor order')\n }\n previous = message\n }\n }\n\n /** Context windows get their OWN validator (0.9.0): `validatePage` measures a page against the backward cursor\n * it was fetched with, and a window centred on a message has no such cursor. Only the per-row predicates are\n * shared. A CENTRED window must carry its target exactly once; a cursor page must not be held to that.\n */\n private validateContextPage(page: Message[], limit: number, targetId?: string): void {\n if (page.length > limit) throw new Error('Message context exceeds the requested limit')\n let previous: Cursor | undefined\n for (const message of page) {\n if (!this.validMessage(message) || (previous && compare(message, previous) >= 0)) {\n throw new Error('Message context must contain distinct, room-scoped rows in newest-first order')\n }\n previous = message\n }\n if (targetId !== undefined && page.filter((message) => message.id === targetId).length !== 1) {\n throw new Error('Centred message context must contain its target exactly once')\n }\n }\n\n private fetchPage(before?: Cursor): Promise<Message[]> {\n return this.client.getMessages({\n conversationId: this.room, limit: this.pageSize,\n ...(before ? { beforeCreatedAt: before.createdAt, beforeId: before.id } : {}),\n })\n }\n\n private overlay(rows: Message[], revision: number): Message[] {\n const byId = new Map(rows.filter((message) => !this.deleted.has(message.id)).map((message) => [message.id, message]))\n for (const [id, change] of this.changes) {\n if (change.revision > revision && !this.deleted.has(id) && (change.insert || byId.has(id))) {\n const current = byId.get(id)\n if (current || change.complete || hasContent(change.message)) {\n byId.set(id, current ? newest(current, change.message, change.complete) : change.message)\n }\n }\n }\n for (const message of this.state.messages) {\n if (isConvoKitPendingMessage(message)) byId.set(message.id, message)\n }\n return mergeMessages([], [...byId.values()])\n }\n\n /** `overlay` for a JUMPED window (0.9.0): the same precedence for rows the window already holds, WITHOUT the\n * pending replay and the `changes`-insert replay, either of which would inject live-tail rows into a\n * historical window. A jumped window only ever holds rows a context response carried.\n */\n private overlayWindow(rows: Message[], revision: number): Message[] {\n const byId = new Map(rows.filter((message) => !this.deleted.has(message.id)).map((message) => [message.id, message]))\n for (const [id, change] of this.changes) {\n const current = byId.get(id)\n if (current && change.revision > revision) byId.set(id, newest(current, change.message, change.complete))\n }\n return mergeMessages([], [...byId.values()])\n }\n\n /** The distinct quoted parents the rendered rows point at (0.9.0). */\n private referencedParents(): Set<string> {\n const referenced = new Set<string>()\n for (const message of this.state.messages) {\n if (message.replyToMessageId) referenced.add(message.replyToMessageId)\n }\n return referenced\n }\n\n /** Cache the terminal `'unavailable'` for a quoted parent that is gone, while any rendered row still quotes it\n * (or an entry for it already exists). Never re-requested: absence from a resolved batch is the only deletion\n * signal the backend gives, and a deleted message cannot come back.\n */\n private markUnavailable(id: string): void {\n const cached = this.state.replyPreviews.get(id)\n if (cached === 'unavailable') return\n if (cached === undefined && !this.referencedParents().has(id)) return\n const next = new Map(this.state.replyPreviews)\n next.set(id, 'unavailable')\n this.stalePreviews.delete(id)\n this.patch({ replyPreviews: next })\n }\n\n /** Re-read every non-terminal preview on the next batch (reconnect/`SUBSCRIBED`). */\n private markPreviewsStale(): void {\n for (const [id, entry] of this.state.replyPreviews) if (entry !== 'unavailable') this.stalePreviews.add(id)\n }\n\n /** A row for a quoted parent reached the store: the preview that references it is refreshed from the rendered\n * row, or marked stale when the parent is outside the window. Previews are re-read, never copied — a parent\n * edit bumps the PARENT's revision, which no row-precedence rule on the reply can see.\n */\n private notePreviewSource(id: string): void {\n const cached = this.state.replyPreviews.get(id)\n if (cached === undefined) return\n const row = this.state.messages.find((message) => message.id === id)\n if (row && !isConvoKitPendingMessage(row)) {\n const fresh = previewOf(row)\n this.stalePreviews.delete(id)\n if (cached !== 'unavailable' && cached.revision === fresh.revision && cached.text === fresh.text\n && cached.mediaCount === fresh.mediaCount) return\n const next = new Map(this.state.replyPreviews)\n next.set(id, fresh)\n this.patch({ replyPreviews: next })\n return\n }\n if (cached === 'unavailable') return\n this.stalePreviews.add(id)\n this.schedulePreviews()\n }\n\n /** Coalesce a burst of live inserts into one batch; the handle is cleared wherever subscriptions are torn down\n * and the callback is dropped when the store is no longer alive for the generation that scheduled it.\n */\n private schedulePreviews(): void {\n if (this.previewTimer !== undefined || !this.support.previews) return\n const generation = this.generation\n const timer = setTimeout(() => {\n this.previewTimer = undefined\n if (this.alive(generation)) void this.resolvePreviews()\n }, 120)\n ;(timer as { unref?: () => void }).unref?.()\n this.previewTimer = timer\n }\n\n /** Resolve the quoted parents of the rendered rows in ONE request, never one per row (0.9.0). A parent inside\n * the loaded window is derived locally and costs nothing; `'unavailable'` is terminal; an id with no entry is\n * \"not resolved yet\", so a rejection — which says nothing about which ids exist — writes no entry at all and\n * the next trigger asks again. `prune` drops entries no rendered row references (reconcile completion), which\n * is what bounds the map to the window.\n */\n private async resolvePreviews(prune = false): Promise<void> {\n if (!this.alive() || !this.support.previews || !this.state.canResolveReplyPreviews) return\n const referenced = this.referencedParents()\n const previews = new Map(this.state.replyPreviews)\n let changed = false\n if (prune) {\n for (const id of [...previews.keys()]) {\n if (referenced.has(id)) continue\n previews.delete(id)\n this.stalePreviews.delete(id)\n changed = true\n }\n }\n const window = new Map(this.state.messages.filter((message) => !isConvoKitPendingMessage(message))\n .map((message) => [message.id, message] as const))\n const wanted: string[] = []\n for (const id of referenced) {\n const local = window.get(id)\n if (local) {\n this.stalePreviews.delete(id)\n const cached = previews.get(id)\n const fresh = previewOf(local)\n if (cached === undefined || cached === 'unavailable' || cached.revision !== fresh.revision\n || cached.text !== fresh.text || cached.mediaCount !== fresh.mediaCount) {\n previews.set(id, fresh)\n changed = true\n }\n continue\n }\n const cached = previews.get(id)\n if (cached === 'unavailable') continue\n if (cached !== undefined && !this.stalePreviews.has(id)) continue\n if (this.requestedPreviews.has(id)) continue\n wanted.push(id)\n }\n if (changed) this.patch({ replyPreviews: previews })\n if (wanted.length === 0) return\n const generation = this.generation\n for (const id of wanted) this.requestedPreviews.add(id)\n try {\n const resolved = await this.client.getReplyPreviews!(this.room, wanted)\n if (!this.alive(generation)) return\n const next = new Map(this.state.replyPreviews)\n const returned = new Set<string>()\n for (const preview of resolved) {\n if (preview.conversationId !== this.room) continue\n returned.add(preview.id)\n next.set(preview.id, preview)\n this.stalePreviews.delete(preview.id)\n }\n // Absence from a RESOLVED result is the deletion signal; the entry is terminal from here.\n for (const id of wanted) {\n if (returned.has(id)) continue\n next.set(id, 'unavailable')\n this.stalePreviews.delete(id)\n }\n this.patch({ replyPreviews: next })\n } catch (cause) {\n if (!this.alive(generation)) return\n // Nothing is written for any id in a rejected batch: they stay unresolved and are asked for again.\n if (isRouteMissing(cause)) {\n this.support.previews = false\n this.patch({ canResolveReplyPreviews: false })\n }\n this.fail(cause, generation)\n } finally {\n for (const id of wanted) this.requestedPreviews.delete(id)\n }\n }\n\n private prune(revision: number): void {\n const safeRevision = Math.min(revision, this.sendRevision ?? Infinity)\n for (const [id, change] of this.changes) if (change.revision <= safeRevision) this.changes.delete(id)\n for (const [id, job] of this.hydrations) if (job.revision <= revision) {\n this.hydrations.delete(id)\n this.hydrationPool.queued.delete(id)\n }\n }\n\n loadInitial = async (): Promise<void> => {\n if (!this.alive()) return\n this.clear()\n const generation = this.generation\n this.patch({ ...blank(this.user, this.support), isInitialLoading: true })\n const revision = this.revision\n try {\n this.attach(generation)\n if (!this.alive(generation)) return\n const [conversation, page] = await Promise.all([this.client.getConversation(this.room), this.fetchPage()])\n if (!this.alive(generation)) return\n if (conversation.id !== this.room) throw new Error('Conversation response belongs to a different room')\n this.validatePage(page)\n this.cursor = page.at(-1)\n this.patch({ conversation, messages: this.overlay(page, revision), hasOlderMessages: page.length === this.pageSize })\n // The DTO is in hand before this open's first acknowledgement: capture its private state now.\n this.captured = capture(conversation)\n this.mergeReads(conversation.participants.map(readEntry))\n this.prune(revision)\n void this.resolvePreviews()\n // The load acknowledgement also covers an automatic one that waited for the DTO (a row inserted during the load).\n if ((this.options.markReadOnLoad ?? true) || this.ack.suppressed) {\n this.ack.suppressed = false\n await this.acknowledge(true)\n }\n } catch (cause) {\n this.fail(cause, generation, true)\n } finally {\n if (this.alive(generation)) {\n this.patch({ isInitialLoading: false, hasLoaded: true })\n this.flushRefresh()\n }\n }\n }\n\n private queueRefresh(): void {\n this.refreshQueued = true\n this.jumpedRefreshQueued = true\n this.flushRefresh()\n }\n private flushRefresh(): void {\n const generation = this.generation\n void Promise.resolve().then(() => {\n if (!this.alive(generation) || !this.refreshQueued || this.state.isInitialLoading\n || this.state.isLoadingOlder || this.state.isLoadingNewer || this.state.isReconciling) return\n // A jumped window is not anchored at the live tail, so the boundary walk `refresh()` performs cannot run\n // here (0.9.0). The gate sits BEFORE the flag is consumed: the tail reconcile stays owed and flushes on\n // the return to `live`, while the jumped window is re-read once per queued refresh instead.\n if (this.state.windowMode === 'jumped') {\n if (!this.jumpedRefreshQueued) return\n this.jumpedRefreshQueued = false\n void this.reconcileWindow()\n return\n }\n this.refreshQueued = false\n this.jumpedRefreshQueued = false\n void this.refresh()\n })\n }\n\n /** Re-fetch the entire viewed range atomically; a first-page-only refresh loses history. */\n refresh = async (): Promise<void> => {\n if (!this.alive()) return\n // A JUMPED window is not anchored at the live tail, so the boundary walk below cannot run over it — not\n // from the queued path and not from a host calling `refresh()` directly (0.9.0). The window is re-read with\n // the same single bounded request instead, and the tail reconcile stays owed for the return to `live`.\n if (this.state.windowMode === 'jumped') {\n this.refreshQueued = true\n if (this.state.isInitialLoading || this.state.isLoadingOlder || this.state.isLoadingNewer\n || this.state.isReconciling) {\n this.jumpedRefreshQueued = true\n return\n }\n this.jumpedRefreshQueued = false\n return this.reconcileWindow()\n }\n if (this.state.isInitialLoading || this.state.isLoadingOlder || this.state.isReconciling) {\n this.refreshQueued = true\n return\n }\n if (!this.state.hasLoaded || !this.subscriptions.length) return this.loadInitial()\n const generation = this.generation\n const revision = this.revision\n const observed = this.state.messages.filter((message) => !isConvoKitPendingMessage(message))\n .concat([...this.changes.values()].filter((change) => change.insert).map((change) => change.message))\n const boundary = observed.reduce<Cursor | undefined>((oldest, message) =>\n !oldest || compare(message, oldest) < 0 ? message : oldest, this.cursor)\n const previouslyExhausted = !this.state.hasOlderMessages\n this.patch({ isReconciling: true, error: null })\n try {\n const conversation = await this.client.getConversation(this.room)\n if (!this.alive(generation)) return\n if (conversation.id !== this.room) throw new Error('Conversation response belongs to a different room')\n const rows: Message[] = []\n let before: Cursor | undefined\n let hasOlder = true\n while (this.alive(generation)) {\n const page = await this.fetchPage(before)\n if (!this.alive(generation)) return\n this.validatePage(page, before)\n rows.push(...page)\n before = page.at(-1) ?? before\n hasOlder = page.length === this.pageSize\n // An empty previous view has no history range to recover: keep its first\n // returning page bounded even if many messages arrived while offline.\n if (!hasOlder || !boundary || (!previouslyExhausted && before && compare(before, boundary) < 0)) break\n }\n this.cursor = before\n const reconciled = this.overlay(rows, revision)\n const survivingIds = new Set(reconciled.map((message) => message.id))\n const known = this.state.messages.filter((message) => !isConvoKitPendingMessage(message)).map((message) => message.id)\n .concat([...this.changes].filter(([, change]) => change.insert && change.revision <= revision).map(([id]) => id))\n // A missed deletion learned from the full viewed range also defeats late acks/replays.\n for (const id of known) if (!survivingIds.has(id)) this.forget(id)\n // A reconcile after a transient first-load failure is this open's first DTO; replacing one never recaptures.\n const opening = this.state.conversation === null\n this.patch({ conversation, messages: reconciled, hasOlderMessages: hasOlder })\n if (opening) this.captured = capture(conversation)\n this.mergeReads(conversation.participants.map(readEntry))\n this.prune(revision)\n void this.resolvePreviews(true)\n // Rows received while the DTO was missing waited for its version; this open's first DTO issues them.\n if (opening) void this.resumeAcknowledgement()\n } catch (cause) {\n this.fail(cause, generation, true)\n } finally {\n if (this.alive(generation)) {\n this.patch({ isReconciling: false })\n this.flushRefresh()\n }\n }\n }\n\n loadOlderMessages = async (): Promise<void> => {\n if (!this.alive() || !this.state.hasLoaded || this.state.isInitialLoading || this.state.isLoadingOlder\n || this.state.isReconciling || this.state.isLoadingNewer || !this.state.hasOlderMessages) return\n // A jumped window pages through its own cursors in both directions (0.9.0), never the tail keyset.\n if (this.state.windowMode === 'jumped') return this.loadContextPage('older')\n const generation = this.generation\n const revision = this.revision\n const cursor = this.cursor\n this.patch({ isLoadingOlder: true, error: null })\n try {\n const page = await this.fetchPage(cursor)\n if (!this.alive(generation)) return\n this.validatePage(page, cursor)\n this.cursor = page.at(-1) ?? cursor\n // Existing live edits always win over an older-page duplicate.\n this.patch({\n messages: this.overlay(mergeMessages(page, this.state.messages), revision),\n hasOlderMessages: page.length === this.pageSize,\n })\n void this.resolvePreviews()\n } catch (cause) {\n this.fail(cause, generation, true)\n } finally {\n if (this.alive(generation)) {\n this.patch({ isLoadingOlder: false })\n this.flushRefresh()\n }\n }\n }\n\n /** Page a jumped window towards the start (0.9.0); a no-op while the window is live or already at the end. */\n loadNewerMessages = async (): Promise<void> => {\n if (!this.alive() || !this.state.hasLoaded || this.state.windowMode !== 'jumped' || !this.state.hasNewerMessages\n || this.state.isInitialLoading || this.state.isLoadingOlder || this.state.isLoadingNewer\n || this.state.isReconciling) return\n return this.loadContextPage('newer')\n }\n\n /** One page of the jumped window in either direction, through the cursor the previous window returned. When\n * the newer side reaches the tail the store does NOT flip to `live` on the spot — `newerCursor: null` was only\n * true as of the server's query time and inserts have been deferred throughout the round trip, so the return\n * to the live tail is a full `returnToLatest()`.\n */\n private async loadContextPage(direction: 'older' | 'newer'): Promise<void> {\n const cursor = direction === 'older' ? this.olderContextCursor : this.newerContextCursor\n if (cursor === null || typeof this.client.getMessageContext !== 'function') return\n const generation = this.generation\n const revision = this.revision\n let reachedTail = false\n this.patch(direction === 'older' ? { isLoadingOlder: true, error: null } : { isLoadingNewer: true, error: null })\n try {\n const page = await this.client.getMessageContext(this.room, {\n ...(direction === 'older' ? { olderCursor: cursor } : { newerCursor: cursor }), limit: this.pageSize,\n })\n if (!this.alive(generation)) return\n this.validateContextPage(page.messages, this.pageSize)\n this.jumpAnchor = undefined\n if (direction === 'older') {\n this.olderContextCursor = page.olderCursor\n this.patch({\n messages: this.overlayWindow(mergeMessages(this.state.messages, page.messages), revision),\n hasOlderMessages: page.olderCursor !== null,\n })\n } else {\n this.newerContextCursor = page.newerCursor\n reachedTail = page.newerCursor === null\n this.patch({\n messages: this.overlayWindow(mergeMessages(this.state.messages, page.messages), revision),\n hasNewerMessages: page.newerCursor !== null,\n })\n }\n void this.resolvePreviews()\n } catch (cause) {\n if (!this.alive(generation)) return\n if (isRouteMissing(cause)) this.retireJump()\n this.fail(cause, generation)\n } finally {\n if (this.alive(generation)) {\n this.patch(direction === 'older' ? { isLoadingOlder: false } : { isLoadingNewer: false })\n this.flushRefresh()\n }\n }\n if (reachedTail && this.alive(generation)) await this.returnToLatest()\n }\n\n /** Re-read the JUMPED window with one bounded request, in place of the tail-anchored boundary walk (0.9.0).\n * The anchor is the jump target while the window has not been paged, otherwise the newest non-pending row at\n * or older than the window's midpoint, and the limit is the window's own size. Tombstones are bounded by the\n * returned range: a known row inside it that the response did not carry is gone, anything outside is not.\n */\n private async reconcileWindow(): Promise<void> {\n const anchor = this.windowAnchor()\n if (!anchor || typeof this.client.getMessageContext !== 'function') return\n const generation = this.generation\n const revision = this.revision\n const rendered = this.state.messages.filter((message) => !isConvoKitPendingMessage(message))\n const limit = Math.min(Math.max(rendered.length, 1), 100)\n this.patch({ isReconciling: true, error: null })\n try {\n // `getConversation` still runs exactly as in live mode (0.9.0), so its failure is the live history\n // failure — 401/403/404 blanks the room instead of leaving a stale window rendered — and it never\n // tombstones the anchor or retires the jump affordance: only the context request can say those things.\n let conversation: Conversation\n try {\n conversation = await this.client.getConversation(this.room)\n } catch (cause) {\n this.fail(cause, generation, true)\n return\n }\n if (!this.alive(generation)) return\n if (conversation.id !== this.room) {\n this.fail(new Error('Conversation response belongs to a different room'), generation, true)\n return\n }\n const page = await this.client.getMessageContext(this.room, { messageId: anchor, limit })\n if (!this.alive(generation)) return\n this.validateContextPage(page.messages, limit, anchor)\n this.olderContextCursor = page.olderCursor\n this.newerContextCursor = page.newerCursor\n const reconciled = this.overlayWindow(page.messages, revision)\n const surviving = new Set(reconciled.map((message) => message.id))\n const newestRow = page.messages[0]\n const oldestRow = page.messages.at(-1)\n if (newestRow && oldestRow) {\n for (const message of rendered) {\n if (surviving.has(message.id)) continue\n if (compare(message, oldestRow) < 0 || compare(message, newestRow) > 0) continue\n this.forget(message.id)\n }\n }\n this.patch({\n conversation, messages: reconciled,\n hasOlderMessages: page.olderCursor !== null, hasNewerMessages: page.newerCursor !== null,\n })\n this.mergeReads(conversation.participants.map(readEntry))\n this.prune(revision)\n void this.resolvePreviews(true)\n } catch (cause) {\n if (!this.alive(generation)) return\n // An anchor the server no longer knows is gone: tombstone it so the next reconcile picks another one,\n // rather than asking about the same missing row forever. The tail is still owed its reconcile.\n if (isMessageMissing(cause)) this.removeMessage(anchor)\n else if (isRouteMissing(cause)) this.retireJump()\n this.fail(cause, generation)\n } finally {\n if (this.alive(generation)) {\n this.patch({ isReconciling: false })\n this.flushRefresh()\n }\n }\n }\n\n /** The row a jumped window re-reads around: its jump target while it has not been paged, otherwise the newest\n * non-pending row at or older than the window's midpoint.\n */\n private windowAnchor(): string | undefined {\n const rendered = this.state.messages.filter((message) => !isConvoKitPendingMessage(message))\n if (rendered.length === 0) return undefined\n if (this.jumpAnchor && rendered.some((message) => message.id === this.jumpAnchor)) return this.jumpAnchor\n return rendered[Math.floor((rendered.length - 1) / 2)]?.id\n }\n\n /** A 0.8 backend does not serve the context route: the jump affordance disappears for the store's life rather\n * than failing repeatedly. A coded `MESSAGE_NOT_FOUND` never trips this — that is a real missing target.\n */\n private retireJump(): void {\n this.support.jump = false\n this.patch({ canJumpToMessage: false })\n }\n\n /** Bring a message into view (0.9.0). A row already in the loaded window is only highlighted and scrolled to;\n * otherwise the window is REPLACED by a context window centred on it and `windowMode` becomes `jumped`. A jump\n * is a window operation, never a re-open: tombstones, the acknowledgement floor, this open's captured private\n * state, edit mode and the reply target all survive it, and it arms no acknowledgement. It is a no-op while a\n * send is in flight, so a replacement can never strand a pending row. A coded `MESSAGE_NOT_FOUND` is the\n * guaranteed answer for a quoted message that was deleted: it marks the preview `'unavailable'` instead of\n * reporting an error. Resolves true once the target is highlighted.\n */\n jumpToMessage = async (messageId: string): Promise<boolean> => {\n if (!this.alive() || !this.state.hasLoaded) return false\n const id = messageId.trim()\n if (!id || this.state.isSending) return false\n const rendered = this.state.messages.find((message) => message.id === id)\n if (rendered) return isConvoKitPendingMessage(rendered) ? false : (this.beginJump(), this.landJump(id), true)\n // A parent this store already knows is gone never becomes a request.\n if (this.deleted.has(id)) {\n this.markUnavailable(id)\n return false\n }\n if (!this.support.jump || typeof this.client.getMessageContext !== 'function') return false\n if (this.state.isInitialLoading || this.state.isLoadingOlder || this.state.isLoadingNewer || this.state.isReconciling) return false\n const generation = this.generation\n this.beginJump()\n this.patch({ isLoadingNewer: true, error: null, highlightedMessageId: null })\n try {\n const page = await this.client.getMessageContext(this.room, { messageId: id, limit: this.pageSize })\n if (!this.alive(generation)) return false\n this.validateContextPage(page.messages, this.pageSize, id)\n this.olderContextCursor = page.olderCursor\n this.newerContextCursor = page.newerCursor\n this.jumpAnchor = id\n // Exactly the rows the response carried, filtered by tombstones only: neither the pending replay nor the\n // `changes` insert replay of `overlay` may re-inject live-tail rows into a historical window.\n this.patch({\n messages: mergeMessages([], page.messages.filter((message) => !this.deleted.has(message.id))),\n windowMode: 'jumped', hasOlderMessages: page.olderCursor !== null, hasNewerMessages: page.newerCursor !== null,\n })\n this.landJump(id)\n void this.resolvePreviews(true)\n return true\n } catch (cause) {\n if (!this.alive(generation)) return false\n this.releaseJump()\n if (isMessageMissing(cause)) {\n this.markUnavailable(id)\n return false\n }\n if (isRouteMissing(cause)) this.retireJump()\n this.fail(cause, generation)\n return false\n } finally {\n if (this.alive(generation)) {\n this.patch({ isLoadingNewer: false })\n // Every terminal loader path flushes: `flushRefresh()` consumes nothing while `isLoadingNewer` is set,\n // so a refresh queued during the jump would stay owed until some unrelated later trigger.\n this.flushRefresh()\n }\n }\n }\n\n /** Drop a jumped window and render the live tail again (0.9.0), through the normal newest-page load. There is\n * no in-place flip: `windowMode` becomes `live` BEFORE the request, so inserts arriving during the round trip\n * are folded in by `overlay` exactly as `loadInitial()` and `refresh()` already tolerate, and the rows\n * deferred while jumped are drained — and acknowledged — with it. A failure stays `jumped` with the window and\n * its affordance intact; the highlight is carried through so the target re-anchors when it is still in the\n * newest page. Resolves true once the live tail is rendered.\n */\n returnToLatest = async (): Promise<boolean> => {\n if (!this.alive() || !this.state.hasLoaded) return false\n if (this.state.windowMode !== 'jumped') return true\n if (this.state.isInitialLoading || this.state.isLoadingOlder || this.state.isLoadingNewer || this.state.isReconciling) return false\n const generation = this.generation\n const revision = this.revision\n const highlighted = this.state.highlightedMessageId\n clearTimeout(this.highlightTimer)\n this.highlightTimer = undefined\n this.patch({ windowMode: 'live', isLoadingNewer: true, error: null, highlightedMessageId: null })\n try {\n const page = await this.fetchPage()\n if (!this.alive(generation)) return false\n this.validatePage(page)\n this.cursor = page.at(-1)\n this.olderContextCursor = null\n this.newerContextCursor = null\n this.jumpAnchor = undefined\n this.patch({\n messages: this.overlay(page, revision),\n hasOlderMessages: page.length === this.pageSize, hasNewerMessages: false,\n })\n this.prune(revision)\n const drained = [...this.deferred].some((id) => this.state.messages.some((message) =>\n message.id === id && message.senderId !== this.user))\n this.deferred.clear()\n void this.resolvePreviews(true)\n // The deferred rows are rendered now, so the acknowledgement they did not issue while jumped is issued\n // now — as is one that was owed when the window turned jumped and the gate held its follow-up.\n if ((drained && (this.options.markReadOnReceive ?? true)) || this.ack.followUp) void this.acknowledge(true)\n if (highlighted && this.state.messages.some((message) => message.id === highlighted)) {\n this.beginJump()\n this.landJump(highlighted)\n }\n return true\n } catch (cause) {\n if (!this.alive(generation)) return false\n this.patch({\n windowMode: 'jumped', hasNewerMessages: this.newerContextCursor !== null, highlightedMessageId: highlighted,\n })\n this.fail(cause, generation, true)\n return false\n } finally {\n if (this.alive(generation)) {\n this.patch({ isLoadingNewer: false })\n this.flushRefresh()\n }\n }\n }\n\n /** The guard the views read while a jump lands: it is set BEFORE the window is replaced, because shrinking the\n * list clamps `scrollTop` and emits a scroll event of its own.\n */\n private beginJump(): void {\n clearTimeout(this.jumpTimer)\n this.jumpTimer = undefined\n clearTimeout(this.highlightTimer)\n this.highlightTimer = undefined\n if (!this.state.jumpInFlight) this.patch({ jumpInFlight: true })\n }\n\n /** The window is in place: highlight the target and release the guard on a timer, never on \"the first scroll\n * event\" — a target already in view produces none. The highlight's own timeout starts when the guard clears.\n */\n private landJump(id: string): void {\n this.patch({ highlightedMessageId: id })\n const generation = this.generation\n const timer = setTimeout(() => {\n this.jumpTimer = undefined\n if (!this.alive(generation)) return\n this.patch({ jumpInFlight: false })\n const clearing = setTimeout(() => {\n this.highlightTimer = undefined\n if (this.alive(generation) && this.state.highlightedMessageId === id) this.patch({ highlightedMessageId: null })\n }, HIGHLIGHT_MS)\n ;(clearing as { unref?: () => void }).unref?.()\n this.highlightTimer = clearing\n }, JUMP_GUARD_MS)\n ;(timer as { unref?: () => void }).unref?.()\n this.jumpTimer = timer\n }\n\n private releaseJump(): void {\n clearTimeout(this.jumpTimer)\n this.jumpTimer = undefined\n if (this.state.jumpInFlight) this.patch({ jumpInFlight: false })\n }\n\n /** Quote a rendered, confirmed message in the composer (0.9.0). A no-op for pending, tombstoned and unknown\n * rows and while the caller's role (when known) is `READ`; any member may quote any row, own or not. Replying\n * and editing are mutually exclusive, so this leaves edit mode. Sends nothing.\n */\n startReply = (messageId: string): void => {\n if (!this.alive() || this.ownRole() === 'READ') return\n const row = this.state.messages.find((message) => message.id === messageId)\n if (!row || isConvoKitPendingMessage(row) || this.deleted.has(messageId)) return\n this.patch({ replyTarget: row, editingMessage: null })\n }\n\n /** Drop the reply target without a request; the draft is untouched (replying never replaces it). */\n cancelReply = (): void => {\n if (this.state.replyTarget) this.patch({ replyTarget: null })\n }\n\n /** Acknowledge through the newest rendered row now, regardless of visibility; no acknowledgement without a\n * target (a room opened with a marker that renders nothing clears the marker instead, once).\n */\n markRead = (): Promise<void> => this.alive() ? this.acknowledge(false) : Promise.resolve()\n\n /** Automatic acknowledgements wait while hidden and are re-issued (once) on becoming visible. */\n setVisible = (visible: boolean): void => {\n this.visible = visible\n if (!visible || !this.alive()) return\n void this.resumeAcknowledgement()\n }\n\n /** Re-issue (once) the automatic acknowledgement that waited while hidden or before this open's DTO, if any. */\n private resumeAcknowledgement(): Promise<void> {\n if (!this.ack.suppressed) return Promise.resolve()\n this.ack.suppressed = false\n return this.acknowledge(true)\n }\n\n /** The newest non-pending rendered row by (createdAt, id), never by list index and never a raw realtime\n * row; rows the server does not know are skipped, and nothing at or before the accepted target is re-sent.\n */\n private ackTarget(ack: Acknowledgement): Cursor | undefined {\n let target: Cursor | undefined\n for (const message of this.state.messages) {\n if (isConvoKitPendingMessage(message) || ack.unacknowledgeable.has(message.id)) continue\n if (!target || compare(message, target) > 0) target = { createdAt: message.createdAt, id: message.id }\n }\n return target && (!ack.acknowledged || compare(target, ack.acknowledged) > 0) ? target : undefined\n }\n\n /** Resolves when the request this call issued or joined settles; a follow-up is issued, not awaited. */\n private acknowledge(automatic: boolean): Promise<void> {\n // A jumped window acknowledges nothing and arms nothing (0.9.0): its newest rendered row is not the newest\n // row in the room, and an acknowledgement carrying this open's captured version would clear the caller's\n // unread marker even when the position did not advance. The owed acknowledgements resume on the return.\n if (this.state.windowMode === 'jumped') return Promise.resolve()\n const ack = this.ack\n // Before this open's DTO is in hand there is no captured version to send: a row inserted during the load (or\n // while a transient first-load failure stands) waits for the capture, like it waits while hidden.\n if (automatic && (!this.visible || this.state.conversation === null)) {\n ack.suppressed = true\n return Promise.resolve()\n }\n if (ack.inFlight) {\n ack.followUp = true\n return ack.inFlight\n }\n return this.issue(ack, this.generation) ?? Promise.resolve()\n }\n\n private issue(ack: Acknowledgement, generation: number): Promise<void> | undefined {\n // The gate `acknowledge()` applies covers this method too, including the follow-up its own continuation\n // re-issues: a jumped window acknowledges nothing (0.9.0) — its newest rendered row is not the newest row\n // in the room and the captured version would clear the caller's marker anyway. The owed acknowledgement\n // stays armed and is issued on the return to `live`.\n if (this.state.windowMode === 'jumped') {\n ack.followUp = true\n return undefined\n }\n ack.followUp = false\n const target = this.ackTarget(ack)\n // An empty marked room clears its marker in the acknowledgement's slot; nothing else is sent without a target.\n const request = target ? this.send(ack, generation, target) : this.clearMarker(ack, generation)\n if (!request) return undefined\n ack.target = target?.id\n ack.inFlight = request.finally(() => {\n ack.inFlight = undefined\n ack.target = undefined\n if (!this.alive(generation) || !ack.followUp) return\n if (!this.visible) {\n ack.followUp = false\n ack.suppressed = true\n } else this.issue(ack, generation)\n })\n return ack.inFlight\n }\n\n /** A room opened with the caller's unread marker that renders no non-pending, acknowledgeable row cannot clear\n * it through a targeted acknowledgement, so it asks the adapter to clear the marker conditionally on the captured\n * version, once per open, under the acknowledgement triggers and visibility gating. Rows rendered later clear it\n * through their acknowledgements; adapters without the member leave it; `cleared: false` is not an error.\n */\n private clearMarker(ack: Acknowledgement, generation: number): Promise<void> | undefined {\n const captured = this.captured\n if (!captured.clearPending || captured.version === undefined || typeof this.client.clearConversationUnread !== 'function'\n || this.state.messages.some((message) => !isConvoKitPendingMessage(message) && !ack.unacknowledgeable.has(message.id))) return undefined\n captured.clearPending = false\n return this.clearUnread(captured.version, generation)\n }\n\n private async clearUnread(version: number, generation: number): Promise<void> {\n try {\n await this.client.clearConversationUnread!(this.room, { ifVersion: version })\n } catch (cause) {\n if (this.alive(generation)) this.fail(cause, generation)\n }\n }\n\n private async send(ack: Acknowledgement, generation: number, target: Cursor): Promise<void> {\n try {\n // Every targeted acknowledgement of this open carries the version captured when it opened (none on 0.6).\n const version = this.captured.version\n await this.client.markConversationRead(this.room, {\n throughMessageId: target.id, ...(version === undefined ? {} : { privateStateVersion: version }),\n })\n if (!this.alive(generation)) return\n // Only persisted participant positions / server read events advance receipts.\n if (!ack.acknowledged || compare(target, ack.acknowledged) > 0) ack.acknowledged = target\n } catch (cause) {\n if (!this.alive(generation)) return\n if (isTargetMiss(cause)) {\n // The server does not know this target (deleted meanwhile): re-issue once with the next newest row.\n ack.unacknowledgeable.add(target.id)\n ack.followUp = true\n } else this.fail(cause, generation)\n }\n }\n\n updateTyping = async (isTyping: boolean): Promise<void> => {\n if (!this.alive()) return\n const generation = this.generation\n clearTimeout(this.ownTypingTimer)\n if (isTyping) this.ownTypingTimer = setTimeout(() => {\n if (this.alive(generation)) void this.updateTyping(false)\n }, this.typingTimeout)\n const now = performance.now()\n // Renew while keystrokes continue, so the receiver's expiry does not hide\n // someone who is still typing. Idle input never generates a keepalive.\n const renew = isTyping && now - this.lastTypingSentAt >= Math.max(1, this.typingTimeout / 2)\n if (this.sentTyping === isTyping && !renew) return\n const revision = ++this.typingRevision\n this.sentTyping = isTyping\n this.lastTypingSentAt = isTyping ? now : -Infinity\n try {\n await this.client.sendTyping({ conversationId: this.room, isTyping })\n } catch (cause) {\n if (this.alive(generation) && revision === this.typingRevision) {\n this.sentTyping = false\n this.fail(cause, generation)\n }\n }\n }\n\n sendMessage = async ({ text, media }: { text?: string; media?: MessageMedia[] }): Promise<Message | null> => {\n const normalized = text?.trim()\n if (!this.alive() || this.state.isSending || (!normalized && !media?.length)) return null\n // A send always lands in the live window (0.9.0). The reply target survives the switch; if the return fails\n // nothing is sent, `isSending` never turns on, and the draft and the quote are left for another attempt.\n if (this.state.windowMode === 'jumped' && !(await this.returnToLatest())) return null\n if (!this.alive() || this.state.isSending) return null\n const generation = this.generation\n const revision = this.revision\n this.sendRevision = revision\n const clientMessageId = createClientMessageId()\n const pendingId = `convokit-pending-${clientMessageId}`\n // The quote is stamped on the optimistic row, so it renders before the server acknowledges the send.\n const replyToMessageId = this.state.replyTarget?.id\n const pending: Message = {\n id: pendingId, clientMessageId, conversationId: this.room, senderId: this.user, text: normalized || null,\n media: media ?? [], createdAt: new Date(), updatedAt: null, revision: 0,\n ...(replyToMessageId ? { replyToMessageId } : {}),\n }\n const send = { pending } as { pending: Message; confirmed?: Message }\n this.activeSend = send\n this.patch({ messages: mergeMessages(this.state.messages, [pending]), isSending: true, error: null })\n try {\n const message = await this.client.sendMessage({\n conversationId: this.room, clientMessageId, ...(normalized ? { text: normalized } : {}), ...(media?.length ? { media } : {}),\n // Omitted entirely when there is no quote, so a plain send is byte-identical to 0.8.\n ...(replyToMessageId ? { replyToMessageId } : {}),\n })\n if (!this.alive(generation)) return null\n if (!this.validMessage(message) || message.senderId !== this.user) throw new Error('Send response belongs to a different room or sender')\n if (message.clientMessageId && message.clientMessageId !== clientMessageId) throw new Error('Send response belongs to a different send')\n const live = this.changes.get(message.id)\n const existing = this.state.messages.find((item) => item.id === message.id)\n let latest = existing ? newest(message, existing, live?.complete !== false) : message\n if (live && live.revision > revision) latest = newest(latest, live.message, live.complete)\n if (!this.deleted.has(message.id)) this.changes.set(message.id, { revision: ++this.revision, message: latest, insert: true, complete: true })\n this.patch({\n messages: mergeMessages(\n this.state.messages.filter((item) => item.id !== pendingId),\n this.deleted.has(message.id) ? [] : [latest],\n ),\n // The quote is spent: it is cleared only once the server accepted the send.\n ...(replyToMessageId ? { replyTarget: null } : {}),\n })\n if (replyToMessageId) void this.resolvePreviews()\n void this.updateTyping(false)\n return this.alive(generation) ? latest : null\n } catch (cause) {\n if (this.alive(generation)) {\n this.patch({ messages: this.state.messages.filter((item) => item.id !== pendingId) })\n // A live/history confirmation is authoritative even if its HTTP acknowledgement was lost.\n // Returning success clears the composer; deleted confirmations are never reinserted.\n if (send.confirmed) {\n void this.updateTyping(false)\n return send.confirmed\n }\n this.fail(cause, generation)\n }\n return null\n } finally {\n if (this.alive(generation)) {\n this.sendRevision = undefined\n this.activeSend = undefined\n this.patch({ isSending: false })\n }\n }\n }\n\n /** The caller's role in the open room when known (0.7 `membership`, else the caller's participant row). */\n private ownRole(): string | undefined {\n const conversation = this.state.conversation\n return conversation?.membership?.role\n ?? conversation?.participants.find((participant) => participant.appUserId === this.user || participant.id === this.user)?.role\n }\n\n /** A rendered, confirmed row of the caller's own that is not known to be gone. */\n private ownRow(messageId: string): Message | undefined {\n const row = this.state.messages.find((message) => message.id === messageId)\n return row && row.senderId === this.user && !isConvoKitPendingMessage(row) && !this.deleted.has(messageId) ? row : undefined\n }\n\n /** Enter edit mode on one of the caller's own confirmed messages (0.8.0): the row as it stands now becomes the\n * snapshot whose `revision` every save sends. A no-op unless the adapter implements `editMessage`, the row is\n * rendered, own, confirmed, not tombstoned and the caller's role (when known) is not `READ`. Sends nothing.\n */\n startEditing = (messageId: string): void => {\n if (!this.alive() || !this.support.edit || this.ownRole() === 'READ') return\n const row = this.ownRow(messageId)\n // Editing and replying are mutually exclusive (0.9.0): entering edit mode drops the quote.\n if (row) this.patch({ editingMessage: row, replyTarget: null })\n }\n\n /** Leave edit mode without a request; the draft is the view's to restore. */\n cancelEditing = (): void => {\n if (this.state.editingMessage) this.patch({ editingMessage: null })\n }\n\n /** Save the edit in progress with the snapshot's revision (never the live row's), trimming the text and sending\n * `null` for an empty caption. Resolves true when the server accepted the edit (the response is merged through the\n * tombstone and precedence guards and edit mode ends); false when nothing was saved: a stale revision (409\n * `REVISION_CONFLICT`) reloads the row once through `getMessage`, replaces the snapshot with it (the next save\n * carries the fresh revision) and reports the conflict through `error`, keeping edit mode; a coded 404\n * (`MESSAGE_NOT_FOUND`, on the save or on that reload) removes the row and ends edit mode; any other failure\n * (403, 500, network, an uncoded 404 from a 0.7 backend) is reported through `error` without evicting anything and\n * keeps edit mode; if a newer row for the message arrived during such a request, that row is then the local\n * conflict (`settleEditing`). A text-only message cannot be saved empty (no request). Rejects when the adapter\n * lacks `editMessage`.\n */\n saveEdit = async (text: string): Promise<boolean> => {\n const client = this.client\n if (typeof client.editMessage !== 'function') {\n throw new TypeError('This ConvoKitUiClient adapter does not implement editMessage (0.8)')\n }\n const snapshot = this.state.editingMessage\n if (!this.alive() || !snapshot || this.activeEdit !== undefined) return false\n const trimmed = text.trim()\n const normalized = trimmed === '' ? null : trimmed\n if (normalized === null && snapshot.media.length === 0) return false\n const generation = this.generation\n const id = snapshot.id\n this.activeEdit = id\n this.patch({ error: null })\n try {\n const message = await client.editMessage(id, { text: normalized, revision: snapshot.revision })\n if (!this.alive(generation)) return false\n if (!this.validMessage(message) || message.id !== id || message.senderId !== this.user) {\n throw new Error('Edit response belongs to a different message or sender')\n }\n // Edit mode ends before the merge so the accepted row is not mistaken for a local conflict.\n if (this.state.editingMessage?.id === id) this.patch({ editingMessage: null })\n this.applyRow(message)\n return true\n } catch (cause) {\n if (!this.alive(generation)) return false\n if (isRevisionConflict(cause)) await this.reloadConflict(id, cause, generation)\n else if (isMessageMissing(cause)) {\n this.removeMessage(id)\n this.patch({ error: cause })\n } else this.fail(cause, generation)\n return false\n } finally {\n if (this.alive(generation)) {\n this.activeEdit = undefined\n this.settleEditing(id)\n }\n }\n }\n\n /** Merge a complete REST row for a known id through the live-row guards: a tombstoned id is dropped, and an older\n * revision (or timestamp) never overwrites the newer row already recorded. Recorded as a non-insert change, so a\n * reconcile keeps it only while the row is still in the fetched range.\n */\n private applyRow(message: Message): void {\n if (this.deleted.has(message.id)) return\n this.record(message, this.changes.get(message.id)?.insert === true, ++this.revision, true)\n }\n\n /** The 409 path: one `getMessage` shows the conflicting content. Its row is merged through the guards and becomes\n * the new snapshot; a `MESSAGE_NOT_FOUND` answer removes the row and ends edit mode; another failure keeps the\n * snapshot. `error` carries the conflict (or the reload failure).\n */\n private async reloadConflict(id: string, conflict: unknown, generation: number): Promise<void> {\n try {\n const current = await this.client.getMessage(id)\n if (!this.alive(generation)) return\n if (!this.validMessage(current) || current.id !== id) throw new Error('Complete message response does not match the edited message')\n this.applyRow(current)\n const row = this.state.messages.find((message) => message.id === id)\n const editing = this.state.editingMessage?.id === id && row ? { editingMessage: row } : {}\n this.patch({ ...editing, error: conflict })\n } catch (cause) {\n if (!this.alive(generation)) return\n if (isTargetMiss(cause)) this.removeMessage(id)\n this.patch({ error: cause })\n }\n }\n\n /** Delete one of the caller's own confirmed messages (0.8.0). The row stays until the server answers: on success,\n * or when the server no longer knows it (`MESSAGE_NOT_FOUND`), it is tombstoned and removed (late responses, row\n * images and hydrations for it are dropped, the acknowledgement target is re-resolved and edit mode on it ends)\n * and the call resolves true; any other failure keeps the row, reports through `error` and resolves false. Rejects\n * when the adapter lacks `deleteMessage`.\n */\n deleteMessage = async (messageId: string): Promise<boolean> => {\n const client = this.client\n if (typeof client.deleteMessage !== 'function') {\n throw new TypeError('This ConvoKitUiClient adapter does not implement deleteMessage (0.8)')\n }\n if (!this.alive() || !this.ownRow(messageId)) return false\n const generation = this.generation\n this.patch({ error: null })\n try {\n await client.deleteMessage(messageId)\n } catch (cause) {\n if (!this.alive(generation)) return false\n if (!isMessageMissing(cause)) {\n this.fail(cause, generation)\n return false\n }\n }\n if (!this.alive(generation)) return false\n this.removeMessage(messageId)\n return true\n }\n\n readerIdsFor = (message: Message): ReadonlySet<string> =>\n readerIdsFor(message, this.state.readAtByUserId, this.state.readPositionByUserId)\n}\n","import type { Conversation, Message, MessageMedia, ReadPosition } from '@convokitapp/sdk'\nimport { isEditedMessage } from '@convokitapp/sdk'\nimport {\n Check,\n CheckCheck,\n ContactRound,\n Download,\n FileText,\n ImageOff,\n LoaderCircle,\n MapPin,\n MessageCircle,\n Pencil,\n Reply,\n Trash2,\n} from '@lucide/vue'\nimport {\n computed,\n defineComponent,\n h,\n nextTick,\n ref,\n watch,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type {\n ConvoKitAppearanceProps,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n MediaSlotProps,\n MessageSlotProps,\n ReadReceiptSlotProps,\n ReplyPreviewEntry,\n} from '../types'\nimport { cx, errorMessage, formatFileSize, formatMessageTime, isConvoKitPendingMessage, partClass, partStyle, readerIdsFor } from '../utils'\n\nexport interface MessageListViewProps extends ConvoKitAppearanceProps {\n conversation: Conversation\n messages: readonly Message[]\n currentUserId: string\n /** Acknowledgement times; the fallback for users without a read position. */\n readAtByUserId?: ReadonlyMap<string, Date>\n /** Read-through positions; a user's position decides their receipts whenever one is present. */\n readPositionByUserId?: ReadonlyMap<string, ReadPosition>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onLoadOlder?: () => void | Promise<void>\n hasOlderMessages?: boolean\n isLoadingOlder?: boolean\n error?: unknown\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n /** Start editing a message (0.8.0). Without it no row offers an edit action and the markup is unchanged. */\n onEditMessage?: (message: Message) => void\n /** Delete a message after confirmation (0.8.0); `false` means the deletion was not accepted. Without it no row\n * offers a delete action.\n */\n onDeleteMessage?: (message: Message) => boolean | void | Promise<boolean | void>\n /** Replaces the default eligibility (the viewer's own confirmed rows while the viewer's role is not `READ`) for\n * both actions; pending rows are never eligible.\n */\n canEditMessage?: (message: Message) => boolean\n /** Replaces the row's inline \"Delete this message?\" prompt (and confirms `remove()` from custom rows). */\n confirmDelete?: (message: Message) => boolean | Promise<boolean>\n /** Quote a message (0.9.0). Without it no row offers a reply action and the markup is unchanged. */\n onReplyToMessage?: (message: Message) => void\n /** Replaces the default reply eligibility (any confirmed row while the viewer's role is not `READ`, 0.9.0).\n * Deliberately separate from `canEditMessage`: an edit-eligibility override must not suppress Reply on rows\n * the viewer does not own.\n */\n canReplyToMessage?: (message: Message) => boolean\n /** Quoted parents by `Message.replyToMessageId` (0.9.0). A row whose id is missing from the map renders its\n * reference with no quoted text (\"not resolved yet\"); `'unavailable'` renders the deleted-parent copy.\n */\n replyPreviewByMessageId?: ReadonlyMap<string, ReplyPreviewEntry>\n /** Bring a message into view (0.9.0). Without it quoted blocks are inert and no row is focusable. */\n onJumpToMessage?: (messageId: string) => void\n /** The row a jump landed on (0.9.0): it is scrolled to the centre, focused and highlighted until the host\n * clears the prop or the viewer scrolls.\n */\n highlightedMessageId?: string | null\n /** Set by the store while a jump lands (0.9.0): the list is `aria-busy`, stick-to-bottom, pagination and the\n * highlight clear are suspended, and the attribute is omitted entirely while it is false.\n */\n jumpInFlight?: boolean\n /** Whether newer messages exist past the top of the window (0.9.0); only ever true in a jumped window. */\n hasNewerMessages?: boolean\n isLoadingNewer?: boolean\n /** Load the page of messages immediately newer than the window (0.9.0); the newer-edge scroll trigger. */\n onLoadNewer?: () => void | Promise<void>\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n reverse?: boolean\n stickToBottom?: boolean\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nfunction defaultMedia(\n media: MessageMedia,\n open: (() => void) | undefined,\n imageLoading: 'eager' | 'lazy',\n): VNodeChild {\n const tag = open ? 'button' : 'div'\n const interactive = open ? { type: 'button', onClick: open } : {}\n if (media.type === 'image') {\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--image' }, [\n media.url\n ? h('img', { src: media.url, alt: media.name ?? 'Shared image', loading: imageLoading })\n : h('span', { class: 'ckui-media-placeholder' }, [h(ImageOff, { 'aria-hidden': 'true' }), ' Image unavailable']),\n media.name ? h('span', { class: 'ckui-media-name' }, media.name) : null,\n ])\n }\n if (media.type === 'file') {\n const size = formatFileSize(media.size)\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--file' }, [\n h(FileText, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Attachment'), size ? h('small', size) : null]),\n open ? h(Download, { size: 18, 'aria-hidden': 'true' }) : null,\n ])\n }\n if (media.type === 'location') {\n const label = media.name || `${media.metadata.lat}, ${media.metadata.lng}`\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--location' }, [\n h(MapPin, { 'aria-hidden': 'true' }),\n h('span', [h('strong', label), h('small', `${media.metadata.lat}, ${media.metadata.lng}`)]),\n ])\n }\n const contact = media.metadata.email || media.metadata.phone || 'Contact details'\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--contact' }, [\n h(ContactRound, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Shared contact'), h('small', String(contact))]),\n ])\n}\n\n/** Controlled message history with read receipts, structured media, and older-page loading. */\nexport const MessageListView = defineComponent({\n name: 'MessageListView',\n inheritAttrs: false,\n props: {\n ...appearanceProps,\n conversation: { type: Object as PropType<Conversation>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readPositionByUserId: { type: Object as PropType<ReadonlyMap<string, ReadPosition>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n hasOlderMessages: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n onEditMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n onDeleteMessage: { type: Function as PropType<(message: Message) => boolean | void | Promise<boolean | void>>, default: undefined },\n canEditMessage: { type: Function as PropType<(message: Message) => boolean>, default: undefined },\n confirmDelete: { type: Function as PropType<(message: Message) => boolean | Promise<boolean>>, default: undefined },\n onReplyToMessage: { type: Function as PropType<(message: Message) => void>, default: undefined },\n canReplyToMessage: { type: Function as PropType<(message: Message) => boolean>, default: undefined },\n replyPreviewByMessageId: { type: Object as PropType<ReadonlyMap<string, ReplyPreviewEntry>>, default: undefined },\n onJumpToMessage: { type: Function as PropType<(messageId: string) => void>, default: undefined },\n highlightedMessageId: { type: String as PropType<string | null>, default: null },\n jumpInFlight: { type: Boolean, default: false },\n hasNewerMessages: { type: Boolean, default: false },\n isLoadingNewer: { type: Boolean, default: false },\n onLoadNewer: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n reverse: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: formatMessageTime },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n },\n emits: ['load-older', 'load-newer', 'attachment-click', 'edit-message', 'delete-message', 'reply-to-message', 'jump-to-message'],\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n /** The row whose inline \"Delete this message?\" prompt is open. */\n const confirming = ref<string | null>(null)\n /** A user-initiated scroll ends the highlight without touching the host's `highlightedMessageId` (0.9.0). */\n const highlightCleared = ref(false)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n let newerInFlight = false\n let lastNewerLength: number | null = null\n let previousMessageCount = 0\n /** The highlight the list has already scrolled to; a jump to another row (or the same row after the host\n * cleared the prop) scrolls again, a re-render of the same one does not.\n */\n let scrolledTo: string | null = null\n let jumpArmed = false\n const participants = computed(() => new Map(props.conversation.participants.flatMap((participant) => [\n [participant.id, participant] as const,\n [participant.appUserId, participant] as const,\n ])))\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestOlder = async () => {\n if (requestInFlight || lastRequestedLength === props.messages.length || props.isLoadingOlder || !props.hasOlderMessages || !props.onLoadOlder) return\n requestInFlight = true\n lastRequestedLength = props.messages.length\n try { await props.onLoadOlder() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n const requestNewer = async () => {\n if (newerInFlight || lastNewerLength === props.messages.length || props.isLoadingNewer || !props.hasNewerMessages || !props.onLoadNewer) return\n newerInFlight = true\n lastNewerLength = props.messages.length\n try { await props.onLoadNewer() }\n catch { lastNewerLength = null }\n finally { newerInFlight = false }\n }\n\n watch(() => [props.messages.length, props.hasOlderMessages, props.hasNewerMessages] as const, async ([count, hasOlder, hasNewer]) => {\n const previous = previousMessageCount\n if (count !== previousMessageCount || !hasOlder) lastRequestedLength = null\n if (count !== previousMessageCount || !hasNewer) lastNewerLength = null\n const appended = count > previous\n const element = internalElement.value\n previousMessageCount = count\n // A jump replaces the window, which grows `messages` and would otherwise yank the view back to the\n // newest row; the guard holds until the jump's own scroll has run (0.9.0).\n if (element && props.reverse && props.stickToBottom && appended && !props.jumpInFlight) {\n const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight\n if (previous === 0 || distanceFromBottom < 320) {\n await nextTick()\n element.scrollTop = element.scrollHeight\n }\n }\n }, { flush: 'post', immediate: true })\n\n /** The row the jump landed on, once it is in the DOM. `behavior: 'instant'` is explicit so a host's\n * `scroll-behavior: smooth` cannot animate past the jump guard, and the focus move (never made for\n * autoscroll, page loads or live inserts) is what announces the target to assistive technology.\n */\n watch(() => [props.highlightedMessageId, props.messages, props.jumpInFlight] as const, ([highlighted, , inFlight]) => {\n // The store re-arms its guard for every jump, including a second jump to the row that is already the\n // target: that edge, not a change of id, is what re-centres and re-tints a row the viewer scrolled away\n // from in the meantime (0.9.0).\n if (inFlight && !jumpArmed) scrolledTo = null\n jumpArmed = !!inFlight\n if (!highlighted) {\n scrolledTo = null\n highlightCleared.value = false\n return\n }\n if (scrolledTo === highlighted) return\n const root = internalElement.value\n const row = root\n ? [...root.querySelectorAll<HTMLElement>('[data-message-id]')].find((node) => node.dataset.messageId === highlighted)\n : undefined\n if (!row) return\n scrolledTo = highlighted\n highlightCleared.value = false\n row.scrollIntoView({ block: 'center', behavior: 'instant' })\n if (props.onJumpToMessage) row.focus({ preventScroll: true })\n }, { flush: 'post' })\n\n /** The viewer's role when the room knows it: the 0.7 `membership` sibling, else the viewer's participant row. */\n const viewerRole = computed(() => props.conversation.membership?.role\n ?? props.conversation.participants.find((participant) => participant.appUserId === props.currentUserId || participant.id === props.currentUserId)?.role)\n /** Delete after confirmation: `confirmDelete` when the view has one, otherwise at once (custom rows own their\n * prompt; the default row opens its inline prompt instead of calling this without one).\n */\n const remove = async (message: Message): Promise<boolean> => {\n if (props.confirmDelete && !(await props.confirmDelete(message))) return false\n return (await props.onDeleteMessage?.(message)) !== false\n }\n\n /** The quoted parent above a reply's text (0.9.0), in its three states: resolved, gone, and not resolved yet\n * — which shows the reference alone and never the unavailable copy. Activatable while the view can jump.\n */\n const renderQuote = (parentId: string, preview: ReplyPreviewEntry | undefined, jump: (() => void) | undefined): VNodeChild => {\n const resolved = preview === undefined || preview === 'unavailable' ? undefined : preview\n const author = resolved ? participants.value.get(resolved.senderId)?.name || resolved.senderId : undefined\n const attachments = resolved && resolved.mediaCount > 0\n ? resolved.mediaCount === 1 ? '1 attachment' : `${resolved.mediaCount} attachments`\n : ''\n const body = resolved\n ? resolved.text?.trim() || attachments\n : preview === 'unavailable' ? 'Original message unavailable' : ''\n return h(jump ? 'button' : 'div', {\n class: cx('ckui-message-quote', preview === 'unavailable' && 'ckui-message-quote--unavailable'),\n 'data-reply-to': parentId,\n 'aria-label': resolved ? `Quoted message from ${author}`\n : preview === 'unavailable' ? 'Original message unavailable' : 'Quoted message',\n ...(jump ? { type: 'button', onClick: jump } : {}),\n }, [\n ...(author ? [h('strong', { class: 'ckui-message-quote__author' }, author)] : []),\n ...(body ? [h('span', { class: 'ckui-message-quote__body' }, body)] : []),\n ])\n }\n\n const renderMessage = (message: Message, index: number): VNodeChild => {\n const isCurrentUser = message.senderId === props.currentUserId\n const sender = participants.value.get(message.senderId)\n const isPending = isConvoKitPendingMessage(message)\n const readerIds = isPending\n ? new Set<string>()\n : props.readersResolver ? props.readersResolver(message) : readerIdsFor(message, props.readAtByUserId, props.readPositionByUserId)\n const isEdited = !isPending && isEditedMessage(message)\n const eligible = !isPending && (props.canEditMessage ? props.canEditMessage(message) : isCurrentUser && viewerRole.value !== 'READ')\n const canEdit = eligible && !!props.onEditMessage\n const canDelete = eligible && !!props.onDeleteMessage\n // Any member may quote any row (0.9.0), so the own-row term of `eligible` is deliberately dropped and the\n // edit override is not consulted; `canReplyToMessage` is the separate reply override.\n const replyEligible = !isPending && (props.canReplyToMessage ? props.canReplyToMessage(message) : viewerRole.value !== 'READ')\n const canReply = replyEligible && !!props.onReplyToMessage\n const edit = () => { props.onEditMessage?.(message) }\n const replyTo = () => { props.onReplyToMessage?.(message) }\n const parentId = message.replyToMessageId\n const replyPreview = parentId ? props.replyPreviewByMessageId?.get(parentId) : undefined\n const jumpToReplyTarget = parentId && props.onJumpToMessage ? () => { props.onJumpToMessage?.(parentId) } : undefined\n const slotProps: MessageSlotProps = {\n message, chronologicalIndex: index, isCurrentUser, sender, readerIds, isEdited, canEdit, canDelete, canReply,\n ...(canEdit ? { edit } : {}),\n ...(canDelete ? { remove: () => remove(message) } : {}),\n ...(canReply ? { reply: replyTo } : {}),\n ...(parentId && replyPreview !== undefined ? { replyPreview } : {}),\n ...(jumpToReplyTarget ? { jumpToReplyTarget } : {}),\n }\n const anchor = {\n 'data-message-id': message.id,\n ...(props.onJumpToMessage ? { tabindex: '-1' } : {}),\n }\n const highlighted = !highlightCleared.value && props.highlightedMessageId === message.id\n const custom = slots.message?.(slotProps)\n // The custom-slot wrapper is the only stable anchor a replaced row has; the default row carries the same\n // attribute on its `article`, which keeps the 0.7 markup of the wrapper byte-identical.\n if (custom) {\n return h('div', {\n key: message.id, role: 'listitem', ...anchor,\n ...(highlighted ? { class: 'ckui-message-highlight' } : {}),\n }, custom)\n }\n const currentAppearance = appearance()\n const messagePart = isCurrentUser ? 'outgoingMessage' : 'incomingMessage'\n const iconButton = (label: string, onClick: () => void, icon: VNodeChild) => h('button', {\n type: 'button', 'aria-label': label, onClick,\n class: partClass('button', currentAppearance, 'ckui-icon-button'),\n style: partStyle('button', currentAppearance),\n }, [icon])\n const actions = canReply || canEdit || canDelete ? h('div', { class: 'ckui-message-actions' }, [\n ...(canReply ? [iconButton('Reply to message', replyTo, h(Reply, { size: 16, 'aria-hidden': 'true' }))] : []),\n ...(canEdit ? [iconButton('Edit message', edit, h(Pencil, { size: 16, 'aria-hidden': 'true' }))] : []),\n ...(canDelete ? [iconButton('Delete message', () => {\n if (props.confirmDelete) void remove(message)\n else confirming.value = message.id\n }, h(Trash2, { size: 16, 'aria-hidden': 'true' }))] : []),\n ]) : null\n const confirm = canDelete && confirming.value === message.id ? h('div', {\n class: 'ckui-message-confirm', role: 'group', 'aria-label': 'Delete this message?',\n }, [\n h('span', 'Delete this message?'),\n h('button', {\n type: 'button', class: 'ckui-link-button', 'aria-label': 'Confirm delete',\n onClick: () => { confirming.value = null; void props.onDeleteMessage?.(message) },\n }, 'Delete'),\n h('button', {\n type: 'button', class: 'ckui-link-button', 'aria-label': 'Cancel delete',\n onClick: () => { confirming.value = null },\n }, 'Cancel'),\n ]) : null\n const mediaNodes = message.media.map((media, mediaIndex) => {\n const open = props.onAttachmentClick\n ? () => {\n props.onAttachmentClick?.(media, message)\n }\n : undefined\n const mediaSlotProps: MediaSlotProps = { media, message, isCurrentUser, ...(open ? { open } : {}) }\n return h('div', {\n key: media.id ?? `${media.type}-${mediaIndex}`,\n class: partClass('media', currentAppearance, 'ckui-media'),\n style: partStyle('media', currentAppearance),\n }, slots.media?.(mediaSlotProps) ?? [defaultMedia(media, open, props.imageLoading)])\n })\n const receiptSlotProps: ReadReceiptSlotProps = { message, readerIds }\n const quote = parentId ? renderQuote(parentId, replyPreview, jumpToReplyTarget) : null\n return h('div', { key: message.id, role: 'listitem' }, [\n h('article', {\n class: cx(\n !props.unstyled && 'ckui-message-row',\n isCurrentUser && !props.unstyled && 'ckui-message-row--outgoing',\n highlighted && 'ckui-message-highlight',\n props.classNames?.message,\n props.classNames?.[messagePart],\n ),\n style: [props.styles?.message, props.styles?.[messagePart]],\n ...anchor,\n }, [\n // Spread, not null: an absent action/label/prompt must not leave a comment node (0.7 markup stays byte-identical).\n ...(actions ? [actions] : []),\n h('div', { class: 'ckui-message-bubble' }, [\n !isCurrentUser ? h('strong', { class: 'ckui-message-sender' }, sender?.name || message.senderId) : null,\n ...(quote ? [quote] : []),\n message.text ? h('div', { class: 'ckui-message-text' }, message.text) : null,\n ...mediaNodes,\n h('span', { class: 'ckui-message-time' }, [\n isPending ? 'Sending…' : props.formatTime(message.createdAt),\n ...(isEdited ? [h('span', { class: 'ckui-message-edited', 'aria-label': 'Edited' }, 'Edited')] : []),\n isCurrentUser && !isPending\n ? readerIds.size > 0\n ? h(CheckCheck, { size: 14, 'aria-label': 'Read' })\n : h(Check, { size: 14, 'aria-label': 'Sent' })\n : null,\n ]),\n ]),\n ...(confirm ? [confirm] : []),\n isCurrentUser && !isPending\n ? slots['read-receipt']?.(receiptSlotProps) ?? h('div', {\n class: partClass('receipt', currentAppearance, 'ckui-read-receipt'),\n style: partStyle('receipt', currentAppearance),\n }, readerIds.size > 0 ? `Read by ${readerIds.size}` : 'Sent')\n : null,\n ]),\n ])\n }\n\n return () => {\n const currentAppearance = appearance()\n const children: VNodeChild[] = []\n if (props.isLoadingOlder) {\n children.push(slots['loading-older']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading older messages…']))\n }\n if (props.error) {\n const retry = props.onLoadOlder ? () => { void requestOlder() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null,\n ]))\n }\n if (props.messages.length === 0 && !props.isLoadingOlder) {\n children.push(slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(MessageCircle, { 'aria-hidden': 'true' }), ' No messages yet']))\n } else {\n children.push(...props.messages.map(renderMessage))\n }\n // The newer end of a jumped window; absent (and byte-identical to 0.8) while the window is live.\n if (props.isLoadingNewer) {\n children.push(slots['loading-newer']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading newer messages…']))\n }\n return h('div', {\n ...attrs,\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui ckui-message-list', props.classNames?.messages, attrs.class),\n style: [props.styles?.messages, attrs.style],\n 'data-density': props.density,\n role: 'log',\n 'aria-live': 'polite',\n 'aria-label': `Messages in ${props.conversation.displayTitle}`,\n // Omitted entirely while idle, never `aria-busy=\"false\"`: the 0.7 markup of this element is pinned.\n ...(props.jumpInFlight ? { 'aria-busy': 'true' } : {}),\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n // A jump's own scroll (and the one shrinking the window emits) is not the viewer's: while the guard is\n // set it neither clears the highlight nor pages (0.9.0).\n if (props.jumpInFlight) return\n if (props.highlightedMessageId && !highlightCleared.value) highlightCleared.value = true\n const element = event.currentTarget as HTMLElement\n const distanceFromOldest = props.reverse\n ? element.scrollTop\n : element.scrollHeight - element.scrollTop - element.clientHeight\n if (distanceFromOldest <= props.paginationThreshold) void requestOlder()\n const distanceFromNewest = props.reverse\n ? element.scrollHeight - element.scrollTop - element.clientHeight\n : element.scrollTop\n if (distanceFromNewest <= props.paginationThreshold) void requestNewer()\n },\n }, children)\n }\n },\n})\n\nexport function defaultReadersResolver(\n readAtByUserId: ReadonlyMap<string, Date>,\n readPositionByUserId: ReadonlyMap<string, ReadPosition> = new Map(),\n): (message: Message) => ReadonlySet<string> {\n return (message) => readerIdsFor(message, readAtByUserId, readPositionByUserId)\n}\n","import type { Conversation, InboxSummary } from '@convokitapp/sdk'\nimport { ChevronRight, Inbox, LoaderCircle, RefreshCw } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n ref,\n watchEffect,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationListController, UseConversationListOptions } from '../composables/use-conversation-list'\nimport { useConversationList } from '../composables/use-conversation-list'\nimport type {\n ConversationFilter,\n ConversationItemSlotProps,\n ConversationPageLoader,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n} from '../types'\nimport { cx, errorMessage, formatMessageTime, inboxPreview, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\n\nexport interface ConversationListViewProps extends ConvoKitAppearanceProps {\n conversations: readonly Conversation[]\n /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge: the count, or\n * a numberless dot when `isUnread` is set without one (0.7.0).\n */\n summaries?: ReadonlyMap<string, InboxSummary>\n /** The viewer; a preview from them reads `You: …`. Absent → no prefix. */\n currentUserId?: string\n selectedConversationId?: string\n onConversationSelect?: (conversation: Conversation) => void\n onRefresh?: () => void | Promise<void>\n onLoadMore?: () => void | Promise<void>\n isInitialLoading?: boolean\n isLoadingMore?: boolean\n hasMore?: boolean\n error?: unknown\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n ariaLabel?: string\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst listViewProps = {\n ...appearanceProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, required: true },\n summaries: { type: Object as PropType<ReadonlyMap<string, InboxSummary>>, default: undefined },\n currentUserId: { type: String, default: undefined },\n selectedConversationId: { type: String, default: undefined },\n onConversationSelect: { type: Function as PropType<(conversation: Conversation) => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadMore: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingMore: { type: Boolean, default: false },\n hasMore: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n ariaLabel: { type: String, default: 'Conversations' },\n} as const\n\n/** Controlled conversation list. It can be used with any state-management layer. */\nexport const ConversationListView = defineComponent({\n name: 'ConversationListView',\n inheritAttrs: false,\n props: listViewProps,\n emits: {\n 'conversation-select': (_conversation: Conversation) => true,\n refresh: () => true,\n 'load-more': () => true,\n },\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestMore = async () => {\n if (requestInFlight || lastRequestedLength === props.conversations.length || props.isInitialLoading || props.isLoadingMore || !props.hasMore || !props.onLoadMore) return\n requestInFlight = true\n lastRequestedLength = props.conversations.length\n try { await props.onLoadMore() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n const selectConversation = (conversation: Conversation) => {\n props.onConversationSelect?.(conversation)\n }\n\n const refresh = () => {\n return props.onRefresh?.()\n }\n\n /** Inline errors retry the next page when one is pending (past the duplicate guard), otherwise refresh. */\n const inlineRetry = (): (() => void) | undefined => {\n if (props.hasMore && props.onLoadMore) return () => { lastRequestedLength = null; void requestMore() }\n if (props.onRefresh) return () => { void refresh() }\n return undefined\n }\n\n /** A count (or a capped count) keeps the numeric badge; a marker without one is a numberless dot named\n * `Unread` (never `0 unread`). Returned as a spread so an absent badge adds no child.\n */\n const unreadBadge = (summary: InboxSummary): VNodeChild[] => {\n if (summary.unreadCount > 0 || summary.unreadCountCapped) {\n const capped = summary.unreadCountCapped || summary.unreadCount > 99\n return [h('span', {\n class: 'ckui-unread-badge',\n role: 'img',\n 'aria-label': `${summary.unreadCountCapped ? '99+' : summary.unreadCount} unread`,\n }, [h('span', { 'aria-hidden': 'true' }, capped ? '99+' : String(summary.unreadCount))])]\n }\n if (summary.isUnread) return [h('span', { class: 'ckui-unread-badge ckui-unread-badge--dot', role: 'img', 'aria-label': 'Unread' })]\n return []\n }\n\n const renderContent = () => {\n const currentAppearance = appearance()\n if (props.isInitialLoading && props.conversations.length === 0) {\n return slots['initial-loading']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversations…'])\n }\n if (props.error && props.conversations.length === 0) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n return slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again') : null,\n ])\n }\n if (props.conversations.length === 0) {\n return slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(Inbox, { 'aria-hidden': 'true' }), ' No conversations yet'])\n }\n const children: VNodeChild[] = props.conversations.flatMap((conversation, index) => {\n const selected = props.selectedConversationId === conversation.id\n const select = () => selectConversation(conversation)\n const summary = props.summaries?.get(conversation.id)\n const slotProps: ConversationItemSlotProps = {\n conversation, index, selected, select,\n ...(summary ? { summary } : {}),\n ...(props.currentUserId === undefined ? {} : { currentUserId: props.currentUserId }),\n }\n const preview = inboxPreview(conversation, summary, props.currentUserId)\n // Consumer-built summaries that omit `isUnread` keep their count-driven badges.\n const unread = summary !== undefined && (summary.isUnread || summary.unreadCount > 0 || summary.unreadCountCapped)\n const item = slots['conversation-item']?.(slotProps) ?? h('button', {\n type: 'button',\n 'data-selected': selected || undefined,\n 'data-unread': unread || undefined,\n 'aria-current': selected ? 'true' : undefined,\n onClick: select,\n class: partClass('listItem', currentAppearance, 'ckui-conversation-item'),\n style: partStyle('listItem', currentAppearance),\n }, [\n h(ConvoKitAvatar, {\n name: conversation.displayTitle,\n src: conversation.imageUrl,\n class: partClass('avatar', currentAppearance, ''),\n style: partStyle('avatar', currentAppearance),\n } as never),\n h('span', { class: 'ckui-conversation-item__body' }, [\n h('strong', conversation.displayTitle),\n h('span', preview || conversation.participants.map((participant) => participant.name).join(', ') || conversation.description || 'No participants'),\n ]),\n // Spread rather than emit `null`: a null child renders a `<!---->` comment, and rows without a\n // summary must keep 0.5's exact markup.\n ...(summary ? [h('span', { class: 'ckui-conversation-item__meta' }, [\n h('time', { class: 'ckui-conversation-item__time', datetime: summary.activityAt.toISOString() }, formatMessageTime(summary.activityAt)),\n ...unreadBadge(summary),\n ])] : []),\n h(ChevronRight, { size: 18, 'aria-hidden': 'true' }),\n ])\n const nodes = [h('div', { key: conversation.id, role: 'listitem' }, [item])]\n if (index < props.conversations.length - 1) {\n nodes.push(h('div', { key: `${conversation.id}-separator` }, slots.separator?.({ index }) ?? h('div', { class: 'ckui-separator' })))\n }\n return nodes\n })\n if (props.error) {\n const retry = inlineRetry()\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n ...(retry ? [h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry')] : []),\n ]))\n } else if (props.isLoadingMore) {\n children.push(slots['load-more']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading more…']))\n }\n return h('div', {\n role: 'list',\n class: partClass('list', currentAppearance, 'ckui-conversation-list__items'),\n style: partStyle('list', currentAppearance),\n }, children)\n }\n\n return () => h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation-list', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, [\n props.onRefresh ? h('div', { class: 'ckui-conversation-list__toolbar' }, [\n h('span', props.ariaLabel),\n h('button', {\n type: 'button',\n 'aria-label': 'Refresh conversations',\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n onClick: () => { void refresh() },\n }, [h(RefreshCw, { size: 17, 'aria-hidden': 'true' })]),\n ]) : null,\n h('div', {\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui-scroll-area', props.classNames?.list),\n style: props.styles?.list,\n 'aria-label': props.ariaLabel,\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n const element = event.currentTarget as HTMLElement\n if (element.scrollHeight - element.scrollTop - element.clientHeight <= props.paginationThreshold) void requestMore()\n },\n }, [renderContent()]),\n ])\n },\n})\n\nexport interface ConversationListProps extends Omit<ConversationListViewProps,\n 'conversations' | 'onRefresh' | 'onLoadMore' | 'isInitialLoading' | 'isLoadingMore' | 'hasMore' | 'error'>,\n Omit<UseConversationListOptions, 'client'> {\n client: ConvoKitUiClient\n onControllerChange?: (controller: ConversationListController) => void\n}\n\n/** Plug-and-play SDK-backed conversation list. */\nexport const ConversationList = defineComponent({\n name: 'ConversationList',\n inheritAttrs: false,\n props: {\n ...listViewProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, default: () => [] },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n pageLoader: { type: Function as PropType<ConversationPageLoader>, default: undefined },\n initialFilter: { type: Object as PropType<ConversationFilter>, default: undefined },\n pageSize: { type: Number, default: 30 },\n autoLoad: { type: Boolean, default: true },\n activityRefreshWindowMs: { type: Number, default: undefined },\n onControllerChange: { type: Function as PropType<(controller: ConversationListController) => void>, default: undefined },\n },\n emits: ['conversation-select', 'controller-change'],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversationList({\n client: () => props.client,\n ...(props.pageLoader ? { pageLoader: props.pageLoader } : {}),\n ...(props.initialFilter ? { initialFilter: props.initialFilter } : {}),\n pageSize: props.pageSize,\n autoLoad: props.autoLoad,\n ...(props.activityRefreshWindowMs === undefined ? {} : { activityRefreshWindowMs: props.activityRefreshWindowMs }),\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n return () => {\n const {\n client: _client,\n pageLoader: _pageLoader,\n initialFilter: _initialFilter,\n pageSize: _pageSize,\n autoLoad: _autoLoad,\n activityRefreshWindowMs: _activityRefreshWindowMs,\n onControllerChange: _onControllerChange,\n conversations: _conversations,\n summaries: _summaries,\n currentUserId: _currentUserId,\n onRefresh: _onRefresh,\n onLoadMore: _onLoadMore,\n isInitialLoading: _isInitialLoading,\n isLoadingMore: _isLoadingMore,\n hasMore: _hasMore,\n error: _error,\n ...forwarded\n } = props\n return h(ConversationListView, {\n ...attrs,\n ...forwarded,\n conversations: controller.conversations.value,\n summaries: controller.summaries.value,\n currentUserId: controller.currentUserId.value,\n onRefresh: controller.refresh,\n onLoadMore: controller.loadMore,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingMore: controller.isLoadingMore.value,\n hasMore: controller.hasMore.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n onConversationSelect: (conversation: Conversation) => {\n emit('conversation-select', conversation)\n },\n } as never, slots)\n }\n },\n})\n","import type { ClearConversationUnreadOptions } from '@convokitapp/sdk'\nimport { computed, getCurrentScope, onScopeDispose, shallowRef, toValue, watch, type MaybeRefOrGetter } from 'vue'\nimport type { ConversationFilter, ConversationListState, ConversationPageLoader, ConvoKitUiClient } from '../types'\nimport { ConversationListStore, type ConversationListSnapshot } from '../conversation-list-store'\n\nexport interface UseConversationListOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n pageLoader?: ConversationPageLoader\n initialFilter?: ConversationFilter\n pageSize?: number\n autoLoad?: boolean\n /** Max-wait window (ms) that coalesces `inbox_activity` signals into one refresh; default 500, 0 = immediate. */\n activityRefreshWindowMs?: number\n}\nexport interface ConversationListController extends ConversationListState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadMore(): Promise<void>\n setFilter(filter: ConversationFilter): Promise<void>\n setQuery(query: string): Promise<void>\n /** Mark a room unread for the viewer only (0.7.0); its summary shows the marker at once. Rejects when the adapter\n * lacks `markConversationUnread`.\n */\n markUnread(conversationId: string): Promise<void>\n /** Remove the viewer's marker, only while it still has `options.ifVersion` when given; resolves to whether this\n * request removed it. Rejects when the adapter lacks `clearConversationUnread`.\n */\n clearUnread(conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean>\n dispose(): Promise<void>\n}\n\nexport function useConversationList(options: UseConversationListOptions): ConversationListController {\n const createStore = () => new ConversationListStore({ ...options, client: toValue(options.client) })\n let store = createStore()\n const snapshot = shallowRef(store.getSnapshot())\n let unsubscribe: (() => void) | undefined\n const stop = watch(\n () => [toValue(options.client), toValue(options.client).sessionIdentity] as const,\n () => {\n store.dispose()\n unsubscribe?.()\n store = createStore()\n snapshot.value = store.getSnapshot()\n unsubscribe = store.subscribe(() => { snapshot.value = store.getSnapshot() })\n store.start(options.autoLoad ?? true)\n },\n { immediate: true, flush: 'sync' },\n )\n const field = <K extends keyof ConversationListSnapshot>(key: K) => computed(() => snapshot.value[key])\n const dispose = async () => {\n stop()\n store.dispose()\n unsubscribe?.()\n unsubscribe = undefined\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n return {\n conversations: field('conversations'), summaries: field('summaries'), currentUserId: field('currentUserId'),\n filter: field('filter'),\n isInitialLoading: field('isInitialLoading'), isLoadingMore: field('isLoadingMore'),\n hasMore: field('hasMore'), hasLoaded: field('hasLoaded'), error: field('error'),\n loadInitial: () => store.loadInitial(), refresh: () => store.refresh(),\n loadMore: () => store.loadMore(), setFilter: (filter) => store.setFilter(filter),\n setQuery: (query) => store.setQuery(query),\n markUnread: (conversationId) => store.markUnread(conversationId),\n clearUnread: (conversationId, options) => store.clearUnread(conversationId, options),\n dispose,\n }\n}\n","import type {\n ClearConversationUnreadOptions, Conversation, ConversationPrivateState, InboxEntry, InboxPage, InboxSummary, RealtimeSubscription,\n} from '@convokitapp/sdk'\nimport type { ConversationFilter, ConversationPageLoader, ConvoKitUiClient } from './types'\nimport { applyConversationFilter, mergeConversations, mergeInboxEntries } from './utils'\n\nexport interface ConversationListSnapshot {\n conversations: Conversation[]\n summaries: ReadonlyMap<string, InboxSummary>\n currentUserId: string\n filter: ConversationFilter\n isInitialLoading: boolean\n isLoadingMore: boolean\n hasMore: boolean\n hasLoaded: boolean\n error: unknown\n}\ninterface Options {\n client: ConvoKitUiClient\n pageLoader?: ConversationPageLoader\n initialFilter?: ConversationFilter\n pageSize?: number\n /** Max-wait window for coalescing `inbox_activity` signals into one refresh; 0 refreshes immediately. */\n activityRefreshWindowMs?: number\n}\nconst defaultActivityRefreshWindowMs = 500\nfunction blank(filter: ConversationFilter): ConversationListSnapshot {\n return {\n conversations: [], summaries: new Map(), currentUserId: '', filter,\n isInitialLoading: false, isLoadingMore: false, hasMore: true, hasLoaded: false, error: null,\n }\n}\nfunction statusOf(cause: unknown): unknown {\n return typeof cause === 'object' && cause !== null && 'status' in cause ? cause.status : undefined\n}\nfunction summaryOf(entry: InboxEntry): InboxSummary {\n const { conversation: _conversation, ...summary } = entry\n return summary\n}\nfunction ids(entries: readonly InboxEntry[]): Conversation[] { return entries.map((entry) => entry.conversation) }\n\n/** Session-owned inbox paging. A page loader must belong to the same authenticated app.\n *\n * Inbox mode (an adapter with `listInbox`, no custom page loader, endpoint available) pages by opaque cursor in\n * activity order and carries per-room summaries; every other configuration is the legacy offset path over\n * `getConversations`, unchanged from 0.5 and without summaries.\n */\nexport class ConversationListStore {\n private readonly owner: object | null\n private readonly user: string\n private readonly pageSize: number\n private readonly activityRefreshWindowMs: number\n private state: ConversationListSnapshot\n private source: Conversation[] = []\n private entries: InboxEntry[] = []\n private offset = 0\n private cursor: string | null = null\n private inboxUnavailable = false\n private inboxWarned = false\n private generation = 0\n private lifecycleGeneration = 0\n private disposed = true\n private lifecycle: RealtimeSubscription | undefined\n private inbox: RealtimeSubscription | undefined\n private activity: RealtimeSubscription | undefined\n private activityTimer: ReturnType<typeof setTimeout> | undefined\n private refreshQueued = false\n private refreshing = false\n private listeners = new Set<() => void>()\n\n constructor(private readonly options: Options) {\n this.owner = options.client.sessionIdentity\n this.user = this.owner ? options.client.currentUserId : ''\n this.pageSize = options.pageSize ?? 30\n if (!Number.isInteger(this.pageSize) || this.pageSize < 1 || this.pageSize > 100) {\n throw new RangeError('pageSize must be an integer between 1 and 100')\n }\n this.activityRefreshWindowMs = options.activityRefreshWindowMs ?? defaultActivityRefreshWindowMs\n if (!Number.isFinite(this.activityRefreshWindowMs) || this.activityRefreshWindowMs < 0) {\n throw new RangeError('activityRefreshWindowMs must be a non-negative number')\n }\n this.state = blank(options.initialFilter ?? {})\n }\n getSnapshot = (): ConversationListSnapshot => this.state\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n private patch(patch: Partial<ConversationListSnapshot>): void {\n this.state = { ...this.state, ...patch }\n for (const listener of this.listeners) listener()\n }\n private alive(generation = this.generation): boolean {\n return !this.disposed && generation === this.generation && this.owner !== null\n && this.options.client.sessionIdentity === this.owner\n }\n private get inboxMode(): boolean {\n return !this.options.pageLoader && typeof this.options.client.listInbox === 'function' && !this.inboxUnavailable\n }\n private currentUserId(): string { return this.inboxMode ? this.user : '' }\n start = (autoLoad = true): void => {\n if (!this.owner || this.options.client.sessionIdentity !== this.owner) return\n if (!this.disposed) return\n this.disposed = false\n this.inboxUnavailable = false\n const lifecycleGeneration = ++this.lifecycleGeneration\n const current = () => this.alive() && lifecycleGeneration === this.lifecycleGeneration\n const reconcile = (cause: Error) => {\n if (current()) {\n this.patch({ error: cause })\n // Reconcile authoritative REST after terminal topic denial as well.\n this.queueRefresh()\n }\n }\n try {\n this.patch({ currentUserId: this.currentUserId() })\n const subscription = this.options.client.onConnectionEvent({\n onEvent: () => {},\n onSessionEnded: () => {\n if (!this.disposed && lifecycleGeneration === this.lifecycleGeneration) this.dispose()\n },\n })\n if (this.alive()) this.lifecycle = subscription\n else void subscription.unsubscribe().catch(() => undefined)\n if (!this.alive()) return\n const inbox = this.options.client.onInboxChanged(() => {\n if (!current()) return\n // Structural changes are immediate and supersede a pending activity window.\n this.clearActivityTimer()\n this.queueRefresh()\n }, reconcile)\n if (this.alive()) this.inbox = inbox\n else void inbox.unsubscribe().catch(() => undefined)\n if (!this.alive()) return\n if (this.inboxMode && typeof this.options.client.onInboxActivity === 'function') {\n const activity = this.options.client.onInboxActivity(() => {\n if (current()) this.scheduleActivityRefresh(lifecycleGeneration)\n }, reconcile)\n if (this.alive()) this.activity = activity\n else void activity.unsubscribe().catch(() => undefined)\n }\n if (autoLoad) void this.loadInitial()\n } catch (cause) { if (this.alive()) this.patch({ error: cause }) }\n }\n dispose = (): void => {\n this.disposed = true\n this.generation++\n this.lifecycleGeneration++\n this.clearActivityTimer()\n const subscription = this.lifecycle\n this.lifecycle = undefined\n if (subscription) void subscription.unsubscribe().catch(() => undefined)\n if (this.inbox) void this.inbox.unsubscribe().catch(() => undefined)\n this.inbox = undefined\n this.stopActivity()\n this.refreshQueued = false\n this.refreshing = false\n this.source = []\n this.entries = []\n this.offset = 0\n this.cursor = null\n this.patch(blank(this.state.filter))\n }\n private stopActivity(): void {\n if (this.activity) void this.activity.unsubscribe().catch(() => undefined)\n this.activity = undefined\n }\n private clearActivityTimer(): void {\n if (this.activityTimer !== undefined) clearTimeout(this.activityTimer)\n this.activityTimer = undefined\n }\n /** Max-wait throttle: the first signal opens a window; later signals wait for it; one refresh runs when it closes. */\n private scheduleActivityRefresh(lifecycleGeneration: number): void {\n if (this.activityRefreshWindowMs === 0) return this.queueRefresh()\n if (this.activityTimer !== undefined) return\n const timer = setTimeout(() => {\n this.activityTimer = undefined\n if (this.alive() && lifecycleGeneration === this.lifecycleGeneration) this.queueRefresh()\n }, this.activityRefreshWindowMs)\n ;(timer as { unref?: () => void }).unref?.()\n this.activityTimer = timer\n }\n private fail(cause: unknown, generation: number): void {\n if (!this.alive(generation)) return\n const status = statusOf(cause)\n if (status === 401 || status === 403 || status === 404) {\n this.source = []\n this.entries = []\n this.offset = 0\n this.cursor = null\n this.patch({ conversations: [], summaries: new Map(), hasMore: false })\n }\n this.patch({ error: cause })\n }\n /** Run an operation in inbox mode, falling back to the legacy path for the rest of this store's life when the\n * inbox route is absent (404: rollback, staging). Loaded rows are kept and the same operation continues.\n */\n private async withFallback(generation: number, inbox: () => Promise<void>, legacy: () => Promise<void>): Promise<void> {\n if (!this.inboxMode) return legacy()\n try { await inbox() }\n catch (cause) {\n if (!this.alive(generation) || statusOf(cause) !== 404) throw cause\n this.inboxUnavailable = true\n this.clearActivityTimer()\n this.stopActivity()\n this.entries = []\n this.cursor = null\n this.offset = this.source.length\n if (!this.inboxWarned) {\n this.inboxWarned = true\n console.warn('ConvoKit inbox endpoint unavailable (404); using getConversations without previews or unread counts.')\n }\n this.patch({ summaries: new Map(), currentUserId: '' })\n await legacy()\n }\n }\n private validateInboxPage(page: InboxPage, limit: number, requestedCursor: string | null): void {\n const seen = new Set<string>()\n for (const entry of page.entries) {\n const id = entry.conversation.id\n if (!id.trim() || seen.has(id)) throw new Error('Invalid conversation page')\n seen.add(id)\n }\n if (page.entries.length > limit) throw new Error('Invalid conversation page')\n if (page.nextCursor !== null && (page.nextCursor === requestedCursor || page.entries.length === 0)) {\n throw new Error('Inbox pagination did not advance')\n }\n }\n /** Swap rows, summaries, cursor and hasMore together, filtered by the filter current at commit time. */\n private commitInbox(entries: InboxEntry[], cursor: string | null): void {\n this.entries = entries\n this.source = ids(entries)\n this.cursor = cursor\n this.patch({\n conversations: applyConversationFilter(this.source, this.state.filter),\n summaries: new Map(entries.map((entry) => [entry.conversation.id, summaryOf(entry)])),\n hasMore: cursor !== null,\n })\n }\n private async loadInboxUntilVisible(generation: number, filter: ConversationFilter): Promise<void> {\n const visibleBefore = applyConversationFilter(this.source, filter).length\n while (this.alive(generation)) {\n const requested = this.cursor\n const page = await this.options.client.listInbox!({ limit: this.pageSize, cursor: requested, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n this.validateInboxPage(page, this.pageSize, requested)\n this.commitInbox(mergeInboxEntries(this.entries, page.entries), page.nextCursor)\n if (page.nextCursor === null || this.state.conversations.length > visibleBefore) return\n }\n }\n private async loadUntilVisible(generation: number, filter: ConversationFilter): Promise<void> {\n const visibleBefore = applyConversationFilter(this.source, filter).length\n while (this.alive(generation)) {\n const request = { limit: this.pageSize, offset: this.offset, filter }\n const page = this.options.pageLoader\n ? await this.options.pageLoader(request)\n : await this.options.client.getConversations({ limit: this.pageSize, offset: this.offset, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n if (page.length > this.pageSize || page.some((conversation) => !conversation.id.trim())) {\n throw new Error('Invalid conversation page')\n }\n const merged = mergeConversations(this.source, page)\n if (page.length === this.pageSize && merged.length === this.source.length) {\n throw new Error('Conversation pagination did not advance')\n }\n this.offset += page.length\n this.source = merged\n const visible = applyConversationFilter(merged, filter)\n const hasMore = page.length === this.pageSize\n this.patch({ conversations: visible, hasMore })\n if (!hasMore || visible.length > visibleBefore) return\n }\n }\n loadInitial = async (): Promise<void> => {\n if (!this.alive()) return\n const generation = ++this.generation\n this.refreshing = false\n this.source = []\n this.entries = []\n this.offset = 0\n this.cursor = null\n this.patch({ ...blank(this.state.filter), currentUserId: this.currentUserId(), isInitialLoading: true })\n const filter = this.state.filter\n try {\n await this.withFallback(generation,\n () => this.loadInboxUntilVisible(generation, filter),\n () => this.loadUntilVisible(generation, filter))\n } catch (cause) { this.fail(cause, generation) }\n finally {\n if (this.alive(generation)) {\n this.patch({ isInitialLoading: false, hasLoaded: true })\n this.flushRefresh()\n }\n }\n }\n private queueRefresh(): void {\n this.refreshQueued = true\n this.flushRefresh()\n }\n private flushRefresh(): void {\n const lifecycle = this.lifecycleGeneration\n void Promise.resolve().then(() => {\n if (!this.alive() || lifecycle !== this.lifecycleGeneration || !this.refreshQueued\n || this.refreshing || this.state.isInitialLoading || this.state.isLoadingMore) return\n this.refreshQueued = false\n void this.refresh()\n })\n }\n /** Re-walk the inbox from the head until the loaded window is covered and something is visible, or the inbox\n * ends. Rooms that moved are re-positioned by the merge; an exhausted inbox publishes what it found.\n */\n private async refreshInbox(generation: number, filter: ConversationFilter): Promise<void> {\n const target = Math.max(this.pageSize, this.entries.length)\n let rows: InboxEntry[] = [], consumed = 0, cursor: string | null = null\n while (this.alive(generation)) {\n const remaining = target - consumed\n // Past the covered window (still nothing visible) continue in page-size steps.\n const limit = remaining >= 1 ? Math.min(100, remaining) : this.pageSize\n const page = await this.options.client.listInbox!({ limit, cursor, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n this.validateInboxPage(page, limit, cursor)\n rows = mergeInboxEntries(rows, page.entries)\n consumed += page.entries.length\n cursor = page.nextCursor\n if (cursor === null || (consumed >= target && applyConversationFilter(ids(rows), this.state.filter).length > 0)) break\n }\n if (!this.alive(generation)) return\n this.commitInbox(rows, cursor)\n }\n private async refreshLegacy(generation: number, filter: ConversationFilter): Promise<void> {\n const target = Math.max(this.pageSize, this.offset)\n // Default REST order is immutable creation time/ID, independent of UI sorting.\n const compare = (a: Conversation, b: Conversation) => a.createdAt.getTime() - b.createdAt.getTime()\n || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)\n const boundary = this.options.pageLoader ? undefined\n : this.source.reduce<Conversation | undefined>((oldest, row) => !oldest || compare(row, oldest) < 0 ? row : oldest, undefined)\n let rows: Conversation[] = [], offset = 0, hasMore = true\n while (this.alive(generation)) {\n const page = this.options.pageLoader\n ? await this.options.pageLoader({ limit: this.pageSize, offset, filter })\n : await this.options.client.getConversations({ limit: this.pageSize, offset, archived: filter.archived ?? false })\n if (!this.alive(generation)) return\n if (page.length > this.pageSize || page.some(row => !row.id.trim())) throw new Error('Invalid conversation page')\n const merged = mergeConversations(rows, page)\n if (page.length === this.pageSize && merged.length === rows.length) throw new Error('Conversation pagination did not advance')\n rows = merged\n offset += page.length\n hasMore = page.length === this.pageSize\n if (!hasMore || (offset >= target && applyConversationFilter(rows, this.state.filter).length > 0\n && (!boundary || page.some(row => compare(row, boundary) <= 0)))) break\n }\n if (!this.alive(generation)) return\n this.source = rows\n this.offset = offset\n this.patch({ conversations: applyConversationFilter(rows, this.state.filter), hasMore })\n }\n /** Replace the loaded window atomically, retaining filters and rows during transient failures. */\n refresh = async (): Promise<void> => {\n if (!this.alive()) return\n if (this.refreshing || this.state.isInitialLoading || this.state.isLoadingMore) {\n this.refreshQueued = true\n return\n }\n if (!this.state.hasLoaded) return this.loadInitial()\n const generation = this.generation\n const filter = this.state.filter\n this.refreshing = true\n this.patch({ error: null })\n try {\n await this.withFallback(generation,\n () => this.refreshInbox(generation, filter),\n () => this.refreshLegacy(generation, filter))\n } catch (cause) { this.fail(cause, generation) }\n finally {\n if (this.alive(generation)) {\n this.refreshing = false\n this.flushRefresh()\n }\n }\n }\n loadMore = async (): Promise<void> => {\n if (!this.alive() || this.refreshing || this.state.isInitialLoading || this.state.isLoadingMore || !this.state.hasMore) return\n const generation = this.generation\n const filter = this.state.filter\n this.patch({ isLoadingMore: true, error: null })\n try {\n await this.withFallback(generation,\n () => this.loadInboxUntilVisible(generation, filter),\n () => this.loadUntilVisible(generation, filter))\n } catch (cause) { this.fail(cause, generation) }\n finally {\n if (this.alive(generation)) {\n this.patch({ isLoadingMore: false })\n this.flushRefresh()\n }\n }\n }\n setFilter = async (filter: ConversationFilter): Promise<void> => {\n if (!this.alive()) return\n const reload = this.options.pageLoader || !this.state.hasLoaded || this.state.isInitialLoading\n || this.state.isLoadingMore || (filter.archived ?? false) !== (this.state.filter.archived ?? false)\n this.patch({ filter, conversations: applyConversationFilter(this.source, filter), error: null })\n if (reload) await this.loadInitial()\n else if (!this.state.conversations.length && this.state.hasMore) await this.loadMore()\n }\n setQuery = (query: string): Promise<void> => this.setFilter({ ...this.state.filter, query })\n /** Mark a room unread for the viewer only; the row's summary takes the response (D10). Rejects when the adapter\n * lacks `markConversationUnread` or the store is not active; a request failure is reported through `error`\n * without evicting rows and rejects.\n */\n markUnread = async (conversationId: string): Promise<void> => {\n const client = this.options.client\n if (typeof client.markConversationUnread !== 'function') {\n throw new TypeError('markUnread requires a ConvoKitUiClient adapter with markConversationUnread (core SDK 0.7)')\n }\n this.assertActive()\n this.applyPrivateState(conversationId, await this.mutate(client.markConversationUnread(conversationId)))\n }\n /** Remove the viewer's marker (conditionally on `options.ifVersion`); resolves to the response's `cleared` (\"this\n * request removed the marker\", not \"the room is read\") and patches the summary on true and false alike (D10).\n * Rejects when the adapter lacks `clearConversationUnread` or the store is not active; failures are reported like\n * `markUnread`.\n */\n clearUnread = async (conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean> => {\n const client = this.options.client\n if (typeof client.clearConversationUnread !== 'function') {\n throw new TypeError('clearUnread requires a ConvoKitUiClient adapter with clearConversationUnread (core SDK 0.7)')\n }\n this.assertActive()\n const result = await this.mutate(client.clearConversationUnread(conversationId, options))\n this.applyPrivateState(conversationId, result)\n return result.cleared\n }\n /** A disposed or session-evicted store never sends a private-state mutation: on a shared client it could go out\n * under a replacement login. Rejected without touching `error` (there is no live snapshot to report into).\n */\n private assertActive(): void {\n if (!this.alive()) throw new Error('ConversationListStore is not active')\n }\n private async mutate<T>(request: Promise<T>): Promise<T> {\n try { return await request }\n catch (cause) {\n if (this.alive()) this.patch({ error: cause })\n throw cause\n }\n }\n /** Apply a mark/clear response to the row's CURRENT summary (a refresh may have swapped it) as one unit, only while\n * the store is alive and the response is not older than the stored version: a delayed response never resurrects a\n * marker a newer action removed (equal versions are an idempotent no-op). `isUnread` is recomputed from the stored\n * counts and the response marker. Other devices learn of the change through `inbox_activity`.\n */\n private applyPrivateState(conversationId: string, state: ConversationPrivateState): void {\n if (!this.alive()) return\n const current = this.entries.find((entry) => entry.conversation.id === conversationId)\n if (!current || state.privateStateVersion < current.privateStateVersion) return\n const { unreadMarkedAt, privateStateVersion } = state\n const patched: InboxEntry = {\n ...current, unreadMarkedAt, privateStateVersion,\n isUnread: current.unreadCount > 0 || current.unreadCountCapped || unreadMarkedAt !== null,\n }\n this.entries = this.entries.map((entry) => entry === current ? patched : entry)\n this.patch({ summaries: new Map(this.entries.map((entry) => [entry.conversation.id, summaryOf(entry)])) })\n }\n}\n","import {\n computed,\n defineComponent,\n h,\n inject,\n provide,\n type CSSProperties,\n type InjectionKey,\n type PropType,\n type Ref,\n} from 'vue'\nimport { cx } from './utils'\n\nexport interface ConvoKitTheme {\n background: string\n surface: string\n primary: string\n text: string\n mutedText: string\n border: string\n error: string\n incomingBubble: string\n outgoingBubble: string\n outgoingText: string\n /** Unread badge and dot background (0.6.0); the badge label uses `outgoingText`. Defaults to the primary color. */\n badge: string\n /** The fading tint on the row a jump landed on (0.9.0). Defaults to the primary color at low opacity. */\n highlight: string\n radius: string\n avatarSize: string\n fontFamily: string\n}\n\nexport const defaultConvoKitTheme: ConvoKitTheme = {\n background: '#fafafa',\n surface: '#ffffff',\n primary: '#18181b',\n text: '#09090b',\n mutedText: '#71717a',\n border: '#e4e4e7',\n error: '#dc2626',\n incomingBubble: '#f4f4f5',\n outgoingBubble: '#18181b',\n outgoingText: '#fafafa',\n badge: '#18181b',\n highlight: 'color-mix(in srgb, #18181b 14%, transparent)',\n radius: '10px',\n avatarSize: '40px',\n fontFamily: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n}\n\nconst themeKey: InjectionKey<Readonly<Ref<ConvoKitTheme>>> = Symbol('ConvoKitTheme')\nconst defaultThemeRef = computed(() => defaultConvoKitTheme)\n\nexport const ConvoKitThemeProvider = defineComponent({\n name: 'ConvoKitThemeProvider',\n inheritAttrs: false,\n props: {\n theme: { type: Object as PropType<Partial<ConvoKitTheme>>, default: () => ({}) },\n class: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n style: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n },\n setup(props, { attrs, slots }) {\n const parent = inject(themeKey, defaultThemeRef)\n const value = computed(() => ({ ...parent.value, ...props.theme }))\n provide(themeKey, value)\n return () => {\n const theme = value.value\n const variables = {\n '--ckui-background': theme.background,\n '--ckui-surface': theme.surface,\n '--ckui-primary': theme.primary,\n '--ckui-text': theme.text,\n '--ckui-muted': theme.mutedText,\n '--ckui-border': theme.border,\n '--ckui-error': theme.error,\n '--ckui-incoming': theme.incomingBubble,\n '--ckui-outgoing': theme.outgoingBubble,\n '--ckui-outgoing-text': theme.outgoingText,\n '--ckui-badge': theme.badge,\n '--ckui-highlight': theme.highlight,\n '--ckui-radius': theme.radius,\n '--ckui-avatar-size': theme.avatarSize,\n '--ckui-font': theme.fontFamily,\n } as CSSProperties\n return h('div', {\n ...attrs,\n class: cx('ckui-theme', props.class, attrs.class),\n style: [variables, props.style, attrs.style],\n }, slots.default?.())\n }\n },\n})\n\nexport function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>> {\n return inject(themeKey, defaultThemeRef)\n}\n"],"mappings":"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","names":["Check","LoaderCircle","Pencil","Reply","defineComponent","h","ref","watch","cached","version","computed","defineComponent","h","watch","h","defineComponent","computed","watch","appearanceProps","defineComponent","ref","watch","text","h","Pencil","Reply","LoaderCircle","Check","LoaderCircle","RefreshCw","defineComponent","h","ref","watchEffect","computed","getCurrentScope","onScopeDispose","shallowRef","toValue","watch","blank","compare","toValue","shallowRef","watch","computed","getCurrentScope","onScopeDispose","options","appearanceProps","defineComponent","ref","h","LoaderCircle","RefreshCw","watchEffect","computed","defineComponent","h","computed","defineComponent","h"]}
|