courrier preview

This commit is contained in:
alma 2025-05-01 15:49:25 +02:00
parent 1f6032941a
commit cdd5bd98bc
2 changed files with 136 additions and 6 deletions

View File

@ -45,11 +45,35 @@ export default function EmailDetailView({
// Render email content based on the email body
const renderEmailContent = () => {
try {
console.log('EmailDetailView renderEmailContent', {
// Enhanced debugging to trace exactly what's in the content
console.log('EmailDetailView renderEmailContent - DETAILED DEBUG', {
emailId: email.id,
subject: email.subject,
hasContent: !!email.content,
contentType: typeof email.content,
contentKeys: email.content && typeof email.content === 'object' ? Object.keys(email.content) : [],
contentStringLength: typeof email.content === 'string' ? email.content.length : 'N/A',
contentHtmlLength: email.content && typeof email.content === 'object' && 'html' in email.content && typeof (email.content as any).html === 'string'
? ((email.content as any).html as string).length
: 0,
contentTextLength: email.content && typeof email.content === 'object' && 'text' in email.content && typeof (email.content as any).text === 'string'
? ((email.content as any).text as string).length
: 0,
contentSample: typeof email.content === 'string'
? email.content.substring(0, 100)
: (email.content && typeof email.content === 'object' && 'html' in email.content && typeof (email.content as any).html === 'string'
? ((email.content as any).html as string).substring(0, 100)
: (email.content && typeof email.content === 'object' && 'text' in email.content && typeof (email.content as any).text === 'string'
? ((email.content as any).text as string).substring(0, 100)
: 'N/A')),
hasHtml: !!email.html,
hasText: !!email.text
htmlLength: email.html?.length || 0,
htmlSample: email.html?.substring(0, 100) || 'N/A',
hasText: !!email.text,
textLength: email.text?.length || 0,
textSample: email.text?.substring(0, 100) || 'N/A',
contentIsNull: email.content === null,
contentIsUndefined: email.content === undefined,
});
// Determine what content to use and how to handle it
@ -59,15 +83,29 @@ export default function EmailDetailView({
// If content is a string, use it directly
if (typeof email.content === 'string') {
contentToUse = email.content;
console.log('Using email.content as string', contentToUse.substring(0, 50));
}
// If content is an object with html/text properties
else if (typeof email.content === 'object') {
contentToUse = email.content.html || email.content.text || '';
const contentObj = email.content as {html?: string; text?: string};
if (contentObj.html) {
contentToUse = contentObj.html;
console.log('Using email.content.html', contentToUse.substring(0, 50));
} else if (contentObj.text) {
// Convert plain text to HTML
contentToUse = contentObj.text
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\n/g, '<br>');
console.log('Using email.content.text (converted)', contentToUse.substring(0, 50));
}
}
}
// Fall back to html or text properties if content is not available
else if (email.html) {
contentToUse = email.html;
console.log('Using fallback email.html', contentToUse.substring(0, 50));
}
else if (email.text) {
// Convert plain text to HTML with line breaks
@ -76,6 +114,15 @@ export default function EmailDetailView({
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\n/g, '<br>');
console.log('Using fallback email.text (converted)', contentToUse.substring(0, 50));
}
// Log if no content was found
if (!contentToUse) {
console.error('No renderable content found in email!', {
id: email.id,
subject: email.subject
});
}
// Return content or fallback message

View File

@ -61,6 +61,84 @@ export const useEmailState = () => {
}
}, []);
// Normalize email content structure to ensure consistency
const normalizeEmailContent = useCallback((emailData: any): any => {
if (!emailData) return emailData;
// Create a clone to avoid modifying the original
const normalizedEmail = { ...emailData };
// Log the incoming email structure
console.log(`[NORMALIZE_EMAIL] Processing email ${normalizedEmail.id || 'unknown'}: ${normalizedEmail.subject || 'No subject'}`);
try {
// Handle content field normalization
if (!normalizedEmail.content) {
// Create content object if it doesn't exist
normalizedEmail.content = { html: '', text: '' };
// Try to populate content from html/text fields
if (normalizedEmail.html) {
normalizedEmail.content.html = normalizedEmail.html;
console.log(`[NORMALIZE_EMAIL] Populated content.html from email.html (${normalizedEmail.html.length} chars)`);
}
if (normalizedEmail.text) {
normalizedEmail.content.text = normalizedEmail.text;
console.log(`[NORMALIZE_EMAIL] Populated content.text from email.text (${normalizedEmail.text.length} chars)`);
}
}
// If content is a string, convert to object format
else if (typeof normalizedEmail.content === 'string') {
const htmlContent = normalizedEmail.content;
normalizedEmail.content = {
html: htmlContent,
text: htmlContent.replace(/<[^>]*>/g, '') // Simple HTML to text conversion
};
console.log(`[NORMALIZE_EMAIL] Converted string content to object (${htmlContent.length} chars)`);
}
// Ensure content object has both html and text properties
else if (typeof normalizedEmail.content === 'object') {
if (!normalizedEmail.content.html && normalizedEmail.content.text) {
// Convert text to simple HTML if only text exists
normalizedEmail.content.html = normalizedEmail.content.text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\n/g, '<br>');
console.log(`[NORMALIZE_EMAIL] Created HTML content from text (${normalizedEmail.content.text.length} chars)`);
} else if (!normalizedEmail.content.text && normalizedEmail.content.html) {
// Create plain text version if only HTML exists
normalizedEmail.content.text = normalizedEmail.content.html.replace(/<[^>]*>/g, '');
console.log(`[NORMALIZE_EMAIL] Created text content from HTML (${normalizedEmail.content.html.length} chars)`);
}
}
// Ensure html and text properties are also set for backward compatibility
if (normalizedEmail.content?.html && !normalizedEmail.html) {
normalizedEmail.html = normalizedEmail.content.html;
}
if (normalizedEmail.content?.text && !normalizedEmail.text) {
normalizedEmail.text = normalizedEmail.content.text;
}
console.log(`[NORMALIZE_EMAIL] Normalized email content structure successfully`, {
hasContentObj: !!normalizedEmail.content,
contentHtmlLength: normalizedEmail.content?.html?.length || 0,
contentTextLength: normalizedEmail.content?.text?.length || 0,
hasHtml: !!normalizedEmail.html,
hasText: !!normalizedEmail.text
});
return normalizedEmail;
} catch (error) {
console.error(`[NORMALIZE_EMAIL] Error normalizing email content:`, error);
// Return the original data if normalization fails
return emailData;
}
}, []);
// Load emails from the server
const loadEmails = useCallback(async (page: number, perPage: number, isLoadMore: boolean = false) => {
// CRITICAL FIX: Do important validation before setting loading state
@ -355,9 +433,11 @@ export const useEmailState = () => {
if (existingEmail && existingEmail.contentFetched) {
// Use the existing email if it has content already
// ENHANCEMENT: Apply content normalization before selecting the email
const normalizedEmail = normalizeEmailContent(existingEmail);
dispatch({
type: 'SELECT_EMAIL',
payload: { emailId, accountId, folder, email: existingEmail }
payload: { emailId, accountId, folder, email: normalizedEmail }
});
// Mark as read if not already
@ -386,10 +466,13 @@ export const useEmailState = () => {
// Mark the email as read on the server
markEmailAsRead(emailId, true, effectiveAccountId);
// ENHANCEMENT: Apply content normalization before selecting the email
const normalizedEmailData = normalizeEmailContent(emailData);
// Select the email
dispatch({
type: 'SELECT_EMAIL',
payload: { emailId, accountId: effectiveAccountId, folder, email: emailData }
payload: { emailId, accountId: effectiveAccountId, folder, email: normalizedEmailData }
});
} catch (error) {
logEmailOp('ERROR', `Failed to select email: ${error instanceof Error ? error.message : String(error)}`);
@ -400,7 +483,7 @@ export const useEmailState = () => {
} finally {
dispatch({ type: 'SET_LOADING', payload: false });
}
}, [state.emails, logEmailOp]);
}, [state.emails, logEmailOp, normalizeEmailContent]);
// Toggle email selection for multi-select
const toggleEmailSelection = useCallback((emailId: string) => {