Commit Graph
4853 Commits
Author SHA1 Message Date
Linus Rath f0e874103d fix: take back certificate grants when a session ends without a sign-out 2026-11-04 03:23:45 +01:00
Linus Rath b1f26a93bf feat: let an organisation turn the system certificate store off by policy 2026-11-04 03:23:44 +01:00
Linus Rath dc8482ace0 Merge branch 'feat/do-quick-compose' into feat/desktop-offline 2026-11-04 02:06:51 +01:00
Linus Rath f570277a61 chore: merge the desktop offline branch into quick compose 2026-11-04 01:45:09 +01:00
Linus Rath 724aed257f Merge branch 'feat/do-sso-certs' into feat/desktop-offline 2026-11-04 01:34:33 +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 889f6ffbd1 fix: fail requests under way when the desktop app closes its connections, and forget client certificates per account 2026-11-04 00:56:09 +01:00
Linus Rath d0a636416d docs: say where quick compose opens its window in the pop-out notes 2026-11-03 23:35:23 +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
Linus Rath 8549e3c4c6 feat: translate the desktop app's client certificate picker and forget chosen certificates at sign-out and account switch 2026-11-03 23:21:56 +01:00
Linus Rath 54bda3ef3d Merge branch 'feat/do-packaging' into feat/desktop-offline
# Conflicts:
#	components/desktop/desktop-host.tsx
#	lib/desktop/languages.ts
2026-11-03 22:02:10 +01:00
Linus Rath 43ba229c7d Merge branch 'feat/do-perf-guard-2' into feat/desktop-offline 2026-11-03 21:50:37 +01:00
Linus Rath 2b4a1171ab fix: show the spelling and unsent-mail labels in the desktop app instead of their raw keys 2026-11-03 21:50:09 +01:00
Linus Rath 7509bd9f53 Merge branch 'main' into feat/desktop-offline 2026-11-03 21:37:32 +01:00
Linus Rath d651ae857c Merge remote-tracking branch 'origin/main' into feat/do-perf-guard 2026-11-03 21:34:59 +01:00
Linus Rath 717747b577 test: restore the session cookies in the forgotten PIN offline case, as Chromium's emulated outage lets a keepalive delete through 2026-11-03 21:33:52 +01:00
Linus Rath a89cae5f28 fix: show the page skeleton from the first frame again, with or without an app lock 2026-11-03 21:33:51 +01:00
Linus Rath fafdb0cdc0 fix: stop every search re-rendering the mail list when nothing is ticked 2026-11-03 21:06:48 +01:00
Linus Rath b4bcce2b01 Merge branch 'main' into feat/desktop-offline 2026-11-03 19:53:36 +01:00
Linus Rath 423fe28b0b Merge branch 'main' into feat/do-ci-fix 2026-11-03 19:50:46 +01:00
Linus Rath 776328b58d chore: keep the vendored SQLite build out of lint 2026-11-03 19:49:57 +01:00
Linus Rath 7bd9768e4c test: mock the desktop commands in the launch handler test, which would load every store 2026-11-03 19:49:57 +01:00
Linus Rath 1efe9bc8b4 test: tell reminders of two accounts apart by uid, since one meeting in both rings once 2026-11-03 19:49:57 +01:00
Linus Rath d890addbf4 test: register devices a second apart in the cap test, since rows of one millisecond have no oldest 2026-11-03 19:49:56 +01:00
Linus Rath 4015bbad76 test: expect the hidden settings row without a plugin, since the desktop app shows it for the window controls 2026-11-03 19:49:56 +01:00
Linus Rath ac2f7cba2b test: allow keystore as the one bare plugin permission, since it has no actions and the S/MIME manifest uses the name 2026-11-03 19:49:56 +01:00
Linus Rath fe3c213cb9 test: spell out the device policy defaults, since the offline caps are numbers where 0 means no cap 2026-11-03 19:49:55 +01:00
Linus Rath 5467f5db93 fix: let the Lite host scan know the desktop app's dictionary host 2026-11-03 19:49:55 +01:00
Linus Rath 984e6fa8d9 fix: label device and pop-out requests in metrics and error reports 2026-11-03 19:49:55 +01:00
Linus Rath 3f59af9c31 fix: delete offline mail right away when the local store doesn't answer 2026-11-03 19:49:55 +01:00
Linus Rath 135d1f000d fix: keep the plugin side panel open while the next message loads 2026-11-03 19:49:54 +01:00
Linus Rath 26c009c302 feat: send the updater's translated text with the desktop menu labels 2026-11-03 19:45:23 +01:00
Linus Rath 529d334496 Merge branch 'fix/ui-bug-hunt' 2026-11-03 19:44:46 +01:00
Linus Rath b8560579a4 Merge branch 'feat/do-import' into feat/desktop-offline
# Conflicts:
#	lib/desktop/types.ts
2026-11-03 19:44:43 +01:00
Linus Rath a96c66fa5e Merge branch 'main' into feat/do-packaging
# Conflicts:
#	components/settings/general-settings.tsx
#	lib/desktop/types.ts
2026-11-03 19:37:41 +01:00
Linus Rath 1e9afb733a fix: let the Docker image build see the script its Next config imports 2026-11-03 19:19:35 +01:00
Linus Rath b92b488e39 fix: stop a local import losing messages on a held file and name what a resume leaves out
Fixes from the review of the desktop import.

- A message another program holds is no longer recorded as deleted. Only a
  real absence moves the import past it; anything else is tried again and
  then reported as a failure, and the next run reads it.
- A resume that can't read some folders names them in a toast with a choice
  to stop trying, keeps the job open and retries only those at the next start.
  Files chosen by hand in the same dialog are named, since they can't come
  back by themselves.
