Settings get a page of their own for accessibility, with presets on top
(screen reader, low vision, dyslexia, focus, keyboard and motor, motion
and seizure safe, deaf and hard of hearing) that change several options
at once and can be undone, then the options by topic, and a reset.
Text size used to be a fixed 14/16/18px on the root, which threw away
the size people set in their browser. It is now a percentage of the
browser's size, from 87.5% to 200%. Motion, contrast and transparency
follow the system by default and can be overridden either way; the
old Animations switch becomes Reduce motion. The visual options are
applied before the first paint, so the page no longer flashes at the
wrong size.
- `lib/accessibility-settings.ts`: the new settings, their allowed
values, and the code that writes them onto `<html>`
- `app/accessibility.css`: bundled fonts (Atkinson Hyperlegible Next,
Lexend, OpenDyslexic), text spacing, a focus outline that survives
Windows contrast themes, more-contrast colours on any theme, reduced
transparency, a large pointer
- admins can preset every new option but lock only shortcuts, send
confirmation and the notification duration; a lock on text size or
another reading aid works as a default
- always-light mail and toolbar labels now sync, and imports drop
values the page doesn't know
- font size and animations move off Appearance, the plain text font
off Reading; everyday settings such as conversation view and undo
send show on both their own page and Accessibility
Stalwart's x:ArchivedItem/query without calculateTotal scans ids
ascending, stops at 5000 and only then reverses them, so the newest
items of a large archive never showed, and admin accounts got every
account's items. The review of the branch also found gaps around
account switches, restores and focus.
- Read the archive in pages of 500 with calculateTotal, newest first,
stop at a whole page older than the days limit, and offer
"Show older" after 2000 items; detection asks for one item.
- Send the accountId filter and fall back without it on
unsupportedFilter; keep only items of the account, never one without
an account id.
- Ask nothing until config and policy are loaded and the policy is the
current account's; the later check after a refusal is forced.
- Show the Trash link only when the archive holds a message inside the
days limit; the Settings page shows whenever the server has the
feature and says that archiving must be on in Stalwart.
- Restore: notFound leaves the list with a note, forbidden hides the
page, results for another account are dropped, the button keeps focus.
- Forget what servers said at a full sign-out.
Change used to pre-fill the closest choice and then replace everything
of that type, so a folder added after "all", a single non-Inbox folder,
a non-default calendar, free/busy only or manager rights were narrowed
or widened on Save. Now a type gets a choice only when the grants match
it exactly; anything else starts at "Keep as it is", which leaves that
type out of the patch. Mixed levels keep each type's rights.
Also in the Delegates page:
- Change and Remove wait, with Try again, while a type couldn't be read
- an answer from the account before an account switch is dropped
- calendars, contacts and files follow their feature gates
- Remove says it covers what was shared from the user's own account
- typing your own address says "That's you"
- groups named only by the session get the group badge
- on Stalwart 1.0 the read hint says read delegates can flag mail
- the person list is plain buttons, not a listbox without arrow keys
- the rights follow sharingRights
Some user-facing strings still said "Bulwark" on a deployment with its own
APP_NAME: Settings > General > Default apps (protocol handlers), the "Open
Bulwark" notification, the rate-limit banner and toast, the plugin connect
dialog, one plugin permission text and the connector page.
These strings now take an {appName} placeholder, filled by productName():
the configured APP_NAME, or "Bulwark" when it is unset or the default
"Webmail" (the same rule as the TOTP issuer and the About card, #1160).
A stock install reads as before.
The settings search (the settings page and api.app.searchSettings) indexes
these texts with the name filled in, so "bulwark" or the configured name
finds Default apps and no result carries the raw placeholder.
Locales: the 13 keys in every locale that has "Bulwark" in them. Languages
that inflect the name (cs, et, hu, ko, ro, sk, tr) use a neutral form such
as "{appName} uygulamasında" instead of a declined "Bulwark'ta"; a native
check of those is welcome.
Not changed on purpose: the mobile app, push relay, Lite, demo and admin
texts, which speak about Bulwark itself.
Closes#1314
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new feature gate, archiveActionEnabled (default on), lets the admin turn the
Archive action off for installations that archive mail elsewhere, such as a
mail gateway. With it off, Bulwark offers no Archive anywhere: the viewer's
button and its overflow entry, the context menu for one or several messages,
Mountain View's selection bar, the hover and swipe actions, the E shortcut and
its help row, archiving after an export, and the archive mode setting (also in
the settings search). With it off nothing creates an Archive folder:
ensureArchiveMailbox returns null. Existing Archive folders stay ordinary
folders, moving mail into them by hand still works, and the plugin API is
unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Calendar, contacts, files and settings still drew the left navigation
rail under Mountain View, so moving away from mail switched to the
default frame. They now show the Mountain View top bar too, without the
mail search and the menu button, which only make sense in mail.