修复收藏/系统消息/通话记录批次的代码审查问题

- 通话结果"已拒绝"文案按视角区分(拒绝方看到"已拒绝"而非"对方已拒绝")
- 通话记录页补充移动端返回头部与加载失败重试态
- 挂断时按是否已接通传递正确的挂断原因(cancelled)
- 系统消息"全部标为已读"翻页加循环护栏,防止游标卡死;按钮可见性改用真实未读总数
- 收藏批量删除/转发在部分失败时保留失败项以便重试,而非无条件退出多选模式
- 收藏卡片边框/分类文字/侧栏图标颜色token修正
This commit is contained in:
Your Name
2026-09-16 12:54:40 +08:00
parent 97e8d7144f
commit 29a1f1c2fd
5 changed files with 67 additions and 14 deletions
+20 -2
View File
@@ -1,5 +1,5 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { Link, useNavigate } from 'react-router-dom';
import { Icon } from '@/app/Icon';
import { getCallHistory, type CallHistoryItem } from '@/lib/api/calls';
@@ -45,12 +45,30 @@ export function CallHistoryView() {
return (
<div className="flex h-full w-full flex-col overflow-y-auto bg-surface-content">
<header className="flex h-15 flex-none items-center border-b border-border-panel bg-white px-6">
{/* `/calls`, like `/favorites`, is only reachable on a narrow viewport via 设置(我的)>通话记录
(SettingsLayout.tsx's MOBILE_SHORTCUTS) -- same "back returns there" convention
FavoritesLayout's own mobile header already uses, and the same gap this file didn't have
until now (there was no way back from here at all short of a system back gesture). */}
<header className="grid h-15 flex-none grid-cols-[44px_1fr_44px] items-center border-b border-border-panel bg-white px-1 md:hidden">
<Link to="/settings" className="grid h-9 w-9 place-items-center text-text-heading">
<Icon name="arrow_back_ios_new" className="text-[18px]" />
</Link>
<strong className="truncate text-center text-base font-semibold text-text-heading">通话记录</strong>
<span />
</header>
<header className="hidden h-15 flex-none items-center border-b border-border-panel bg-white px-6 md:flex">
<strong className="text-base font-semibold text-text-heading">通话记录</strong>
</header>
<div className="flex flex-col gap-2 p-6">
{query.isLoading ? (
<div className="py-10 text-center text-sm text-text-tertiary-4">加载中…</div>
) : query.isError ? (
<div className="flex flex-col items-center gap-2 py-10 text-sm text-danger-text">
<span>加载失败,请重试</span>
<button type="button" onClick={() => query.refetch()} className="text-accent">
重试
</button>
</div>
) : items.length === 0 ? (
<div className="py-10 text-center text-sm text-text-tertiary-4">暂无通话记录</div>
) : (
+4 -1
View File
@@ -375,8 +375,11 @@ function EndedCallOverlay() {
return { label: durationMs > 0 ? `通话时长 ${formatCallDuration(durationMs)}` : '通话已结束', danger: false };
case 'missed':
return { label: wasCaller ? '对方未接听,已取消' : '未接听', danger: true };
// `wasCaller` here is `false` exactly when this device is the one that just clicked
// "拒绝" (rejectCall() only runs during `phase==='incoming'`) -- same distinction `missed`
// right above already makes, "对方已拒绝" is backwards on the decliner's own screen.
case 'declined':
return { label: '对方已拒绝', danger: true };
return { label: wasCaller ? '对方已拒绝' : '已拒绝', danger: true };
case 'disconnected':
return { label: '通话连接异常,已结束', danger: true };
case 'busy':