补上好友申请前后关系状态聊天页的入口,并把验证留言渲染成真实消息气泡
第3章要求pending_inbound/pending_outbound/none/blocked几种关系状态都能在真实聊天 窗口里看到(参考图 个人对话框(对方的状态)/(我的状态).png、开启沟通页面.png)。 messages-view.jsx里对应的横幅逻辑("以上是打招呼的消息"/"好友申请正在等待处理"等) 本身早就是对的,但排查发现两个问题: 1. 全项目没有任何入口能导航进这个视图——"新朋友"列表(FriendRequests)每一行没有 onClick;好友个人主页(Profile)非好友分支只显示一段cannotAddReason纯文字,没有 任何可点击进聊天的按钮。发起方和接收方在成为好友之前都完全看不到这个视图。 2. 验证留言原文(发好友申请时填的那段话,存在im_friend_requests表的message字段, 不是真实Tinode消息,没有走topic.publish())没有被当作消息渲染出来,参考图里 明确是作为聊天页第一条消息气泡展示的。 修复: - contact-management-view.jsx: FriendRequests每一行加onClick,用(onCreateTopic|| onTopicSelected)跳进对应聊天(同一套Profile.openChat已经验证过的冷启动安全写法, 接受/拒绝按钮补stopPropagation不受影响);Profile非好友分支(blocked_by_peer/ blocked_by_me/pending_inbound/pending_outbound)补一个"查看聊天"按钮,跟 cannotAddReason文字并排展示(不复用people-profile-actions的两列grid,那是给 发消息+音视频通话两个平级按钮设计的)。ContactManagementView/sidepanel-view.jsx 早前就已经把onCreateTopic透传到位,这次只是多接一层。 - messages-view.jsx: loadRelationshipContext新增loadPendingRequestMessage, relationship是pending_inbound/pending_outbound时,用relationshipContext自带的 request_id去GET /friend-requests换真实留言文本(没有留言用参考图默认文案"请求 添加你为好友"兜底),渲染成一条合成的消息气泡插在消息列表最前面(不进 messageNodes、不调用发消息接口)——pending_inbound左对齐、pending_outbound右 对齐,气泡样式直接复用chat-message.jsx真实消息已经在用的.bubble/.left/.right 这套CSS(app里"发出的"气泡实际是这套已实现的浅色而非参考图的蓝色,保持跟同一 会话里其它真实消息一致,不単独改这一条的颜色去凑旧版参考图)。 验证:真实两个新账号(vcm909641发起→hankqa14b接收)走了一遍完整流程—— 从"新朋友"列表点击行正确进入聊天页,留言气泡+"以上是打招呼的消息"横幅正确显示; 从Profile页"查看聊天"进入,留言气泡右对齐+"好友申请正在等待处理"横幅正确显示; 点"通过验证"接受申请后正确留在列表页不误触发导航;接受后重新打开同一会话, 合成气泡正确消失,被真实的"你们已成为好友,现在可以开始聊天了。"系统消息取代, 无残留/无重复。
This commit is contained in:
@@ -172,7 +172,7 @@ function requestStatusLabel(item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function FriendRequests({onToast}) {
|
||||
function FriendRequests({onToast, onTopicSelected, onCreateTopic}) {
|
||||
const [items, setItems] = React.useState([]);
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [loadError, setLoadError] = React.useState(false);
|
||||
@@ -189,13 +189,19 @@ function FriendRequests({onToast}) {
|
||||
onToast(err.message || '操作失败');
|
||||
});
|
||||
};
|
||||
// 参考图 个人对话框(对方的状态)/(我的状态).png:申请的验证留言应该在真实聊天窗口里以消息
|
||||
// 气泡展示,横幅提示("以上是打招呼的消息"/"好友申请正在等待处理")已经在 messages-view.jsx
|
||||
// 里做对了,但这个列表原来每一行完全没有 onClick,点了毫无反应——点进去看这条留言/横幅的入口
|
||||
// 一直不存在。跟 Profile 的 openChat 用同一个"优先走 onCreateTopic 保证冷启动也能订阅"的写法。
|
||||
const openChat = item => (onCreateTopic || onTopicSelected) &&
|
||||
(onCreateTopic || onTopicSelected)(item.direction === 'inbound' ? item.applicant_id : item.target_user_id);
|
||||
return <div className="people-page"><Header title="新朋友" back="address-book" /><main className="people-request-list">
|
||||
{loading ? <p className="people-empty-hint">加载中…</p> : items.length === 0 ? <p className="people-empty-hint">{loadError ? '加载失败,请重试' : '暂无新朋友申请'}</p> : null}
|
||||
{items.map(item => <article key={item.request_id}>
|
||||
{items.map(item => <article key={item.request_id} role="button" tabIndex={0} onClick={() => openChat(item)}>
|
||||
<Avatar person={item.peer} />
|
||||
<div><strong>{(item.peer && item.peer.display_name) || item.applicant_id}</strong><p>{item.message || '请求添加您为好友'}</p><small>{new Date(item.created_at).toLocaleString()}</small></div>
|
||||
{item.status === 'pending' && item.direction === 'inbound' ?
|
||||
<span><button type="button" onClick={() => handle(item, false)}>拒绝</button><button type="button" className="primary" onClick={() => handle(item, true)}>通过验证</button></span> :
|
||||
<span><button type="button" onClick={e => { e.stopPropagation(); handle(item, false); }}>拒绝</button><button type="button" className="primary" onClick={e => { e.stopPropagation(); handle(item, true); }}>通过验证</button></span> :
|
||||
<em>{requestStatusLabel(item)}</em>}
|
||||
</article>)}
|
||||
</main></div>;
|
||||
@@ -511,7 +517,17 @@ function Profile({uid, friend, onTopicSelected, onCreateTopic, onToast}) {
|
||||
<button type="button" onClick={openChat}><Icon>call</Icon>音视频通话</button>
|
||||
</div> :
|
||||
canAdd ? <button type="button" className="people-primary" onClick={() => navigate('friend-verification', uid)}><Icon>person_add_alt</Icon>添加好友</button> :
|
||||
<p className="people-empty-hint">{cannotAddReason}</p>}
|
||||
// cannotAddReason 覆盖的四种关系(blocked_by_peer/blocked_by_me/pending_inbound/
|
||||
// pending_outbound)在 messages-view.jsx 里都已经有对应的、真实可用的聊天视图(对方发来的
|
||||
// 留言气泡+"以上是打招呼的消息"横幅,或"好友申请正在等待处理"横幅,或拉黑后仍可输入、发送
|
||||
// 失败再展示具体原因)——原来这个非好友分支只显示 cannotAddReason 这段纯文字,没有任何
|
||||
// 入口能点进去看。同一套 openChat(优先 onCreateTopic 保证冷启动)。按钮不套进
|
||||
// .people-profile-actions 的两列grid(那是给"发消息+音视频通话"两个平级按钮设计的),
|
||||
// 单独一个满宽按钮,跟上面纯文字提示分两行。
|
||||
<>
|
||||
<p className="people-empty-hint">{cannotAddReason}</p>
|
||||
<button type="button" className="people-primary" onClick={openChat}><Icon>chat_bubble_outline</Icon>查看聊天</button>
|
||||
</>}
|
||||
</main>
|
||||
</div>;
|
||||
}
|
||||
@@ -674,7 +690,7 @@ export default function ContactManagementView({view, hashParams, myUserId, tinod
|
||||
const uid = hashParams && hashParams.uid;
|
||||
let content;
|
||||
if (view === 'address-book') content = <AddressBook myUserId={myUserId} onTopicSelected={onTopicSelected} />;
|
||||
else if (view === 'friend-requests') content = <FriendRequests onToast={setToast} />;
|
||||
else if (view === 'friend-requests') content = <FriendRequests onToast={setToast} onTopicSelected={onTopicSelected} onCreateTopic={onCreateTopic} />;
|
||||
else if (view === 'add-friend' || view === 'friend-search-result') content = <AddFriend result={view === 'friend-search-result'} onToast={setToast} onOpenScanner={onOpenScanner} />;
|
||||
else if (view === 'my-friend-qr') content = <QrPage onToast={setToast} />;
|
||||
else if (view === 'friend-qr') content = <FriendQr uid={uid} onToast={setToast} />;
|
||||
|
||||
Reference in New Issue
Block a user