diff --git a/src/views/messages-view.jsx b/src/views/messages-view.jsx index e8c229d6..1e91548b 100644 --- a/src/views/messages-view.jsx +++ b/src/views/messages-view.jsx @@ -1525,7 +1525,6 @@ class MessagesView extends React.Component { // We are forwarding a message. msg = this.props.forwardMessage.msg; head = this.props.forwardMessage.head; - this.handleCancelReply(); } else if (this.state.reply) { if (this.state.reply.editing) { if (msg == this.state.contentToEdit) { @@ -1545,7 +1544,6 @@ class MessagesView extends React.Component { } msg = Drafty.append(Drafty.sanitizeEntities(this.state.reply.content), msg); } - this.handleCancelReply(); } else if (typeof msg == 'string' && this.mentionedUsers && this.mentionedUsers.length) { // 4.2-4.3 @提醒:Drafty.parse 本来就会把纯文本里的"@word"自动识别成 MN 实体,但 // data.val 存的是匹配到的原始文字(tinode.dev.js 的 ENTITY_TYPES 表,pack: val => @@ -1584,6 +1582,19 @@ class MessagesView extends React.Component { // the same backend version=0-skips-the-lock issue explained in handleComposerChange above. const draftVersionAtSend = this.state.draftVersion || 0; const doSend = () => { + // Was called eagerly above (right after building `msg`/`head` from `this.state.reply`/ + // `this.props.forwardMessage`), synchronously and unconditionally -- including on a message + // that turns out to need the URL risk dialog below, which only resolves *after* this function + // already returned. That meant clicking send on a reply/edit containing a link made the + // "回复"/编辑 preview bar vanish immediately, before the user had even seen the risk prompt; + // clicking "取消发送" then left the reply/edit permanently abandoned -- the quoted message was + // gone from the composer with no way back except manually replying again, even though the user + // only meant to cancel sending the flagged text, not the reply itself. Moving the call here + // means it only fires at the point a send is actually going to happen: immediately for the + // common non-URL case (this function runs synchronously right away, same timing as before), + // or deferred until "继续发送" for a flagged one -- and never at all if the dialog is cancelled, + // so the reply/edit state and its preview bar correctly survive a cancelled risk prompt. + this.handleCancelReply(); const result = this.props.sendMessage(msg, uploadCompletionPromise, uploader, head); // Only a plain-text compose (not a reply/edit/forward, all of which pass a Drafty object or // reuse contentToEdit rather than the persisted draft) has a server-side draft worth clearing.