"use client" import { useState, useEffect, useRef } from "react" import { useTranslations } from "next-intl" import { Loader2, Share2 } from "lucide-react" import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" import { Label } from "@/components/ui/label" import { useTheme } from "next-themes" import { useToast } from "@/components/ui/use-toast" import { ShareMessageDialog } from "./share-message-dialog" interface Message { id: string from_address?: string to_address?: string subject: string content: string html?: string received_at?: number sent_at?: number } interface MessageViewProps { emailId: string messageId: string messageType?: 'received' | 'sent' onClose: () => void } type ViewMode = "html" | "text" export function MessageView({ emailId, messageId, messageType = 'received' }: MessageViewProps) { const t = useTranslations("emails.messageView") const tList = useTranslations("emails.list") const [message, setMessage] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [viewMode, setViewMode] = useState("html") const iframeRef = useRef(null) const { theme } = useTheme() const { toast } = useToast() useEffect(() => { const fetchMessage = async () => { try { setLoading(true) setError(null) const url = `/api/emails/${emailId}/${messageId}${messageType === 'sent' ? '?type=sent' : ''}`; const response = await fetch(url) if (!response.ok) { const errorData = await response.json() const errorMessage = (errorData as { error?: string }).error || t("loadError") setError(errorMessage) toast({ title: tList("error"), description: errorMessage, variant: "destructive" }) return } const data = await response.json() as { message: Message } setMessage(data.message) if (!data.message.html) { setViewMode("text") } } catch (error) { const errorMessage = t("networkError") setError(errorMessage) toast({ title: tList("error"), description: errorMessage, variant: "destructive" }) console.error("Failed to fetch message:", error) } finally { setLoading(false) } } fetchMessage() }, [emailId, messageId, messageType, toast, t, tList]) const updateIframeContent = () => { if (viewMode === "html" && message?.html && iframeRef.current) { const iframe = iframeRef.current const doc = iframe.contentDocument || iframe.contentWindow?.document if (doc) { doc.open() doc.write(` ${message.html} `) doc.close() // 更新高度以填充容器 const updateHeight = () => { const container = iframe.parentElement if (container) { iframe.style.height = `${container.clientHeight}px` } } updateHeight() window.addEventListener('resize', updateHeight) // 监听内容变化 const resizeObserver = new ResizeObserver(updateHeight) resizeObserver.observe(doc.body) // 监听图片加载 doc.querySelectorAll('img').forEach((img: HTMLImageElement) => { img.onload = updateHeight }) return () => { window.removeEventListener('resize', updateHeight) resizeObserver.disconnect() } } } } // 监听主题变化和内容变化 useEffect(() => { updateIframeContent() }, [message?.html, viewMode, theme]) if (loading) { return (
{t("loading")}
) } if (error) { return (

{error}

) } if (!message) return null return (

{message.subject}

} />
{message.from_address && (

{t("from")}: {message.from_address}

)} {message.to_address && (

{t("to")}: {message.to_address}

)}

{t("time")}: {new Date(message.sent_at || message.received_at || 0).toLocaleString()}

{message.html && message.content && (
setViewMode(value as ViewMode)} className="flex items-center gap-4" >
)}
{viewMode === "html" && message.html ? (