修复群成员非好友主页文案错误、添加好友按钮永不出现(第5章复测发现)
navigateToProfile 原来只从群成员列表数据({acs, display_name, group_nickname?, mentionable,
role, user_id})里摘字段做种子缓存,这份数据里根本没有 capabilities/relationship——Profile
组件正是靠这两个字段判断"要不要显示添加好友按钮"和"该显示哪句失败文案"。缺了它们,非好友的
群成员主页会落到 cannotAddReason 的默认分支:不管真实关系是什么,一律显示"好友申请正在等待
验证",添加好友按钮永远不出现。
Profile 组件自己的 getUserProfile(uid) 对非好友是 403(服务端隐私默认),403 时会保留种子
不报错——这个保留种子的兜底本身是对的,问题是种子从一开始就没给对数据。
改用 GET /groups/{topic}/members/{user_id}/profile(getGroupMemberProfile,早就封装好但
零调用点)——群上下文里权限判断更宽松,实测对方哪怕不是好友也能拿到
{capabilities, relationship}。navigateToProfile 现在异步补种:跳转后台发起这个请求,回来后
用真实数据覆盖种子并派发一个事件让已经挂载的 Profile 重新读取。
已用真实账号验证:点击群成员头像后,getGroupMemberProfile 真实请求 200,返回
relationship:"friend"、capabilities.can_add_friend:false;Profile 组件的 React state 和
最终渲染的 DOM 都正确更新成"发消息/音视频通话"(通过 React Fiber 直接读取 state 确认,不只是
看界面文字)。当前两个测试账号互为好友,没能用真正的陌生人群成员验证"添加好友"按钮出现的
那条分支,但接口返回结构已经证实包含判断所需的全部字段,逻辑上会正确生效。
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
0dcef54fed
commit
997f8f71d2
@@ -393,6 +393,20 @@ function Profile({uid, friend, onTopicSelected, onToast}) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [uid]);
|
}, [uid]);
|
||||||
|
// group-management-view.jsx 的 navigateToProfile 在跳转之后异步用 getGroupMemberProfile 把
|
||||||
|
// capabilities/relationship 补进种子缓存(那两个字段 getUserProfile 对非好友会 403 拿不到,
|
||||||
|
// 群场景权限更宽松能拿到)。这个组件已经挂载了,不会自己重新读缓存,靠这个事件通知它有更新。
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!uid) return undefined;
|
||||||
|
const onSeedUpdated = e => {
|
||||||
|
if (e.detail && e.detail.uid === uid) {
|
||||||
|
const updated = readCachedData('profile-seed:' + uid);
|
||||||
|
if (updated) setProfile(updated);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('profile-seed-updated', onSeedUpdated);
|
||||||
|
return () => window.removeEventListener('profile-seed-updated', onSeedUpdated);
|
||||||
|
}, [uid]);
|
||||||
if (!profile) return <div className="people-page"><Header title="个人资料" back={friend ? 'address-book' : 'chat-standard'} /><main className="people-profile"><p className="people-empty-hint">{loadError ? '资料加载失败,请重试' : '加载中…'}</p></main></div>;
|
if (!profile) return <div className="people-page"><Header title="个人资料" back={friend ? 'address-book' : 'chat-standard'} /><main className="people-profile"><p className="people-empty-hint">{loadError ? '资料加载失败,请重试' : '加载中…'}</p></main></div>;
|
||||||
const canAdd = profile.capabilities && profile.capabilities.can_add_friend;
|
const canAdd = profile.capabilities && profile.capabilities.can_add_friend;
|
||||||
const isFriend = profile.relationship === 'friend';
|
const isFriend = profile.relationship === 'friend';
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import {
|
|||||||
acceptGroupJoinRequest, rejectGroupJoinRequest, getLatestGroupAnnouncement,
|
acceptGroupJoinRequest, rejectGroupJoinRequest, getLatestGroupAnnouncement,
|
||||||
updateCurrentGroupAnnouncement, getGroupGovernance, updateGroupGovernance, addGroupAdmins,
|
updateCurrentGroupAnnouncement, getGroupGovernance, updateGroupGovernance, addGroupAdmins,
|
||||||
deleteGroupAdmin, muteGroupMembers, getGroupMutes, unmuteGroupMember, transferGroupOwner,
|
deleteGroupAdmin, muteGroupMembers, getGroupMutes, unmuteGroupMember, transferGroupOwner,
|
||||||
getGroupFiles, addGroupFile, deleteGroupFile, uploadLargeFile, getFileUrl, getUserProfile
|
getGroupFiles, addGroupFile, deleteGroupFile, uploadLargeFile, getFileUrl, getUserProfile,
|
||||||
|
getGroupMemberProfile
|
||||||
} from '../lib/im-api.js';
|
} from '../lib/im-api.js';
|
||||||
import { readCachedData, writeCachedData, useDebouncedValue } from '../lib/use-cached-data.js';
|
import { readCachedData, writeCachedData, useDebouncedValue } from '../lib/use-cached-data.js';
|
||||||
|
|
||||||
@@ -28,7 +29,12 @@ const navigate = (view, topic) => {
|
|||||||
// 因为 GET /users/{id}/profile 对非好友按隐私默认直接 403(imPrivacyAllowsProfile)。群成员里
|
// 因为 GET /users/{id}/profile 对非好友按隐私默认直接 403(imPrivacyAllowsProfile)。群成员里
|
||||||
// 大部分不是好友,不 seed 的话点进去就是"资料加载失败,请重试"。第5章自己的入口
|
// 大部分不是好友,不 seed 的话点进去就是"资料加载失败,请重试"。第5章自己的入口
|
||||||
// (contact-management-view.jsx 的 seedProfile)一直是这么做的,这里漏了。
|
// (contact-management-view.jsx 的 seedProfile)一直是这么做的,这里漏了。
|
||||||
const navigateToProfile = (userId, member) => {
|
const navigateToProfile = (topic, userId, member) => {
|
||||||
|
// 先用群成员列表里已有的字段摆一个立即可用的种子(避免导航瞬间空白),
|
||||||
|
// 但这份种子缺 capabilities/relationship——GET /groups/{topic}/members 从不返回这两个字段
|
||||||
|
// (已实测确认),Profile 组件正是靠它们判断"要不要显示添加好友按钮"和"该显示哪句失败文案"。
|
||||||
|
// 缺了它们,非好友的群成员主页会落到 cannotAddReason 的默认分支——不管真实关系是什么,
|
||||||
|
// 一律显示"好友申请正在等待验证",添加好友按钮永远不出现。
|
||||||
if (member && userId) {
|
if (member && userId) {
|
||||||
writeCachedData('profile-seed:' + userId, {
|
writeCachedData('profile-seed:' + userId, {
|
||||||
user_id: userId,
|
user_id: userId,
|
||||||
@@ -41,6 +47,17 @@ const navigateToProfile = (userId, member) => {
|
|||||||
}
|
}
|
||||||
HashNavigation.navigateTo(
|
HashNavigation.navigateTo(
|
||||||
HashNavigation.addUrlParam(HashNavigation.setUrlSidePanel(window.location.hash, 'group-member-profile'), 'uid', userId));
|
HashNavigation.addUrlParam(HashNavigation.setUrlSidePanel(window.location.hash, 'group-member-profile'), 'uid', userId));
|
||||||
|
// 群场景下真正该用的是 GET /groups/{topic}/members/{user_id}/profile——群上下文里权限判断更
|
||||||
|
// 宽松,实测对方哪怕不是好友也能拿到 {capabilities, relationship}(Profile 组件目标页读的
|
||||||
|
// GET /users/{id}/profile 对非好友是 403,只能回退用种子)。异步补种:请求回来后如果用户还
|
||||||
|
// 停在这个人的资料页(没有连点跳到别处),用真实数据覆盖种子并强制该页面重新读取。
|
||||||
|
if (topic && userId) {
|
||||||
|
getGroupMemberProfile(topic, userId).then(real => {
|
||||||
|
const current = readCachedData('profile-seed:' + userId) || {};
|
||||||
|
writeCachedData('profile-seed:' + userId, {...current, ...real});
|
||||||
|
window.dispatchEvent(new CustomEvent('profile-seed-updated', {detail: {uid: userId}}));
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GROUP_MANAGEMENT_VIEWS = [
|
export const GROUP_MANAGEMENT_VIEWS = [
|
||||||
@@ -425,7 +442,7 @@ function GroupSettings({topic, myUserId, tinode, onToast}) {
|
|||||||
<strong>群成员</strong><small>共 {group.member_count} 位成员</small>
|
<strong>群成员</strong><small>共 {group.member_count} 位成员</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="group-member-grid">
|
<div className="group-member-grid">
|
||||||
{members.slice(0, 9).map(item => <button type="button" key={item.user_id} onClick={() => navigateToProfile(item.user_id, item)}>
|
{members.slice(0, 9).map(item => <button type="button" key={item.user_id} onClick={() => navigateToProfile(topic, item.user_id, item)}>
|
||||||
<Avatar item={item} icon="person" /><small>{item.group_nickname || item.display_name}</small>
|
<Avatar item={item} icon="person" /><small>{item.group_nickname || item.display_name}</small>
|
||||||
</button>)}
|
</button>)}
|
||||||
<button type="button" onClick={() => onToast('请通过转发/分享群二维码邀请成员')}>
|
<button type="button" onClick={() => onToast('请通过转发/分享群二维码邀请成员')}>
|
||||||
|
|||||||
+27
-2
@@ -8127,6 +8127,17 @@ function Profile({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [uid]);
|
}, [uid]);
|
||||||
|
react__WEBPACK_IMPORTED_MODULE_0___default().useEffect(() => {
|
||||||
|
if (!uid) return undefined;
|
||||||
|
const onSeedUpdated = e => {
|
||||||
|
if (e.detail && e.detail.uid === uid) {
|
||||||
|
const updated = (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_5__.readCachedData)('profile-seed:' + uid);
|
||||||
|
if (updated) setProfile(updated);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('profile-seed-updated', onSeedUpdated);
|
||||||
|
return () => window.removeEventListener('profile-seed-updated', onSeedUpdated);
|
||||||
|
}, [uid]);
|
||||||
if (!profile) return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
if (!profile) return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||||
className: "people-page",
|
className: "people-page",
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Header, {
|
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Header, {
|
||||||
@@ -10477,7 +10488,7 @@ const navigate = (view, topic) => {
|
|||||||
hash = topic ? _lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].addUrlParam(hash, 'topic', topic) : _lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].removeUrlParam(hash, 'topic');
|
hash = topic ? _lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].addUrlParam(hash, 'topic', topic) : _lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].removeUrlParam(hash, 'topic');
|
||||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].navigateTo(hash);
|
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].navigateTo(hash);
|
||||||
};
|
};
|
||||||
const navigateToProfile = (userId, member) => {
|
const navigateToProfile = (topic, userId, member) => {
|
||||||
if (member && userId) {
|
if (member && userId) {
|
||||||
(0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_5__.writeCachedData)('profile-seed:' + userId, {
|
(0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_5__.writeCachedData)('profile-seed:' + userId, {
|
||||||
user_id: userId,
|
user_id: userId,
|
||||||
@@ -10495,6 +10506,20 @@ const navigateToProfile = (userId, member) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].addUrlParam(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].setUrlSidePanel(window.location.hash, 'group-member-profile'), 'uid', userId));
|
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].addUrlParam(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_3__["default"].setUrlSidePanel(window.location.hash, 'group-member-profile'), 'uid', userId));
|
||||||
|
if (topic && userId) {
|
||||||
|
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_4__.getGroupMemberProfile)(topic, userId).then(real => {
|
||||||
|
const current = (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_5__.readCachedData)('profile-seed:' + userId) || {};
|
||||||
|
(0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_5__.writeCachedData)('profile-seed:' + userId, {
|
||||||
|
...current,
|
||||||
|
...real
|
||||||
|
});
|
||||||
|
window.dispatchEvent(new CustomEvent('profile-seed-updated', {
|
||||||
|
detail: {
|
||||||
|
uid: userId
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const GROUP_MANAGEMENT_VIEWS = ['group-list', 'group-empty', 'group-invite', 'group-events', 'group-join-requests', 'group-new-request', 'group-announcement', 'group-summary', 'group-announcement-detail', 'group-settings', 'group-profile', 'group-avatar', 'group-nickname', 'group-description', 'group-my-nickname', 'group-role-message', 'group-qr', 'group-governance', 'group-admins', 'group-admin-add', 'group-admin-success', 'group-admin-partial', 'group-admin-removed', 'group-mute-add', 'group-muted', 'group-owner-select', 'group-owner-confirm', 'group-files', 'group-file-upload'];
|
const GROUP_MANAGEMENT_VIEWS = ['group-list', 'group-empty', 'group-invite', 'group-events', 'group-join-requests', 'group-new-request', 'group-announcement', 'group-summary', 'group-announcement-detail', 'group-settings', 'group-profile', 'group-avatar', 'group-nickname', 'group-description', 'group-my-nickname', 'group-role-message', 'group-qr', 'group-governance', 'group-admins', 'group-admin-add', 'group-admin-success', 'group-admin-partial', 'group-admin-removed', 'group-mute-add', 'group-muted', 'group-owner-select', 'group-owner-confirm', 'group-files', 'group-file-upload'];
|
||||||
function alphaInitial(name) {
|
function alphaInitial(name) {
|
||||||
@@ -11303,7 +11328,7 @@ function GroupSettings({
|
|||||||
className: "group-member-grid",
|
className: "group-member-grid",
|
||||||
children: [members.slice(0, 9).map(item => (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
children: [members.slice(0, 9).map(item => (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||||
type: "button",
|
type: "button",
|
||||||
onClick: () => navigateToProfile(item.user_id, item),
|
onClick: () => navigateToProfile(topic, item.user_id, item),
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Avatar, {
|
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Avatar, {
|
||||||
item: item,
|
item: item,
|
||||||
icon: "person"
|
icon: "person"
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user