courrier clean 2
This commit is contained in:
parent
97fb21a632
commit
051bcb08a4
@ -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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user