修复好友资料/验证页对"当前关系"的两处判断遗漏,与已有的好友申请状态机修复形成完整闭环

现象一:Profile 组件(好友/陌生人资料页)在 getConversationContext 回来后只合并了
relationship 字段,没有一并合并 capabilities——这个组件判断"能否显示添加好友按钮"
用的是 profile.capabilities.can_add_friend,不是 relationship 本身。已实测复现:
刚发送好友申请、relationship 已经变成 pending_outbound 时,若走的是"直接刷新这个
资料页"而不是 Verification 组件自己的发送成功回调(该回调已由另一处提交单独修复),
canAdd 依然读到发送前搜索结果种子里的 can_add_friend:true,"添加好友"按钮继续可点,
可再次触发一次好友申请(配合后端不去重的缺口——新增44)。

现象二:Verification 组件(好友验证/发送申请页)完全没有用 getConversationContext
校正过 relationship,只依赖 getUserProfile——但该接口对非好友直接 403,403 时的
catch 分支什么都不做。真实复现:本次会话内先成为好友、再解除好友关系后,若该好友的
profile-seed 缓存还留着"好友"时期的旧数据,重新打开验证页会一直显示"你们已经是
好友了",且不提供发送框,除非整页刷新清掉内存缓存,否则无法向这个人重新发起好友申请。

修复:两处都在 getConversationContext 成功回调里,把它返回的字段当作当前关系的权威
来源合并进本地 profile 状态——Profile 一并合并 capabilities(而不只是 relationship),
Verification 补上原本没有的 getConversationContext 调用去合并 relationship。

验证:真实浏览器操作,两个全新注册账号之间反复走查——(1) 发送好友申请后直接刷新
资料页,"添加好友"按钮正确消失、显示"好友申请正在等待验证";(2) 成为好友后互相
删除好友关系,立刻重新打开验证页,正确显示可发送的验证留言表单,不再卡在"你们已经
是好友了"。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-06 15:41:36 +08:00
co-authored by Claude Sonnet 5
parent 605cd12a6e
commit 5ddace97f4
+25 -1
View File
@@ -356,6 +356,20 @@ function Verification({uid, onToast}) {
React.useEffect(() => {
if (!uid) return;
getUserProfile(uid).then(data => { writeCachedData('profile-seed:' + uid, data); setProfile(data); }).catch(() => {});
// getUserProfile 403s for anyone who isn't currently a friend (server privacy default) -- same
// gap Profile already works around below. Without this, a `profile-seed` left over from *earlier
// in the same session* (e.g. this pair really were friends before one side unfriended them, or a
// request was sent and then rejected) stayed on screen forever: alreadyFriend/alreadyPending read
// straight off `profile.relationship`, and the 403 catch above has nothing to correct it with.
// Confirmed live: unfriend someone, then re-open this exact page for them (still reachable via
// their still-cached, now-stale seed) -- it kept claiming "你们已经是好友了" and hid the compose
// box entirely, with no way to send a new request short of a full page reload to drop the cache.
// getConversationContext isn't gated on friendship and reports the true current relationship.
getConversationContext(uid).then(ctx => {
if (ctx && ctx.relationship) {
setProfile(current => current ? {...current, relationship: ctx.relationship} : current);
}
}).catch(() => {});
}, [uid]);
const alreadyPending = profile && (profile.relationship === 'pending_outbound' || profile.relationship === 'pending_inbound');
const alreadyFriend = profile && profile.relationship === 'friend';
@@ -420,9 +434,19 @@ function Profile({uid, friend, onTopicSelected, onToast}) {
// handles below. getConversationContext resolves for a P2P conversation regardless of block
// status and correctly reports the real relationship, so it's used here purely to refresh that
// one field on top of whatever getUserProfile/the seed cache already provided for the rest.
//
// 同时必须把 ctx.capabilities 一起合并进去,不能只更新 relationship:canAdd 这个渲染判断读的是
// profile.capabilities.can_add_friend,不是 relationship 本身。实测复现:从陌生人搜索结果进来的
// seed 一直带着 capabilities.can_add_friend=true(搜索时 can_add 确实是 true),发送好友申请后
// relationship 变成 pending_outbound,可这里原来只覆盖 relationship 字段,capabilities 原样保留
// 着申请前的 can_add_friend:true——canAdd 分支判断不看 relationship,于是"添加好友"按钮在申请
// 已发出后继续显示、可以重复点击再次发起申请(配合后端不去重的缺口——新增44——实际造成重复申请)。
// ctx.capabilities 本身就是服务端针对当前 relationship 算出来的权威值(此时 can_add_friend 已经
// 是 false),直接一起合并即可,不需要在前端另外推导一套"这些 relationship 不能加好友"的规则。
getConversationContext(uid).then(ctx => {
if (ctx && ctx.relationship) {
setProfile(current => current ? {...current, relationship: ctx.relationship} : current);
setProfile(current => current ? {...current, relationship: ctx.relationship,
capabilities: ctx.capabilities || current.capabilities} : current);
}
}).catch(() => {});
}, [uid]);