Commit Graph
2682 Commits
Author SHA1 Message Date
Linus Rath 749f2e938e feat: put pictures dropped on an open composer into the message text 2026-11-04 06:32:19 +01:00
Linus Rath a9064dd972 fix: open Move to in a message's own window again after the menu fixes 2026-11-04 06:32:16 +01:00
Linus Rath 2f46eb6b46 Merge branch 'feat/do-menu-fixes' into feat/do-drop-overlay 2026-11-04 06:20:02 +01:00
Linus Rath a80c44b776 Merge branch 'feat/desktop-offline' into feat/do-drop-overlay 2026-11-04 06:19:39 +01:00
Linus Rath 277e1aa55d Merge branch 'feat/do-menu-altbar' into feat/do-menu-fixes 2026-11-04 06:19:29 +01:00
Linus Rath 5fc87eafbd Merge branch 'feat/do-menu-audit' into feat/do-menu-fixes
# Conflicts:
#	components/email/email-context-menu.tsx
#	components/mail/mail-app.tsx
2026-11-04 06:19:07 +01:00
Linus Rath f7c6f6b7b1 Merge branch 'feat/do-menu-overflow' into feat/do-menu-fixes 2026-11-04 06:12:13 +01:00
Linus Rath daf67152eb Merge branch 'feat/do-menu-winctl' into feat/do-menu-fixes 2026-11-04 06:12:10 +01:00
Linus Rath 6efa589448 Merge branch 'feat/do-menu-pos' into feat/do-menu-fixes 2026-11-04 06:12:08 +01:00
Linus Rath 53eb91ab0e fix: keep the message details panel readable in a narrow reader, with addresses, dates and sign-in results that fit 2026-11-04 05:58:47 +01:00
Linus Rath 1cf03ff0e4 feat: add a developer tools switch to the desktop app's troubleshooting settings 2026-11-04 05:38:59 +01:00
Linus Rath e211ae905e feat: offer attach or upload when files are dragged onto any screen
Files dragged into the window from outside now bring up a full-window
overlay with large drop zones: attach to a new message and upload to
Files, with the open composer first, "Upload to <folder>" on the Files
screen, and add to calendar, add to contacts, open or import for .ics,
.vcf and .eml files. At most four zones, the one under the pointer
highlights, Esc or dragging out cancels, a drop beside the zones does
nothing. Drags that start in the app never show it. A file pasted
outside a text field gets the same choices as a keyboard dialog.

The desktop app used to turn any file dropped on the window into a new
draft (lib/desktop/window-files.ts). That handling moved to the
overlay, so the "files on the window" tests in os-window.test.tsx went
with it: the same cases are now in components/file-drop/__tests__.
2026-11-04 05:37:35 +01:00
Linus Rath 4508eddccb fix: keep a tall menu under its button and scroll it, instead of covering the button 2026-11-04 05:35:57 +01:00
Linus Rath 059015c8d1 fix: let a long submenu use the window's height, and draw one focus ring round the folder filter 2026-11-04 05:35:44 +01:00
Linus Rath 8dfaa39607 fix: leave Edit, Move and Delete out for contacts in a read-only address book
The two "Add to group" tests click the entry by its new key, which ends
in "…" because it opens a group picker.
2026-11-04 05:32:24 +01:00
Linus Rath fc7b607ff7 fix: end Files and composer menu entries that open a dialog with …, and translate Share
The Files tests now look for the new menuAudit keys: the menu entries
moved to them so they can end in "…" while toolbar buttons keep the
plain label.
2026-11-04 05:32:23 +01:00
Linus Rath f92b7d942d fix: grey out folder and message actions that can't work offline or with nothing unread 2026-11-04 05:32:23 +01:00
Linus Rath e74d2aaa72 fix: keep the app's own buttons out from under the window's controls and move a pane's close away from the window's 2026-11-04 05:27:57 +01:00
Linus Rath d8b2488f88 fix: order rule folder pickers like Move to, and refuse Drafts as a drop target 2026-11-04 05:22:03 +01:00
Linus Rath 4d404929e2 fix: show the message's own folders in Move to, in mail-client order, with recents and a filter
The Move lists (message menu, reader Move button and its phone panel,
selection toolbar, Move dialog) now share one model in lib/move-menu.ts.
In the desktop app the native copy of the menu lost the shared accounts'
headers and every folder's nesting, so Inbox, Sent, Spam and Trash
showed once per account with nothing to tell them apart.

- Only the message's own account at the top; other accounts a move can
  reach are submenus under their names.
- System folders first (Inbox, Sent, Archive, Spam, Trash), then the
  user's folders by name; subfolders nest, as submenus natively.
- The open folder shows greyed instead of missing.
- A Recent group, a filter field on long lists, and "Choose folder…"
  for the dialog, which has the filter too.

