import { Archive, ArrowLeft, Clock, Forward, Mail, MailOpen, MoreHorizontal, Reply, RotateCcw, Star, Tag, FolderInput, ShieldAlert, Trash2, ChevronDown, } from "lucide-react"; import AgentSpark from "./AgentSpark"; import SenderAvatar from "./SenderAvatar"; import { addressText, senderDisplayName } from "../utils/senderAvatar"; import { attachmentCount } from "../utils/inboxSignals"; const ICON = { size: 17, strokeWidth: 1.7 }; function joinAddresses(value) { if (!value) return ""; const addresses = Array.isArray(value) ? value : [value]; return addresses .map((item) => { if (typeof item === "string") return item; if (item?.name && item?.address) return `${item.name} <${item.address}>`; return item?.email || item?.address || ""; }) .filter(Boolean) .join(", "); } function messageBody(email) { const text = (email?.body_text || email?.text_body || email?.plain_text || "").trim(); if (text) return { mode: "text", value: text }; const html = (email?.body_html || "").trim(); if (html) return { mode: "html", value: html }; const snippet = (email?.snippet || "").trim(); if (snippet) return { mode: "text", value: snippet }; return { mode: "text", value: "This message has no readable content." }; } function plainTextParagraphs(text) { return text .split(/\n{2,}/) .map((block) => block.trim()) .filter(Boolean); } function detailTime(email) { const value = email?.received_at || email?.sent_at || email?.created_at || email?.updated_at; if (!value) return { absolute: "", relative: "" }; const date = new Date(value); if (Number.isNaN(date.getTime())) return { absolute: "", relative: "" }; const absolute = new Intl.DateTimeFormat(undefined, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit", }).format(date); const diffMs = Date.now() - date.getTime(); const diffHours = Math.max(1, Math.round(diffMs / (1000 * 60 * 60))); const relative = diffHours < 24 ? `${diffHours}h ago` : `${Math.round(diffHours / 24)}d ago`; return { absolute, relative }; } function senderIdentity(email) { const name = senderDisplayName(email); const address = addressText(email.sender || email.from); if (name && address && !name.includes("@")) { return `${name} <${address}>`; } return address || name || "Unknown sender"; } function recipientLabel(email, viewerEmail) { const recipients = email.recipients || email.to || []; const list = Array.isArray(recipients) ? recipients : [recipients]; const addresses = list .map((item) => (typeof item === "string" ? item : item?.address || item?.email || "")) .filter(Boolean); if (!addresses.length) return "Undisclosed recipients"; if (viewerEmail && addresses.length === 1 && addresses[0].toLowerCase() === viewerEmail.toLowerCase()) { return "to me"; } if (addresses.length === 1) return `to ${addresses[0]}`; return `to ${addresses.length} recipients`; } function formatFileSize(bytes) { if (!bytes) return ""; if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } function mailboxLabel(mailbox) { if (mailbox === "inbox") return "Inbox"; if (mailbox === "sent") return "Sent"; if (mailbox === "trash") return "Trash"; return mailbox; } function ToolbarButton({ title, label, onClick, disabled, danger, children }) { return ( ); } export default function MailDetail({ email, loading, error, mailbox, busy, viewerEmail, threadSize = 1, onClose, onToggleRead, onToggleStar, onTrash, onRestore, onDelete, onArchive, onSpam, onSnooze, onMove, onReply, onForward, onExtractActions, onSummarizeThread, onAnalyzeAttachment, onDraftReply, }) { const files = email ? attachmentCount(email) : 0; const body = email ? messageBody(email) : null; const time = email ? detailTime(email) : { absolute: "", relative: "" }; const attachments = email?.attachments || []; const summarizeLabel = threadSize > 1 ? "Summarize thread" : "Summarize email"; return (
{email && ( <>
{loading &&
Opening message…
} {error &&
{error}
} {email && !loading && (

{email.subject?.trim() || "(No subject)"}

{mailboxLabel(mailbox)} {email.is_starred && Starred}
{files > 0 && ( )}
{senderIdentity(email)}
To: {joinAddresses(email.recipients || email.to) || "Undisclosed"} {joinAddresses(email.cc) && Cc: {joinAddresses(email.cc)}}
{body?.mode === "html" ? (
) : (
{plainTextParagraphs(body?.value || "").map((paragraph) => (

{paragraph.split("\n").map((line, index, lines) => ( {line} {index < lines.length - 1 &&
}
))}

))}
)}
{attachments.length > 0 && (
{attachments.map((file) => (
📄
{file.filename} {file.content_type || "File"} · {formatFileSize(file.size)}
))}
)}
)}
); }