import type { ApiFolder } from '@/lib/api/types' import type { FolderTreeNode } from '@/lib/sidebar-nav-maps' function imapPathDelimiter(remoteNames: string[]): string { if (remoteNames.some((n) => n.includes('/'))) return '/' if (remoteNames.some((n) => n.includes('.'))) return '.' return '/' } function splitImapPath(remoteName: string, delimiter: string): string[] { return remoteName.split(delimiter).filter(Boolean) } /** Custom IMAP folders (system folders use fixed route slugs in the sidebar). */ export function filterImapFoldersForNav( folders: ApiFolder[], accountId?: string ): ApiFolder[] { return folders.filter( (folder) => folder.folder_type === 'custom' && (!accountId || folder.account_id === accountId) ) } /** Build a hierarchical tree from IMAP folder paths (remote_name). */ export function buildFolderTreeFromImap( folders: ApiFolder[], accountId?: string ): FolderTreeNode[] { const custom = filterImapFoldersForNav(folders, accountId).sort((a, b) => a.remote_name.localeCompare(b.remote_name) ) if (custom.length === 0) return [] const delimiter = imapPathDelimiter(custom.map((f) => f.remote_name)) const nodesByRemote = new Map(custom.map((f) => [f.remote_name, f])) const childrenOf = new Map() for (const folder of custom) { const segments = splitImapPath(folder.remote_name, delimiter) let parentRemote: string | null = null for (let i = 0; i < segments.length - 1; i++) { const prefix = segments.slice(0, i + 1).join(delimiter) if (nodesByRemote.has(prefix)) { parentRemote = prefix } } const list = childrenOf.get(parentRemote) ?? [] list.push(folder) childrenOf.set(parentRemote, list) } function walk(parentRemote: string | null): FolderTreeNode[] { const kids = childrenOf.get(parentRemote) ?? [] return kids .sort((a, b) => a.name.localeCompare(b.name)) .map((folder) => { const node: FolderTreeNode = { id: folder.id, label: folder.name, } if (folder.unread_count > 0) node.count = folder.unread_count const children = walk(folder.remote_name) if (children.length) node.children = children return node }) } return walk(null) } export type ImapFolderSettingsNode = { id: string label: string remoteName?: string children?: ImapFolderSettingsNode[] } /** Settings tree with IMAP remote paths for display. */ export function buildImapFolderSettingsTree( folders: ApiFolder[], accountId: string ): ImapFolderSettingsNode[] { const custom = filterImapFoldersForNav(folders, accountId) const remoteById = new Map(custom.map((f) => [f.id, f.remote_name])) function attachRemote(nodes: FolderTreeNode[]): ImapFolderSettingsNode[] { return nodes.map((node) => ({ id: node.id, label: node.label, remoteName: remoteById.get(node.id), children: node.children?.length ? attachRemote(node.children) : undefined, })) } return attachRemote(buildFolderTreeFromImap(folders, accountId)) }