diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 1434a8ef..75bf143d 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -101,137 +101,42 @@ function splitEmailHeadersAndBody(emailBody: string): { headers: string; body: s } function EmailContent({ email }: { email: Email }) { - const [content, setContent] = useState(null); - const [error, setError] = useState(null); - const [isLoading, setIsLoading] = useState(false); - - useEffect(() => { - let mounted = true; - - async function loadContent() { - if (!email) return; - - setIsLoading(true); - try { - // First try to directly render any available content - if (email.content && mounted) { - setContent( -
- ); - setIsLoading(false); - return; - } - - if (email.textContent && mounted) { - setContent( -
- {email.textContent} -
- ); - setIsLoading(false); - return; - } - - // If we have nothing to display, try the client-side decoding - if (!email.content && !email.textContent && !email.body && !email.rawContent) { - if (mounted) { - setContent(
No content available
); - setIsLoading(false); - } - return; - } - - const formattedEmail = (email.content || email.body || email.rawContent || '').trim(); - if (!formattedEmail) { - if (mounted) { - setContent(
No content available
); - setIsLoading(false); - } - return; - } - - try { - const parsedEmail = await decodeEmail(formattedEmail); - - if (mounted) { - if (parsedEmail.html) { - setContent( -
- ); - } else if (parsedEmail.text) { - setContent( -
- {parsedEmail.text} -
- ); - } else if (email.rawContent) { - // Use raw content directly if available and nothing else worked - setContent( -
- {email.rawContent} -
- ); - } else { - // Fall back to displaying the raw content - setContent( -
- {formattedEmail} -
- ); - } - setError(null); - } - } catch (parseError) { - console.error('Error parsing email:', parseError); - // Fallback to displaying raw content on parse error - if (mounted) { - setContent( -
- {email.rawContent || formattedEmail} -
- ); - } - } - - if (mounted) { - setIsLoading(false); - } - } catch (err) { - console.error('Error rendering email content:', err); - if (mounted) { - setError('Error rendering email content. Please try again.'); - setContent(null); - setIsLoading(false); - } - } - } - - loadContent(); - - return () => { - mounted = false; - }; - }, [email?.content, email?.body, email?.textContent, email?.rawContent]); - - if (isLoading) { + // Use state to track if we've rendered content + const [renderedContent, setRenderedContent] = useState(false); + + // If textContent is available, render it directly + if (email.textContent && !renderedContent) { + setRenderedContent(true); return ( -
-
+
+ {email.textContent}
); } - - if (error) { - return
{error}
; + + // If html content is available, render it directly + if (email.content && !renderedContent) { + setRenderedContent(true); + return ( +
+ ); } - - return content ||
No content available
; + + // Fallback to raw content if available + if (email.rawContent && !renderedContent) { + setRenderedContent(true); + return ( +
+ {email.rawContent} +
+ ); + } + + // Last resort + return
No content available
; } function renderEmailContent(email: Email) { @@ -531,6 +436,7 @@ export default function CourrierPage() { content: string; type: 'reply' | 'reply-all' | 'forward'; } | null>(null); + const [selectEmailLoading, setSelectEmailLoading] = useState(false); // Debug logging for email distribution useEffect(() => { @@ -677,70 +583,59 @@ export default function CourrierPage() { // Update handleEmailSelect to set selectedEmail correctly and improve error handling const handleEmailSelect = async (emailId: string) => { try { - // First, set partial selectedEmail to show something immediately - const emailToSelect = emails.find(email => email.id === emailId); - if (emailToSelect) { - console.log('Setting preliminary selected email:', { - id: emailToSelect.id, - subject: emailToSelect.subject, - hasContent: !!emailToSelect.content, - }); - setSelectedEmail(emailToSelect); - } - - // Then fetch the full content - console.log(`Fetching email content for ID: ${emailId}`); + // Set a provisional selected email immediately for better UX + const initialEmail = emails.find((e) => e.id === emailId) || null; + setSelectedEmail(initialEmail); + setSelectEmailLoading(true); + + console.log(`Fetching email ${emailId} from folder ${currentView}`); const response = await fetch(`/api/courrier/${emailId}?folder=${currentView}`); if (!response.ok) { - const errorText = await response.text(); - console.error(`Error response (${response.status}): ${errorText}`); - throw new Error(`Failed to fetch email content: ${response.status} ${response.statusText}`); + console.error(`Error fetching email: ${response.status} ${response.statusText}`); + setSelectEmailLoading(false); + return; } const fullEmail = await response.json(); - console.log('Received full email data:', { - id: fullEmail.id, - subject: fullEmail.subject, - hasContent: !!fullEmail.content, - fields: Object.keys(fullEmail), - }); + console.log("API RESPONSE for email:", JSON.stringify(fullEmail, null, 2)); - // Set the complete selectedEmail with all content - setSelectedEmail(fullEmail); + // Create a safe version of the email with guaranteed fields + const safeEmail = { + ...fullEmail, + content: fullEmail.content || "", + textContent: fullEmail.textContent || "", + rawContent: fullEmail.rawContent || "", + body: fullEmail.body || "" + }; - // Also update the email in the list - setEmails(prevEmails => prevEmails.map(email => - email.id === emailId - ? { ...email, read: true } - : email - )); - - // Try to mark as read in the background + // Set the selected email with complete information + setSelectedEmail(safeEmail); + + // Update the email in the list to mark it as read + setEmails((prevEmails) => + prevEmails.map((email) => + email.id === emailId ? { ...email, read: true } : email + ) + ); + + // Try to mark the email as read in the background try { - const markReadResponse = await fetch(`/api/mail/mark-read?folder=${currentView}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - emailId, - isRead: true, - }), + const markReadResponse = await fetch(`/api/mail/mark-read?id=${emailId}&folder=${currentView}`, { + method: "POST", }); - + if (!markReadResponse.ok) { - console.error('Failed to mark email as read:', await markReadResponse.text()); + console.error(`Error marking email as read: ${markReadResponse.status} ${markReadResponse.statusText}`); } - } catch (error) { - console.error('Error marking email as read:', error); + } catch (markReadError) { + console.error("Error calling mark-read API:", markReadError); } + + setSelectEmailLoading(false); } catch (error) { - console.error('Error fetching email:', error); - // Keep the selected email if it was set initially - if (!selectedEmail) { - setError('Failed to load email content. Please try again.'); - } + console.error("Error in handleEmailSelect:", error); + setSelectEmailLoading(false); } }; @@ -1107,6 +1002,17 @@ export default function CourrierPage() { Viewing message from: {selectedEmail.from} • {new Date(selectedEmail.date).toLocaleString()}

+ {/* Direct content display for debugging */} +
+
+

Direct Content Preview

+
+
+ Content: {selectedEmail.content ? selectedEmail.content.substring(0, 200) : 'Empty'}
+ Text Content: {selectedEmail.textContent ? selectedEmail.textContent.substring(0, 200) : 'Empty'}
+
+
+
{/* Go back to using the original renderEmailContent function */} {renderEmailContent(selectedEmail)}