"use client" import { useMemo, useState } from "react" import { Star, Info } from "lucide-react" import { useMessage } from "@/lib/api/hooks/use-mail-queries" import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip" import { cn } from "@/lib/utils" import { mailFlagIsStarred, messageIsSpam } from "@/lib/mail-flags" import { avatarColor, cleanSenderName, senderInitial, } from "@/lib/sender-display" import { MailDateText } from "@/components/gmail/mail-date-text" import type { ApiMessageFull, Recipient } from "@/lib/api/types" import { resolveMessageFrom } from "@/lib/mail-message-participants" import { buildMessageHeaderDetails, type MessageHeaderDetails, } from "@/lib/mail-message-header-details" import type { EmailAttachment } from "@/lib/email-data" import { ContactHoverCard } from "@/components/gmail/contact-hover-card" import { EmailViewMessageToolbar } from "@/components/gmail/email-view/email-view-toolbar" import { MessageBodyContent } from "@/components/gmail/email-view/message-body-content" import { MessageAttachmentsSection } from "@/components/gmail/email-view/message-attachments" import { MAIL_MESSAGE_HOVER_CLASS, MAIL_TOOLTIP_CONTENT_CLASS, } from "@/lib/mail-chrome-classes" import { repairMimeBodies } from "@/lib/mail-mime-body" import { plainTextToDisplayHtml } from "@/lib/mail-plain-text-html" export function plainTextBodyFallback( full: { body_text?: string; body_html?: string } | null | undefined ): string | undefined { const { bodyText } = repairMimeBodies(full?.body_text, full?.body_html) const t = bodyText?.trim() return t || undefined } export function formatApiMessageBody( full: { body_html?: string; body_text?: string } | null | undefined, snippet: string | undefined, loading: boolean ): string { const snippetHtml = snippet?.trim() ? `
${snippet.trim()}
` : "" if (loading) { return snippetHtml } const repaired = repairMimeBodies(full?.body_text, full?.body_html) const html = repaired.bodyHtml?.trim() if (html) return html const text = repaired.bodyText?.trim() if (text) { return plainTextToDisplayHtml(text) } if (full) { const s = snippet?.trim() if (s) { return `${s}
` } return `Ce message n’a pas de contenu.
` } const s = snippet?.trim() return s ? `${s}
` : "" } /** Prior message in a thread: loads full body on expand via GET /mail/messages/:id. */ export function ThreadPriorMessage({ message, isExpanded, onToggle, onPrintConversation, onReply, onForward, selfEmails, selfDisplayName, collapseQuotedReplies = false, }: { message: ApiMessageFull isExpanded: boolean onToggle: () => void onPrintConversation?: () => void onReply?: () => void onForward?: () => void selfEmails: string[] selfDisplayName?: string collapseQuotedReplies?: boolean }) { const [detailsOpen, setDetailsOpen] = useState(false) const loadFull = isExpanded || detailsOpen const { data: fullMessage, isPending } = useMessage(loadFull ? message.id : null) const merged = fullMessage ?? message const resolved = useMemo( () => resolveMessageFrom(merged.from, { selfEmails, selfDisplayName }), [merged.from, selfEmails, selfDisplayName] ) const headerDetails = useMemo( () => buildMessageHeaderDetails(merged, { selfEmails, selfDisplayName, subject: message.subject, }), [merged, selfEmails, selfDisplayName, message.subject] ) const body = useMemo( () => formatApiMessageBody( fullMessage, message.snippet, isExpanded && isPending && !fullMessage ), [fullMessage, message.snippet, isExpanded, isPending] ) const plainTextFallback = useMemo( () => plainTextBodyFallback(fullMessage), [fullMessage] ) const isSpam = messageIsSpam(merged.flags, merged.labels) if (!isExpanded) { return ({message.snippet}
Pourquoi ce message est-il dans le spam ?{" "} Ce message est semblable à des messages identifiés comme spam par le passé.
{onNotSpam && ( )}