courrier clean 2

This commit is contained in:
alma 2025-04-26 14:52:19 +02:00
parent 97fb21a632
commit 051bcb08a4

View File

@ -340,20 +340,6 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
return; return;
} }
// Debug the email object structure
console.log('Forwarding email object:', {
id: initialEmail.id,
subject: initialEmail.subject,
fromLength: initialEmail.from?.length,
from: initialEmail.from,
to: initialEmail.to,
date: initialEmail.date,
hasContent: Boolean(initialEmail.content),
contentLength: initialEmail.content?.length,
hasHtml: Boolean(initialEmail.html),
htmlLength: initialEmail.html?.length
});
try { try {
// Format subject with Fwd: prefix if needed // Format subject with Fwd: prefix if needed
const subjectBase = initialEmail.subject || '(No subject)'; const subjectBase = initialEmail.subject || '(No subject)';
@ -364,62 +350,58 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
setSubject(subject); setSubject(subject);
// Format the forwarded message with a well-structured header // Format the forwarded message as a simple text representation with clean formatting
let forwardedText = '';
// Format the "From" field
const fromString = Array.isArray(initialEmail.from) && initialEmail.from.length > 0 const fromString = Array.isArray(initialEmail.from) && initialEmail.from.length > 0
? initialEmail.from.map(addr => addr.name ? initialEmail.from.map(addr => addr.name
? `${addr.name} <${addr.address}>` ? `${addr.name} <${addr.address}>`
: addr.address).join(', ') : addr.address).join(', ')
: 'Unknown'; : 'Unknown';
// Format the "To" field
const toString = Array.isArray(initialEmail.to) && initialEmail.to.length > 0 const toString = Array.isArray(initialEmail.to) && initialEmail.to.length > 0
? initialEmail.to.map(addr => addr.name ? initialEmail.to.map(addr => addr.name
? `${addr.name} <${addr.address}>` ? `${addr.name} <${addr.address}>`
: addr.address).join(', ') : addr.address).join(', ')
: ''; : '';
// Format the date
const dateString = initialEmail.date const dateString = initialEmail.date
? typeof initialEmail.date === 'string' ? typeof initialEmail.date === 'string'
? new Date(initialEmail.date).toLocaleString() ? new Date(initialEmail.date).toLocaleString()
: initialEmail.date.toLocaleString() : initialEmail.date.toLocaleString()
: new Date().toLocaleString(); : new Date().toLocaleString();
// Create a clean header with inline styles only - no external CSS // Create a simple text representation of the forwarded header
const headerHtml = ` forwardedText += '---------- Forwarded message ---------\n';
<div style="border-top: 1px solid #e1e1e1; margin-top: 20px; padding-top: 15px; font-family: Arial, sans-serif; color: #333;"> forwardedText += `From: ${fromString}\n`;
<div style="margin-bottom: 15px;"> forwardedText += `Date: ${dateString}\n`;
<div style="font-weight: normal; margin-bottom: 10px;">---------- Forwarded message ---------</div> forwardedText += `Subject: ${subjectBase}\n`;
<div><b>From:</b> ${fromString}</div> forwardedText += `To: ${toString}\n\n`;
<div><b>Date:</b> ${dateString}</div>
<div><b>Subject:</b> ${subjectBase}</div>
<div><b>To:</b> ${toString}</div>
</div>
</div>
`;
// Default content is a clear "no content" message // Add the content - clean and sanitize the HTML to prevent formatting issues
let contentHtml = '<div style="color: #666; font-style: italic; padding: 15px; font-size: 14px; border: 1px dashed #ccc; margin: 15px 0; text-align: center; background-color: #f9f9f9; border-radius: 4px;">No content available in original email</div>';
// Check if we have content to forward
if (initialEmail.content || initialEmail.html || initialEmail.text) { if (initialEmail.content || initialEmail.html || initialEmail.text) {
// Use the most complete version of content available // Try to extract text from HTML content
contentHtml = DOMPurify.sanitize( const tempDiv = document.createElement('div');
initialEmail.content || initialEmail.html || tempDiv.innerHTML = initialEmail.content || initialEmail.html || initialEmail.text || '';
`<pre style="white-space: pre-wrap;">${initialEmail.text || ''}</pre>`,
{ // Get the text content, preserving line breaks
ADD_ATTR: ['style', 'class'], let cleanContent = tempDiv.textContent || tempDiv.innerText || '';
ALLOW_DATA_ATTR: true,
USE_PROFILES: { html: true } // Add the clean content
} forwardedText += cleanContent;
); } else {
forwardedText += 'No content available in original email';
} }
// Set the original content for display // Set the forwarded text as the original content (plain text preserves formatting better)
setOriginalContent(`${headerHtml}<div class="forwarded-content" style="color: #333;">${contentHtml}</div>`); setOriginalContent(forwardedText);
// Leave the editorRef empty to allow user to type their message // Keep user message separate
setUserMessage(''); setUserMessage('');
setBody(''); setBody('');
} catch (error) { } catch (error) {
console.error('Error formatting forwarded email:', error); console.error('Error formatting forwarded email:', error);
setBody('<div style="color: #666; font-style: italic;">Error formatting forwarded email content</div>'); setBody('<div style="color: #666; font-style: italic;">Error formatting forwarded email content</div>');
@ -483,12 +465,23 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
try { try {
setSending(true); setSending(true);
// Combine user message with original content for forwarded emails
let finalBody = '';
if (type === 'forward' && originalContent) {
// Format the user message + forwarded content properly
finalBody = `${userMessage}\n\n${originalContent}`;
} else {
// For other cases, use the current body
finalBody = editorRef.current?.innerHTML || body;
}
await onSend({ await onSend({
to, to,
cc: cc || undefined, cc: cc || undefined,
bcc: bcc || undefined, bcc: bcc || undefined,
subject, subject,
body: editorRef.current?.innerHTML || body, body: finalBody,
attachments attachments
}); });
@ -507,12 +500,8 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
const content = editorRef.current.innerHTML; const content = editorRef.current.innerHTML;
setUserMessage(content); setUserMessage(content);
// Combine user message with original content // Simply update body with user message - we'll combine with original content when sending
if (originalContent) { setBody(content);
setBody(`${content}<div class="quote-divider"></div>${originalContent}`);
} else {
setBody(content);
}
} }
}; };
@ -648,58 +637,21 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
}} }}
/> />
{/* Original content display with visual separation - editable for replies/forwards */} {/* Original content display with visual separation - now as plain text for better reliability */}
{type !== 'new' && originalContent && ( {type !== 'new' && originalContent && (
<div className="border-t"> <div className="border-t">
<div className="px-4 py-2 bg-gray-50 text-xs font-medium text-gray-500"> <div className="px-4 py-2 bg-gray-50 text-xs font-medium text-gray-500">
{type === 'forward' ? 'Forwarded content (editable)' : 'Original message (editable)'} {type === 'forward' ? 'Forwarded content' : 'Original message'}
</div> </div>
<div <pre
className="p-4 bg-gray-50 text-sm original-content" className="p-4 bg-gray-50 text-sm original-content font-mono whitespace-pre-wrap overflow-auto"
contentEditable={!sending}
dangerouslySetInnerHTML={{ __html: originalContent }}
style={{ style={{
opacity: 1.0, lineHeight: '1.5',
overflow: 'auto', maxHeight: '400px'
whiteSpace: 'pre-wrap',
wordBreak: 'break-word',
overflowWrap: 'break-word'
}} }}
onInput={(e) => { >
// Prevent default behavior that might cause text flow issues {originalContent}
e.preventDefault(); </pre>
// Get the current caret position to restore it later
const selection = window.getSelection();
const range = selection?.getRangeAt(0);
const offset = range?.startOffset || 0;
const node = range?.startContainer;
// Update content
const target = e.target as HTMLDivElement;
setOriginalContent(target.innerHTML);
// Update the complete body without disturbing the text flow
const userPart = editorRef.current?.innerHTML || '';
setBody(`${userPart}<div class="quote-divider"></div>${target.innerHTML}`);
// Try to restore cursor position after state update
setTimeout(() => {
try {
if (selection && range && node && node.parentNode) {
// Attempt to find the same node
const newRange = document.createRange();
newRange.setStart(node, Math.min(offset, node.textContent?.length || 0));
newRange.collapse(true);
selection.removeAllRanges();
selection.addRange(newRange);
}
} catch (err) {
console.error('Error restoring cursor position:', err);
}
}, 0);
}}
/>
</div> </div>
)} )}
</div> </div>