mail page fix design dang
This commit is contained in:
parent
30684cb3b9
commit
795211f785
@ -41,7 +41,7 @@ import {
|
|||||||
import DOMPurify from 'isomorphic-dompurify';
|
import DOMPurify from 'isomorphic-dompurify';
|
||||||
import ComposeEmail from '@/components/ComposeEmail';
|
import ComposeEmail from '@/components/ComposeEmail';
|
||||||
|
|
||||||
interface Account {
|
export interface Account {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
@ -49,7 +49,7 @@ interface Account {
|
|||||||
folders?: string[];
|
folders?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Email {
|
export interface Email {
|
||||||
id: number;
|
id: number;
|
||||||
accountId: number;
|
accountId: number;
|
||||||
from: string;
|
from: string;
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { Paperclip, X } from 'lucide-react';
|
import { Paperclip, X } from 'lucide-react';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { decodeComposeContent, encodeComposeContent } from '@/lib/compose-mime-decoder';
|
import { decodeComposeContent, encodeComposeContent } from '@/lib/compose-mime-decoder';
|
||||||
|
import { Email } from '@/app/courrier/page';
|
||||||
|
|
||||||
interface ComposeEmailProps {
|
interface ComposeEmailProps {
|
||||||
showCompose: boolean;
|
showCompose: boolean;
|
||||||
@ -32,6 +33,16 @@ interface ComposeEmailProps {
|
|||||||
content: string;
|
content: string;
|
||||||
type: 'reply' | 'reply-all' | 'forward';
|
type: 'reply' | 'reply-all' | 'forward';
|
||||||
};
|
};
|
||||||
|
onSend: (email: Email) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
onBodyChange?: (body: string) => void;
|
||||||
|
initialTo?: string;
|
||||||
|
initialSubject?: string;
|
||||||
|
initialBody?: string;
|
||||||
|
initialCc?: string;
|
||||||
|
initialBcc?: string;
|
||||||
|
replyTo?: Email;
|
||||||
|
forwardFrom?: Email;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ComposeEmail({
|
export default function ComposeEmail({
|
||||||
@ -54,68 +65,75 @@ export default function ComposeEmail({
|
|||||||
attachments,
|
attachments,
|
||||||
setAttachments,
|
setAttachments,
|
||||||
handleSend,
|
handleSend,
|
||||||
originalEmail
|
originalEmail,
|
||||||
|
onSend,
|
||||||
|
onCancel,
|
||||||
|
onBodyChange,
|
||||||
|
initialTo,
|
||||||
|
initialSubject,
|
||||||
|
initialBody,
|
||||||
|
initialCc,
|
||||||
|
initialBcc,
|
||||||
|
replyTo,
|
||||||
|
forwardFrom
|
||||||
}: ComposeEmailProps) {
|
}: ComposeEmailProps) {
|
||||||
const composeBodyRef = useRef<HTMLDivElement>(null);
|
const composeBodyRef = useRef<HTMLDivElement>(null);
|
||||||
const [localContent, setLocalContent] = useState('');
|
const [localContent, setLocalContent] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (composeBodyRef.current) {
|
if (composeBodyRef.current) {
|
||||||
// Only initialize once when empty or first loading
|
// Initialize the content structure
|
||||||
if (!composeBody || composeBody.trim() === '') {
|
const originalContent = originalEmail?.content || '';
|
||||||
// Simple structure with one area for new text and one for original
|
composeBodyRef.current.innerHTML = `
|
||||||
composeBodyRef.current.innerHTML = `
|
<div id="new-reply-area" dir="ltr" style="margin-bottom: 20px; min-height: 40px;"></div>
|
||||||
<div id="new-reply-area" dir="ltr" style="margin-bottom: 20px; min-height: 40px;"></div>
|
<div id="original-email" dir="ltr" style="border-top: 1px solid #e0e0e0; padding-top: 10px; color: #555;">
|
||||||
<div id="original-email" dir="ltr" style="border-top: 1px solid #e0e0e0; padding-top: 10px; color: #555;">
|
${originalContent}
|
||||||
${composeBody ? decodeComposeContent(composeBody) : ''}
|
</div>
|
||||||
</div>
|
`;
|
||||||
`;
|
|
||||||
|
// Place cursor at the beginning of new reply area
|
||||||
// Place cursor at the beginning of new reply area
|
const newReplyArea = composeBodyRef.current.querySelector('#new-reply-area');
|
||||||
const newReplyArea = composeBodyRef.current.querySelector('#new-reply-area');
|
if (newReplyArea) {
|
||||||
if (newReplyArea) {
|
const range = document.createRange();
|
||||||
const range = document.createRange();
|
const sel = window.getSelection();
|
||||||
const sel = window.getSelection();
|
range.setStart(newReplyArea, 0);
|
||||||
range.setStart(newReplyArea, 0);
|
range.collapse(true);
|
||||||
range.collapse(true);
|
sel?.removeAllRanges();
|
||||||
sel?.removeAllRanges();
|
sel?.addRange(range);
|
||||||
sel?.addRange(range);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// For existing content, just update the original email part
|
|
||||||
const originalEmailDiv = composeBodyRef.current.querySelector('#original-email');
|
|
||||||
if (originalEmailDiv) {
|
|
||||||
originalEmailDiv.innerHTML = decodeComposeContent(composeBody);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []); // Only run once on initial mount, not on every composeBody change
|
}, [originalEmail]); // Run when originalEmail changes
|
||||||
|
|
||||||
// Modified input handler to prevent nested structures
|
// Modified input handler to prevent nested structures
|
||||||
const handleInput = (e: React.FormEvent<HTMLDivElement>) => {
|
const handleInput = (e: React.FormEvent<HTMLDivElement>) => {
|
||||||
// Get raw content from the editable div
|
if (!composeBodyRef.current) return;
|
||||||
const currentContent = e.currentTarget.innerHTML;
|
|
||||||
|
// Get the new reply content
|
||||||
// Store the original content reference
|
const newReplyArea = composeBodyRef.current.querySelector('#new-reply-area');
|
||||||
const originalEmailDiv = e.currentTarget.querySelector('#original-email');
|
const originalEmailArea = composeBodyRef.current.querySelector('#original-email');
|
||||||
const originalContent = originalEmailDiv?.innerHTML || '';
|
|
||||||
|
|
||||||
// Extract user-typed content (everything before original-email div)
|
|
||||||
const userContent = currentContent.split('<div id="original-email"')[0];
|
|
||||||
|
|
||||||
|
if (!newReplyArea || !originalEmailArea) return;
|
||||||
|
|
||||||
|
const newReplyContent = newReplyArea.innerHTML;
|
||||||
|
const originalContent = originalEmailArea.innerHTML;
|
||||||
|
|
||||||
// Update local state
|
// Update local state
|
||||||
setLocalContent(userContent);
|
setComposeBody(newReplyContent);
|
||||||
|
|
||||||
// Combine new reply and original formatted correctly
|
// Combine both contents while maintaining formatting
|
||||||
const combinedContent = `
|
const formattedContent = `
|
||||||
${userContent}
|
<div id="new-reply-area" dir="ltr" style="margin-bottom: 20px; min-height: 40px;">
|
||||||
|
${newReplyContent}
|
||||||
|
</div>
|
||||||
<div id="original-email" dir="ltr" style="border-top: 1px solid #e0e0e0; padding-top: 10px; color: #555;">
|
<div id="original-email" dir="ltr" style="border-top: 1px solid #e0e0e0; padding-top: 10px; color: #555;">
|
||||||
${originalContent}
|
${originalContent}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Update the compose body
|
// Update the compose form
|
||||||
setComposeBody(combinedContent);
|
if (onBodyChange) {
|
||||||
|
onBodyChange(formattedContent);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFileAttachment = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileAttachment = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user