102 lines
2.7 KiB
TypeScript
102 lines
2.7 KiB
TypeScript
export type FolderTreeNode = {
|
||
id: string
|
||
label: string
|
||
count?: number
|
||
color?: string
|
||
children?: FolderTreeNode[]
|
||
}
|
||
|
||
export type LabelRowItem = {
|
||
id: string
|
||
label: string
|
||
color: string
|
||
count?: number
|
||
/** Icône Iconify (ex. mdi:inbox) — onglets + sidebar pour libellés système. */
|
||
icon?: string
|
||
/** Onglet boîte de réception (Principale + ces onglets). */
|
||
tabbed?: boolean
|
||
/** Bloc favoris sous les dossiers principaux. */
|
||
favorite?: boolean
|
||
/** Masque de Principale quand le libellé est sur le mail (si activé). */
|
||
excludeFromPrincipal?: boolean
|
||
/** Pastille dans la liste / en-tête message. */
|
||
showInMessageList?: boolean
|
||
/** Désactivé : pas d’onglet, pas de sidebar, pas de pastille, exclude ignoré. */
|
||
enabled?: boolean
|
||
}
|
||
|
||
export function buildFolderIdToLabelRecord(
|
||
tree: FolderTreeNode[],
|
||
labelRows: readonly LabelRowItem[]
|
||
): Record<string, string> {
|
||
const m: Record<string, string> = {}
|
||
for (const n of tree) {
|
||
walkFolderTreeIds(n, m)
|
||
}
|
||
for (const row of labelRows) {
|
||
m[row.id] = row.label
|
||
}
|
||
m.scheduled = "scheduled"
|
||
return m
|
||
}
|
||
|
||
function walkFolderTreeIds(node: FolderTreeNode, acc: Record<string, string>) {
|
||
acc[node.id] = node.label
|
||
if (node.children?.length) {
|
||
for (const c of node.children) walkFolderTreeIds(c, acc)
|
||
}
|
||
}
|
||
|
||
/** Tous les ids de dossiers du sous-arbre (nœud + descendants). */
|
||
export function collectSubtreeFolderIds(
|
||
tree: FolderTreeNode[],
|
||
folderId: string
|
||
): string[] | null {
|
||
for (const n of tree) {
|
||
if (n.id === folderId) {
|
||
const ids: string[] = []
|
||
const collect = (node: FolderTreeNode) => {
|
||
ids.push(node.id)
|
||
node.children?.forEach(collect)
|
||
}
|
||
collect(n)
|
||
return ids
|
||
}
|
||
if (n.children?.length) {
|
||
const hit = collectSubtreeFolderIds(n.children, folderId)
|
||
if (hit) return hit
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
|
||
/** @deprecated Préférer collectSubtreeFolderIds + libellé par id de dossier. */
|
||
export function subtreeMatchLabels(
|
||
tree: FolderTreeNode[],
|
||
folderId: string
|
||
): string[] | null {
|
||
const ids = collectSubtreeFolderIds(tree, folderId)
|
||
if (!ids) return null
|
||
const labels: string[] = []
|
||
const walk = (nodes: FolderTreeNode[]) => {
|
||
for (const n of nodes) {
|
||
if (ids.includes(n.id)) labels.push(n.label)
|
||
if (n.children?.length) walk(n.children)
|
||
}
|
||
}
|
||
walk(tree)
|
||
return labels
|
||
}
|
||
|
||
export function buildEmailLabelToSidebarFolderId(
|
||
folderIdToLabel: Record<string, string>
|
||
): Record<string, string> {
|
||
const inv: Record<string, string> = {}
|
||
for (const [id, lab] of Object.entries(folderIdToLabel)) {
|
||
inv[lab] = id
|
||
}
|
||
inv.spam = "spam"
|
||
inv.scheduled = "scheduled"
|
||
return inv
|
||
}
|