mail page fix design
This commit is contained in:
parent
47ec859fe2
commit
1757201730
@ -6,6 +6,7 @@ import { Input } from '@/components/ui/input';
|
|||||||
import { Label } from '@/components/ui/label';
|
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';
|
||||||
|
|
||||||
interface ComposeEmailProps {
|
interface ComposeEmailProps {
|
||||||
showCompose: boolean;
|
showCompose: boolean;
|
||||||
@ -54,23 +55,15 @@ export default function ComposeEmail({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (composeBodyRef.current) {
|
if (composeBodyRef.current) {
|
||||||
// Remove any existing content
|
const decodedContent = decodeComposeContent(composeBody);
|
||||||
composeBodyRef.current.innerHTML = '';
|
composeBodyRef.current.innerHTML = decodedContent;
|
||||||
|
|
||||||
// Create a temporary div to parse the HTML
|
|
||||||
const tempDiv = document.createElement('div');
|
|
||||||
tempDiv.innerHTML = composeBody;
|
|
||||||
|
|
||||||
// Append the parsed content to the contentEditable div
|
|
||||||
while (tempDiv.firstChild) {
|
|
||||||
composeBodyRef.current.appendChild(tempDiv.firstChild);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [composeBody]);
|
}, [composeBody]);
|
||||||
|
|
||||||
const handleInput = (e: React.FormEvent<HTMLDivElement>) => {
|
const handleInput = (e: React.FormEvent<HTMLDivElement>) => {
|
||||||
if (composeBodyRef.current) {
|
if (composeBodyRef.current) {
|
||||||
setComposeBody(composeBodyRef.current.innerHTML);
|
const encodedContent = encodeComposeContent(composeBodyRef.current.innerHTML);
|
||||||
|
setComposeBody(encodedContent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -228,12 +221,9 @@ export default function ComposeEmail({
|
|||||||
ref={composeBodyRef}
|
ref={composeBodyRef}
|
||||||
contentEditable
|
contentEditable
|
||||||
onInput={handleInput}
|
onInput={handleInput}
|
||||||
className="w-full h-full mt-1 bg-white border border-gray-300 rounded-md p-2 text-gray-900 overflow-y-auto prose max-w-none"
|
className="w-full h-full mt-1 bg-white border border-gray-300 rounded-md p-2 text-gray-900 overflow-y-auto"
|
||||||
style={{
|
style={{
|
||||||
minHeight: '200px',
|
minHeight: '200px'
|
||||||
direction: 'inherit' as const,
|
|
||||||
textAlign: 'start',
|
|
||||||
unicodeBidi: 'plaintext'
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
82
lib/compose-mime-decoder.ts
Normal file
82
lib/compose-mime-decoder.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* Simple MIME decoder for compose message box
|
||||||
|
* Handles basic email content and text direction
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function decodeComposeContent(content: string): string {
|
||||||
|
if (!content) return '';
|
||||||
|
|
||||||
|
// Simple text direction detection
|
||||||
|
const hasRtlChars = /[\u0591-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC]/.test(content);
|
||||||
|
const direction = hasRtlChars ? 'rtl' : 'ltr';
|
||||||
|
|
||||||
|
// Basic HTML cleaning
|
||||||
|
let cleaned = content
|
||||||
|
// Remove script and style tags
|
||||||
|
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
|
||||||
|
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
|
||||||
|
// Remove meta tags
|
||||||
|
.replace(/<meta[^>]*>/gi, '')
|
||||||
|
// Remove head and title
|
||||||
|
.replace(/<head[^>]*>[\s\S]*?<\/head>/gi, '')
|
||||||
|
.replace(/<title[^>]*>[\s\S]*?<\/title>/gi, '')
|
||||||
|
// Preserve body attributes
|
||||||
|
.replace(/<body[^>]*>/gi, (match) => {
|
||||||
|
const dir = match.match(/dir=["'](rtl|ltr)["']/i)?.[1] || direction;
|
||||||
|
return `<body dir="${dir}">`;
|
||||||
|
})
|
||||||
|
.replace(/<\/body>/gi, '')
|
||||||
|
// Remove html tags
|
||||||
|
.replace(/<html[^>]*>/gi, '')
|
||||||
|
.replace(/<\/html>/gi, '')
|
||||||
|
// Handle basic formatting
|
||||||
|
.replace(/<br\s*\/?>/gi, '\n')
|
||||||
|
.replace(/<p[^>]*>/gi, '\n')
|
||||||
|
.replace(/<\/p>/gi, '\n')
|
||||||
|
.replace(/<div[^>]*>/gi, '\n')
|
||||||
|
.replace(/<\/div>/gi, '\n')
|
||||||
|
// Handle lists
|
||||||
|
.replace(/<ul[^>]*>/gi, '\n')
|
||||||
|
.replace(/<\/ul>/gi, '\n')
|
||||||
|
.replace(/<ol[^>]*>/gi, '\n')
|
||||||
|
.replace(/<\/ol>/gi, '\n')
|
||||||
|
.replace(/<li[^>]*>/gi, '• ')
|
||||||
|
.replace(/<\/li>/gi, '\n')
|
||||||
|
// Handle basic text formatting
|
||||||
|
.replace(/<strong[^>]*>/gi, '**')
|
||||||
|
.replace(/<\/strong>/gi, '**')
|
||||||
|
.replace(/<b[^>]*>/gi, '**')
|
||||||
|
.replace(/<\/b>/gi, '**')
|
||||||
|
.replace(/<em[^>]*>/gi, '*')
|
||||||
|
.replace(/<\/em>/gi, '*')
|
||||||
|
.replace(/<i[^>]*>/gi, '*')
|
||||||
|
.replace(/<\/i>/gi, '*')
|
||||||
|
// Handle links
|
||||||
|
.replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi, '$2 ($1)')
|
||||||
|
// Handle basic entities
|
||||||
|
.replace(/ /g, ' ')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, "'")
|
||||||
|
// Clean up whitespace
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
// Wrap in a div with proper direction
|
||||||
|
return `<div dir="${direction}" style="direction: ${direction}; text-align: ${direction === 'rtl' ? 'right' : 'left'}">${cleaned}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encodeComposeContent(content: string): string {
|
||||||
|
if (!content) return '';
|
||||||
|
|
||||||
|
// Basic HTML encoding
|
||||||
|
return content
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''')
|
||||||
|
.replace(/\n/g, '<br>');
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user