fix(email): keep messages with draft replies expanded in thread view#5041
Conversation
A draft reply renders inline inside the message it replies to, but only while that message is expanded. When a newer message arrived, the drafted-on message collapsed and the draft disappeared from view. Now a message with an in-progress draft stays expanded (desktop only — mobile edits drafts in the compose drawer), matching Gmail/Superhuman. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughSummary by CodeRabbit
WalkthroughUpdated 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
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 |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/web/src/features/block-email/component/MessageList.tsx (1)
140-159: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueReplace
createMemowith derived signals for cheap derivations.
hasDraftandisExpandedperform simple object lookups and boolean evaluations. As per coding guidelines, do not usecreateMemofor cheap derivations; use standard functions (derived signals) instead to avoid unnecessary reactive node overhead.♻️ Proposed refactor
- const hasDraft = createMemo(() => { + const hasDraft = () => { const messageID = message().db_id; if (!messageID || isMobile()) return false; return !!context.drafts.getDraftForMessage(messageID); - }); + }; - const isExpanded = createMemo(() => { + const isExpanded = () => { const messageID = message().db_id; if (!messageID) return false; const manuallyExpanded = context.messages.isBodyExpanded(messageID); return ( manuallyExpanded || isLastMessage() || isNewMessage() || hasDraft() ); - }); + };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/features/block-email/component/MessageList.tsx` around lines 140 - 159, Replace the createMemo wrappers for hasDraft and isExpanded with standard derived functions while preserving their existing message ID checks, draft lookup, and expansion conditions. Update their call sites if needed to use the derived-function form, without changing behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@apps/web/src/features/block-email/component/MessageList.tsx`:
- Around line 140-159: Replace the createMemo wrappers for hasDraft and
isExpanded with standard derived functions while preserving their existing
message ID checks, draft lookup, and expansion conditions. Update their call
sites if needed to use the derived-function form, without changing behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d305ee94-5261-41aa-9467-bfe2cfceed25
📒 Files selected for processing (1)
apps/web/src/features/block-email/component/MessageList.tsx
Summary
In the email thread view, a draft reply renders inline inside the message it replies to — but only while that message is expanded. If you started a draft on a message and then a newer message arrived, the drafted-on message collapsed (it was no longer the last/unread message) and the draft vanished from view.
Messages with an in-progress draft reply now always stay expanded, matching Gmail and Superhuman behavior.
Changes
hasDraftcondition to theisExpandedmemo inMessageList.tsx, backed bycontext.drafts.getDraftForMessage()(a reactive store populated from the thread query, so this applies on initial load and when a draft appears later).