Tests changed: the open folder is now shown disabled rather than left
out, the own account of a shared-mailbox message is a submenu, and the
selection toolbar's filter field has its own label.
2026-11-04 05:20:14 +01:00
Linus Rath ad970b35ef feat: move a message from its own window with Message > Move to… 2026-11-04 05:20:03 +01:00
Linus Rath 674845df4e fix: keep the desktop menus and tray in the language the app shows 2026-11-04 05:20:02 +01:00
Linus Rath ff0e16c755 feat: show the desktop app's menu bar as a row at the top on Alt, or always 2026-11-04 05:20:02 +01:00
Linus Rath 2525c27a7d fix: group the message menus and keep app-level items out of the reader's more menu
The reader's more menu no longer offers Star while the star sits by the
subject, so the tests that expected Star in the menu and the phone panel
now expect it gone. Import mail moved to the command palette (it stays in
the folder menu and Settings); Keyboard shortcuts stay behind ?, the rail
and Help.
2026-11-04 05:19:08 +01:00
Linus Rath 551b5ce4fa fix: name the account sign out leaves in the command palette, add star, hide dead key hints 2026-11-04 05:09:09 +01:00
Linus Rath f44be446bb fix: show the keys for reply, delete, star and the rest in the message menu 2026-11-04 05:09:06 +01:00
Linus Rath 3fa82849a8 fix: open menus next to what opened them and show their keys apart from the label 2026-11-04 05:00:02 +01:00
Linus Rath f9503570ca Merge branch 'feat/desktop-offline' into feat/do-key-fixes
# Conflicts:
#	components/settings/app-lock-settings.tsx
#	stores/auth-store.ts
2026-11-04 04:16:14 +01:00
Linus Rath 88d64b7f95 fix: protect the keys to the mail on this device for real
The review found the store key readable from a copy of the disk. The
desktop app only added its OS layer with the lock on, the record from
before a lock stayed in LevelDB and opened the mail with no PIN, any
frame could unwrap the PIN record and guess at it, a lock left the key
in the renderer's memory, and a store waiting after a refused login went
to whoever signed in next under the same username@host.

- The desktop app wraps the store key with safeStorage, lock or no lock.
  A record without the layer gets it at its next open. A refusal is said
  out loud, and only a computer with no key store goes without, which
  settings say. So do they for a browser, which has no such layer.
- A record that gained layers, and every record after a changed PIN, asks
  for a new key: `sqlite3_backup` into a new file under a new key while
  the store keeps working, one write to the record, then the old file
  goes. A changed PIN makes a new lock key, since the old PIN's record
  stays on disk too. The passkey and OS unlock go with the old key.
- `wrap` and `unwrap` come through `claim()`, and the key under the PIN
  takes a secret from main, one counted trip per guess.
- A lock on the desktop ends the renderer rather than reload in it.
- A sign-in compares the waiting store's JMAP account and server first,
  and wipes on a mismatch. The account id keeps its form: every store,
  setting and server record of an account is keyed by it.
- The 30 days also run in an app that stays open.

Changes an existing assertion: turning the lock off now keeps the
safeStorage layer, by decision, so that test expects it to stay.
2026-11-04 04:15:31 +01:00
Linus Rath be8aba2ae7 Merge remote-tracking branch 'origin/main' into feat/desktop-offline
# Conflicts:
#	stores/auth-store.ts
2026-11-04 03:42:18 +01:00
Linus Rath 484ce34f5d Merge branch 'feat/do-browser-signin' into feat/desktop-offline 2026-11-04 03:19:32 +01:00
Linus Rath cb9a5ac810 Merge branch 'feat/do-edit-attachments' into feat/desktop-offline 2026-11-04 03:16:35 +01:00
Linus Rath 97b3ddefae test: cover what the page tells the worker about a quiet login 2026-11-04 03:13:59 +01:00
Linus Rath 8cb218ce3c fix: apply email notifications off and do not disturb per login, not to every login's mail 2026-11-04 03:13:59 +01:00
Linus Rath 09d6bff12a fix: say push isn't available in the demo instead of offering a switch that fails 2026-11-04 03:13:58 +01:00
Linus Rath 8b4fb72357 fix: say in plain words why push could not be turned on or off 2026-11-04 03:13:57 +01:00
Linus Rath 37d0200e43 Merge branch 'feat/desktop-offline' into feat/do-browser-signin 2026-11-04 03:11:34 +01:00
Linus Rath 81d6948240 Merge branch 'main' of https://github.com/bulwarkmail/webmail 2026-11-04 03:08:16 +01:00
Linus Rath 97c0bd633a Merge branch 'feat/desktop-offline' into feat/do-edit-attachments
# Conflicts:
#	lib/desktop/languages.ts
#	locales/ar/common.json
#	locales/ca/common.json
#	locales/cs/common.json
#	locales/da/common.json
#	locales/de/common.json
#	locales/en/common.json
#	locales/es/common.json
#	locales/et/common.json
#	locales/fa/common.json
#	locales/fr/common.json
#	locales/he/common.json
#	locales/hu/common.json
#	locales/it/common.json
#	locales/ja/common.json
#	locales/ko/common.json
#	locales/lv/common.json
#	locales/mn/common.json
#	locales/nb/common.json
#	locales/nl/common.json
#	locales/pl/common.json
#	locales/pt/common.json
#	locales/ro/common.json
#	locales/ru/common.json
#	locales/sk/common.json
#	locales/th/common.json
#	locales/tr/common.json
#	locales/uk/common.json
#	locales/vi/common.json
#	locales/zh-TW/common.json
#	locales/zh/common.json
2026-11-04 02:40:47 +01:00
Linus Rath ab21bf2df3 fix: keep a desktop sign-in in the browser's page until the user says yes
The hand-off parked a password before its question, for up to five
minutes, and on a shared computer another local user could ask for
someone's sign-in with a link of their own. Now nothing leaves the page
before the yes, and the instance has a switch for such machines.

