174 lines
6.7 KiB
TypeScript
174 lines
6.7 KiB
TypeScript
"use client"
|
|
|
|
import {
|
|
Info,
|
|
HardDrive,
|
|
File,
|
|
FileText,
|
|
Image as ImageIcon,
|
|
} from "lucide-react"
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip"
|
|
import { cn } from "@/lib/utils"
|
|
import type { EmailAttachment, EmailAttachmentKind } from "@/lib/email-data"
|
|
import {
|
|
attachmentPreviewTooltip,
|
|
resolveAttachmentKind,
|
|
shouldUseAttachmentPillsInPreview,
|
|
} from "@/lib/attachment-display"
|
|
import { MAIL_TOOLTIP_CONTENT_CLASS } from "@/lib/mail-chrome-classes"
|
|
|
|
function MessageAttachmentCard({ name, kind }: { name: string; kind: EmailAttachmentKind }) {
|
|
return (
|
|
<>
|
|
<div className="relative flex h-[132px] shrink-0 flex-col items-center justify-center bg-linear-to-b from-muted to-muted/70 dark:from-[#3c4043] dark:to-[#303134]">
|
|
{kind === "image" ? (
|
|
<ImageIcon className="size-11 text-[#9aa0a6]" strokeWidth={1.25} aria-hidden />
|
|
) : kind === "pdf" ? (
|
|
<div
|
|
className="rounded border border-border bg-mail-surface px-4 py-5 shadow-sm"
|
|
aria-hidden
|
|
>
|
|
<span className="text-[11px] font-bold leading-none text-[#d93025]">PDF</span>
|
|
</div>
|
|
) : (
|
|
<File className="size-11 text-[#9aa0a6]" strokeWidth={1.25} aria-hidden />
|
|
)}
|
|
</div>
|
|
<div className="flex min-h-[38px] items-center gap-2 border-t border-border bg-muted px-2 py-1.5">
|
|
{kind === "pdf" ? (
|
|
<FileText className="size-4 shrink-0 text-[#d93025]" strokeWidth={1.5} aria-hidden />
|
|
) : kind === "image" ? (
|
|
<ImageIcon className="size-4 shrink-0 text-[#1a73e8]" strokeWidth={1.5} aria-hidden />
|
|
) : (
|
|
<File className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} aria-hidden />
|
|
)}
|
|
<span className="min-w-0 flex-1 truncate text-xs leading-tight text-[#3c4043]">
|
|
{name}
|
|
</span>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function MessageAttachmentPill({
|
|
name,
|
|
kind,
|
|
sizeBytes,
|
|
}: {
|
|
name: string
|
|
kind: EmailAttachmentKind
|
|
sizeBytes?: number
|
|
}) {
|
|
const tip = attachmentPreviewTooltip(name, sizeBytes)
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<button
|
|
type="button"
|
|
className="inline-flex max-w-[min(100%,320px)] min-w-0 shrink-0 items-center gap-2 rounded-full border border-border bg-muted py-1.5 pl-2.5 pr-3 text-left text-sm text-foreground shadow-sm transition hover:border-border hover:bg-accent hover:shadow focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
|
|
>
|
|
{kind === "pdf" ? (
|
|
<FileText className="size-4 shrink-0 text-[#d93025]" strokeWidth={1.5} aria-hidden />
|
|
) : kind === "image" ? (
|
|
<ImageIcon className="size-4 shrink-0 text-[#1a73e8]" strokeWidth={1.5} aria-hidden />
|
|
) : (
|
|
<File className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} aria-hidden />
|
|
)}
|
|
<span className="min-w-0 truncate font-medium">{name}</span>
|
|
</button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="bottom" className={cn(MAIL_TOOLTIP_CONTENT_CLASS, "max-w-xs whitespace-pre-line text-xs")}>
|
|
{tip}
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
)
|
|
}
|
|
|
|
export function MessageAttachmentsSection({ attachments }: { attachments: EmailAttachment[] }) {
|
|
const n = attachments.length
|
|
if (n === 0) return null
|
|
|
|
const summary = n === 1 ? "Une pièce jointe" : `${n} pièces jointes`
|
|
const asPills = shouldUseAttachmentPillsInPreview(attachments)
|
|
|
|
return (
|
|
<div className="mt-4 border-t border-border px-4 pb-4 pl-[68px] pt-4 max-sm:pl-4 max-sm:pr-4">
|
|
<div className="mb-3 flex min-w-0 flex-wrap items-center justify-between gap-x-3 gap-y-2">
|
|
<div className="flex min-w-0 max-w-[min(100%,28rem)] items-center gap-1 text-sm text-muted-foreground">
|
|
<span className="min-w-0 truncate">
|
|
{summary}
|
|
<span aria-hidden> · </span>
|
|
<span>Analysé par VirusTotal</span>
|
|
</span>
|
|
<Tooltip delayDuration={400}>
|
|
<TooltipTrigger asChild>
|
|
<button
|
|
type="button"
|
|
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:bg-accent"
|
|
aria-label="Informations sur l'analyse VirusTotal des pièces jointes"
|
|
>
|
|
<Info className="size-4" strokeWidth={1.75} />
|
|
</button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="bottom" className={cn(MAIL_TOOLTIP_CONTENT_CLASS, "max-w-xs text-xs")}>
|
|
VirusTotal analyse les pièces jointes et les compare à une base de signatures pour
|
|
repérer les virus et logiciels malveillants.
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
className="flex shrink-0 items-center gap-2 rounded-md py-1 pl-1 pr-2 text-sm font-medium text-primary hover:bg-accent"
|
|
aria-label="Ajouter à UltiDrive"
|
|
>
|
|
<HardDrive className="size-[18px] shrink-0" strokeWidth={1.5} aria-hidden />
|
|
Ajouter à UltiDrive
|
|
</button>
|
|
</div>
|
|
|
|
<div
|
|
className={
|
|
asPills
|
|
? "flex flex-wrap gap-2 pb-1"
|
|
: "flex flex-nowrap gap-3 overflow-x-auto overflow-y-hidden pb-1 [-webkit-overflow-scrolling:touch]"
|
|
}
|
|
role="list"
|
|
aria-label="Pièces jointes"
|
|
>
|
|
{attachments.map((att, index) => {
|
|
const kind = resolveAttachmentKind(att.name, att.kind)
|
|
const tip = attachmentPreviewTooltip(att.name, att.sizeBytes)
|
|
if (asPills) {
|
|
return (
|
|
<div key={`${att.name}-${index}`} className="shrink-0" role="listitem">
|
|
<MessageAttachmentPill name={att.name} kind={kind} sizeBytes={att.sizeBytes} />
|
|
</div>
|
|
)
|
|
}
|
|
return (
|
|
<div key={`${att.name}-${index}`} className="shrink-0" role="listitem">
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<button
|
|
type="button"
|
|
className="flex w-[200px] flex-col overflow-hidden rounded border border-border bg-mail-surface text-left shadow-sm transition hover:border-border hover:shadow-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
|
|
>
|
|
<MessageAttachmentCard name={att.name} kind={kind} />
|
|
</button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="bottom" className={cn(MAIL_TOOLTIP_CONTENT_CLASS, "max-w-xs whitespace-pre-line text-xs")}>
|
|
{tip}
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|