From f769d15bb11052ba5e8d14930e4751ceef57990d Mon Sep 17 00:00:00 2001 From: alma Date: Sun, 18 Jan 2026 15:03:26 +0100 Subject: [PATCH] attachments courrier --- components/email/EmailDetailView.tsx | 80 ++++++++++++++++++++++------ components/email/EmailListItem.tsx | 13 +++-- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/components/email/EmailDetailView.tsx b/components/email/EmailDetailView.tsx index 0caf6c9..21cf3d6 100644 --- a/components/email/EmailDetailView.tsx +++ b/components/email/EmailDetailView.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { - ChevronLeft, Reply, ReplyAll, Forward, Star, MoreHorizontal + ChevronLeft, Reply, ReplyAll, Forward, Star, MoreHorizontal, Eye, Download } from 'lucide-react'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; @@ -191,6 +191,7 @@ export default function EmailDetailView({ const handleDownload = async (e: React.MouseEvent) => { e.preventDefault(); + e.stopPropagation(); try { // Fetch the attachment const response = await fetch(downloadUrl); @@ -219,29 +220,76 @@ export default function EmailDetailView({ } }; + const handlePreview = async (e: React.MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); + try { + // Fetch the attachment + const response = await fetch(downloadUrl); + + if (!response.ok) { + throw new Error(`Failed to preview attachment: ${response.statusText}`); + } + + // Get the blob + const blob = await response.blob(); + + // Check if it's an image or PDF that can be previewed + const contentType = attachment.contentType || response.headers.get('content-type') || ''; + const isImage = contentType.startsWith('image/'); + const isPDF = contentType === 'application/pdf'; + const isText = contentType.startsWith('text/'); + + if (isImage || isPDF || isText) { + // Create a temporary URL and open in new tab + const url = window.URL.createObjectURL(blob); + window.open(url, '_blank'); + // Cleanup after a delay (browser will keep it open) + setTimeout(() => window.URL.revokeObjectURL(url), 1000); + } else { + // For other file types, trigger download + handleDownload(e); + } + } catch (error) { + console.error('Error previewing attachment:', error); + alert(`Failed to preview attachment: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + }; + + // Determine if file can be previewed + const contentType = attachment.contentType || ''; + const isImage = contentType.startsWith('image/'); + const isPDF = contentType === 'application/pdf'; + const isText = contentType.startsWith('text/'); + const canPreview = isImage || isPDF || isText; + return (

{attachment.filename}

{(attachment.size / 1024).toFixed(1)} KB

- +
+ {canPreview && ( + + )} + +
); })} diff --git a/components/email/EmailListItem.tsx b/components/email/EmailListItem.tsx index e7fd5ee..7957b17 100644 --- a/components/email/EmailListItem.tsx +++ b/components/email/EmailListItem.tsx @@ -1,7 +1,7 @@ 'use client'; import React from 'react'; -import { Star, Mail, MailOpen } from 'lucide-react'; +import { Star, Mail, MailOpen, Paperclip } from 'lucide-react'; import { Checkbox } from '@/components/ui/checkbox'; import { cn } from '@/lib/utils'; import { Email } from '@/hooks/use-courrier'; @@ -188,9 +188,14 @@ export default function EmailListItem({ -

- {email.subject || '(No subject)'} -

+
+

+ {email.subject || '(No subject)'} +

+ {email.hasAttachments && ( + + )} +
{getPreviewText(email.content)}