Fix email reply, scheduling, and message handling bugs#3926
Conversation
Bug fixes found in a package-wide review:
Components
- EmailContext: archiveThread no longer archives twice (the unconditional
mutate ran in addition to mark-done, which also archives and whose undo
couldn't undo the extra mutate; the else branch was a verbatim duplicate)
- EmailContext: make the thread sort comparator transitive by comparing
per-message timestamps (internal_date_ts ?? sent_at) instead of requiring
both messages to share a field
- Block: don't crash rendering threads whose first message has a null
subject, and make the 'Email' title fallback reachable
- Email: handleTargetMessage no longer double-scrolls (missing else before
case 3), polling loops stop on unmount, dead checks removed, and
firstUnreadMessageId stops re-sorting the already-sorted list
- Email: fix vacuous isDraft check (draft !== null was always true)
- EmailMessageBody: fall back to the full sanitized HTML when body_replyless
is empty and there is no .macro_quote, instead of rendering a blank body;
don't pass undefined body_text to StaticMarkdown
- MessageActions: fix inverted allActionsHidden check (it tested whether
hidden actions were valid, not whether all actions were hidden)
- BaseInput: sends now honor the user-selected "from" inbox
(form().selectedLinkId()) like draft saves already did, so the send goes
out from the inbox shown in the UI
- BaseInput: only clear the module-level undo-send restore slot if this
instance still owns it (two inputs can be mounted at once)
- BaseInput: re-attach onDirty/onReplyTypeApplied when the form memo re-keys
after a send, so autosave keeps working without a remount
- BaseInput: quote toggle works when replying to a thread's root message
(guard on db_id, not replying_to_id)
- BaseInput/Compose: failed schedule-send no longer leaves the composer
stuck in a phantom "scheduled" state with Send disabled; schedule errors
are caught and surfaced
- date-selector: time input validation actually validates (Number.isNaN was
called on strings)
Utils
- prepareEmailBody: body_text now includes all user content (was truncated
to the first top-level element after paragraph flattening) while still
excluding the quoted thread; reply header no longer renders "undefined"
for a missing sender; malformed data-block-params no longer aborts
send/draft-save; data-collapsed parsed as === 'true' instead of
Boolean('false') being true; $findPreviousEmailNode returns instead of
falling through when no ID is given
- DocumentMentionNode: export the collapsed state as data-collapsed instead
of a bogus DOMConversionMap attribute, so it survives HTML round trips
- subjectText: null subjects no longer become "Re: null", and existing
Re:/RE:/re: prefixes are detected case-insensitively at the start of the
subject only (with tests)
- emailUser/recipientConversion/mentionToCc: email comparisons are now
case-insensitive via a shared emailsMatch helper, fixing "Me" labels,
reply-all self-filtering and CC dedupe for case-differing addresses
- plainTextToHtml: a blank source line renders as one blank line, not two
- emailHotkeys: remove stubbed reply/reply-all/forward hotkeys that consumed
keypresses and showed dead entries in the hotkey UI
- scrollToMessage: check for message-not-found before applying the reversed
index mapping; drop dead helpers
Also removes dead code: _appendItemsAsMacroMentions, attachButtonRef
plumbing in ComposeToolbar, unused bodyDiv ref in ComposeBody.
https://claude.ai/code/session_01GJDgV1YUdUHqAB8GDXu5QQ
|
Warning Review limit reached
More reviews will be available in 8 minutes and 23 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (21)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This PR addresses multiple bugs and edge cases in the email compose and message handling flows, with a focus on improving reliability and correctness.
Summary
Fixes several issues in email reply composition, message scheduling, recipient handling, and message scrolling. Includes improvements to error handling, state management, and email address comparison logic.
Key Changes
Compose & Scheduling:
scheduleMessageandflagArchivedcallsrestoreUndoCallbackto only clear when the current instance owns it, preventing interference between multiple BaseInput instancesonMounttocreateEffectfor form callbacks to handle re-keying when reply context changesEmail Address Handling:
emailsMatch()utility for case-insensitive email comparisonMessage Display & Scrolling:
scrollToMessage()to check bounds before applying reversed index calculationfirstUnreadMessageIdmemo (messages already sorted in context)loadMessagesUntilFoundto return false when disposed instead of infinite loopReply Handling:
db_idinstead ofreplying_to_id(root messages have no replying_to_id)buildHeaderDescriptorto handle missing sender name/email with fallback to empty string$findPreviousEmailNodegenerator to usereturninstead ofyieldwhen no replyingToIDDraft Content Detection:
prepareEmailBodyto exclude quoted thread text when extracting plain text, preventing empty replies from being mistaken as having content.macro_quoteelements before extracting textSubject Line Handling:
getSubjectTextto use case-insensitive regex for detecting existing "Re:" prefixesHTML/Text Conversion:
plainTextToHtmlto not double blank lines (empty lines map to '' with join providing the break)UI & Hotkeys:
Code Quality:
https://claude.ai/code/session_01GJDgV1YUdUHqAB8GDXu5QQ