fix(categories): correct all seven smart-folder bugs at the source (PHASE 2)
CI / backend (pull_request) Successful in 56s
CI / frontend (pull_request) Successful in 12s
CI / format (pull_request) Successful in 52s
CI / db-tests (pull_request) Successful in 57s
Security / secrets (pull_request) Successful in 3s
Security / dependencies (pull_request) Successful in 57s
Security / sast (pull_request) Successful in 37s
CI / backend (pull_request) Successful in 56s
CI / frontend (pull_request) Successful in 12s
CI / format (pull_request) Successful in 52s
CI / db-tests (pull_request) Successful in 57s
Security / secrets (pull_request) Successful in 3s
Security / dependencies (pull_request) Successful in 57s
Security / sast (pull_request) Successful in 37s
Root causes + fixes: - Archive leaked Sent mail: filter was just 'not in inbox'. Added ExcludeGmailLabels; Archive now excludes SENT/DRAFT/SPAM/TRASH/CHAT by label. - Read Later / Pinned / Unlabelled returned EVERYTHING (no folder case -> default all). Pinned = IsImportant; Read Later = new local IsReadLater marker (+toggle endpoints); Unlabelled = HasUserLabels=false. - Trash & Spam always empty: IncludeSpamTrash=false + sync never set IsTrashed nor created EmailLabel rows. Now fetches spam/trash, sets IsTrashed from the TRASH label, and links every message to its Gmail labels (also fixes Sent/Spam/category-by-label/Unlabelled). - Old Mail: now strictly older than 6 months (was 1 year). Guardrail: sync upsert is now idempotent (drops prior copy before reinsert) so re-sync can't duplicate a message or leave stale labels. 4 new filter tests; 65 backend + frontend green; migration is a single non-destructive column add. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -94,13 +94,22 @@ function folderToRequest(slug, page, pageSize) {
|
||||
case 'starred': return { ...base, isStarred: true };
|
||||
case 'sent': return { ...base, gmailLabel: 'SENT' };
|
||||
case 'drafts': return { ...base, gmailLabel: 'DRAFT' };
|
||||
case 'archive': return { ...base, isInInbox: false, isTrashed: false };
|
||||
// Archive = filed away: not in inbox, not trashed, and NOT Sent/Spam/Draft/Chat.
|
||||
// Excluding those labels stops sent mail leaking into Archive.
|
||||
case 'archive': return { ...base, isInInbox: false, isTrashed: false, excludeGmailLabels: ['SENT', 'DRAFT', 'SPAM', 'TRASH', 'CHAT'] };
|
||||
case 'spam': return { ...base, gmailLabel: 'SPAM' };
|
||||
case 'trash': return { ...base, isTrashed: true };
|
||||
// Pinned = Gmail's "Important" marker (a real per-message flag), not "everything".
|
||||
case 'pinned': return { ...base, isImportant: true };
|
||||
// Read Later = only emails the user explicitly flagged (local marker).
|
||||
case 'readlater': return { ...base, isReadLater: true };
|
||||
// Unlabelled = emails not filed under any user-created label.
|
||||
case 'unlabelled': return { ...base, hasUserLabels: false };
|
||||
// ── Special filters ──
|
||||
case 'large': return { ...base, minSizeBytes: 5_000_000 };
|
||||
// Old Mail = strictly older than 6 months.
|
||||
case 'old': {
|
||||
const d = new Date(); d.setFullYear(d.getFullYear() - 1);
|
||||
const d = new Date(); d.setMonth(d.getMonth() - 6);
|
||||
return { ...base, to: d.toISOString().slice(0, 10) };
|
||||
}
|
||||
// ── Smart folders ──
|
||||
|
||||
Reference in New Issue
Block a user