修复消息发送失败/排队中时长按菜单仍提供"撤回"
判断只查 params.seq > 0,未排除 tinode-sdk 本地占位 seq(LOCAL_SEQID, 268435455,同样是正数)——发送失败/仍在排队的消息会被误判成"已持久化 的真实消息",点击撤回后端正确拒绝(无此消息),却给用户一个答非所问 的"请求内容有误"提示。 第十一轮最小粒度测试 Ch3-4 发现。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
89fdd31cd4
commit
fc757cc043
@@ -3,7 +3,7 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import { Drafty, Tinode, TheCard } from 'tinode-sdk';
|
||||
import { Drafty, Tinode, TheCard, LOCAL_SEQID } from 'tinode-sdk';
|
||||
|
||||
const CallPanel = React.lazy(_ => import('../widgets/call-panel.jsx'));
|
||||
import ChatMessage from '../widgets/chat-message.jsx';
|
||||
@@ -1088,10 +1088,22 @@ class MessagesView extends React.Component {
|
||||
// allowAdmin=true, so the backend has always accepted this; the reference screenshot
|
||||
// (消息页面—长按弹出.png) lists "群撤回" as its own, always-shown menu item alongside "撤回" --
|
||||
// this was previously never offered at all since the only condition checked was authorship.
|
||||
//
|
||||
// `params.seq > 0` alone is not enough to mean "a real, server-persisted message": Tinode
|
||||
// SDK gives every message that hasn't been confirmed by the server yet (still sending, or
|
||||
// failed outright) a local placeholder seq of LOCAL_SEQID (0xFFFFFFF = 268435455) -- a large
|
||||
// *positive* number, so it passed this check. Round 11 live testing reproduced this: sending
|
||||
// a message into a since-blocked P2P topic left a bubble stuck in "发送失败" with seq
|
||||
// 268435455, and this menu still offered "撤回" for it -- clicking it fired
|
||||
// POST /topics/.../messages/268435455/recall, which the server correctly rejects (no such
|
||||
// message), surfacing a confusing "请求内容有误,请稍后重试" toast for an action that should
|
||||
// never have been offered. `seq < LOCAL_SEQID` excludes exactly that placeholder range,
|
||||
// matching the same bound the SDK itself uses internally to distinguish a confirmed seq from
|
||||
// a queued one.
|
||||
const recallWindow = this.state.messagePolicy ? this.state.messagePolicy.recall_window_seconds : 0;
|
||||
const canRecallAsAdmin = topic.isGroupType() && topic.getAccessMode() && topic.getAccessMode().isAdmin();
|
||||
if ((params.userFrom == this.props.myUserId || canRecallAsAdmin) && params.seq > 0 && recallWindow > 0 &&
|
||||
params.timestamp && params.timestamp.getTime() > (new Date().getTime() - recallWindow * 1000)) {
|
||||
if ((params.userFrom == this.props.myUserId || canRecallAsAdmin) && params.seq > 0 && params.seq < LOCAL_SEQID &&
|
||||
recallWindow > 0 && params.timestamp && params.timestamp.getTime() > (new Date().getTime() - recallWindow * 1000)) {
|
||||
menuItems.push('menu_item_recall');
|
||||
}
|
||||
// Self -> (1) always hard-delete with [Delete] title.
|
||||
|
||||
Reference in New Issue
Block a user