mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 08:12:43 +00:00
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
108 lines
6.3 KiB
TypeScript
108 lines
6.3 KiB
TypeScript
/**
|
|
* Every setting an admin can lock, hide or limit (SettingRestriction in
|
|
* lib/admin/types.ts), with where the admin panel offers it. The User policy
|
|
* page lists the ones with page `policy`; each Organisation page lists its
|
|
* own next to the settings they belong to. New user-facing options add their
|
|
* key here instead of a lock flag of their own.
|
|
*/
|
|
|
|
import type { AdminPageId } from './admin-nav';
|
|
|
|
export interface RestrictionKeyDef {
|
|
key: string;
|
|
label: string;
|
|
/** One sentence for the admin: what locking or hiding it does for users. */
|
|
description?: string;
|
|
category: string;
|
|
type: 'boolean' | 'number' | 'enum';
|
|
allowedValues?: string[];
|
|
/** The admin page that lists it. */
|
|
page: AdminPageId;
|
|
/** Which of locked, hidden and allowed values make sense for it. */
|
|
modes?: ReadonlyArray<'locked' | 'hidden' | 'allowedValues'>;
|
|
}
|
|
|
|
export const RESTRICTION_KEYS: readonly RestrictionKeyDef[] = [
|
|
// Text size, motion, contrast and the other reading aids are left out on
|
|
// purpose: an admin can preset them (policy defaults) but not lock or hide
|
|
// them, see UNLOCKABLE_SETTING_KEYS in lib/accessibility-settings.ts.
|
|
{ key: 'density', label: 'Density', category: 'Appearance', type: 'enum', allowedValues: ['extra-compact', 'compact', 'regular', 'comfortable'], page: 'policy' },
|
|
{ key: 'interfaceLayout', label: 'Interface Layout', category: 'Appearance', type: 'enum', allowedValues: ['default', 'mountain-view'], page: 'policy' },
|
|
{
|
|
key: 'singleKeyShortcuts',
|
|
label: 'Single-key shortcuts',
|
|
description: 'Lock: users keep the shortcuts as set here. Turning them off helps people who use speech input, where a dictated letter can delete or archive mail.',
|
|
category: 'Accessibility',
|
|
type: 'boolean',
|
|
page: 'policy',
|
|
modes: ['locked'],
|
|
},
|
|
{
|
|
key: 'toastDuration',
|
|
label: 'Notification duration',
|
|
description: 'How long messages such as "Moved to Archive" with their Undo button stay, in seconds (0 = until closed). With a minimum, users can make them stay longer but not shorter.',
|
|
category: 'Accessibility',
|
|
type: 'number',
|
|
page: 'policy',
|
|
modes: ['locked'],
|
|
},
|
|
{ key: 'markAsReadDelay', label: 'Mark as Read Delay', category: 'Email', type: 'number', page: 'policy' },
|
|
{ key: 'deleteAction', label: 'Delete Action', category: 'Email', type: 'enum', allowedValues: ['trash', 'trash-and-read', 'permanent'], page: 'policy' },
|
|
{ key: 'showPreview', label: 'Show Preview', category: 'Email', type: 'boolean', page: 'policy' },
|
|
{ key: 'mailLayout', label: 'Mail Layout', category: 'Email', type: 'enum', allowedValues: ['split', 'focus', 'horizontal'], page: 'policy' },
|
|
{ key: 'emailsPerPage', label: 'Emails Per Page', category: 'Email', type: 'number', page: 'policy' },
|
|
{ key: 'externalContentPolicy', label: 'External Content Policy', category: 'Email', type: 'enum', allowedValues: ['allow', 'block', 'ask'], page: 'policy' },
|
|
{ key: 'sendConfirmation', label: 'Send Confirmation', category: 'Composer', type: 'boolean', page: 'policy' },
|
|
{ key: 'defaultReplyMode', label: 'Default Reply Mode', category: 'Composer', type: 'enum', allowedValues: ['reply', 'replyAll'], page: 'policy' },
|
|
{ key: 'autoSelectReplyIdentity', label: 'Auto-select Reply Identity', category: 'Composer', type: 'boolean', page: 'policy' },
|
|
{ key: 'replyIdentityMatch', label: 'Reply Identity Matching', category: 'Composer', type: 'enum', allowedValues: ['exact', 'domain'], page: 'policy' },
|
|
{ key: 'plainTextMode', label: 'Plain Text Only', category: 'Composer', type: 'boolean', page: 'policy' },
|
|
{ key: 'emailNotificationsEnabled', label: 'Email Notifications', category: 'Notifications', type: 'boolean', page: 'policy' },
|
|
{ key: 'calendarNotificationsEnabled', label: 'Calendar Notifications', category: 'Notifications', type: 'boolean', page: 'policy' },
|
|
{ key: 'pushNotifyInboxOnly', label: 'Inbox-only Push Notifications', category: 'Notifications', type: 'boolean', page: 'policy' },
|
|
{ key: 'debugMode', label: 'Debug Mode', category: 'Advanced', type: 'boolean', page: 'policy' },
|
|
{
|
|
key: 'signature',
|
|
label: 'Signatures',
|
|
description: "Lock: users can't change signatures, and the organisation signature replaces their own. Hide: users get no signature editor at all.",
|
|
category: 'Composer',
|
|
type: 'boolean',
|
|
page: 'org-signatures',
|
|
modes: ['locked', 'hidden'],
|
|
},
|
|
{
|
|
key: 'personalTemplates',
|
|
label: 'Personal templates',
|
|
description: "Hide: users get only the organisation and team templates and can't save templates of their own. The ones they have are kept, not deleted.",
|
|
category: 'Composer',
|
|
type: 'boolean',
|
|
page: 'org-templates',
|
|
modes: ['hidden'],
|
|
},
|
|
{
|
|
key: 'teamTemplates',
|
|
label: 'Team templates',
|
|
description: 'Lock: members of a group mailbox can use its templates but not add, change or delete them.',
|
|
category: 'Composer',
|
|
type: 'boolean',
|
|
page: 'org-templates',
|
|
modes: ['locked'],
|
|
},
|
|
{
|
|
key: 'sharedTags',
|
|
label: 'Shared tags',
|
|
description: "Lock: users can tag mail with the shared tags of their group mailboxes but can't add, rename or delete them. Unlock it in a group scope for the people who look after the tags.",
|
|
category: 'Sharing',
|
|
type: 'boolean',
|
|
page: 'org-sharing',
|
|
modes: ['locked'],
|
|
},
|
|
{ key: 'delegation', label: 'Delegates', description: 'Hide removes Settings > Sharing > Delegates, so users can no longer give someone access to mail, calendars and contacts in one step.', category: 'Sharing', type: 'boolean', page: 'org-sharing', modes: ['hidden'] },
|
|
{ key: 'sharingRights', label: 'Rights users can give', description: 'Untick "write" and every share dialog in Bulwark (folders, calendars, address books, files, Delegates) offers read access only.', category: 'Sharing', type: 'enum', allowedValues: ['read', 'write'], page: 'org-sharing', modes: ['allowedValues'] },
|
|
{ key: 'deletedItemsRecovery', label: 'Recover deleted items', description: 'Hide removes Settings > Recover deleted items and its link in Trash, so users can no longer restore mail they deleted for good.', category: 'Sharing', type: 'boolean', page: 'org-sharing', modes: ['hidden'] },
|
|
];
|
|
|
|
export function restrictionKeysForPage(page: AdminPageId): RestrictionKeyDef[] {
|
|
return RESTRICTION_KEYS.filter((def) => def.page === page);
|
|
}
|