- `/check` tests a password and keeps nothing, `/park` runs on the yes and
  hands over tokens wherever the server allows, a password as a last
  resort
- `/discard` and a timer take out what SSO has to park first, and a no
  revokes the refresh token, and the shared store's TTL is the real expiry
- `DESKTOP_BROWSER_SIGN_IN`, default on, closes the routes, the page's
  hand-off and the app's button; the question says which device asked
- tokens from a typed password stay a password account under the name
  typed (#1432)
- redeem refuses a server of the user's own when the device's rule says
  no
- the park budget is reserved before going upstream, and only failures
  count
- "Not now" ends the flow in the app at once, and the question names the
  account

`desktop-handoff-routes.test.ts` now tests the two-step flow against the
real budgets. `sso-start-route.test.ts`'s config mock answers the new
setting, and the SSO test's expected answer has the account in it.
2026-11-04 02:40:37 +01:00
Linus Rath d31d0af560 fix: say what an open program still holds, keep forwarded parts under their rules, and let main decide what a sent draft leaves 2026-11-04 02:36:48 +01:00
Linus Rath 02a900ef07 Merge commit 'dc8482ace' into feat/do-browser-signin 2026-11-04 02:11:07 +01:00
Linus Rath 71aaadef50 fix: run plugins' compose check in quick compose, keep a composer with one owner, and bring it back after a crash
The first version of quick compose skipped `onBeforeCompose`, a composer
moved back could end up open in both windows, a reply moved back under
Pro flagged the selected message, and a crashed pop-out came back blank.

- A new message in a pop-out runs `onBeforeCompose` with the same result
  as the main window: a plugin that stops it closes the window.
- The way back has two steps, so a pop-out that gave up can't leave a
  second owner. A handoff behind a plugin's gate makes it say busy.
- A Pro tab made from a composer moved back answers its own message.
- Each save writes `draft`, `account` and `owner` into the pop-out's
  address, which a reload after a crash starts from. What was typed since
  the last save, up to the 2 s autosave delay, is still lost.
- The recorder refuses keys that type a character on this keyboard, and
  what the shell refuses from a page, and says why.
2026-11-04 01:31:43 +01:00
Linus Rath c8c98e79d4 feat: sign in to the desktop app in your browser, with your password manager
The desktop login page gets "Sign in with your browser…" as its main
button. On an instance it opens the instance's real login page in the
system browser, with a PKCE challenge. The page checks the password or
runs SSO, parks the sign-in under a one-time code, asks once, and sends
the code to the app's loopback listener. This browser gets no session
out of it, and the app's own page redeems the code, so SameSite=Strict
is fine. Standalone runs the mail server's OAuth against the listener,
with a page from main for a server with no OAuth at all.

- `/api/auth/desktop-handoff/park` and `redeem`, and `sso/complete` parks
  tokens the same way for a loopback target
- `auth.claim()`: the calls are taken once per document, in the first
  render, in `WindowControlsHost`
- `BrowserSignIn` policy, default on, with its ADMX and samples
- strings in all 30 languages, and the old button's are gone

`runDesktopBrowserSignIn`'s tests changed because the code no longer goes
through the callback page's address: it's redeemed where it arrives.
2026-11-04 01:09:12 +01:00
Linus Rath e696fb1610 fix: ask before sending an older attachment also when the save was a moment ago 2026-11-04 00:17:15 +01:00
Linus Rath 69313623e0 fix: keep the edited file offers clear of the account menu 2026-11-04 00:02:34 +01:00
Linus Rath c0cf12c431 fix: show the edited file offers over the sidebar 2026-11-03 23:58:25 +01:00
Linus Rath 05e2e79ccf fix: keep the edited file offers clear of the toasts 2026-11-03 23:49:34 +01:00
Linus Rath e74248b37b feat: edit attachments in their own program from the desktop app and take the saved file back into mail 2026-11-03 23:37:40 +01:00
Linus Rath 3da18cc2c0 feat: set the quick compose keys in the desktop settings and move a composer back into the main window 2026-11-03 23:25:10 +01:00