Commit Graph
186 Commits
Author SHA1 Message Date
Linus Rath e5568ba23b Merge branch 'feat/desktop-offline' into feat/do-ux-p2-pim-fix 2026-11-04 14:07:47 +01:00
Linus Rath 1b7b689662 Merge branch 'feat/desktop-offline' into feat/do-ux-p2-mail-fix
# Conflicts:
#	components/ui/first-start-notice.tsx
2026-11-04 13:46:47 +01:00
Linus Rath b588954ea4 feat: pick an event's time zone by city with search, and open Duplicate as an unsaved copy at the same time
The editor's time zone test now picks a zone through the searchable picker instead of a select's change event, since the select is gone.
2026-11-04 13:42:36 +01:00
Linus Rath 6975f96a4b Merge branch 'feat/desktop-offline' into feat/do-ux-p2-mail-fix
# Conflicts:
#	components/email/email-viewer.tsx
#	components/email/thread-conversation-view.tsx
#	components/mail/mail-app.tsx
#	components/ui/toast.tsx
#	lib/keyboard-shortcuts/mail.ts
#	lib/window-controls-overlay.ts
2026-11-04 13:37:49 +01:00
Linus Rath 09335c76c5 Merge branch 'feat/do-ux-p2-settings-fix' into feat/desktop-offline
# Conflicts:
#	components/settings/__tests__/notification-settings.test.tsx
2026-11-04 13:32:16 +01:00
Linus Rath 0f2fa7bafe Merge branch 'feat/do-ux-p2-compose-fix' into feat/desktop-offline 2026-11-04 13:28:56 +01:00
Linus Rath 49286649dd Merge branch 'feat/do-ux-p2-settings-fix' into feat/do-ux-p2-pim-fix
# Conflicts:
#	components/settings/__tests__/notification-settings.test.tsx
2026-11-04 13:27:06 +01:00
Linus Rath 6a2bedc442 fix: name Ctrl+N and Ctrl+K in the desktop app's welcome tips instead of single keys 2026-11-04 13:10:26 +01:00
Linus Rath c5eb55467d fix: lift toasts above the quick reply box and a docked reply while they are on screen
The toast-layout assertion changes because toasts now clear a bar taller
than 5rem while a composer is open, instead of a fixed 5rem.
2026-11-04 12:53:52 +01:00
Linus Rath 68bdaaac33 fix: hold the offline notice until the welcome tips are closed, also when they show in the reading pane 2026-11-04 12:41:37 +01:00
Linus Rath af8c8a6ea4 fix: keep toasts above the quick reply box 2026-11-04 12:39:07 +01:00
Linus Rath 4333cc4080 fix: find time zones by abbreviation and list the exact offset first 2026-11-04 12:04:32 +01:00
Linus Rath 267e668137 fix: keep the first-start notice to one line and hide it while offline
The offline-host test now expects the shorter one-line text (offline_default_on) the notice switched to.
2026-11-04 11:29:29 +01:00
Linus Rath ac4c53b247 fix: show the welcome tips once per device and point them at the bar on the left 2026-11-04 11:08:16 +01:00
Linus Rath 989385f4f6 Merge branch 'feat/desktop-offline' into feat/do-ux-compose-fixes
# Conflicts:
#	components/email/email-viewer.tsx
#	components/settings/accessibility-settings.tsx
#	lib/__tests__/settings-search.test.ts
#	lib/settings-search.ts
2026-11-04 09:54:25 +01:00
Linus Rath aa62855759 Merge branch 'feat/do-ux-settings-fixes' into feat/desktop-offline
# Conflicts:
#	components/layout/__tests__/account-switcher-mountain-view.test.tsx
#	components/layout/account-switcher.tsx
#	components/settings/accessibility-settings.tsx
#	components/settings/reading-settings.tsx
2026-11-04 09:44:51 +01:00
Linus Rath 4a764150b2 Merge branch 'feat/desktop-offline' into feat/do-ux-settings-fixes 2026-11-04 09:22:44 +01:00
Linus Rath ceaceb7f2a Merge branch 'feat/desktop-offline' into feat/do-ux-compose-fixes
# Conflicts:
#	components/email/email-composer.tsx
#	components/email/email-viewer.tsx
#	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 09:20:50 +01:00
Linus Rath fcc9fc0cc0 Merge branch 'feat/desktop-offline' into feat/do-ux-mail-fixes
# Conflicts:
#	components/email/email-viewer.tsx
#	components/mail/mail-app.tsx
#	components/offline/offline-host.tsx
#	components/ui/welcome-banner.tsx
#	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 09:11:09 +01:00
Linus Rath 91b237330e Merge branch 'feat/desktop-offline' into feat/do-ux-settings-fixes
# Conflicts:
#	components/settings/desktop-os-settings.tsx
#	components/settings/notification-settings.tsx
#	components/settings/protocol-handler-settings.tsx
2026-11-04 08:35:53 +01:00
Linus Rath 2f31b435a2 Merge branch 'feat/desktop-offline' into feat/do-menu-fixes
# Conflicts:
#	components/desktop/desktop-host.tsx
2026-11-04 07:57:50 +01:00
Linus Rath de09da137b Merge branch 'feat/do-menu-winctl' into feat/do-menu-fixes 2026-11-04 07:50:16 +01:00
Linus Rath 242d0bacfc fix: keep toasts at the bottom instead of over the composer's close button 2026-11-04 07:16:24 +01:00
Linus Rath b7e9af0b1b fix: sort the language list by each language's own name
The arrow-key test expected Slovenčina right after Česky for the query "sk"; in the sorted list Dansk comes between them, so it now expects Dansk.
2026-11-04 07:09:28 +01:00
Linus Rath e29a6553e6 fix: keep notices and the offline bar clear of the window's controls, give each a close, and put a pane's close first where it would sit beside the window's 2026-11-04 07:02:53 +01:00
Linus Rath 3a9ec61232 fix: mark the row a menu is open for, and leave the item under the pointer alone until it moves 2026-11-04 07:00:56 +01:00
Linus Rath 2859260a72 feat: add Move to the selection bar and use the empty reading pane for a selection and the first-run tips
The selection bar showed Archive, Delete and Tag, with Move only in its
more menu and both read buttons only on wide bars. The reading pane said
"No conversation selected" next to a selection, and the first-run tips
took a third of the list.

