137 lines
3.7 KiB
TypeScript
137 lines
3.7 KiB
TypeScript
import type { Email } from "@/lib/email-data"
|
|
import {
|
|
folderTree as defaultFolderTree,
|
|
sidebarNavFolderIdToLabel as defaultSidebarNavFolderIdToLabel,
|
|
type FolderTreeNode,
|
|
} from "@/lib/sidebar-nav-data"
|
|
import { collectSubtreeFolderIds } from "@/lib/sidebar-nav-maps"
|
|
|
|
export type MailFolderFilterCtx = {
|
|
starredEmailIds: string[]
|
|
importantEmailIds: string[]
|
|
}
|
|
|
|
/** Carte navigation dynamique (sidebar). Si absent, valeurs par défaut du module. */
|
|
export type MailNavFolderMaps = {
|
|
folderIdToLabel: Record<string, string>
|
|
folderTree: FolderTreeNode[]
|
|
}
|
|
|
|
const CATEGORY_EMAIL_TAB_IDS = new Set([
|
|
"social",
|
|
"promotions",
|
|
"updates",
|
|
"forums",
|
|
])
|
|
|
|
/** Catégories latérales (sidebar) → libellé optionnel sur `email.labels`. */
|
|
const SIDEBAR_CATEGORY_EXTRA_LABEL: Partial<Record<string, string>> = {
|
|
purchases: "Achats",
|
|
travel: "Déplacements",
|
|
finance: "Finance",
|
|
}
|
|
|
|
function effectiveStarred(email: Email, ctx: MailFolderFilterCtx): boolean {
|
|
return ctx.starredEmailIds.includes(email.id) || email.starred
|
|
}
|
|
|
|
function effectiveImportant(email: Email, ctx: MailFolderFilterCtx): boolean {
|
|
return ctx.importantEmailIds.includes(email.id) || email.important
|
|
}
|
|
|
|
function isInInbox(email: Email): boolean {
|
|
if (email.spam) return false
|
|
const ls = email.labels
|
|
if (!ls?.length) return true
|
|
return ls.includes("inbox")
|
|
}
|
|
|
|
function resolveNavMaps(maps?: MailNavFolderMaps | null): MailNavFolderMaps {
|
|
if (maps) return maps
|
|
return {
|
|
folderIdToLabel: defaultSidebarNavFolderIdToLabel as Record<string, string>,
|
|
folderTree: defaultFolderTree,
|
|
}
|
|
}
|
|
|
|
function emailHasAnyLabel(email: Email, labels: string[]): boolean {
|
|
const ls = email.labels
|
|
if (!ls?.length) return false
|
|
const lower = new Set(ls.map((x) => x.toLowerCase()))
|
|
return labels.some((lab) => lower.has(lab.toLowerCase()))
|
|
}
|
|
|
|
function matchesFolderLabelRow(
|
|
email: Email,
|
|
folderId: string,
|
|
maps: MailNavFolderMaps
|
|
): boolean {
|
|
const label = maps.folderIdToLabel[folderId]
|
|
if (!label) return false
|
|
return emailHasAnyLabel(email, [label])
|
|
}
|
|
|
|
/** Dossier hiérarchique : ce nœud ou n'importe quel sous-dossier (décompte unique par mail). */
|
|
function matchesLabelNav(
|
|
email: Email,
|
|
folderId: string,
|
|
maps: MailNavFolderMaps
|
|
): boolean {
|
|
const subtreeIds = collectSubtreeFolderIds(maps.folderTree, folderId)
|
|
if (subtreeIds) {
|
|
return subtreeIds.some((id) => matchesFolderLabelRow(email, id, maps))
|
|
}
|
|
return matchesFolderLabelRow(email, folderId, maps)
|
|
}
|
|
|
|
export function emailMatchesFolder(
|
|
email: Email,
|
|
folderId: string,
|
|
ctx: MailFolderFilterCtx,
|
|
maps?: MailNavFolderMaps | null
|
|
): boolean {
|
|
const nav = resolveNavMaps(maps)
|
|
|
|
switch (folderId) {
|
|
case "inbox":
|
|
return isInInbox(email)
|
|
case "starred":
|
|
return effectiveStarred(email, ctx)
|
|
case "snoozed":
|
|
return email.labels?.includes("snoozed") ?? false
|
|
case "important":
|
|
return effectiveImportant(email, ctx)
|
|
case "sent":
|
|
return email.labels?.includes("sent") ?? false
|
|
case "drafts":
|
|
return email.labels?.includes("drafts") ?? false
|
|
case "scheduled":
|
|
return email.labels?.includes("scheduled") ?? false
|
|
case "spam":
|
|
return email.spam === true || (email.labels?.includes("spam") ?? false)
|
|
case "notifications":
|
|
return email.category === "updates"
|
|
case "purchases":
|
|
case "travel":
|
|
case "finance": {
|
|
const extra = SIDEBAR_CATEGORY_EXTRA_LABEL[folderId]
|
|
if (!extra) return false
|
|
return email.labels?.includes(extra) ?? false
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
|
|
if (CATEGORY_EMAIL_TAB_IDS.has(folderId)) {
|
|
return email.category === folderId
|
|
}
|
|
|
|
if (nav.folderIdToLabel[folderId]) {
|
|
return matchesLabelNav(email, folderId, nav)
|
|
}
|
|
|
|
if (email.labels?.includes(folderId)) return true
|
|
|
|
return false
|
|
}
|