compose mime

This commit is contained in:
alma 2025-04-24 19:58:21 +02:00
parent da1390fb51
commit 616d52d8fb
2 changed files with 56 additions and 83 deletions

View File

@ -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

View File

@ -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 = `
<div class="compose-area" contenteditable="true" style="min-height: 100px; padding: 10px; color: #000000;">
<br/>
<div id="reply-placeholder">Loading original message...</div>
// 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 = `
<div><br/>${prefix}</div>
<div style="${quoteStyle}">
${originalContent}
</div>
`;
// 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 ? `
<div style="border-top: 1px solid #e5e7eb; padding-top: 20px; margin-top: 20px; color: #6b7280; font-size: 0.875rem;">
---------- Forwarded message ---------<br/>
From: ${forwardFrom.from}<br/>
Date: ${new Date(forwardFrom.date).toLocaleString()}<br/>
Subject: ${forwardFrom.subject}<br/>
To: ${forwardFrom.to}<br/>
${forwardFrom.cc ? `Cc: ${forwardFrom.cc}<br/>` : ''}
<br/>
${decodedContent.html || decodedContent.text || 'No content available'}
</div>
` : `
<div style="border-top: 1px solid #e5e7eb; padding-top: 20px; margin-top: 20px; color: #6b7280; font-size: 0.875rem;">
On ${new Date(replyTo?.date || '').toLocaleString()}, ${replyTo?.from} wrote:
</div>
<blockquote style="margin: 0; padding-left: 1em; border-left: 2px solid #e5e7eb; color: #6b7280;">
${decodedContent.html || decodedContent.text || 'No content available'}
</blockquote>
`}
`;
// 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 = `<div class="compose-area" contenteditable="true" style="min-height: 100px; padding: 10px; color: #000000;"></div>`;
composeBodyRef.current.innerHTML = content;
setLocalContent(content);
}
};
initializeContent();
};
initializeContent();
}
}, [replyTo, forwardFrom]);
const handleInput = (e: React.FormEvent<HTMLDivElement>) => {