Skip to content

fix(thread): show every message of the thread, not just the tapped one - #43

Open
lucletoffe wants to merge 1 commit into
bulwarkmail:mainfrom
lucletoffe:fix/thread-view-all-messages
Open

fix(thread): show every message of the thread, not just the tapped one#43
lucletoffe wants to merge 1 commit into
bulwarkmail:mainfrom
lucletoffe:fix/thread-view-all-messages

Conversation

@lucletoffe

Copy link
Copy Markdown
Contributor

Problem

The email list collapses same-thread messages into one row with a count badge — but tapping that row shows a single message. EmailThreadScreen receives a threadId route param and never uses it: each pager pane renders only the tapped email, and Prev/Next walk the flat mailbox list. The rest of the conversation — including your own replies filed in Sent — is unreachable from the thread view.

What this PR does

Each pager pane now renders the whole thread, oldest first:

  • The thread is fetched once per threadId (Thread/get + a light Email/get, coalesced and cached across the three mounted panes) and follows the server's ordering (RFC 8621 §3).
  • Messages other than the tapped one start collapsed: sender, one preview line, date, unread dot. Tapping unfolds a message in place, loads its full body on demand, and marks it read. Tapping an expanded message's header folds it back.
  • The tapped message is expanded from the start and keeps the existing configurable mark-as-read delay.
  • The subject row shows the real thread size — which can exceed the list badge, since that badge only counts messages in the open folder.
  • A thread fetch failure (or a single-message thread) degrades to the exact previous single-message view.

Implementation notes

  • The former pane body (sender header, attachment chips, calendar banner, EmailBodyView) is extracted as MessageSection, rendered once per expanded message; the single-message path renders it identically to before (header stays non-pressable there).
  • Mark-read on expand: a thread member living in another folder isn't in the store's list, and the store's markRead would rebuild its keyword map from nothing — JMAP Email/set replaces keywords wholesale, wiping $flagged and user labels server-side. Such messages go through setEmailKeywords with the keywords merged from the fetched copy instead; in-list messages keep the store's optimistic path.
  • Shared/group accounts: Thread/get/Email/get ride the pane's ownerAccountId.
  • orderThreadEmails (server order, drops ids whose metadata didn't come back) is a pure function in lib/email-threading.ts, unit-tested.

Tests

  • orderThreadEmails: server-order preservation, expunged-id drop, empty thread.
  • npx tsc --noEmit clean; vitest 438/438 passing (the auth-store.test.ts collection error is pre-existing on main).

🤖 Generated with Claude Code

https://claude.ai/code/session_01ACzTUX8qVZ4qAp8gqUHb5t

The list collapses same-thread messages into one row with a count badge,
but opening it showed a single message: EmailThreadScreen never used its
threadId param, so the rest of the conversation — including replies filed
in Sent — was unreachable from the thread view.

Each pager pane now fetches the thread (Thread/get + a light Email/get,
coalesced across the three mounted panes) and renders it oldest-first:
collapsed header rows (sender, preview, date, unread dot) that unfold in
place, the tapped message expanded from the start. Expanding a message
loads its body on demand and marks it read. The subject row shows the
real thread size, which can exceed the list badge (that badge only counts
messages in the open folder).

The former pane body (sender header, attachments, calendar banner, body)
is extracted as MessageSection, rendered once per expanded message; a
thread fetch failure degrades to the previous single-message view.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACzTUX8qVZ4qAp8gqUHb5t
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant