From e9806b4a2a5ba30cce4d3e053ec99284a665eea8 Mon Sep 17 00:00:00 2001 From: zxyszx <299979470+zxyszx@users.noreply.github.com> Date: Sun, 2 Aug 2026 11:42:21 +0800 Subject: [PATCH] fix: tighten unread states and mail width --- apps/web/src/index.css | 2 +- apps/web/src/pages/mail.tsx | 44 ++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 8c22cf5..8b20330 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -103,7 +103,7 @@ border-right: 1px solid hsl(var(--border)); } - @media (max-width: 1179px) { + @media (max-width: 979px) { .mail-content-grid { grid-template-columns: minmax(0, 1fr); } diff --git a/apps/web/src/pages/mail.tsx b/apps/web/src/pages/mail.tsx index 819ad6b..33e195a 100644 --- a/apps/web/src/pages/mail.tsx +++ b/apps/web/src/pages/mail.tsx @@ -89,7 +89,7 @@ const emptyAdvancedSearch: AdvancedMailSearch = { from: "", to: "", subject: "", const emptyAdvancedSearchDraft: AdvancedMailSearchDraft = { ...emptyAdvancedSearch } const mailboxSelectionStorageVersion = "2" const mailCompactBreakpoint = 768 -const mailDetailBreakpoint = 1180 +const mailDetailBreakpoint = 980 function useMaxViewportWidth(maxWidth: number) { const [matches, setMatches] = React.useState(false) @@ -285,6 +285,7 @@ export function MailPage() { await qc.invalidateQueries({ queryKey: ["messages"] }) await qc.invalidateQueries({ queryKey: ["message", variables.id] }) await qc.invalidateQueries({ queryKey: ["folders"] }) + await qc.invalidateQueries({ queryKey: ["mailboxes"] }) await qc.invalidateQueries({ queryKey: ["mail-stats"] }) }, onError: (error) => toast({ title: "操作失败", description: error.message }), @@ -377,8 +378,8 @@ export function MailPage() { }, onSettled: () => { qc.invalidateQueries({ queryKey: ["labels"] }); qc.invalidateQueries({ queryKey: ["messages"] }) }, }) - const del = useMutation({ mutationFn: (id: string) => api.delete(id), onSuccess: async () => { setSelectedId(null); setPendingConfirm(null); await qc.invalidateQueries({ queryKey: ["messages"] }); await qc.invalidateQueries({ queryKey: ["folders"] }); await qc.invalidateQueries({ queryKey: ["mail-stats"] }); await qc.invalidateQueries({ queryKey: ["labels"] }); toast({ title: "已删除" }) }, onError: (error) => toast({ title: "删除失败", description: error.message }) }) - const move = useMutation({ mutationFn: ({ id, folder }: { id: string; folder: string }) => api.move(id, folder), onSuccess: async () => { setSelectedId(null); await qc.invalidateQueries({ queryKey: ["messages"] }); await qc.invalidateQueries({ queryKey: ["folders"] }); await qc.invalidateQueries({ queryKey: ["mail-stats"] }); await qc.invalidateQueries({ queryKey: ["labels"] }); toast({ title: "已移动" }) } }) + const del = useMutation({ mutationFn: (id: string) => api.delete(id), onSuccess: async () => { setSelectedId(null); setPendingConfirm(null); await qc.invalidateQueries({ queryKey: ["messages"] }); await qc.invalidateQueries({ queryKey: ["folders"] }); await qc.invalidateQueries({ queryKey: ["mailboxes"] }); await qc.invalidateQueries({ queryKey: ["mail-stats"] }); await qc.invalidateQueries({ queryKey: ["labels"] }); toast({ title: "已删除" }) }, onError: (error) => toast({ title: "删除失败", description: error.message }) }) + const move = useMutation({ mutationFn: ({ id, folder }: { id: string; folder: string }) => api.move(id, folder), onSuccess: async () => { setSelectedId(null); await qc.invalidateQueries({ queryKey: ["messages"] }); await qc.invalidateQueries({ queryKey: ["folders"] }); await qc.invalidateQueries({ queryKey: ["mailboxes"] }); await qc.invalidateQueries({ queryKey: ["mail-stats"] }); await qc.invalidateQueries({ queryKey: ["labels"] }); toast({ title: "已移动" }) } }) const cancelScheduledSend = useMutation({ mutationFn: (item: ScheduledSend) => api.cancelScheduledSend(item.id), onMutate: (item) => setCancelingScheduledId(item.id), @@ -466,6 +467,7 @@ export function MailPage() { onSuccess: async (count) => { await qc.invalidateQueries({ queryKey: ["messages"] }) await qc.invalidateQueries({ queryKey: ["folders"] }) + await qc.invalidateQueries({ queryKey: ["mailboxes"] }) await qc.invalidateQueries({ queryKey: ["mail-stats"] }) await qc.invalidateQueries({ queryKey: ["labels"] }) toast({ title: count > 0 ? `已标记 ${count} 封邮件为已读` : "当前没有未读邮件" }) @@ -668,6 +670,7 @@ export function MailPage() { qc.invalidateQueries({ queryKey: ["mail-external-folders"] }), qc.invalidateQueries({ queryKey: ["mail-external-accounts"] }), qc.invalidateQueries({ queryKey: ["folders"] }), + qc.invalidateQueries({ queryKey: ["mailboxes"] }), qc.invalidateQueries({ queryKey: ["mail-stats"] }), qc.invalidateQueries({ queryKey: ["labels"] }), qc.invalidateQueries({ queryKey: ["scheduled-sends"] }), @@ -1439,7 +1442,7 @@ export function MailPage() { /> ) : (
-
+
@@ -1497,7 +1500,7 @@ export function MailPage() { {canOrganizeMail && } - +
@@ -1527,7 +1530,7 @@ export function MailPage() {
-
+
{!selectedId && (
@@ -2959,7 +2962,11 @@ function CompactMessageRow({ message, active, checked, scheduled, onCheckedChang const hiddenLabelCount = Math.max((message.labels?.length || 0) - visibleLabels.length, 0) const senderName = senderDisplayName(message) return ( -
+
onCheckedChange(value === true)} onClick={(event) => event.stopPropagation()} className="mt-0.5 shrink-0 sm:mt-0" /> {message.isRead ? ( @@ -2969,7 +2976,10 @@ function CompactMessageRow({ message, active, checked, scheduled, onCheckedChang )}
-
{senderName}
+
+
{senderName}
+ {!message.isRead && } +
{formatDate(message.receivedAt)} {canOrganize &&
-
{message.snippet}
+
{message.snippet}
{formatDate(message.receivedAt)}
@@ -3098,7 +3108,7 @@ function MailboxSwitcher({ collapsed, mailboxes, selectedMailboxId, selectedMail const [mailboxQuery, setMailboxQuery] = React.useState("") const isAllSelected = selectedMailboxId === "all" const displayAddress = isAllSelected ? "全部邮箱" : selectedMailbox?.address || fallbackAddress || "选择邮箱" - const selectedUnreadCount = isAllSelected ? unreadCount : selectedMailbox?.unreadCount || 0 + const selectedUnreadCount = isAllSelected ? unreadCount : (selectedMailbox?.unreadCount ?? unreadCount) const normalizedQuery = mailboxQuery.trim().toLowerCase() const showAllMailboxOption = !normalizedQuery || "全部邮箱".includes(normalizedQuery) || "all".includes(normalizedQuery) const filteredMailboxes = React.useMemo(() => { @@ -3385,7 +3395,12 @@ function MessageRow({ const quickActionsVisible = checked || active const quickButtonClass = "h-6 w-6 text-muted-foreground hover:bg-accent hover:text-foreground" const archiveLabel = message.folder === "Archive" ? "移回收件箱" : "归档" - return
+ return
-
{senderName}
+
+
{senderName}
+ {!message.isRead && } +
{canOrganize && (
@@ -3431,7 +3449,7 @@ function MessageRow({ {hiddenLabelCount > 0 && +{hiddenLabelCount}} {message.hasAttachments && }
-
{message.snippet}
+
{message.snippet}