ultisuite-client/components/gmail/email-list/email-list-helpers.ts
2026-05-20 16:01:08 +02:00

146 lines
4.2 KiB
TypeScript

import { cn } from "@/lib/utils"
import { labelPillTextClassForTailwindBgUtility } from "@/lib/label-pill-contrast"
import { buildInboxCategoryTabIcons } from "@/lib/inbox-category-tabs"
type InboxTabBarItem = {
id: string
label: string
icon: string
badgeColor: string
}
import { INBOX_ALL_TAB } from "@/lib/mail-url"
import type { Email } from "@/lib/email-data"
import type { FolderTreeNode, LabelRowItem } from "@/lib/sidebar-nav-data"
import type { MailRouteState } from "@/lib/mail-url"
import { formatMailDetailDate } from "@/lib/mail-date"
import {
MAIL_LIST_ROW_CHECKBOX_CIRCULAR_CLASS,
MAIL_LIST_ROW_CHECKBOX_SQUARE_CLASS,
} from "@/lib/mail-chrome-classes"
export const LIST_PAGE_SIZE = 50
export {
PULL_HOLD_HEIGHT,
PULL_REFRESH_THRESHOLD,
PULL_REFRESH_MAX,
PULL_SNAP_BACK_TRANSITION,
REFRESH_SPIN_CLASS,
PULL_ICON_FADE_MS,
PULL_SPINNER_REVEAL_OFFSET,
computePullOffset,
computeSpinnerRevealProgress,
} from "@/hooks/use-mail-list-pull-refresh"
export interface EmailListProps {
selectedFolder: string
inboxTab: string
listPage: number
openMailId: string | null
splitView?: boolean
onToggleSidebar?: () => void
onMailRouteNavigate: (patch: Partial<MailRouteState>) => void
onSelectFolder?: (folder: string) => void
onFolderUnreadCountsChange?: (counts: Record<string, number>) => void
onXsViewChromeChange?: (chrome: import("@/lib/mail-xs-view-chrome").MailXsViewChrome | null) => void
}
export function collectTreeLabels(nodes: FolderTreeNode[]): string[] {
const out: string[] = []
for (const n of nodes) {
out.push(n.label)
if (n.children?.length) out.push(...collectTreeLabels(n.children))
}
return out
}
export function formatScheduledDateTimeDisplay(iso: string | undefined): string {
if (!iso) return "—"
return formatMailDetailDate(iso)
}
export function scheduledIsoToDatetimeLocalValue(iso: string | undefined): string {
if (!iso) return ""
const d = new Date(iso)
if (Number.isNaN(d.getTime())) return ""
const p = (n: number) => String(n).padStart(2, "0")
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}T${p(d.getHours())}:${p(d.getMinutes())}`
}
export function parseDatetimeLocalToIso(value: string): string | null {
const d = new Date(value)
if (Number.isNaN(d.getTime())) return null
return d.toISOString()
}
export function contextMenuTargetIdsForRow(
emailId: string,
selectedEmails: string[],
selectedFolder: string,
pool: Email[]
): string[] {
const raw = selectedEmails.includes(emailId) ? selectedEmails : [emailId]
if (selectedFolder !== "scheduled") return raw
const onlyScheduled = raw.filter((id) =>
pool.some((e) => e.id === id && e.labels?.includes("scheduled"))
)
return onlyScheduled.length > 0 ? onlyScheduled : [emailId]
}
export function escapeHtml(text: string): string {
return text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
}
export function importantSignalIcon(isSpam: boolean, isImportant: boolean): string {
if (isSpam) return "mdi:flag-outline"
if (isImportant) return "mdi:label-variant"
return "mdi:label-variant-outline"
}
export function buildInboxTabBarItems(labelRows: readonly LabelRowItem[]): InboxTabBarItem[] {
return [
...buildInboxCategoryTabIcons(labelRows),
{
id: INBOX_ALL_TAB,
label: "Tous les messages",
icon: "mdi:inbox",
badgeColor: "bg-[#0b57d0]",
},
]
}
export function inboxTabBadgeCountClass(badgeColor: string) {
return cn(
"shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium leading-none",
badgeColor,
labelPillTextClassForTailwindBgUtility(badgeColor)
)
}
export function inboxTabBadgeDotClass(badgeColor: string) {
return cn(
"absolute -right-0.5 -top-0.5 size-2 rounded-full ring-2 ring-mail-surface",
badgeColor
)
}
export const CATEGORY_TAB_ICON_CLASS = "h-4 w-4 shrink-0"
export function listRowCheckboxClass(circular: boolean) {
return circular
? MAIL_LIST_ROW_CHECKBOX_CIRCULAR_CLASS
: MAIL_LIST_ROW_CHECKBOX_SQUARE_CLASS
}
export function listRowQuickHoverTrayToneClass(isSelected: boolean, isRead: boolean) {
return isSelected
? "bg-mail-row-selected"
: isRead
? "bg-mail-row-read"
: "bg-mail-row-unread"
}