Commit Graph
157 Commits
Author SHA1 Message Date
Linus Rath 03031fcb13 feat: jump to the next unread message with n #514 2026-10-17 19:18:20 +02:00
Linus Rath 3fd93df4b2 feat: extend the message selection with shift+arrow keys #992 2026-10-17 19:18:15 +02:00
Linus Rath 7d882be734 fix: delete only the clicked mail when another account has a message with the same id #857 2026-10-17 19:18:00 +02:00
Linus Rath cbf917372c fix: show the mail's own date in the list and keep it on .eml import #891 2026-10-17 19:17:58 +02:00
Linus Rath 2f10374bab fix: let plugins gate batch forwards and keep each attachment's account #1070 2026-10-15 23:54:39 +02:00
daluchenandClaude Code c7cac25b7b fix: resolve the batch forward selection through account-scoped keys
Upstream renamed the store's selection from bare email ids to
account-scoped selectedEmailKeys, and a bare id can name a different
message in another account. Route the batch forward-as-attachment
handler through resolveSelectedEmails like the other batch actions:
it matches keys against the loaded rows and expanded thread members,
and the scheduled view it used to special-case offers no selection.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-15 15:03:43 +08:00
daluchenandClaude Code 5dde5e00e1 feat: add batch forward-as-attachment for selected emails
Multi-select emails in the list, right-click, and pick "Forward as
attachments" to open one composer carrying every selected message as
its own message/rfc822 (.eml) attachment - the batch sibling of the
existing single-message action.

- lib/forward-as-attachment.ts: buildBatchForwardAsAttachmentPayload
  builds one payload from many emails. The subject is count-based
  (there is no single original subject), with the count localized via
  an injected label so the subject never claims more attachments than
  the composer carries. Emails without a blobId are skipped; null when
  none has one, matching the single flow's silent no-op.
- mail-app.tsx: handleBatchForwardAsAttachment resolves the selection
  through useEmailStore.getState() (fresh state, list-ordered
  attachments, stale ids drop out), runs the plugin transform and veto
  hooks per email - one veto cancels the whole compose - and opens the
  composer with the attachments seeded via replyTo. Clears the
  selection only on success.
- email-context-menu.tsx / email-list.tsx: new batch menu item shown
  when the right-clicked email belongs to a multi-selection; hidden in
  the scheduled view like the single item.
- locales: context_menu.forward_as_attachments and
  email_composer.forward_batch_count in all 27 locales.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-15 14:50:31 +08:00
