Commit Graph
25 Commits
Author SHA1 Message Date
Linus Rath cf2c27157d Merge branch 'main' into feat/stalwart-1.0
# Conflicts:
#	components/contacts/contacts-app.tsx
#	components/email/__tests__/composer-discard.test.tsx
#	components/email/calendar-invitation-banner.tsx
#	components/email/email-composer.tsx
#	components/mail/mail-app.tsx
#	components/pro/pro-compose-tab-body.tsx
#	components/pro/pro-email-tab-body.tsx
#	components/ui/__tests__/avatar.test.tsx
#	components/ui/avatar.tsx
#	hooks/use-mailbox-drop.ts
#	lib/__tests__/calendar-alerts.test.ts
#	lib/__tests__/jmap-calendar-tasks.test.ts
#	lib/__tests__/jmap-send-threading.test.ts
#	lib/demo/demo-client.ts
#	lib/demo/fixtures/calendars.ts
#	lib/jmap/client-interface.ts
#	lib/jmap/client.ts
#	lib/web-push.ts
#	stores/__tests__/contact-store.test.ts
#	stores/__tests__/email-store-thread-key.test.ts
#	stores/calendar-store.ts
#	stores/contact-store.ts
#	stores/email-store.ts
2026-10-26 10:14:12 +01:00
Linus Rath 58f968a48c refactor: lead notifications with new mail, move the tab badge in and invitation parsing to calendar 2026-10-19 17:48:57 +02:00
Linus Rath 41a0716c50 Merge branch 'main' into feat/stalwart-1.0 2026-10-16 01:41:48 +02:00
Linus Rath dd2104cdda feat: mute notifications for single folders or whole accounts #1169 2026-10-15 21:50:08 +02:00
Linus Rath c633185cda Merge branch 'main' into feat/stalwart-1.0
# Conflicts:
#	CONTRIBUTING.md
#	LICENSE
#	README.md
#	app/api/calendar-agenda/route.ts
#	app/api/wopi/files/[fileId]/contents/route.ts
#	app/api/wopi/launch/route.ts
#	components/calendar/calendar-app.tsx
#	components/calendar/calendar-day-view.tsx
#	components/calendar/calendar-month-view.tsx
#	components/calendar/calendar-week-view.tsx
#	components/calendar/event-modal.tsx
#	components/contacts/contact-detail.tsx
#	components/email/email-composer.tsx
#	components/email/email-list.tsx
#	components/files/file-browser.tsx
#	components/files/files-app.tsx
#	components/files/folder-tree-sidebar.tsx
#	components/filters/filter-rule-modal.tsx
#	components/mail/mail-app.tsx
#	hooks/use-mailbox-drop.ts
#	integration/run-tests.sh
#	lib/__tests__/calendar-agenda-route.test.ts
#	lib/__tests__/jmap-draft-lifecycle.test.ts
#	lib/__tests__/web-push.test.ts
#	lib/account-state-manager.ts
#	lib/jmap/client-interface.ts
#	lib/jmap/client.ts
#	lib/jmap/types.ts
#	lib/message-list-order.ts
#	lib/sieve/generator.ts
#	lib/sieve/parser.ts
#	lib/telemetry/payload.ts
#	lib/thread-utils.ts
#	lib/unified-mailbox.ts
#	lib/web-push.ts
#	lib/wopi/token.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/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/tr/common.json
#	locales/uk/common.json
#	locales/zh-TW/common.json
#	locales/zh/common.json
#	scripts/lite/lib.mjs
#	stores/__tests__/calendar-store-synthetic-ids.test.ts
#	stores/__tests__/email-store-shared-folder-keywords.test.ts
#	stores/__tests__/email-store-unified-actions.test.ts
#	stores/__tests__/file-store.test.ts
#	stores/email-store.ts
#	stores/file-store.ts
#	stores/message-list-tabs-store.ts
2026-10-12 08:35:08 +02:00
Linus Rath 02923fc1f1 Merge pull request #1054 from lucamzanon/feat/multi-account-push
feat: enable push notifications for several accounts at once
2026-10-10 19:24:10 +02:00
lucamzanon ce3b12aa21 fix(settings): check push again when the user comes back to the tab
The notification settings read the push state once, when they opened.
Push turned off meanwhile - in the browser's site settings, or from
another tab - still showed as on until the page was reloaded. The state
is now read again when the window regains focus or the tab becomes
visible, unless an enable or disable is in progress or has just failed.
A failed check reads as off instead of leaving the panel unchanged.
2026-10-01 12:43:40 +02:00
lucamzanon 42994c5d5a Merge remote-tracking branch 'origin/main' into feat/multi-account-push 2026-09-30 08:43:20 +02:00
Linus Rath 5a553a315b fix: report refused read changes and re-register push at its limit
Follow-ups to the review of the push, keyword and identity work:

- A send that names no sender, like the List-Unsubscribe mailto: of the
  unified view, fell back to the first identity in server order, which
  on Stalwart 1.0 is a group's. It now takes the login's own identity,
  with addresses compared regardless of case.
- Re-register creates the replacement subscription before it destroys
  the old one, so at Stalwart's limit (15 per account by default) it
  failed with `overQuota`. It now frees the old record's place and
  tries once more.
- On 1.0 the push settings note goes by the emailpush capability alone
  and ignores refusals remembered under 0.16. On 0.16 a group the user
  belongs to is recognised by its identity, so a member without
  calendars, contacts or files keeps the group's junk filter and is no
  longer told the group sends no notifications.
- Plugin imports can no longer set Stalwart 1.0's attachment keywords,
  and `keywords.discover` leaves them out.
