courrier preview
This commit is contained in:
parent
1f6032941a
commit
cdd5bd98bc
@ -45,11 +45,35 @@ export default function EmailDetailView({
|
|||||||
// Render email content based on the email body
|
// Render email content based on the email body
|
||||||
const renderEmailContent = () => {
|
const renderEmailContent = () => {
|
||||||
try {
|
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,
|
hasContent: !!email.content,
|
||||||
contentType: typeof 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,
|
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
|
// 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 content is a string, use it directly
|
||||||
if (typeof email.content === 'string') {
|
if (typeof email.content === 'string') {
|
||||||
contentToUse = email.content;
|
contentToUse = email.content;
|
||||||
|
console.log('Using email.content as string', contentToUse.substring(0, 50));
|
||||||
}
|
}
|
||||||
// If content is an object with html/text properties
|
// If content is an object with html/text properties
|
||||||
else if (typeof email.content === 'object') {
|
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, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.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
|
// Fall back to html or text properties if content is not available
|
||||||
else if (email.html) {
|
else if (email.html) {
|
||||||
contentToUse = email.html;
|
contentToUse = email.html;
|
||||||
|
console.log('Using fallback email.html', contentToUse.substring(0, 50));
|
||||||
}
|
}
|
||||||
else if (email.text) {
|
else if (email.text) {
|
||||||
// Convert plain text to HTML with line breaks
|
// Convert plain text to HTML with line breaks
|
||||||
@ -76,6 +114,15 @@ export default function EmailDetailView({
|
|||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
.replace(/>/g, '>')
|
.replace(/>/g, '>')
|
||||||
.replace(/\n/g, '<br>');
|
.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
|
// Return content or fallback message
|
||||||
|
|||||||
@ -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, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.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
|
// Load emails from the server
|
||||||
const loadEmails = useCallback(async (page: number, perPage: number, isLoadMore: boolean = false) => {
|
const loadEmails = useCallback(async (page: number, perPage: number, isLoadMore: boolean = false) => {
|
||||||
// CRITICAL FIX: Do important validation before setting loading state
|
// CRITICAL FIX: Do important validation before setting loading state
|
||||||
@ -355,9 +433,11 @@ export const useEmailState = () => {
|
|||||||
|
|
||||||
if (existingEmail && existingEmail.contentFetched) {
|
if (existingEmail && existingEmail.contentFetched) {
|
||||||
// Use the existing email if it has content already
|
// Use the existing email if it has content already
|
||||||
|
// ENHANCEMENT: Apply content normalization before selecting the email
|
||||||
|
const normalizedEmail = normalizeEmailContent(existingEmail);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SELECT_EMAIL',
|
type: 'SELECT_EMAIL',
|
||||||
payload: { emailId, accountId, folder, email: existingEmail }
|
payload: { emailId, accountId, folder, email: normalizedEmail }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mark as read if not already
|
// Mark as read if not already
|
||||||
@ -386,10 +466,13 @@ export const useEmailState = () => {
|
|||||||
// Mark the email as read on the server
|
// Mark the email as read on the server
|
||||||
markEmailAsRead(emailId, true, effectiveAccountId);
|
markEmailAsRead(emailId, true, effectiveAccountId);
|
||||||
|
|
||||||
|
// ENHANCEMENT: Apply content normalization before selecting the email
|
||||||
|
const normalizedEmailData = normalizeEmailContent(emailData);
|
||||||
|
|
||||||
// Select the email
|
// Select the email
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SELECT_EMAIL',
|
type: 'SELECT_EMAIL',
|
||||||
payload: { emailId, accountId: effectiveAccountId, folder, email: emailData }
|
payload: { emailId, accountId: effectiveAccountId, folder, email: normalizedEmailData }
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logEmailOp('ERROR', `Failed to select email: ${error instanceof Error ? error.message : String(error)}`);
|
logEmailOp('ERROR', `Failed to select email: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
@ -400,7 +483,7 @@ export const useEmailState = () => {
|
|||||||
} finally {
|
} finally {
|
||||||
dispatch({ type: 'SET_LOADING', payload: false });
|
dispatch({ type: 'SET_LOADING', payload: false });
|
||||||
}
|
}
|
||||||
}, [state.emails, logEmailOp]);
|
}, [state.emails, logEmailOp, normalizeEmailContent]);
|
||||||
|
|
||||||
// Toggle email selection for multi-select
|
// Toggle email selection for multi-select
|
||||||
const toggleEmailSelection = useCallback((emailId: string) => {
|
const toggleEmailSelection = useCallback((emailId: string) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user