- A wipe or sign-out releases the job in the shell before the record goes.
  Leaving the dialog without starting releases the confirmed files. Job
  records are per account, and a start is refused while another window holds
  that account's job.
- Dedupe goes by the bytes without state headers: a reused Message-ID of the
  same length dropped a real message. Older records still count, so nothing
  goes in twice.
- A lost connection on a folder or Email/import pauses instead of counting
  towards the failures that stop an import.
- The taskbar goes through `lib/desktop/taskbar-progress.ts`.

Test changes: the taskbar test now renders the host, because its helper in
`local-import-job.ts` is gone, and the dedupe tests use `check`, which replaced
`keyFor` and `has`.
2026-11-03 19:17:38 +01:00
Linus Rath 5849f9dc42 Merge branch 'main' into feat/desktop-offline 2026-11-03 19:07:04 +01:00
Linus Rath 151cedf992 Merge branch 'feat/do-app-lock' into feat/desktop-offline 2026-11-03 18:46:05 +01:00
Linus Rath ef3e428ff3 Merge branch 'feat/desktop-offline' into feat/do-import
# Conflicts:
#	components/mail-transfer/mail-transfer-host.tsx
#	lib/desktop/types.ts
2026-11-03 18:34:24 +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 88f4b20487 fix: open the calendar from a reminder without a full page load 2026-11-03 18:02:03 +01:00
Linus Rath 084f93a786 feat: import Thunderbird and Outlook data from this computer in the desktop app
The import dialog in the desktop app can now find Thunderbird profiles and
Outlook PST files, show what it found and import what the user confirms.
Browsers behave as before.

- The bridge's `localImport` gives opaque handles and range URLs. The shell
  asks natively before it looks, before it reads and before it goes on after
  a restart.
- `lib/mail-import` gets a Maildir source and a per-file `folder`, so
  Thunderbird's `.sbd` tree maps onto the account's folders. The PST worker
  reads through a synchronous range XHR when there is no Blob.
- What was imported is remembered by Message-ID and size per folder, because
  compacting a folder changes its checkpoint key and Email/import doesn't
  dedupe. It runs from the dialog and on a resume.
- The job's record lives in IndexedDB, since Chromium writes localStorage too
  late to survive a kill. Windows wait for the job's lock, so one takes over
  when another goes.
- The desktop dialog says how long an import takes at the upload limit, warns
  when Thunderbird is running, and turns down .ost files with the reason.

The engine used to be able to lose an import while offline: uploadBlob kept
the file on this device under a stand-in id and reported success. It now
passes `noHold`, Email/import is network only, an offline spell pauses without
using up a message's tries, and a device-only client stops at once. The same
fix applies to imports in the browser.
2026-11-03 17:57:54 +01:00
Linus Rath 335e1edc10 Merge branch 'feat/desktop-offline' into feat/do-app-lock
# Conflicts:
#	components/settings/general-settings.tsx
#	hooks/use-calendar-alerts.ts
#	lib/desktop/app-lock-state.ts
#	lib/desktop/policy-schema.ts
#	lib/desktop/types.ts
2026-11-03 17:52:30 +01:00
Linus Rath 99bc974f8b Merge branch 'feat/do-telemetry' into feat/desktop-offline
# Conflicts:
#	lib/desktop/types.ts
2026-11-03 17:42:32 +01:00
Linus Rath dc9e0aec26 test: wait out the page's own reloads in the app lock's offline and 5xx cases 2026-11-03 17:41:44 +01:00
Linus Rath dcfe25c754 Merge branch 'feat/do-store-export' into feat/desktop-offline 2026-11-03 17:39:54 +01:00
Linus Rath 3d5b02b75f fix: stop a page reporting once consent goes, and let nothing on disk aim the desktop app's telemetry
A review found that an open page kept sending to a DSN after consent was
taken back, that a state file or config file could name where telemetry
goes, and that `BULWARK_TELEMETRY=off` did nothing on the desktop build.
A due heartbeat now waits a random 30 s to 10 min, a refusal from the
collector isn't retried, crash files go at sign-out and account switch,
and server builds parse stacks as they did.

Existing assertions changed in the desktop telemetry tests: the catch-up
wait is now a range, the endpoint comes from the shell, and the platform
is `desktop` against the collector's patched branch.
2026-11-03 17:38:04 +01:00
Linus Rath 530364b11c fix: stop a cancelled or wiped export from downloading, and say why an export stopped
Review of the local store export. A cancel, sign-out or wipe during the
final step still downloaded the file; now the sink takes the job's signal
and drops the Blob, and a job that outlasts the wait is forgotten when it
ends. Finished exports are in a list a later wipe or sign-out can empty,
also after the dialog closed.

- `localExportAllowed` uses `scopeDecided`, so a domain or group scope
  can't be missed before the subject arrives. It's checked before the
  save picker, in the same tick as the click.
- WebKit holds the final Blob in memory: exports stop at 1 GB, and a
  larger choice or one over `storage.estimate()` is refused up front.
- An empty folder that refuses during a full listing counts as empty,
  only when the store's own count agrees. Any other refusal stops the run.
- A picked file goes on an abort or an all-failed run; if it can't, the
  dialog names it. Failure texts come from our strings, not the browser's.
- A selection keeps to the chosen folders on a retry.

The test that the organisation shows as the reason now flips the policy
through the policy store, because the old one replaced the guard and so
never reached the watch that a real change goes through. The spec moves
to an account of its own, dso-export: other specs running at the same
time work in ent-dave, and its folder went missing there mid-run.
2026-11-03 17:29:42 +01:00
Linus Rath e3dec865da fix: let the webmail build again with the device registry's rate limit out of its route 2026-11-03 17:19:39 +01:00