From 8e0ed84eac44db025f1c85b3da5fcd971d28c4b7 Mon Sep 17 00:00:00 2001 From: Sirius Date: Wed, 15 Jul 2026 19:48:05 +0100 Subject: [PATCH] Fixed sending url preview bundles relying on update delay (#34266) * Fixed url preview bundle using url previews generated after the composer is cleared when sending message * lint fix * added comment * fixed linting error * added comments --- .../components/views/rooms/MessageComposer.tsx | 8 ++++++-- .../views/rooms/SendMessageComposer.tsx | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/apps/web/src/components/views/rooms/MessageComposer.tsx b/apps/web/src/components/views/rooms/MessageComposer.tsx index faf41f1559..e9debaf223 100644 --- a/apps/web/src/components/views/rooms/MessageComposer.tsx +++ b/apps/web/src/components/views/rooms/MessageComposer.tsx @@ -401,6 +401,10 @@ export class MessageComposer extends React.Component { }; private sendMessage = async (): Promise => { + // snapshot need to be captured before the composer is cleared + // otherwise the send message function will think there are no URLs in + // message and will not attach URL bundles + const urlPreviewSnapshot = this.props.urlPreviewVm.getSnapshot(); this.props.urlPreviewVm.updateWithText({ content: "", debounced: false }); if (this.state.haveRecording && this.voiceRecordingButton.current) { // There shouldn't be any text message to send when a voice recording is active, so @@ -409,7 +413,7 @@ export class MessageComposer extends React.Component { return; } - this.messageComposerInput.current?.sendMessage(); + this.messageComposerInput.current?.sendMessage({ urlPreviewSnapshot }); if (this.state.isWysiwygLabEnabled) { const { relation, replyToEvent } = this.props; @@ -424,7 +428,7 @@ export class MessageComposer extends React.Component { roomContext: this.context, relation, replyToEvent, - urlPreviewSnapshot: this.props.urlPreviewVm.getSnapshot(), + urlPreviewSnapshot, }); } }; diff --git a/apps/web/src/components/views/rooms/SendMessageComposer.tsx b/apps/web/src/components/views/rooms/SendMessageComposer.tsx index dc0ce2d100..914499250a 100644 --- a/apps/web/src/components/views/rooms/SendMessageComposer.tsx +++ b/apps/web/src/components/views/rooms/SendMessageComposer.tsx @@ -67,6 +67,7 @@ import { EMOJI_REGEX } from "../../../HtmlUtils"; import { attachMentions, attachRelation, attachUrlPreviews } from "../../../utils/messages"; import { type RoomUploadViewModel, useRoomUploadViewModel } from "../../../viewmodels/room/RoomUploadViewModel"; import { type MessageComposerUrlPreviewViewModel } from "../../../viewmodels/composer/MessageComposerUrlPreviewViewModel"; +import { type MessageComposerUrlPreviewSnapshot } from "@element-hq/web-shared-components"; // The prefix used when persisting editor drafts to localstorage. export const EDITOR_STATE_STORAGE_PREFIX = "mx_cider_state_"; @@ -141,6 +142,10 @@ interface ISendMessageComposerProps extends MatrixClientProps { urlPreviewVm: MessageComposerUrlPreviewViewModel; } +interface ISendMessageActionProps { + urlPreviewSnapshot: MessageComposerUrlPreviewSnapshot; +} + export class SendMessageComposer extends React.Component { public static contextType = RoomContext; declare public context: React.ContextType; @@ -197,10 +202,12 @@ export class SendMessageComposer extends React.Component { + /* + * The URL preview VM snapshot before the composer is cleared + */ + public async sendMessage({ urlPreviewSnapshot }: ISendMessageActionProps): Promise { const model = this.model; if (model.isEmpty) { @@ -443,7 +453,7 @@ export class SendMessageComposer extends React.Component