import { InfiniteData } from '@tanstack/react-query' import { chatQueryClient } from '../../contexts/api_provider' import { ApiCollection, CurrentPersonResource, MessageResource } from '../../types' import { DenormalizedAttachmentResource } from '../../types/resources/denormalized_attachment_resource' import { DenormalizedAttachmentResourceForCreate } from '../../types/resources/denormalized_attachment_resource_for_create' import { getMessagesQueryKey } from '../../utils/request/get_messages' import { convertAttachmentsForCreate } from '../convert_attachments_for_create' import { generatePlaceholderUlid } from '../generate_placeholder_ulid' import { updateOrCreateRecordInPagesData } from './page_mutations' export function optimisticallyCreateMessage({ conversationId, text, attachments, currentPerson, message, replyRootId, idempotentKey, }: { conversationId: number text: string attachments?: DenormalizedAttachmentResourceForCreate[] currentPerson: CurrentPersonResource message?: MessageResource replyRootId?: string | null idempotentKey?: string }) { const id = message?.id || generateTempMessageId() // Convert attachments to denormalized format for optimistic UI const decoratedAttachments: DenormalizedAttachmentResource[] = convertAttachmentsForCreate( attachments || [] ) // Create an optimistic message const optimisticMessage: MessageResource = { ...message, type: 'Message', messageType: 'user', id, text, html: '', // Will be filled by server createdAt: new Date().toISOString(), deletedAt: null, textEditedAt: null, mine: true, attachments: decoratedAttachments, attachmentsForCreate: attachments || [], author: currentPerson, reactionCounts: [], renderAuthor: false, renderTime: true, myLatestInConversation: true, lastInGroup: true, pending: true, replyCount: 0, replyRootId: replyRootId || null, idempotentKey, } // Add the optimistic message to the cache type QueryData = InfiniteData> const queryKey = getMessagesQueryKey({ conversation_id: conversationId, reply_root_id: replyRootId, }) chatQueryClient.setQueryData(queryKey, data => updateOrCreateRecordInPagesData({ data, record: optimisticMessage as MessageResource, }) ) return optimisticMessage } const generateTempMessageId = () => { // Put it 5 seconds in the future to account for server lag of previously created messages // that are still pending. This gets overwritten by the server anyway. return `${generatePlaceholderUlid({ offsetMs: 5000 })}-temp` }