From 8431f83ede1c0af25786e8b94679b7619357c9a8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 16 Sep 2026 18:03:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=8E=E5=A5=BD=E5=8F=8B?= =?UTF-8?q?=E8=B5=84=E6=96=99=E9=A1=B5"=E5=8F=91=E6=B6=88=E6=81=AF"?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E8=BF=9B=E5=85=A5=E6=96=B0P2P=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E6=97=B6=E5=90=8D=E7=A7=B0/=E5=9C=A8=E7=BA=BF?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=B0=B8=E4=B9=85=E7=BC=BA=E5=A4=B1=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因比此前提交(ff69e454)修复的isCommType()问题更深一层:即使会话能正确 出现在列表里,openConversation()走的withLaterDesc()增量查询在这条特定 路径(从未经过整页刷新,纯SPA内跳转)下会订阅成功但不返回desc/presence, topic.public永久为null、在线状态永久为"离线",等待再久也不会自愈——整页 刷新之所以从未复现过这个问题,是因为subscribeMeTopic()自己的全量重新 订阅逻辑无条件覆盖了这个缺口。 改为在topic.public缺失时,用me.getMeta(withOneSub(topic))主动拉取——这 是SDK自己的presence路由内部用于"刚得知这个话题"场景的同一个调用,一次 返回desc+在线状态两者,且me话题的onMetaSub/onSubsUpdated回调早已在登录 时挂好,响应到达后会自动使聊天列表失效重新渲染。 已用全新测试账号对(systester9+systester2)在开发服务器实机验证:通过 真实DOM点击(非navigate()整页刷新)从通讯录进入全新会话,标题栏与侧边栏 立即正确显示对方名称与"在线"状态。 Co-Authored-By: Claude Sonnet 5 --- .../features/messages/ConversationView.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/web/src/features/messages/ConversationView.tsx b/web/src/features/messages/ConversationView.tsx index f182d932..2f390b54 100644 --- a/web/src/features/messages/ConversationView.tsx +++ b/web/src/features/messages/ConversationView.tsx @@ -157,6 +157,27 @@ export function ConversationView() { // the URL to the real name the instant it's known makes every later `getTopic(topicId)` in // this component resolve the SAME object subscribe() just populated, not a fresh impostor. if (topic.name !== topicId) navigate(`/messages/${topic.name}`, { replace: true }); + // Real, live-confirmed gap on top of the rename issue above: for exactly this brand-new-P2P- + // via-alias case, `openConversation`'s own `withLaterDesc()` (an incremental "only if changed + // since I last knew" fetch) can come back with the subscribe successful but NO desc AND no + // presence at all -- `topic.public` stays permanently `null` and `topic.online` stays falsy + // (confirmed live: still true 10+ seconds later, no amount of waiting fixes either one), + // which is why the header/chat-list fall back to the raw topic id and "离线" forever on THIS + // specific path (reached live via a friend's profile "发消息" button, never through a fresh + // page load -- a full reload's own `subscribeMeTopic()` happens to paper over this by + // fetching every contact's full subscription state unconditionally, which is exactly why this + // was never caught by any test that reloaded the page as part of "opening" a conversation). + // `me.getMeta(withOneSub(topic))` is the same targeted-refresh call the SDK's own presence + // routing (`_routePres`, tinode.dev.js) uses for "just learned about this topic" -- unlike a + // plain desc fetch on the topic itself, this one comes back with BOTH desc AND online status + // in the same `sub` entry (confirmed live capturing the raw frame during an earlier + // investigation), and `TopicMe`'s own `_processMetaSubs` merges both onto this exact topic + // object before notifying -- wireTopicCallbacks already wired `me`'s `onMetaSub`/ + // `onSubsUpdated` at login, so the response correctly invalidates the chat list once it lands. + if (!topic.public) { + const me = tinode.getMeTopic(); + me.getMeta(me.startMetaQuery().withOneSub(undefined, topic.name).build()).catch(() => {}); + } }) .catch((err) => showError(err, '加载会话失败,请重试')); return () => {