ultisuite-client/lib/attachment-display.ts
2026-05-15 17:40:17 +02:00

81 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Email, EmailAttachment, EmailAttachmentKind } from "@/lib/email-data"
/** Pièce jointe calendrier (invitation) — masquée dans la liste des messages. */
export function isCalendarInvitationAttachment(name: string): boolean {
return name.toLowerCase().endsWith(".ics")
}
/** PJ visibles dans la liste (hors fichiers .ics dinvitation). */
export function attachmentsForEmailList(
email: Pick<Email, "attachments" | "hasAttachment" | "hasInvitation">
): EmailAttachment[] {
if (email.attachments?.length) {
return email.attachments.filter((a) => !isCalendarInvitationAttachment(a.name))
}
if (email.hasAttachment && email.hasInvitation !== true) {
return [{ name: "Pièce jointe", kind: "other" }]
}
return []
}
/** Fichiers « riches » (cartes type Gmail) : PDF, images, vidéos, bureautique. */
const RICH_PREVIEW_EXT =
/\.(mp4|mpe?g|webm|mov|avi|mkv|m4v|wmv|flv|xls|xlsx|xlsm|ods|numbers|ppt|pptx|key|odp|doc|docx|odt|rtf)$/i
/** Seuil « petit fichier » pour la rangée en pills (aperçu message uniquement). */
export const ATTACHMENT_PILL_MAX_BYTES = 2 * 1024 * 1024
export function resolveAttachmentKind(
name: string,
kind?: EmailAttachment["kind"]
): EmailAttachmentKind {
if (kind) return kind
const lower = name.toLowerCase()
if (lower.endsWith(".pdf")) return "pdf"
if (/\.(png|jpe?g|gif|webp|svg|avif|bmp|heic)$/.test(lower)) return "image"
return "other"
}
export function isRichPreviewAttachment(name: string, kind?: EmailAttachment["kind"]): boolean {
const resolved = resolveAttachmentKind(name, kind)
if (resolved === "pdf" || resolved === "image") return true
return RICH_PREVIEW_EXT.test(name.toLowerCase())
}
export function isSmallEnoughForPillRow(sizeBytes?: number): boolean {
if (sizeBytes === undefined) return true
return sizeBytes >= 0 && sizeBytes <= ATTACHMENT_PILL_MAX_BYTES
}
/** Tous les fichiers simples + petits → UI pills dans laperçu message. */
export function shouldUseAttachmentPillsInPreview(attachments: EmailAttachment[]): boolean {
if (attachments.length === 0) return false
return attachments.every(
(a) => !isRichPreviewAttachment(a.name, a.kind) && isSmallEnoughForPillRow(a.sizeBytes)
)
}
function decFr(n: number): string {
return String(n).replace(".", ",")
}
export function formatAttachmentSize(sizeBytes: number): string {
if (!Number.isFinite(sizeBytes) || sizeBytes < 0) return "—"
if (sizeBytes < 1000) {
return `${Math.round(sizeBytes)}\u00a0o`
}
const kb = sizeBytes / 1024
if (kb < 1024) {
const v = kb >= 10 ? Math.round(kb) : Math.round(kb * 10) / 10
return `${decFr(v)}\u00a0Ko`
}
const mb = kb / 1024
const v = mb >= 10 ? Math.round(mb) : Math.round(mb * 10) / 10
return `${decFr(v)}\u00a0Mo`
}
export function attachmentPreviewTooltip(name: string, sizeBytes?: number): string {
if (sizeBytes === undefined) return name
return `${name}\n${formatAttachmentSize(sizeBytes)}`
}