- The bar has Archive, Delete, Move, one read/unread button ("Mark as
  read" while anything selected is unread) and Tag, then the rest.
- With a selection the empty reading pane shows "5 conversations
  selected" and the same buttons.
- The first-run tips sit in the empty reading pane where it shows beside
  the list; phones and layouts without that pane keep them above the list.
- A bulk move's toast names the folder.
2026-11-04 06:51:13 +01:00
Linus Rath 141748e1d6 fix: show first-start notices one at a time above the message list, each with a close button
The dictionary test now reads the notice queue instead of the toasts: the
question is no longer a toast.
2026-11-04 06:29:23 +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 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 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 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 529d334496 Merge branch 'fix/ui-bug-hunt' 2026-11-03 19:44:46 +01:00
Linus Rath deb73cc6e2 Merge branch 'feat/do-native-ui' into feat/desktop-offline 2026-11-03 18:28:49 +01:00
Linus Rath 383e579eec feat: run the app to the top of the window, with the window's controls in its own toolbars
The desktop app and an installed PWA had a row across the whole window
with the title and the window controls. That row is gone. The rail,
sidebar, list and reader run to the top of the window in their own
colours, and the controls sit in the top row of whatever is rightmost.

- `lib/window-controls-overlay.ts` finds and marks those rows before
  paint, and they reserve the controls' width through
  `--titlebar-right-inset`
- the rows and the rail are the drag area, everything clickable is
  `no-drag`, and an invisible band lets a page with no row still move
- settings and the admin shell get a row only under the overlay, Pro's
  tab strip and Mountain View's bar match the controls' height
- Alt floats the menu over the top left, in `window-menu-bar.tsx`
- skeletons carry the same marks, so nothing shifts when the app loads
2026-11-03 16:52:42 +01:00
Linus Rath e20aded171 fix: keep restored desktop composers off sent mail and on their own From, check links from the native menu, and fetch no dictionary without asking
A restored composer opened whatever the id named. Sending keeps the id, so its autosave would have destroyed the Sent copy, Send mailed it twice and Discard deleted it. It now needs the login in its address and a real draft, keeps its From with several accounts, and stays on the list if the server doesn't answer. A message from a bulwark:// link no longer marks itself read or sends a receipt. Native menus speak all 30 languages. Spellcheck dictionaries come from Google only after a yes, never in no-third-party mode.
2026-11-03 12:53:40 +01:00
Linus Rath a802411cdd feat: fire calendar reminders from the local store, with native snooze and join buttons and one summary of what was missed 2026-11-03 12:31:58 +01:00
Linus Rath d9c9fc03f7 feat: give the desktop app a native menu bar and native right-click menus built from the webmail's own 2026-11-03 10:44:03 +01:00
Linus Rath bb2393cf04 feat: open messages and drafts in their own windows and save all attachments to a folder
An installed app had no title bar of its own, no way to save attachments
except a zip, and "pop out" stayed inside the page. A new window was a
second copy of the app that had to restore the session itself, and on
start-up that evicts any login made without "Remember me" from the list
every window shares.

- Title bar: `display_override` with `window-controls-overlay`, one
  `--titlebar-inset` variable at the page roots and skeletons, and a drag
  strip with the window title. 0 without an overlay, so nothing moves.
- Save all to a folder: `showDirectoryPicker`, asking the device policy
  before the picker and before each file, with the zip as the fallback.
- Pop-out routes `/popout/message/<id>` and `/popout/compose`, on offer in
  an installed app or when the desktop bridge has windows. Hidden in Lite.
- A pop-out borrows the main window's session and never evicts or starts a
  token timer. Every renewal now takes a Web Lock, so two windows can't
  send the same refresh token, which Stalwart 1.0 may treat as a replay.
- A draft moves to its window under the same id. A closing window hands
  unsaved text to the main window to save, since its own request wouldn't
  survive the close.
- Read state, drafts, theme and language follow across windows, and
  `html[data-desktop]` gates the app-like behaviour in `app/desktop.css`.
2026-11-03 06:50:21 +01:00
Linus Rath 54f7b175fd fix: wrap long folder names in menus instead of stretching the submenu across the window 2026-11-03 06:32:06 +01:00
Linus Rath 9e12266e1b fix: stop the welcome banner and message list running under the bottom bar on short screens 2026-11-03 06:00:20 +01:00
Linus Rath 8877686ae4 fix: wrap dialog buttons instead of squeezing them on small screens 2026-11-03 05:22:03 +01:00
Linus Rath b3369c7e78 feat: send every link click through the link check 2026-11-01 08:31:27 +01:00
Linus Rath 341b84fe19 Merge pull request #1448 from vietnamvps/add-vietnamese
feat(i18n): add Vietnamese language support
2026-10-31 16:24:47 +01:00
Linus Rath c13b87c0e8 fix: keep the undo toast off the header on phones #1472 2026-10-31 16:15:58 +01:00
vietnamvps 2aa39d93de feat(i18n): add Vietnamese flag icon 2026-10-30 11:09:33 +07:00
vietnamvps 50bcf01d75 feat(i18n): add Vietnamese to language picker 2026-10-30 11:07:04 +07:00
Linus Rath cf0eb03c4a feat: show the sender's BIMI logo as the sender icon when the message passes DMARC
Stalwart does no BIMI, so sender icons were only ever favicons, which
anyone controls for any domain. The webmail server now does the
receiver side itself at /api/bimi, and avatars ask it only for
messages whose own Authentication-Results say dmarc=pass for the exact
From domain.

- `lib/bimi/`: DMARC policy check (quarantine or reject, pct=100, the
  parent domain's sp and p for subdomains), the assertion record with
  fallback to the parent domain, mark certificate validation (chain to
  pinned DigiCert, GlobalSign and SSL.com VMC roots, BIMI key purpose,
  validity, SAN, SCTs present, CRL revocation, logo from the logotype
  extension), SVG Tiny PS checks and rendering to PNG, caching
- logos backed only by the DNS record show by default; the admin
  setting "Require a mark certificate" (`BIMI_REQUIRE_CERTIFICATE`)
  limits them to VMC and CMC backed ones
- a check mark beside the sender's name for certificate-backed logos
- avatars try contact photo, BIMI logo, plugin avatar, favicon; the
  sender warning shield still wins, and logos follow the sender icons
  setting and the no-third-party-traffic mode
- the two-label public suffix list moved to `lib/root-domain.ts`

SCT signatures are not verified and only the default selector is used.
2026-10-30 00:12:24 +01:00