fix: optimistic message send — no full timeline reload
Instead of calling openCommunicationThread() after sending (which triggered a full timeline refetch, destroyed audio waveforms, and caused the chat to jump), we now: - Optimistically append the sent message to clientTimelineItems - Scroll to bottom smoothly - Refresh contacts sidebar for lastMessageText preview - Auto-scroll only fires on thread switch (empty→loaded), not on every timeline update, preserving audio waveform DOM elements Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -844,17 +844,17 @@ async function sendCommMessage() {
|
|||||||
const text = commDraft.value.trim();
|
const text = commDraft.value.trim();
|
||||||
if (!text || commSending.value || !selectedCommThread.value) return;
|
if (!text || commSending.value || !selectedCommThread.value) return;
|
||||||
commSending.value = true;
|
commSending.value = true;
|
||||||
|
const contactId = selectedCommThreadId.value;
|
||||||
|
const contactName = selectedCommThread.value.contact;
|
||||||
try {
|
try {
|
||||||
const channel = commSendChannel.value;
|
const channel = commSendChannel.value;
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
const { useMutation } = await import("@vue/apollo-composable");
|
const { useMutation } = await import("@vue/apollo-composable");
|
||||||
const { CreateCommunicationMutationDocument, CommunicationsQueryDocument, ContactInboxesQueryDocument } = await import("~~/graphql/generated");
|
const { CreateCommunicationMutationDocument } = await import("~~/graphql/generated");
|
||||||
const { mutate: doCreateCommunication } = useMutation(CreateCommunicationMutationDocument, {
|
const { mutate: doCreateCommunication } = useMutation(CreateCommunicationMutationDocument);
|
||||||
refetchQueries: [{ query: CommunicationsQueryDocument }, { query: ContactInboxesQueryDocument }],
|
const result = await doCreateCommunication({
|
||||||
});
|
|
||||||
await doCreateCommunication({
|
|
||||||
input: {
|
input: {
|
||||||
contact: selectedCommThread.value.contact,
|
contact: contactName,
|
||||||
channel,
|
channel,
|
||||||
kind: "message",
|
kind: "message",
|
||||||
direction: "out",
|
direction: "out",
|
||||||
@@ -862,7 +862,36 @@ async function sendCommMessage() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
commDraft.value = "";
|
commDraft.value = "";
|
||||||
openCommunicationThread(selectedCommThread.value.contact);
|
|
||||||
|
// Optimistically append the sent message to timeline (no full reload)
|
||||||
|
const newId = result?.data?.createCommunication?.id ?? `temp-${Date.now()}`;
|
||||||
|
const now = new Date().toISOString();
|
||||||
|
clientTimelineItems.value = [
|
||||||
|
...clientTimelineItems.value,
|
||||||
|
{
|
||||||
|
id: newId,
|
||||||
|
contactId,
|
||||||
|
contentType: "message",
|
||||||
|
contentId: newId,
|
||||||
|
datetime: now,
|
||||||
|
message: {
|
||||||
|
id: newId,
|
||||||
|
at: now,
|
||||||
|
contact: contactName,
|
||||||
|
contactInboxId: "",
|
||||||
|
sourceExternalId: "",
|
||||||
|
sourceTitle: "",
|
||||||
|
channel: channel as CommItem["channel"],
|
||||||
|
kind: "message",
|
||||||
|
direction: "out",
|
||||||
|
text,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
scrollCommThreadToBottom();
|
||||||
|
|
||||||
|
// Refresh sidebar preview (lastMessageText) — lightweight
|
||||||
|
void refetchContacts();
|
||||||
} finally {
|
} finally {
|
||||||
commSending.value = false;
|
commSending.value = false;
|
||||||
}
|
}
|
||||||
@@ -1145,9 +1174,9 @@ function scrollCommThreadToBottom() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to bottom whenever timeline items change (thread switch or new message)
|
// Scroll to bottom when a new thread loads (items go from [] → [items])
|
||||||
watch(clientTimelineItems, (items) => {
|
watch(clientTimelineItems, (items, oldItems) => {
|
||||||
if (items.length) scrollCommThreadToBottom();
|
if (items.length && (!oldItems || oldItems.length === 0)) scrollCommThreadToBottom();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user