feat(drafts): open drafts in the composer for editing, with save-draft on close - #42
Open
lucletoffe wants to merge 1 commit into
Open
feat(drafts): open drafts in the composer for editing, with save-draft on close#42lucletoffe wants to merge 1 commit into
lucletoffe wants to merge 1 commit into
Conversation
…t on close Drafts were dead ends: tapping one opened the read-only thread view whose only actions (reply, tag, mark unread) treat it like a received message — there was no way to resume editing, and the composer never saved drafts. - Tapping a $draft message in the list now reopens the composer prefilled with its recipients, subject, body, attachments (reused by blobId) and hydrated inline cid images; the thread view gains an Edit button for drafts reached through other paths. - Sending an edited draft destroys the original after submission; JMAP emails being immutable (RFC 8621 §4), saving re-creates the draft with $draft in the drafts mailbox and destroys the replaced one atomically. - Closing a dirty composer now offers Save draft next to Discard; an untouched reopened draft closes silently (content-fingerprint baseline). - A draft's Bcc and In-Reply-To/References survive the round trip even though the composer UI doesn't expose them yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACzTUX8qVZ4qAp8gqUHb5t
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Drafts are currently dead ends in the mobile app. Tapping a message in the Drafts folder opens the read-only thread view, whose only actions (reply, forward, tag, mark read/unread…) treat it like any received message — there is no way to resume editing a draft, and the composer itself never offers to save one. Drafts written in the webmail (or any other JMAP client) can be viewed but not continued on mobile.
Root cause: there is simply no edit path in the code.
Composeonly knowsreply | replyAll | forward(src/navigation/types.ts), and a row tap always navigates toEmailThreadregardless of the$draftkeyword (App.tsx).What this PR does
$draftmessage tapped in the list reopens the composer prefilled with its recipients, subject, body, and attachments (reused byblobId, no re-upload). Inlinecid:images are hydrated to data URLs (same 2 MB ceiling asEmailBodyView) so they render and survive the round trip; non-hydrated cid parts keep theircidso the reference still resolves for the recipient.saveDraftre-creates the message with$draftin the drafts mailbox and destroys the replaced one in the sameEmail/setcall.BccandIn-Reply-To/Referencessurvive editing even though the composer UI doesn't expose those fields yet.Implementation notes
src/api/email.ts: the email-object assembly is extracted fromsendEmailintobuildEmailCreate(shared with the newsaveDraft);sendEmail's request shape and submission behaviour are unchanged.src/lib/draft-compose.ts: pureEmail → composer statemapping (body extraction mirrorsEmailBodyView, sanitized withstripDangerousTags), plus thecid:→ data-URL rewrite (stamps the editor'sdata-cidmarker sorewriteInlineImagesconverts them back at send time).setHtmlinto the webview.Tests
saveDraft: create with$draftin the drafts mailbox, atomic destroy of the replaced draft, recipient-less drafts, server rejection.draftToComposeInit: field mapping, text→HTML escaping, dangerous-tag stripping, attachment classification and cid unwrapping, threading headers, empty-draft defaults.rewriteCidSrcToDataUrls: rewrite +data-cidstamp, non-hydrated cid left untouched, no-op without cid refs.npx tsc --noEmitclean;vitest448/448 passing (theauth-store.test.tscollection error is pre-existing onmain).🤖 Generated with Claude Code
https://claude.ai/code/session_01ACzTUX8qVZ4qAp8gqUHb5t