Linus Rath 8491f7d8db perf: stop loading the editor while the login form renders 2026-10-15 04:44:51 +02:00
Linus Rath a30ae541f9 perf: show the login form without loading the app a second time 2026-10-15 03:27:44 +02:00
Linus Rath d0abf6b494 perf: read the Sent folder for recipient suggestions once, after login settles 2026-10-15 02:57:30 +02:00
Linus Rath 84a53e9ea3 perf: stop re-rendering the folder sidebar when a message opens 2026-10-15 02:20:56 +02:00
Linus Rath 4edaf2663f perf: stop loading the mailboxes and first page twice after login 2026-10-15 02:16:50 +02:00
Linus Rath 59d762a385 perf: start loading a message when the mouse is pressed on it 2026-10-15 01:17:39 +02:00
Linus Rath 9e5f78ab6d perf: show the message header from the list row while its body loads 2026-10-15 00:41:07 +02:00
Linus Rath 06d00e10ee perf: keep the list on screen while a search runs and stop re-rendering on every keystroke 2026-10-15 00:12:59 +02:00
Linus Rath b59e3520f8 perf: stop re-rendering the message rows and mail view on unrelated store changes 2026-10-15 00:00:28 +02:00
Linus Rath 3fac196d3f fix: ask plugins before creating archive folders and marking whole folders read 2026-10-14 20:08:37 +02:00
Linus Rath 8204678847 fix: stop reporting mail actions as done when a plugin stopped them 2026-10-14 19:44:54 +02:00
Linus Rath 5d83d76436 feat: let plugins open a reply to the open message with text to start from 2026-10-14 11:37:51 +02:00
Linus Rath 2b493f8f9c feat: show the reader's plugin frames and actions on the open message of a phone conversation 2026-10-14 09:46:03 +02:00
Linus Rath 86e593a752 feat: add a command palette on Ctrl+K where plugins can add their own commands 2026-10-14 05:10:10 +02:00
Linus Rath b57fa64557 feat: let plugins add buttons to the top bar, and to the header menu on phones 2026-10-14 04:50:21 +02:00
Linus Rath 8ad8f44e78 Merge branch 'feat/plugin-host-apis' into feat/plugin-system-audit
# Conflicts:
#	lib/plugin-sandbox/permission-text.ts
#	lib/plugin-sandbox/permissions.ts
#	lib/protocol-handlers/mailto.ts
#	locales/en/common.json
2026-10-14 04:34:14 +02:00
Linus Rath ead925c1b8 feat: let plugins open a filled-in composer and save drafts 2026-10-14 04:23:17 +02:00
Linus Rath c464ca2030 Merge branch 'hooks/mailstore' into feat/plugin-system-audit 2026-10-14 04:00:59 +02:00
Linus Rath cc9553590c Merge branch 'hooks/mailui' into feat/plugin-system-audit 2026-10-14 04:00:45 +02:00
Linus Rath 2fe865f108 feat: tell plugins when the server accepted a sent or scheduled message, but not an undone one 2026-10-14 03:58:58 +02:00
Linus Rath 7323310b21 feat: tell plugins about new inbox mail, sync progress and the live-update connection 2026-10-14 03:56:37 +02:00
Linus Rath 286cce6877 feat: tell plugins when messages are deleted, moved, archived, marked or tagged, and let them stop it 2026-10-14 03:54:40 +02:00
Linus Rath 7b2119456d feat: let plugins stop or prefill the composer and mailto links, and tell them when it opens, closes and saves a draft 2026-10-14 03:50:55 +02:00
Linus Rath 69dbc1b661 feat: tell plugins when a message body is on screen or a conversation unfolds, and let them rewrite links 2026-10-14 03:39:13 +02:00
Linus Rath 606861eb71 feat: tell plugins about the app's lifecycle and navigation on every page, not only in mail 2026-10-14 03:19:54 +02:00
Linus Rath e09676126b feat: keep the selection while reading a message in mountain view #1231 2026-10-13 15:40:13 +02:00
Linus Rath 9cae33e3cb feat: keep the mountain view compose window open while reading other mail #1229 2026-10-13 15:25:56 +02:00
Linus Rath 693d9613c0 feat: let users turn off the prompt before deleting several messages #1225 2026-10-13 15:16:05 +02:00
Linus Rath 8daa316c18 fix: show a mountain view message together with its conversation #1223 2026-10-13 14:48:58 +02:00
Linus Rath 6f281ef10a fix: open mountain view threads as a conversation on the phone #1224 2026-10-13 14:35:12 +02:00
Linus Rath ddab7c781f feat: open several messages of a conversation at once in mountain view #1222 2026-10-13 14:24:47 +02:00
Linus Rath 66122ae652 feat: order Mountain View's bulk actions like Gmail's and search the Move to menu 2026-10-12 01:54:15 +02:00
Linus Rath 5efe718cf0 feat: order Mountain View's message menu like Gmail's and add Find emails from 2026-10-12 01:45:35 +02:00
Linus Rath 986daef90b feat: add Gmail's side panel with calendar, tasks and contacts to Mountain View 2026-10-12 01:40:30 +02:00
Linus Rath cedac10c29 feat: use Gmail's advanced search form in Mountain View 2026-10-12 01:34:02 +02:00
Linus Rath 78e68e8886 feat: write Mountain View replies in place under the conversation 2026-10-12 01:29:55 +02:00
Linus Rath c652fec371 feat: give Mountain View's compose window Gmail's title bar and bottom bar 2026-10-12 01:26:03 +02:00
Linus Rath 943a92bd42 feat: show the whole conversation around the open message in Mountain View 2026-10-12 01:16:15 +02:00
Linus Rath 1980de68c8 feat: give Mountain View's open message Gmail's toolbar, pager and header 2026-10-12 01:10:10 +02:00
Linus Rath ae151cec25 feat: set Mountain View's content on a rounded card over a tinted canvas 2026-10-12 00:37:59 +02:00
Shuki Vaknin 2a45f6099c fix: take a re-opened draft's body from its body parts only
A draft that carried attachments and no message re-opened with the
contents of one of the attachments as its text. Attach a .csv to an
empty draft, save it, re-open it: the editor shows the rows of the csv
as what you had written, and the next save or send makes that the real
message.

Both edit-draft paths built the text body by joining every value in
bodyValues:

    Object.values(draft.bodyValues).map(v => v.value).join('\n')

bodyValues is keyed by part id, and getEmail asks for
fetchAllBodyValues, which per RFC 8621 4.1.4 returns a value for every
text/* part of the message - attachments included. So any attached
.csv, .txt, .log or .md was joined in as body text, and with no html
body to prefer it became the whole message.

Take the body from the parts the server lists as the body instead, and
from nothing else. A draft whose textBody is empty now re-opens empty,
which is what an attachments-only draft is.

The selection lives in lib/email-body-selection.ts beside
getRenderableHtmlBody, which exists because the viewer and the mobile
thread view had already drifted apart once (#489). mail-app and the pro
email tab held character-for-character copies of this join, so the same
drift was already in place.
2026-10-11 18:04:26 +00:00
Linus Rath a5c60ef597 fix: hide Undo send when the delay is over and say when an undo fails 2026-10-11 19:13:10 +02:00
Linus Rath 1614cab78b fix: return to the message list after sending a new message on a phone 2026-10-11 19:04:02 +02:00