import type { Email } from "@/lib/email-data" import { applyLabelEditsToEmails, mergeEmailNotSpam } from "@/lib/label-edits" import { emailMatchesFolder, type MailFolderFilterCtx, type MailNavFolderMaps, } from "@/lib/mail-folder-filter" import type { LabelEditState } from "@/lib/stores/mail-store" import { folderTree as defaultFolderTree, sidebarNavFolderIdToLabel, type FolderTreeNode, } from "@/lib/sidebar-nav-data" export const MAIN_NAV_FOLDER_IDS = [ "inbox", "starred", "snoozed", "important", "sent", "drafts", "scheduled", "spam", ] as const export const CATEGORY_NAV_IDS = [ "purchases", "travel", "social", "notifications", "updates", "forums", "finance", "promotions", ] as const function collectTreeIds(nodes: FolderTreeNode[]): string[] { const out: string[] = [] for (const n of nodes) { out.push(n.id) if (n.children?.length) out.push(...collectTreeIds(n.children)) } return out } const MAIN_SET = new Set(MAIN_NAV_FOLDER_IDS) const CATEGORY_SET = new Set(CATEGORY_NAV_IDS) /** Tous les ids de lignes sidebar pour lesquelles on calcule un décompte « non lus ». */ export function allSidebarNavFolderIds(maps?: MailNavFolderMaps | null): string[] { const tree = maps?.folderTree ?? defaultFolderTree const idToLabel = maps?.folderIdToLabel ?? (sidebarNavFolderIdToLabel as Record) const treeIds = collectTreeIds(tree) const labelRowIds = Object.keys(idToLabel).filter((id) => { if (MAIN_SET.has(id) || CATEGORY_SET.has(id)) return false if (id === "scheduled") return false if (treeIds.includes(id)) return false return true }) return [...MAIN_NAV_FOLDER_IDS, ...CATEGORY_NAV_IDS, ...treeIds, ...labelRowIds] } function effectiveRead( email: Email, readOverrides: Record ): boolean { return readOverrides[email.id] !== undefined ? readOverrides[email.id]! : email.read } export function countUnreadInFolder( allEmails: Email[], folderId: string, ctx: MailFolderFilterCtx, hiddenIds: Set, readOverrides: Record, maps?: MailNavFolderMaps | null ): number { if (folderId === "scheduled" || folderId === "snoozed") { let n = 0 for (const e of allEmails) { if (hiddenIds.has(e.id)) continue if (!emailMatchesFolder(e, folderId, ctx, maps)) continue n++ } return n } let n = 0 for (const e of allEmails) { if (hiddenIds.has(e.id)) continue if (!emailMatchesFolder(e, folderId, ctx, maps)) continue if (!effectiveRead(e, readOverrides)) n++ } return n } export function computeFolderUnreadCounts( allEmails: Email[], ctx: MailFolderFilterCtx, hiddenEmailIds: string[], readOverrides: Record, maps?: MailNavFolderMaps | null, labelEdits?: LabelEditState, notSpamEmailIds?: readonly string[] ): Record { let pool = labelEdits && (Object.keys(labelEdits.additions).length > 0 || Object.keys(labelEdits.removals).length > 0) ? applyLabelEditsToEmails(allEmails, labelEdits) : allEmails pool = pool.map((e) => mergeEmailNotSpam(e, notSpamEmailIds ?? [])) const hidden = new Set(hiddenEmailIds) const out: Record = {} for (const id of allSidebarNavFolderIds(maps)) { out[id] = countUnreadInFolder(pool, id, ctx, hidden, readOverrides, maps) } return out }