courrier refactor rebuild preview
This commit is contained in:
parent
1d7f0b2b69
commit
3c738f179a
@ -1,9 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect, useMemo } from 'react';
|
||||||
import EmailPreview from './EmailPreview';
|
import EmailPreview from './EmailPreview';
|
||||||
import ComposeEmail from './ComposeEmail';
|
import ComposeEmail from './ComposeEmail';
|
||||||
import { Loader2 } from 'lucide-react';
|
import { Loader2 } from 'lucide-react';
|
||||||
|
import { formatReplyEmail, EmailMessage as FormatterEmailMessage } from '@/lib/utils/email-formatter';
|
||||||
|
|
||||||
// Add local EmailMessage interface
|
// Add local EmailMessage interface
|
||||||
interface EmailAddress {
|
interface EmailAddress {
|
||||||
@ -68,6 +69,41 @@ export default function EmailPanel({
|
|||||||
const [isComposing, setIsComposing] = useState<boolean>(false);
|
const [isComposing, setIsComposing] = useState<boolean>(false);
|
||||||
const [composeType, setComposeType] = useState<'new' | 'reply' | 'reply-all' | 'forward'>('new');
|
const [composeType, setComposeType] = useState<'new' | 'reply' | 'reply-all' | 'forward'>('new');
|
||||||
|
|
||||||
|
// Create a formatted version of the email content using the same formatter as ComposeEmail
|
||||||
|
const formattedEmail = useMemo(() => {
|
||||||
|
if (!email) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Convert to the formatter message format - this is what ComposeEmail does
|
||||||
|
const formatterEmail: FormatterEmailMessage = {
|
||||||
|
id: email.id,
|
||||||
|
messageId: email.messageId,
|
||||||
|
subject: email.subject,
|
||||||
|
from: email.from || [],
|
||||||
|
to: email.to || [],
|
||||||
|
cc: email.cc || [],
|
||||||
|
bcc: email.bcc || [],
|
||||||
|
date: email.date,
|
||||||
|
content: email.content,
|
||||||
|
html: email.html,
|
||||||
|
text: email.text,
|
||||||
|
hasAttachments: email.hasAttachments || false
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use the formatter to get properly formatted content
|
||||||
|
const { content } = formatReplyEmail(formatterEmail, 'reply');
|
||||||
|
|
||||||
|
// Return a new email object with the formatted content
|
||||||
|
return {
|
||||||
|
...email,
|
||||||
|
formattedContent: content
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error formatting email content:', error);
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
}, [email]);
|
||||||
|
|
||||||
// Load email content when selectedEmailId changes
|
// Load email content when selectedEmailId changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedEmailId) {
|
if (selectedEmailId) {
|
||||||
@ -201,7 +237,7 @@ export default function EmailPanel({
|
|||||||
) : (
|
) : (
|
||||||
<div className="max-w-4xl mx-auto h-full">
|
<div className="max-w-4xl mx-auto h-full">
|
||||||
<EmailPreview
|
<EmailPreview
|
||||||
email={email}
|
email={formattedEmail}
|
||||||
onReply={handleReply}
|
onReply={handleReply}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -41,6 +41,7 @@ interface EmailMessage {
|
|||||||
content?: string;
|
content?: string;
|
||||||
html?: string;
|
html?: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
|
formattedContent?: string;
|
||||||
hasAttachments?: boolean;
|
hasAttachments?: boolean;
|
||||||
attachments?: Array<{
|
attachments?: Array<{
|
||||||
filename: string;
|
filename: string;
|
||||||
@ -63,7 +64,6 @@ interface EmailPreviewProps {
|
|||||||
export default function EmailPreview({ email, loading = false, onReply }: EmailPreviewProps) {
|
export default function EmailPreview({ email, loading = false, onReply }: EmailPreviewProps) {
|
||||||
// Add editorRef to match ComposeEmail exactly
|
// Add editorRef to match ComposeEmail exactly
|
||||||
const editorRef = useRef<HTMLDivElement>(null);
|
const editorRef = useRef<HTMLDivElement>(null);
|
||||||
const [formattedContent, setFormattedContent] = useState<string>('');
|
|
||||||
|
|
||||||
// Format the date
|
// Format the date
|
||||||
const formatDate = (date: Date | string) => {
|
const formatDate = (date: Date | string) => {
|
||||||
@ -101,39 +101,6 @@ export default function EmailPreview({ email, loading = false, onReply }: EmailP
|
|||||||
.slice(0, 2);
|
.slice(0, 2);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Format the email content using the EXACT same formatter as ComposeEmail
|
|
||||||
useEffect(() => {
|
|
||||||
if (email) {
|
|
||||||
try {
|
|
||||||
// Convert to the formatter message format
|
|
||||||
const formatterEmail: FormatterEmailMessage = {
|
|
||||||
id: email.id,
|
|
||||||
messageId: email.messageId,
|
|
||||||
subject: email.subject,
|
|
||||||
from: email.from || [],
|
|
||||||
to: email.to || [],
|
|
||||||
cc: email.cc || [],
|
|
||||||
bcc: email.bcc || [],
|
|
||||||
date: email.date,
|
|
||||||
content: email.content,
|
|
||||||
html: email.html,
|
|
||||||
text: email.text,
|
|
||||||
hasAttachments: email.hasAttachments || false
|
|
||||||
};
|
|
||||||
|
|
||||||
// Use EXACTLY the same formatter function as ComposeEmail uses
|
|
||||||
const { content } = formatReplyEmail(formatterEmail, 'reply');
|
|
||||||
|
|
||||||
// Set the identical formatted content
|
|
||||||
setFormattedContent(content);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error formatting email content:', error);
|
|
||||||
// Fallback to raw content if formatting fails
|
|
||||||
setFormattedContent(email.content || email.html || email.text || '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [email]);
|
|
||||||
|
|
||||||
// Display loading state
|
// Display loading state
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
@ -158,6 +125,10 @@ export default function EmailPreview({ email, loading = false, onReply }: EmailP
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sender = email.from && email.from.length > 0 ? email.from[0] : undefined;
|
const sender = email.from && email.from.length > 0 ? email.from[0] : undefined;
|
||||||
|
|
||||||
|
// Use the directly formatted content provided by the parent component
|
||||||
|
// This is now exactly the same content that ComposeEmail would use
|
||||||
|
const displayContent = email.formattedContent || email.content || email.html || email.text || '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="flex flex-col h-full overflow-hidden border-0 shadow-none">
|
<Card className="flex flex-col h-full overflow-hidden border-0 shadow-none">
|
||||||
@ -236,7 +207,7 @@ export default function EmailPreview({ email, loading = false, onReply }: EmailP
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Email content - IDENTICAL to what ComposeEmail would show when replying */}
|
{/* Email content - using the preformatted content */}
|
||||||
<ScrollArea className="flex-1">
|
<ScrollArea className="flex-1">
|
||||||
<div className="space-y-2 p-6">
|
<div className="space-y-2 p-6">
|
||||||
<div className="border rounded-md overflow-hidden">
|
<div className="border rounded-md overflow-hidden">
|
||||||
@ -244,7 +215,7 @@ export default function EmailPreview({ email, loading = false, onReply }: EmailP
|
|||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
contentEditable={false}
|
contentEditable={false}
|
||||||
className="w-full p-4 min-h-[300px] focus:outline-none email-content-display"
|
className="w-full p-4 min-h-[300px] focus:outline-none email-content-display"
|
||||||
dangerouslySetInnerHTML={{ __html: formattedContent }}
|
dangerouslySetInnerHTML={{ __html: displayContent }}
|
||||||
dir="rtl"
|
dir="rtl"
|
||||||
style={{
|
style={{
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user