- Batch mark-as-read showed messages the server refused as read. It now
  updates only what was written and reports the rest, and thread
  expansion and category-tab moves keep what a partly refused batch
  did write.
- Refused read and star changes from shortcuts, the list, the viewer
  and Pro tabs show "Failed to update email" instead of an unhandled
  rejection. The automatic mark-as-read on opening stays quiet.
- A tag whose id predates the 128-byte limit can have its colour
  changed again.
- The state-regression guard notes that a multi-node 1.0 cluster can
  trip it harmlessly, at the cost of one extra full fetch.
2026-09-25 21:57:11 +02:00
Linus Rath ffa909600c fix: keep web push on when someone shares a mailbox with you
Stalwart refuses a push subscription's whole emailPush map as
`forbidden` when it names a mailbox shared by ACL (0.16.16 and later,
and 1.0). Bulwark put every account with mailboxes in the map, so
enabling push showed raw JSON, and the background re-sync destroyed the
working subscription after its refresh was refused and dropped its key:
push stopped without a word and could not be turned back on while the
share existed. A network error, a timeout or rate limiting during the
refresh ended it the same way.

- The map holds the primary account and the accounts that list
  `urn:ietf:params:jmap:emailpush`, which 1.0 leaves off ACL shares.
  0.16 lists it everywhere, so a refused map narrows to the accounts
  that look owned, then to the primary account, as the mobile app does.
  Refused accounts are remembered under
  `bulwark.push.emailPushRefused.v1.<id>`; Re-register and disable
  clear the list.
- A subscription ends only when a verified replacement exists, the user
  turns push off, or the server no longer has it. The old record is
  destroyed after the new one is verified. A failed listing, a network
  error or a refused method call leave it and its key alone.
- PushSubscription/set failures throw typed errors (`jmapSetError` for
  a refused object, `jmapError` for a refused call) instead of JSON in
  the message or `false`, and the client exposes `getAccountInfo`.
- Settings says that mailboxes others share don't send background
  notifications, and `forbidden` and `overQuota` read as plain text in
  settings and the onboarding prompt.
2026-09-25 17:59:17 +02:00
Linus Rath 8c746fb7af fix: keep inbox-only push working for accounts shared without an inbox #983 2026-09-23 05:56:28 +02:00
Aaron Guise 4078a7494a fix(notifications): don't let the inbox-only re-sync hang on "Working…" 🐛
The re-sync effect depended on pushStatus.kind, so its own
setPushStatus({ kind: 'busy' }) re-fired the effect, whose cleanup
cancelled the in-flight enableWebPush - the push row then sat on
"Working…" forever and never updated the filter. Depend only on the
setting flip; read client/relay/status live from the recreated closure.
2026-09-23 11:07:58 +12:00
Aaron Guise c89fdcbf0c feat(notifications): apply inbox-only push filter immediately on toggle ✨
Flipping the setting only wrote to the store; the server-side JMAP push
filter stayed stale until the next app launch ran resyncWebPush. When push
is already enabled on the device, re-run enableWebPush on change so the
toggle takes effect without a restart.
2026-09-23 11:07:58 +12:00
Aaron Guise 887b9e7f92 feat(notifications): add toggleable inbox-only push notifications ✨ 2026-09-23 11:07:58 +12:00
Linus Rath d7548a4bab refactor: migrate icon set from Lucide to Tabler Icons 2026-09-19 13:32:41 +02:00
lucamzanon e468b08fb7 feat: enable push notifications for several accounts at once
The notification panel only ever addresses the account on screen, so
arming a browser for five accounts meant switching account five times
and answering the same permission prompt on each pass.

The browser holds a single push subscription: enabling an account
registers it against that one subscription rather than creating another.
A section in the notification settings now lists every connected account
with its current state and turns push on or off for the ones selected,
walking them against the same subscription.

A refusal at the browser level - unsupported, or permission denied -
applies to every account, so it stops the walk instead of failing each
account in turn and prompting repeatedly.
2026-09-19 05:44:45 +02:00
Linus Rath 2d4a562432 fix: harden Bulwark Lite login, deep-link replay and settings gating 2026-09-18 22:16:57 +02:00
Linus Rath b37313af95 fix: recreate the push subscription on re-register and add per-device revoke #841 2026-08-16 23:35:34 +02:00
Linus Rath 548200131b feat: pick push relay from an admin-defined list instead of a URL field 2026-08-16 23:13:36 +02:00
Linus Rath 5b8ddc352b feat: pick push relay from admin-defined list instead of a URL field 2026-08-16 23:04:22 +02:00
Linus Rath 8ae5ecba41 feat: policy-controlled push relay URL with optional user lock 2026-05-28 19:45:14 +02:00
Linus Rath bb7e1c4538 fix: per-account push subscriptions so multi-account notifications work #298 2026-05-16 22:50:01 +02:00
Linus Rath f3d9115ecd feat: web push notifications for PWA #233 2026-05-01 00:26:48 +02:00
Linus Rath 29a222eef4 feat: add plugin/theme disable gates and move policy controls to their admin pages
- Add `pluginsEnabled` and `themesEnabled` master feature gates to FeatureGates
- Move theme policy UI (default theme, built-in/admin theme toggles, user uploads toggle) from policy page to themes admin page
- Add plugin policy UI (plugins enabled toggle) to plugins admin page
- Remove theme policy section and plugin/theme gates from policy page (with note directing to respective pages)
- Hide Themes and Plugins settings tabs when their feature gate is disabled
- Fix dark mode visibility of all admin toggle switches (bg-white → bg-background, increase off-state track opacity)
2026-03-25 00:44:04 +01:00
Linus Rath 8eff9fdfab feat: add notification settings with sound picker and preview 2026-03-22 01:55:21 +01:00