From 616d52d8fb9dac7f0f882f4264923f86f9b68ed8 Mon Sep 17 00:00:00 2001 From: alma Date: Thu, 24 Apr 2025 19:58:21 +0200 Subject: [PATCH] compose mime --- app/courrier/page.tsx | 17 ++--- components/ComposeEmail.tsx | 122 ++++++++++++++---------------------- 2 files changed, 56 insertions(+), 83 deletions(-) diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index e1ea1135..4dd2bced 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -509,6 +509,7 @@ export default function CourrierPage() { // Process emails keeping exact folder names and sort by date const processedEmails = (data.emails || []) + .filter((email: any) => email && email.body) // Filter out emails with no body .map((email: any) => ({ id: Number(email.id), accountId: 1, @@ -527,20 +528,20 @@ export default function CourrierPage() { raw: email.body || '' })); - // Only update unread count if we're in the Inbox folder - if (currentView === 'INBOX') { - const unreadInboxEmails = processedEmails.filter( - (email: Email) => !email.read && email.folder === 'INBOX' - ).length; - setUnreadCount(unreadInboxEmails); - } - // Sort emails by date, ensuring most recent first const sortedEmails = processedEmails.sort((a: Email, b: Email) => { const dateA = new Date(a.date).getTime(); const dateB = new Date(b.date).getTime(); return dateB - dateA; // Most recent first }); + + // Only update unread count if we're in the Inbox folder + if (currentView === 'INBOX') { + const unreadInboxEmails = sortedEmails.filter( + (email: Email) => !email.read && email.folder === 'INBOX' + ).length; + setUnreadCount(unreadInboxEmails); + } if (isLoadMore) { // When loading more, merge with existing emails and re-sort diff --git a/components/ComposeEmail.tsx b/components/ComposeEmail.tsx index 2bd0b68b..8c70cae8 100644 --- a/components/ComposeEmail.tsx +++ b/components/ComposeEmail.tsx @@ -84,90 +84,62 @@ export default function ComposeEmail({ const [isLoading, setIsLoading] = useState(false); useEffect(() => { - const initializeContent = async () => { - if (!composeBodyRef.current) return; - - let content = ''; - - if (replyTo || forwardFrom) { - setIsLoading(true); + if (replyTo || forwardFrom) { + const initializeContent = async () => { try { - const originalContent = replyTo?.body || forwardFrom?.body || ''; + const emailToProcess = replyTo || forwardFrom; + if (!emailToProcess?.body) { + console.error('No email body found to process'); + return; + } + + // Parse the original email using the API + const response = await fetch('/api/parse-email', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email: emailToProcess.body }), + }); + + if (!response.ok) { + throw new Error('Failed to parse email'); + } + + const parsedEmail = await response.json(); + const originalContent = parsedEmail.html || parsedEmail.text || ''; - // Create initial content without waiting for parsing - content = ` -
-
-
Loading original message...
+ // Format the reply/forward content + const prefix = replyTo ? '\n\n' : '\n\n---------- Forwarded message ----------\n\n'; + const quoteStyle = 'border-left: 2px solid #ccc; margin-left: 1em; padding-left: 1em;'; + const formattedContent = ` +

${prefix}
+
+ ${originalContent}
`; - - // Set initial content immediately - composeBodyRef.current.innerHTML = content; - setLocalContent(content); - - // Place cursor at the beginning - const composeArea = composeBodyRef.current.querySelector('.compose-area'); - if (composeArea) { + + // Set the content in the compose area + if (composeBodyRef.current) { + composeBodyRef.current.innerHTML = formattedContent; + // Place cursor at the beginning + const selection = window.getSelection(); const range = document.createRange(); - const sel = window.getSelection(); - range.setStart(composeArea, 0); + range.setStart(composeBodyRef.current.firstChild || composeBodyRef.current, 0); range.collapse(true); - sel?.removeAllRanges(); - sel?.addRange(range); - (composeArea as HTMLElement).focus(); - } - - // Now parse the email content - if (originalContent.trim()) { - const decodedContent = await decodeComposeContent(originalContent); - - const quotedContent = ` - ${forwardFrom ? ` -
- ---------- Forwarded message ---------
- From: ${forwardFrom.from}
- Date: ${new Date(forwardFrom.date).toLocaleString()}
- Subject: ${forwardFrom.subject}
- To: ${forwardFrom.to}
- ${forwardFrom.cc ? `Cc: ${forwardFrom.cc}
` : ''} -
- ${decodedContent.html || decodedContent.text || 'No content available'} -
- ` : ` -
- On ${new Date(replyTo?.date || '').toLocaleString()}, ${replyTo?.from} wrote: -
-
- ${decodedContent.html || decodedContent.text || 'No content available'} -
- `} - `; - - // Replace placeholder with actual content - const placeholder = composeBodyRef.current.querySelector('#reply-placeholder'); - if (placeholder) { - placeholder.insertAdjacentHTML('beforebegin', quotedContent); - placeholder.remove(); - } + selection?.removeAllRanges(); + selection?.addRange(range); } + + // Update compose state + setComposeBody(formattedContent); } catch (error) { - console.error('Error parsing email:', error); - const placeholder = composeBodyRef.current.querySelector('#reply-placeholder'); - if (placeholder) { - placeholder.textContent = 'Error loading original message.'; - } - } finally { - setIsLoading(false); + console.error('Error initializing compose content:', error); } - } else { - content = `
`; - composeBodyRef.current.innerHTML = content; - setLocalContent(content); - } - }; - - initializeContent(); + }; + + initializeContent(); + } }, [replyTo, forwardFrom]); const handleInput = (e: React.FormEvent) => {