diff --git a/components/ComposeEmail.tsx b/components/ComposeEmail.tsx index 2ac5c515..41f07b65 100644 --- a/components/ComposeEmail.tsx +++ b/components/ComposeEmail.tsx @@ -154,7 +154,7 @@ export default function ComposeEmail({ // Format the reply/forward content const quotedContent = forwardFrom ? ` -
+
---------- Forwarded message ---------
From: ${emailToProcess.from}
Date: ${new Date(emailToProcess.date).toLocaleString()}
@@ -162,22 +162,22 @@ export default function ComposeEmail({ To: ${emailToProcess.to}
${emailToProcess.cc ? `Cc: ${emailToProcess.cc}
` : ''}
-
+
${emailContent}
` : ` -
+
On ${new Date(emailToProcess.date).toLocaleString()}, ${emailToProcess.from} wrote:
-
+
${emailContent} -
+
`; // Set the content in the compose area with proper structure const formattedContent = `
-

+

${quotedContent}
`; @@ -188,7 +188,7 @@ export default function ComposeEmail({ // Place cursor at the beginning before the quoted content const selection = window.getSelection(); const range = document.createRange(); - const firstDiv = composeBodyRef.current.querySelector('div[style*="min-height: 20px;"]'); + const firstDiv = composeBodyRef.current.querySelector('.cursor-position'); if (firstDiv) { range.setStart(firstDiv, 0); range.collapse(true); @@ -197,10 +197,75 @@ export default function ComposeEmail({ (firstDiv as HTMLElement).focus(); } + // Add event listeners to handle scrolling within message-content zone + const messageContentDivs = composeBodyRef.current.querySelectorAll('.message-content'); + messageContentDivs.forEach(div => { + // Change cursor to text when hovering over the message content + div.addEventListener('mouseenter', () => { + (div as HTMLElement).style.outline = '1px solid #d1d5db'; + (div as HTMLElement).style.cursor = 'text'; + }); + + div.addEventListener('mouseleave', () => { + (div as HTMLElement).style.outline = 'none'; + }); + + // Make sure clicking inside positions cursor correctly + div.addEventListener('click', (e: Event) => { + const mouseEvent = e as MouseEvent; + mouseEvent.stopPropagation(); + + // Get precise click position for cursor placement + const selection = window.getSelection(); + if (!selection) return; + + try { + const range = document.caretRangeFromPoint(mouseEvent.clientX, mouseEvent.clientY); + if (range) { + selection.removeAllRanges(); + selection.addRange(range); + } else { + // Fallback if caretRangeFromPoint is not available + const newRange = document.createRange(); + if (e.target instanceof Node) { + // Try to place at exact position + if (e.target.nodeType === Node.TEXT_NODE) { + const offset = Math.floor((e.target as Text).length / 2); + newRange.setStart(e.target, offset); + } else { + newRange.selectNodeContents(e.target); + } + newRange.collapse(true); + selection.removeAllRanges(); + selection.addRange(newRange); + } + } + } catch (err) { + console.error("Error positioning cursor:", err); + } + }); + + // Handle wheel events to scroll within the zone + div.addEventListener('wheel', (e: Event) => { + const wheelEvent = e as WheelEvent; + const target = wheelEvent.currentTarget as HTMLElement; + const scrollAmount = wheelEvent.deltaY; + + // Adjust scroll position + target.scrollTop += scrollAmount; + + // Prevent page scroll when scrolling inside the message content + if ((target.scrollTop > 0 && scrollAmount > 0) || + (target.scrollTop < target.scrollHeight - target.clientHeight && scrollAmount < 0)) { + e.preventDefault(); + } + }); + }); + // Update compose state setComposeBody(formattedContent); setLocalContent(formattedContent); - console.log('[DEBUG] Successfully set compose content'); + console.log('[DEBUG] Successfully set compose content with scrollable message area'); } } catch (error) { console.error('[DEBUG] Error initializing compose content:', error); @@ -240,6 +305,14 @@ export default function ComposeEmail({ if (onBodyChange) { onBodyChange(content); } + + // Ensure scrolling and cursor behavior works after edits + const messageContentDivs = composeBodyRef.current.querySelectorAll('.message-content'); + messageContentDivs.forEach(div => { + // Make sure the div remains scrollable after input events + (div as HTMLElement).style.maxHeight = '300px'; + (div as HTMLElement).style.overflowY = 'auto'; + }); }; const handleSendEmail = async () => {