codereview修复:资料弹窗好友关系判断、转发内容克隆、账号切换缓存残留等
三路独立codereview(群成员UI+资料弹窗 / 未读红点+转发修复 / 搜索+复制修复) 发现并修复: - UserCardRoot 资料弹窗此前完全没读 profile.relationship,对陌生人也直接 显示"发消息"/通话按钮——现在按好友/待验证/对方已申请/不可添加/添加好友 五态分支,和 FriendProfileView 保持一致,接入 AddFriendModal。 - useEscapeKey 注册位置错误:挂在常驻的 UserCardRoot 而不是随卡片开关的 UserCardPanel,导致从其他弹层里打开资料卡片时,按 Escape 关掉的是底下 那层弹层而不是卡片本身。 - "移出"格子的可见性此前只判断 isAdmin,在"群主+多个管理员、没有普通成员" 的群里会显示格子但点进去一个能移出的都没有——改成同时判断成员列表里 是否真的存在能移出的对象。 - flatForwardPayload 对图片/文件/语音/视频/名片/通话结果类消息,转发时直接 返回了原消息的 content 对象引用而不是拷贝——SDK 出站前会就地删除假值 字段,等于转发的同时悄悄改写了原消息在本地缓存里的内容。改成每次转发都 返回浅拷贝;顺手让检查顺序和其余识别这几种格式的地方保持一致(先判类型 明确的附件/名片/通话结果,再判无类型标记的纯文本),并补上和 mobileAttachmentContentOf/contactCardContentOf 同样的字段合法性校验。 - confirmedReadSeq 等聊天列表相关的模块级缓存此前从未在登出/切换企业时清 空——同一个标签页不刷新页面直接换账号登录,会把上一个账号的"已读到哪" 当成新账号的下限,把新账号真实未读的自聊消息误判为已读。补了统一的 reset监听机制(connection.ts 的 resetTinode 现在会广播),topics.ts 据此 清空所有相关缓存。 - 复制功能补final `?? ''`兜底,防止附件数据本身不完整时仍复制出"undefined"。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
105ff76959
commit
0ba5c97d78
@@ -15,7 +15,7 @@ import type { Contact, StoredMessage, Topic } from 'tinode-sdk';
|
||||
import { getGroup } from '@/lib/api/groups';
|
||||
import { MESSAGES_PAGE } from '@/lib/config';
|
||||
|
||||
import { getTinode, onReauthenticated } from './connection';
|
||||
import { getTinode, onReauthenticated, onTinodeReset } from './connection';
|
||||
|
||||
const topicListeners = new Map<string, Set<() => void>>();
|
||||
const anyTopicListeners = new Set<() => void>();
|
||||
@@ -676,6 +676,25 @@ onReauthenticated(() => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Real, reproduced bug (2026-09-25 review): every module-level cache below is scoped by topic NAME,
|
||||
* not by account -- and topic names collide across accounts by construction, not edge case (`'slf'`
|
||||
* is the literal self-chat topic name for every account, `isChatListTopicName` below). Without this,
|
||||
* logging out and into a DIFFERENT account in the same tab (no full reload -- resetTinode() itself
|
||||
* never reloads the page) carries the previous account's cached state forward: `confirmedReadSeq`
|
||||
* specifically was confirmed to silently mark the new account's genuinely-unread 'slf' messages as
|
||||
* read the next time reconcileMeSubs() ticked, since it read the OLD account's higher confirmed seq
|
||||
* as a floor for the new account's much-lower real one. Same reasoning extends to every other cache
|
||||
* here: none of them should outlive the session that populated them.
|
||||
*/
|
||||
onTinodeReset(() => {
|
||||
confirmedReadSeq.clear();
|
||||
previewPrefetched.clear();
|
||||
messageSnapshots.clear();
|
||||
goneTopicNames.clear();
|
||||
chatListSnapshot = null;
|
||||
});
|
||||
|
||||
const ME_RECONCILE_INTERVAL_MS = 30_000;
|
||||
let meReconcileTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user