通讯录/新朋友/黑名单列表区分"加载失败"与"真的是空"
三处都用 .catch(() => {}) 吞掉网络错误,loading 结束后空数组直接落到
"暂无好友"/"暂无新朋友申请"/"黑名单为空",加载失败和真的没数据在界面
上无法区分。改成 group-management-view.jsx 里 11 处同类组件已经在用
的 loadError 状态模式。
第十轮最小粒度测试 Ch5-6 发现。
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
4dbe76f2bd
commit
89fdd31cd4
@@ -106,6 +106,7 @@ function AddressBook({myUserId, onTopicSelected}) {
|
||||
const [friends, setFriends] = React.useState(() => (friendsCacheKey && readCachedData(friendsCacheKey)) || []);
|
||||
const [pendingCount, setPendingCount] = React.useState(0);
|
||||
const [loading, setLoading] = React.useState(() => !(friendsCacheKey && readCachedData(friendsCacheKey)));
|
||||
const [loadError, setLoadError] = React.useState(false);
|
||||
// Same bootstrap the message center already fetches (and caches under the same key) -- only need
|
||||
// it here for the file assistant's real topic, so a plain read of the shared cache is enough.
|
||||
const [bootstrap] = useCachedData(myUserId ? 'bootstrap:' + myUserId : null, getBootstrap, [myUserId]);
|
||||
@@ -117,7 +118,7 @@ function AddressBook({myUserId, onTopicSelected}) {
|
||||
fetchAllPages(cursor => getFriends('', cursor)).then(list => {
|
||||
if (friendsCacheKey) { writeCachedData(friendsCacheKey, list); }
|
||||
setFriends(list);
|
||||
}).catch(() => {}).finally(() => setLoading(false));
|
||||
}).catch(() => setLoadError(true)).finally(() => setLoading(false));
|
||||
fetchAllPages(cursor => getFriendRequests('inbound', 'pending', cursor))
|
||||
.then(list => setPendingCount(list.length)).catch(() => {});
|
||||
}, []);
|
||||
@@ -148,7 +149,7 @@ function AddressBook({myUserId, onTopicSelected}) {
|
||||
<main className="people-scroll">
|
||||
<section className="people-entry-list">{entries.map(item => <button type="button" key={item.label} onClick={() => openEntry(item)}><Avatar icon={item.icon} /><strong>{item.label}</strong>{item.badge ? <em>{item.badge}</em> : null}<Icon>chevron_right</Icon></button>)}</section>
|
||||
<h3 className="people-section-title">好友通讯录</h3>
|
||||
{loading ? <p className="people-empty-hint">加载中…</p> : sortedKeys.length === 0 ? <p className="people-empty-hint">暂无好友</p> : null}
|
||||
{loading ? <p className="people-empty-hint">加载中…</p> : sortedKeys.length === 0 ? <p className="people-empty-hint">{loadError ? '通讯录加载失败' : '暂无好友'}</p> : null}
|
||||
{sortedKeys.map(initial => <section className="people-group" id={'people-group-' + initial} key={initial}><h2>{initial}</h2>
|
||||
{groups[initial].map(person => <button type="button" key={person.user_id} onClick={() => { seedProfile(person); navigate('friend-profile', person.user_id); }}>
|
||||
{/* 副行只在确实是另一个名字时才显示。后端在有备注时会把 display_name 也设成备注
|
||||
@@ -174,9 +175,10 @@ function requestStatusLabel(item) {
|
||||
function FriendRequests({onToast}) {
|
||||
const [items, setItems] = React.useState([]);
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [loadError, setLoadError] = React.useState(false);
|
||||
React.useEffect(() => {
|
||||
fetchAllPages(cursor => getFriendRequests('all', 'all', cursor))
|
||||
.then(setItems).catch(() => {}).finally(() => setLoading(false));
|
||||
.then(setItems).catch(() => setLoadError(true)).finally(() => setLoading(false));
|
||||
}, []);
|
||||
const handle = (item, accept) => {
|
||||
const nextStatus = accept ? 'accepted' : 'rejected';
|
||||
@@ -188,7 +190,7 @@ function FriendRequests({onToast}) {
|
||||
});
|
||||
};
|
||||
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">暂无新朋友申请</p> : null}
|
||||
{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}>
|
||||
<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>
|
||||
@@ -574,8 +576,9 @@ function Settings({uid, initialBlocked, pinBlocked, onToast}) {
|
||||
function BlockList({onToast}) {
|
||||
const [people, setPeople] = React.useState([]);
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [loadError, setLoadError] = React.useState(false);
|
||||
React.useEffect(() => {
|
||||
fetchAllPages(cursor => getBlocks(cursor)).then(setPeople).catch(() => {}).finally(() => setLoading(false));
|
||||
fetchAllPages(cursor => getBlocks(cursor)).then(setPeople).catch(() => setLoadError(true)).finally(() => setLoading(false));
|
||||
}, []);
|
||||
const remove = userId => {
|
||||
unblockUser(userId).then(() => { setPeople(items => items.filter(item => item.user_id !== userId)); onToast('已移出黑名单'); })
|
||||
@@ -586,7 +589,7 @@ function BlockList({onToast}) {
|
||||
return <div className="people-page"><Header title="黑名单" back="android-settings" /><main className="people-block-list">
|
||||
{loading ? <p className="people-empty-hint">加载中…</p> : people.length ?
|
||||
people.map(item => <article key={item.user_id}><Avatar person={item.user} /><span><strong>{(item.user && item.user.display_name) || item.user_id}</strong><small>已阻止消息和通话</small></span><button type="button" onClick={() => remove(item.user_id)}>移出</button></article>) :
|
||||
<div className="people-empty"><Icon>person_off</Icon><strong>黑名单为空</strong></div>}
|
||||
<div className="people-empty"><Icon>person_off</Icon><strong>{loadError ? '黑名单加载失败' : '黑名单为空'}</strong></div>}
|
||||
</main></div>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user