mail list redesign, folder actions, empty-folder, unread badges & empty-state art
Frontend:
- Redesign the mail list rows (avatar + sender + subject/snippet + right rail),
even-spaced attachment/pin/archive/trash icons, hover-reveal actions, pink
always-on pin, monocolor paperclip, row gaps, wider sender-subject gap.
- Sidebar folder badges: Inbox unread + Drafts counts (live via WS + mutations).
- Trash/Spam/Archive: hover Restore icon (replaces Archive), permanent delete in
Trash; "Empty trash" / "Empty spam" buttons on the sort bar.
- Reading pane empty state: email illustration above an enlarged
"Select a conversation".
- Search field clear (X) button; mark-read after a 4s dwell instead of instantly.
Backend:
- GET /api/mailboxes/counts (inbox unread + drafts) for the sidebar badges.
- POST /api/folders/{special}/empty + empty_folder_job to permanently clear a
Trash/Spam/Archive folder (server EXPUNGE + DB rows + thread cleanup).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U72FZiF1W1pb8XxyWBTREA
This commit is contained in:
@@ -423,6 +423,8 @@ export function ThreadView({
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["thread"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["threads"] });
|
||||
// Mark read/unread changes the Inbox unread badge.
|
||||
queryClient.invalidateQueries({ queryKey: ["folder-counts"] });
|
||||
},
|
||||
});
|
||||
const move = useMutation({
|
||||
@@ -431,6 +433,7 @@ export function ThreadView({
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["thread"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["threads"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["folder-counts"] });
|
||||
},
|
||||
});
|
||||
|
||||
@@ -518,7 +521,7 @@ export function ThreadView({
|
||||
className="rounded p-1.5 text-app-muted hover:bg-app-hover hover:text-app-fg"
|
||||
title={t("mail.print")}
|
||||
aria-label={t("mail.print")}
|
||||
onClick={() => void printMessages(subject, messages)}
|
||||
onClick={() => void printMessages(subject, visual)}
|
||||
>
|
||||
<Icon name="print" size={16} />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user