feat(settings): quick wins from the settings audit (#453)
CI / Build & Quality Checks (push) Skipped
CI / Secret scan (gitleaks) (push) Skipped
CI / Playwright smoke (e2e) (push) Skipped
CI / Build & Quality Checks (pull_request) Successful in 3m18s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 12s
CI / Playwright smoke (e2e) (pull_request) Successful in 24m56s
CI / Build & Quality Checks (push) Skipped
CI / Secret scan (gitleaks) (push) Skipped
CI / Playwright smoke (e2e) (push) Skipped
CI / Build & Quality Checks (pull_request) Successful in 3m18s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 12s
CI / Playwright smoke (e2e) (pull_request) Successful in 24m56s
- #456 Copy pass: sentence case for every setting title and section, plainer names ("Hide joins and leaves", "Link previews", "Emoji style: Twemoji", "Rejoin calls after a restart", "Also use the browser's noise suppression", "Push-to-talk key"...) and grammar fixes ("when messages arrive", "Play a sound when a new message arrives", blocked users "Enter their Matrix ID"). Labels only: no setting is renamed in storage. - #455 One theme control: Theme: System / Light / Dark. System shows the light and dark variant pickers, Light or Dark one picker of that kind. Replaces the System switch plus a Theme dropdown that was greyed out whenever the switch was on. Uses the existing settings (no migration); picking a variant also remembers it for System. - #457 Remove the "Block Messages" stub from Notifications; the GIF picker row only appears in builds with a GIF key. - #458 (part 1) "Export/Import Messages Data" -> "Export/Import encryption keys", with a sentence on when you need it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0d4f2e4a87
commit
5d15013a27
@@ -205,7 +205,7 @@ export function About({ requestClose }: AboutProps) {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Clear Cache & Reload"
|
||||
title="Clear cache and reload"
|
||||
description="Clear all your locally stored data and reload from server. This also deletes this device's encryption keys — older encrypted messages stay unreadable here unless key backup is set up."
|
||||
after={
|
||||
<Button
|
||||
|
||||
@@ -22,14 +22,14 @@ export function ContactInformation() {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Contact Information</Text>
|
||||
<Text size="L400">Contact information</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile title="Email Address" description="Email address attached to your account.">
|
||||
<SettingTile title="Email address" description="Email address attached to your account.">
|
||||
<Box>
|
||||
{emailIds?.map((email) => (
|
||||
<Chip key={email.address} as="span" variant="Secondary" radii="Pill">
|
||||
|
||||
@@ -136,7 +136,7 @@ export function IgnoredUserList() {
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box alignItems="Center" justifyContent="SpaceBetween" gap="200">
|
||||
<Text size="L400">Blocked Users</Text>
|
||||
<Text size="L400">Blocked users</Text>
|
||||
</Box>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
@@ -145,8 +145,8 @@ export function IgnoredUserList() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Select User"
|
||||
description="Prevent receiving messages or invites from user by adding their userId."
|
||||
title="Block someone"
|
||||
description="Stop someone's messages and invites reaching you. Enter their Matrix ID, e.g. @name:server."
|
||||
>
|
||||
<Box direction="Column" gap="300">
|
||||
<IgnoreUserInput userList={ignoredUsers} />
|
||||
|
||||
@@ -31,7 +31,7 @@ export function OidcManageAccount() {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Account Management</Text>
|
||||
<Text size="L400">Account management</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
|
||||
@@ -72,7 +72,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Enable Developer Tools"
|
||||
title="Enable developer tools"
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
@@ -90,7 +90,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Access Token"
|
||||
title="Access token"
|
||||
description="Copy access token to clipboard."
|
||||
after={
|
||||
<Button
|
||||
|
||||
@@ -35,7 +35,7 @@ export function CryptoDiagnostics() {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Crypto Diagnostics</Text>
|
||||
<Text size="L400">Crypto diagnostics</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
@@ -43,8 +43,8 @@ export function CryptoDiagnostics() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Crypto Diagnostics — captures E2EE error signatures this session"
|
||||
description="Ring-buffers up to 200 matched console warnings/errors for the KE-1..KE-4 bug cluster. Local only — no network calls. The downloaded report includes the matched log lines as evidence."
|
||||
title="Crypto diagnostics"
|
||||
description="Captures encryption error signatures from this session. Ring-buffers up to 200 matched console warnings/errors for the KE-1..KE-4 bug cluster. Local only — no network calls. The downloaded report includes the matched log lines as evidence."
|
||||
after={
|
||||
<Box alignItems="Center" gap="200" shrink="No">
|
||||
<Badge variant={count > 0 ? 'Critical' : 'Secondary'} fill="Solid" radii="Pill">
|
||||
|
||||
@@ -93,8 +93,8 @@ export function Devices({ requestClose }: DevicesProps) {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Device Verification"
|
||||
description="To verify device identity and grant access to encrypted messages."
|
||||
title="Device verification"
|
||||
description="Verify this device so it can read your encrypted messages and others can trust it."
|
||||
after={
|
||||
<>
|
||||
<EnableVerification visible={!crossSigningActive} />
|
||||
|
||||
@@ -130,8 +130,8 @@ function ExportKeysTile() {
|
||||
return (
|
||||
<>
|
||||
<SettingTile
|
||||
title="Export Messages Data"
|
||||
description="Save password protected copy of encryption data on your device to decrypt messages later."
|
||||
title="Export encryption keys"
|
||||
description="Save a password-protected file of your encryption keys. Useful when moving to a device without key backup, or as an offline copy."
|
||||
after={
|
||||
<Box>
|
||||
<Button
|
||||
@@ -260,8 +260,8 @@ function ImportKeysTile() {
|
||||
return (
|
||||
<>
|
||||
<SettingTile
|
||||
title="Import Messages Data"
|
||||
description="Load password protected copy of encryption data from device to decrypt your messages."
|
||||
title="Import encryption keys"
|
||||
description="Load a password-protected encryption key file to read older encrypted messages on this device."
|
||||
after={
|
||||
<Box>
|
||||
{file ? (
|
||||
@@ -307,7 +307,7 @@ function ImportKeysTile() {
|
||||
export function LocalBackup() {
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Local Backup</Text>
|
||||
<Text size="L400">Encryption key backup file</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
|
||||
@@ -135,7 +135,7 @@ export function OtherDevices({ devices, refreshDeviceList, showVerification }: O
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Device Dashboard"
|
||||
title="Device dashboard"
|
||||
description="Manage your devices on OIDC dashboard."
|
||||
after={
|
||||
<Button
|
||||
|
||||
@@ -423,7 +423,7 @@ export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
|
||||
return (
|
||||
<>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Favorite Packs</Text>
|
||||
<Text size="L400">Favourite packs</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
@@ -431,7 +431,7 @@ export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Select Pack"
|
||||
title="Add a pack"
|
||||
description="Pick emojis and stickers pack from rooms to use in all rooms."
|
||||
after={
|
||||
<>
|
||||
|
||||
@@ -31,7 +31,7 @@ export function UserPack({ onViewPack }: UserPackProps) {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Default Pack</Text>
|
||||
<Text size="L400">Default pack</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
|
||||
@@ -155,7 +155,7 @@ function DesktopChromeSetting() {
|
||||
return (
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Custom Window Chrome (Beta)"
|
||||
title="Custom window chrome (beta)"
|
||||
description="Replace the system title bar with a Lotus-styled one. Desktop only — reloads to apply."
|
||||
after={<Switch variant="Primary" value={customChrome} onChange={handleToggle} />}
|
||||
/>
|
||||
@@ -263,7 +263,7 @@ function KeychainMirrorSetting() {
|
||||
}
|
||||
return (
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile title="Login in the system keychain" description={description} />
|
||||
<SettingTile title="Keep your sign-in in the system keychain" description={description} />
|
||||
</SequenceCard>
|
||||
);
|
||||
}
|
||||
@@ -294,12 +294,18 @@ const ThemeSelector = as<'div', ThemeSelectorProps>(
|
||||
),
|
||||
);
|
||||
|
||||
function SelectTheme({ disabled }: { disabled?: boolean }) {
|
||||
const themes = useThemes();
|
||||
function SelectTheme({ disabled, kind }: { disabled?: boolean; kind?: ThemeKind }) {
|
||||
const allThemes = useThemes();
|
||||
const themes = kind ? allThemes.filter((theme) => theme.kind === kind) : allThemes;
|
||||
const themeNames = useThemeNames();
|
||||
const [themeId, setThemeId] = useSetting(settingsAtom, 'themeId');
|
||||
const [, setLightThemeId] = useSetting(settingsAtom, 'lightThemeId');
|
||||
const [, setDarkThemeId] = useSetting(settingsAtom, 'darkThemeId');
|
||||
const [menuCords, setMenuCords] = useState<RectCords>();
|
||||
const selectedTheme = themes.find((theme) => theme.id === themeId) ?? LightTheme;
|
||||
const selectedTheme =
|
||||
themes.find((theme) => theme.id === themeId) ??
|
||||
themes[0] ??
|
||||
(kind === ThemeKind.Dark ? DarkTheme : LightTheme);
|
||||
|
||||
const handleThemeMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||
setMenuCords(evt.currentTarget.getBoundingClientRect());
|
||||
@@ -307,6 +313,10 @@ function SelectTheme({ disabled }: { disabled?: boolean }) {
|
||||
|
||||
const handleThemeSelect = (theme: Theme) => {
|
||||
setThemeId(theme.id);
|
||||
// [Gitea #455] Also remember it as this kind's variant, so switching to
|
||||
// System later keeps the user's pick.
|
||||
if (theme.kind === ThemeKind.Light) setLightThemeId(theme.id);
|
||||
else setDarkThemeId(theme.id);
|
||||
setMenuCords(undefined);
|
||||
};
|
||||
|
||||
@@ -391,7 +401,7 @@ function SystemThemePreferences() {
|
||||
return (
|
||||
<Box wrap="Wrap" gap="400">
|
||||
<SettingTile
|
||||
title="Light Theme:"
|
||||
title="Light theme:"
|
||||
after={
|
||||
<Chip
|
||||
variant={themeKind === ThemeKind.Light ? 'Primary' : 'Secondary'}
|
||||
@@ -432,7 +442,7 @@ function SystemThemePreferences() {
|
||||
}
|
||||
/>
|
||||
<SettingTile
|
||||
title="Dark Theme:"
|
||||
title="Dark theme:"
|
||||
after={
|
||||
<Chip
|
||||
variant={themeKind === ThemeKind.Dark ? 'Primary' : 'Secondary'}
|
||||
@@ -534,6 +544,26 @@ function PageZoomInput() {
|
||||
|
||||
function Appearance() {
|
||||
const [systemTheme, setSystemTheme] = useSetting(settingsAtom, 'useSystemTheme');
|
||||
const allThemes = useThemes();
|
||||
const [themeId, setThemeId] = useSetting(settingsAtom, 'themeId');
|
||||
const [lightThemeId] = useSetting(settingsAtom, 'lightThemeId');
|
||||
const [darkThemeId] = useSetting(settingsAtom, 'darkThemeId');
|
||||
const currentKind = allThemes.find((t) => t.id === themeId)?.kind ?? ThemeKind.Light;
|
||||
let themeMode: 'system' | 'light' | 'dark' = 'system';
|
||||
if (!systemTheme) themeMode = currentKind === ThemeKind.Dark ? 'dark' : 'light';
|
||||
const chooseThemeMode = (mode: 'system' | 'light' | 'dark') => {
|
||||
if (mode === 'system') {
|
||||
setSystemTheme(true);
|
||||
return;
|
||||
}
|
||||
setSystemTheme(false);
|
||||
// Use the variant already chosen for that kind (or the default one).
|
||||
const kind = mode === 'dark' ? ThemeKind.Dark : ThemeKind.Light;
|
||||
if (allThemes.find((t) => t.id === themeId)?.kind === kind) return;
|
||||
const preferred = mode === 'dark' ? darkThemeId : lightThemeId;
|
||||
const fallback = mode === 'dark' ? DarkTheme.id : LightTheme.id;
|
||||
setThemeId(allThemes.find((t) => t.id === preferred && t.kind === kind)?.id ?? fallback);
|
||||
};
|
||||
const [monochromeMode, setMonochromeMode] = useSetting(settingsAtom, 'monochromeMode');
|
||||
const [twitterEmoji, setTwitterEmoji] = useSetting(settingsAtom, 'twitterEmoji');
|
||||
const [perMessageProfiles, setPerMessageProfiles] = useSetting(
|
||||
@@ -575,38 +605,64 @@ function Appearance() {
|
||||
direction="Column"
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="System Theme"
|
||||
description="Choose between light and dark theme based on system preference."
|
||||
after={<Switch variant="Primary" value={systemTheme} onChange={setSystemTheme} />}
|
||||
/>
|
||||
{systemTheme && <SystemThemePreferences />}
|
||||
</SequenceCard>
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
{/* [Gitea #455] One control instead of a System switch plus a Theme
|
||||
dropdown that was greyed out whenever the switch was on. */}
|
||||
<SettingTile
|
||||
title="Theme"
|
||||
description="Theme to use when system theme is not enabled."
|
||||
after={<SelectTheme disabled={systemTheme} />}
|
||||
description={
|
||||
themeMode === 'system'
|
||||
? "Follows your device's light or dark setting."
|
||||
: 'Always use this theme, whatever your device is set to.'
|
||||
}
|
||||
after={
|
||||
<Box gap="100" role="radiogroup" aria-label="Theme" shrink="No" wrap="Wrap">
|
||||
{(
|
||||
[
|
||||
['system', 'System'],
|
||||
['light', 'Light'],
|
||||
['dark', 'Dark'],
|
||||
] as const
|
||||
).map(([mode, label]) => (
|
||||
<Chip
|
||||
key={mode}
|
||||
role="radio"
|
||||
aria-checked={themeMode === mode}
|
||||
variant={themeMode === mode ? 'Primary' : 'Secondary'}
|
||||
outlined={themeMode === mode}
|
||||
radii="Pill"
|
||||
onClick={() => chooseThemeMode(mode)}
|
||||
>
|
||||
<Text size="B300">{label}</Text>
|
||||
</Chip>
|
||||
))}
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
{themeMode === 'system' && <SystemThemePreferences />}
|
||||
{themeMode !== 'system' && (
|
||||
<SettingTile
|
||||
title={themeMode === 'light' ? 'Light theme:' : 'Dark theme:'}
|
||||
after={<SelectTheme kind={themeMode === 'light' ? ThemeKind.Light : ThemeKind.Dark} />}
|
||||
/>
|
||||
)}
|
||||
</SequenceCard>
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Monochrome Mode"
|
||||
title="Monochrome mode"
|
||||
after={<Switch variant="Primary" value={monochromeMode} onChange={setMonochromeMode} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Twitter Emoji"
|
||||
title="Emoji style: Twemoji"
|
||||
after={<Switch variant="Primary" value={twitterEmoji} onChange={setTwitterEmoji} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile title="Page Zoom" after={<PageZoomInput />} />
|
||||
<SettingTile title="Page zoom" after={<PageZoomInput />} />
|
||||
</SequenceCard>
|
||||
|
||||
<SequenceCard
|
||||
@@ -616,7 +672,7 @@ function Appearance() {
|
||||
gap="200"
|
||||
>
|
||||
<SettingTile
|
||||
title="Chat Background"
|
||||
title="Chat background"
|
||||
description="Pattern applied behind the message timeline."
|
||||
/>
|
||||
<Box style={{ padding: `0 ${config.space.S400} ${config.space.S300}` }}>
|
||||
@@ -626,7 +682,7 @@ function Appearance() {
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Pause Background Animations"
|
||||
title="Pause background animations"
|
||||
description="Stop background animation to reduce motion or improve performance."
|
||||
after={<Switch variant="Primary" value={pauseAnimations} onChange={setPauseAnimations} />}
|
||||
/>
|
||||
@@ -639,7 +695,7 @@ function Appearance() {
|
||||
gap="200"
|
||||
>
|
||||
<SettingTile
|
||||
title="Seasonal Theme"
|
||||
title="Seasonal theme"
|
||||
description="Decorative overlays for holidays and events. “Auto” follows the calendar — each theme below shows the dates it turns on. Click to select."
|
||||
/>
|
||||
<Box style={{ padding: `0 ${config.space.S400} ${config.space.S300}` }}>
|
||||
@@ -659,7 +715,7 @@ function Appearance() {
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Show Profile on Every Message"
|
||||
title="Show name and avatar on every message"
|
||||
description="Display avatar and name on each message instead of grouping consecutive messages."
|
||||
after={
|
||||
<Switch variant="Primary" value={perMessageProfiles} onChange={setPerMessageProfiles} />
|
||||
@@ -673,7 +729,7 @@ function Appearance() {
|
||||
gap="200"
|
||||
>
|
||||
<SettingTile
|
||||
title="Night Light"
|
||||
title="Night light"
|
||||
description="Reduce blue light with a warm orange tint overlay."
|
||||
after={
|
||||
<Switch variant="Primary" value={nightLightEnabled} onChange={setNightLightEnabled} />
|
||||
@@ -753,7 +809,7 @@ function Appearance() {
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Glassmorphism Sidebar"
|
||||
title="Glass sidebar"
|
||||
description="Semi-transparent sidebar with frosted glass effect. Works best with custom chat backgrounds."
|
||||
after={
|
||||
<Switch
|
||||
@@ -767,8 +823,8 @@ function Appearance() {
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Lotus Terminal Mode"
|
||||
description="LotusGuild Terminal Design System: Anduril Orange + Ice Cyan + Matrix Green, dot-grid background, CRT scanlines, and boot sequence animation (press Escape to skip)."
|
||||
title="Lotus Terminal mode"
|
||||
description="A retro terminal look: orange and cyan on a dot grid, CRT scanlines and a boot animation (press Esc to skip)."
|
||||
after={
|
||||
<Box direction="Row" gap="200" alignItems="Center">
|
||||
{lotusTerminal && (
|
||||
@@ -802,7 +858,7 @@ function Appearance() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="UI Font"
|
||||
title="Interface font"
|
||||
description="Font used throughout the interface."
|
||||
after={
|
||||
<SettingsSelect
|
||||
@@ -822,7 +878,7 @@ function Appearance() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="@Mention Highlight Color"
|
||||
title="@mention highlight colour"
|
||||
description="Color used to highlight messages that mention you. Leave empty to use the theme default."
|
||||
after={
|
||||
<HexColorPickerPopOut
|
||||
@@ -866,7 +922,7 @@ function Appearance() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Custom Accent Color"
|
||||
title="Custom accent colour"
|
||||
description={
|
||||
lotusTerminal
|
||||
? 'Only applies to non-TDS themes. Disable Lotus Terminal Mode to use a custom accent.'
|
||||
@@ -1240,7 +1296,7 @@ function SelectDateFormat() {
|
||||
return (
|
||||
<>
|
||||
<SettingTile
|
||||
title="Date Format"
|
||||
title="Date format"
|
||||
description={customDateFormat ? dayjs().format(dateFormatString) : ''}
|
||||
after={<PresetDateFormat value={selectedDateFormat} onChange={handlePresetChange} />}
|
||||
/>
|
||||
@@ -1256,10 +1312,10 @@ function DateAndTime() {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Date & Time</Text>
|
||||
<Text size="L400">Date and time</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="24-Hour Time Format"
|
||||
title="24-hour time"
|
||||
after={<Switch variant="Primary" value={hour24Clock} onChange={setHour24Clock} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
@@ -1471,7 +1527,7 @@ function Editor() {
|
||||
<Text size="L400">Editor</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="ENTER for Newline"
|
||||
title="Enter for a new line"
|
||||
description={`Use ${
|
||||
isMacOS() ? KeySymbol.Command : 'Ctrl'
|
||||
} + ENTER to send message and ENTER for newline.`}
|
||||
@@ -1480,20 +1536,20 @@ function Editor() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Markdown Formatting"
|
||||
title="Markdown formatting"
|
||||
after={<Switch variant="Primary" value={isMarkdown} onChange={setIsMarkdown} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Offer to Format Pasted Code"
|
||||
title="Offer to format pasted code"
|
||||
description="When something you paste looks like code, offer to turn it into a code block. Nothing changes unless you accept."
|
||||
after={<Switch variant="Primary" value={offerCodePaste} onChange={setOfferCodePaste} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Formatting Toolbar"
|
||||
title="Formatting toolbar"
|
||||
description="Show bold, italic, code and other formatting buttons above the message input."
|
||||
after={<Switch variant="Primary" value={editorToolbar} onChange={setEditorToolbar} />}
|
||||
/>
|
||||
@@ -1505,7 +1561,7 @@ function Editor() {
|
||||
gap="300"
|
||||
>
|
||||
<SettingTile
|
||||
title="Composer Toolbar"
|
||||
title="Composer toolbar"
|
||||
description="Drag to reorder buttons, and tap a button to show or hide it in the message composer."
|
||||
/>
|
||||
<Box direction="Column" style={{ paddingBottom: config.space.S200 }}>
|
||||
@@ -1540,28 +1596,28 @@ function Privacy() {
|
||||
<Text size="L400">Privacy</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Strip Tracking Parameters from Links"
|
||||
title="Strip tracking parameters from links"
|
||||
description="Remove utm_, fbclid, YouTube si= and other ad/analytics identifiers from links you paste or send, and from links shown in chat. Runs entirely on this device."
|
||||
after={<Switch variant="Primary" value={stripTracking} onChange={setStripTracking} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Remove Photo Metadata Before Sending"
|
||||
title="Remove photo metadata before sending"
|
||||
description="Strip location, camera model and timestamp (EXIF/XMP) from JPEG, PNG and WebP images you send or set as an avatar. Pixels are untouched; the rotation is kept. Videos and GIFs are not covered."
|
||||
after={<Switch variant="Primary" value={stripImageMeta} onChange={setStripImageMeta} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Hide Typing & Read Receipts"
|
||||
title="Hide typing and read receipts"
|
||||
description="Turn off both typing status and read receipts to keep your activity private."
|
||||
after={<Switch variant="Primary" value={hideActivity} onChange={setHideActivity} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Private Read Receipts"
|
||||
title="Private read receipts"
|
||||
description="Send read receipts only to you and the server — other users won't see when you've read messages."
|
||||
after={
|
||||
<Switch
|
||||
@@ -1574,7 +1630,7 @@ function Privacy() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Hide Online Status"
|
||||
title="Hide online status"
|
||||
description="Appear offline to everyone while still using the app. Disables online, away, and idle indicators."
|
||||
after={<Switch variant="Primary" value={hidePresence} onChange={setHidePresence} />}
|
||||
/>
|
||||
@@ -1656,7 +1712,7 @@ function SettingsSyncSection() {
|
||||
<Text size="L400">Sync</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Sync Settings Across Devices"
|
||||
title="Sync settings across devices"
|
||||
description="Keep your preferences (theme, composer toolbar, notifications, quiet hours, call keys…) the same on every device, stored as account data on your own homeserver. Device-specific settings such as zoom, media auto-load, noise suppression and volumes stay local."
|
||||
after={<Switch variant="Primary" value={settingsSync} onChange={setSettingsSync} />}
|
||||
/>
|
||||
@@ -1664,7 +1720,7 @@ function SettingsSyncSection() {
|
||||
{settingsSync && (
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Use This Device's Settings Everywhere"
|
||||
title="Use this device's settings everywhere"
|
||||
description="Push this device's current preferences so every other device adopts them, even ones that changed something more recently."
|
||||
// [Gitea #273] On phones the two buttons squeezed the text into a
|
||||
// narrow column; put them under the description there.
|
||||
@@ -1799,14 +1855,14 @@ function Calls() {
|
||||
<Text size="L400">Calls</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Join with Camera On"
|
||||
title="Join with camera on"
|
||||
description="Enable camera automatically when joining a voice or video call. Camera is off by default."
|
||||
after={<Switch variant="Primary" value={cameraOnJoin} onChange={setCameraOnJoin} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Noise Suppression"
|
||||
title="Noise suppression"
|
||||
description={
|
||||
<Box direction="Column" gap="200">
|
||||
{/* [Gitea #271] T200 like every other setting description. */}
|
||||
@@ -1863,7 +1919,7 @@ function Calls() {
|
||||
<Box direction="Column" gap="200">
|
||||
<Text size="L400">Model</Text>
|
||||
<SettingTile
|
||||
title="ML Model"
|
||||
title="ML model"
|
||||
description="Choose the machine learning model used for noise removal. Heavier models clean more aggressively at a higher CPU cost."
|
||||
after={
|
||||
<SettingsSelect<DenoiseModelId>
|
||||
@@ -1979,7 +2035,7 @@ function Calls() {
|
||||
>
|
||||
<Text size="L400">Enhancements</Text>
|
||||
<SettingTile
|
||||
title="Series Suppression"
|
||||
title="Also use the browser's noise suppression"
|
||||
description="Run the browser's native stationary noise filter before the ML model. Recommended for eliminating fan hum."
|
||||
after={
|
||||
<Switch
|
||||
@@ -1991,7 +2047,7 @@ function Calls() {
|
||||
/>
|
||||
|
||||
<SettingTile
|
||||
title="Noise Gate"
|
||||
title="Noise gate"
|
||||
description="Hard-cut audio when you aren't speaking to ensure absolute silence between sentences."
|
||||
after={
|
||||
<Switch variant="Primary" value={callDenoiseGate} onChange={setCallDenoiseGate} />
|
||||
@@ -2027,7 +2083,7 @@ function Calls() {
|
||||
borderTop: `${config.borderWidth.B300} solid ${color.Surface.ContainerLine}`,
|
||||
}}
|
||||
>
|
||||
<Text size="L400">Test & calibrate</Text>
|
||||
<Text size="L400">Test and calibrate</Text>
|
||||
<Text size="T200" priority="300">
|
||||
Audition the selected model and tune the gate without joining a call. Changes to the
|
||||
settings above apply the next time you start a monitor or play a clip.
|
||||
@@ -2049,7 +2105,7 @@ function Calls() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="After a Restart"
|
||||
title="Rejoin calls after a restart"
|
||||
description="If Lotus crashes, reloads or restarts for an update while you are in a voice room, put you back in."
|
||||
after={
|
||||
<SettingsSelect<'ask' | 'auto' | 'off'>
|
||||
@@ -2064,7 +2120,7 @@ function Calls() {
|
||||
}
|
||||
/>
|
||||
<SettingTile
|
||||
title="Summary After Calls"
|
||||
title="Summary after calls"
|
||||
description="When a call ends, show how long it was and how the connection held up, with a Details button for who was there, network numbers and your own talk/mute time."
|
||||
after={
|
||||
<Switch variant="Primary" value={callSummaryToast} onChange={setCallSummaryToast} />
|
||||
@@ -2072,19 +2128,19 @@ function Calls() {
|
||||
/>
|
||||
{hapticsSupported() && (
|
||||
<SettingTile
|
||||
title="Haptic Feedback"
|
||||
title="Haptic feedback"
|
||||
description="A short vibration when push-to-talk engages or releases and when you send a reaction. Off automatically when your system prefers reduced motion."
|
||||
after={<Switch variant="Primary" value={haptics} onChange={setHaptics} />}
|
||||
/>
|
||||
)}
|
||||
<SettingTile
|
||||
title="Push to Talk"
|
||||
title="Push to talk"
|
||||
description="Mute your microphone by default. Hold the PTT key to speak."
|
||||
after={<Switch variant="Primary" value={pttMode} onChange={setPttMode} />}
|
||||
/>
|
||||
{pttMode && (
|
||||
<SettingTile
|
||||
title="PTT Key"
|
||||
title="Push-to-talk key"
|
||||
description={pttBind.error ?? 'Press a key to bind it as your push-to-talk key.'}
|
||||
after={
|
||||
<Button
|
||||
@@ -2102,7 +2158,7 @@ function Calls() {
|
||||
/>
|
||||
)}
|
||||
<SettingTile
|
||||
title="Push to Deafen"
|
||||
title="Push to deafen"
|
||||
description={
|
||||
deafenBind.error ??
|
||||
(deafenHotkey
|
||||
@@ -2143,7 +2199,7 @@ function Calls() {
|
||||
/>
|
||||
{isTauriEnv() && (
|
||||
<SettingTile
|
||||
title="Hotkeys Work Outside the Window"
|
||||
title="Hotkeys work outside the window"
|
||||
description="Keep Push to Talk and Push to Deafen working while a game or another app has focus. The keys are only watched during a call and are never blocked from other apps. Windows only; some anti-cheat systems may prevent it."
|
||||
after={
|
||||
<Switch variant="Primary" value={globalCallHotkeys} onChange={setGlobalCallHotkeys} />
|
||||
@@ -2165,13 +2221,13 @@ function Calls() {
|
||||
}
|
||||
/>
|
||||
<SettingTile
|
||||
title="AFK Auto-Mute"
|
||||
title="AFK auto-mute"
|
||||
description="Automatically mute your microphone when you have been silent in a call."
|
||||
after={<Switch variant="Primary" value={afkAutoMute} onChange={setAfkAutoMute} />}
|
||||
/>
|
||||
{afkAutoMute && (
|
||||
<SettingTile
|
||||
title="Idle Timeout"
|
||||
title="Idle timeout"
|
||||
description="How long to wait before auto-muting."
|
||||
after={
|
||||
<SettingsSelect
|
||||
@@ -2203,7 +2259,7 @@ function Calls() {
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile title="Ringtone Volume" description="Volume of the incoming call ringtone." />
|
||||
<SettingTile title="Ringtone volume" description="Volume of the incoming call ringtone." />
|
||||
<Box
|
||||
direction="Row"
|
||||
alignItems="Center"
|
||||
@@ -2227,7 +2283,7 @@ function Calls() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Join & Leave Sounds"
|
||||
title="Join and leave sounds"
|
||||
description="Play a sound when someone joins or leaves a call you are in. Selecting an option plays a preview."
|
||||
after={
|
||||
<SettingsSelect
|
||||
@@ -2246,7 +2302,7 @@ function Calls() {
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Microphone Bitrate"
|
||||
title="Microphone bitrate"
|
||||
description="Cap the audio bitrate your mic sends in calls. Lower saves bandwidth; higher is clearer. Auto lets Element Call decide."
|
||||
after={
|
||||
<SettingsSelect<CallAudioBitrate>
|
||||
@@ -2260,7 +2316,7 @@ function Calls() {
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Screenshare Bitrate"
|
||||
title="Screen share bitrate"
|
||||
description="Cap the bitrate used when you share your screen. Lower is smoother on poor connections; higher is sharper."
|
||||
after={
|
||||
<SettingsSelect<ScreenshareBitrate>
|
||||
@@ -2274,7 +2330,7 @@ function Calls() {
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Screenshare Framerate"
|
||||
title="Screen share frame rate"
|
||||
description="Cap the frames-per-second of your screenshare. 60 fps suits motion/gaming; 15 fps suits slides and saves bandwidth."
|
||||
after={
|
||||
<SettingsSelect<ScreenshareFramerate>
|
||||
@@ -2300,7 +2356,7 @@ function Calls() {
|
||||
/>
|
||||
{soundboardEnabled && (
|
||||
<>
|
||||
<SettingTile title="Soundboard Volume" />
|
||||
<SettingTile title="Soundboard volume" />
|
||||
<Box
|
||||
alignItems="Center"
|
||||
gap="200"
|
||||
@@ -2645,14 +2701,14 @@ function Messages() {
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Messages</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile title="Message Layout" after={<SelectMessageLayout />} />
|
||||
<SettingTile title="Message layout" after={<SelectMessageLayout />} />
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile title="Message Spacing" after={<SelectMessageSpacing />} />
|
||||
<SettingTile title="Message spacing" after={<SelectMessageSpacing />} />
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Legacy Username Color"
|
||||
title="Legacy username colour"
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
@@ -2664,7 +2720,7 @@ function Messages() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Hide Membership Change"
|
||||
title="Hide joins and leaves"
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
@@ -2676,7 +2732,7 @@ function Messages() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Hide Profile Change"
|
||||
title="Hide name and avatar changes"
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
@@ -2688,7 +2744,7 @@ function Messages() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Disable Media Auto Load"
|
||||
title="Don't load media automatically"
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
@@ -2700,14 +2756,14 @@ function Messages() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="URL Preview"
|
||||
title="Link previews"
|
||||
description="Your homeserver fetches and caches link previews. It will see the URLs of all links you preview."
|
||||
after={<Switch variant="Primary" value={urlPreview} onChange={setUrlPreview} />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="URL Preview in Encrypted Rooms"
|
||||
title="Link previews in encrypted rooms"
|
||||
description={
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="T200" priority="300">
|
||||
@@ -2731,34 +2787,29 @@ function Messages() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Inline Media Players"
|
||||
title="Inline media players"
|
||||
description="Play YouTube, Vimeo, TikTok, Twitch, Spotify and more right in the chat. Nothing loads from the third-party site until you press play."
|
||||
after={
|
||||
<Switch variant="Primary" value={inlineMediaEmbeds} onChange={setInlineMediaEmbeds} />
|
||||
}
|
||||
/>
|
||||
</SequenceCard>
|
||||
{/* [Gitea #457] Only where this build has a GIF key: a disabled switch
|
||||
with a paragraph about missing configuration helps nobody. */}
|
||||
{gifAvailable && (
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="GIF picker"
|
||||
description="Every search term (and your IP address) is sent directly to Giphy, not through your homeserver. Off by default."
|
||||
after={
|
||||
<Switch variant="Primary" value={gifPickerEnabled} onChange={setGifPickerEnabled} />
|
||||
}
|
||||
/>
|
||||
</SequenceCard>
|
||||
)}
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="GIF Picker"
|
||||
description={
|
||||
gifAvailable
|
||||
? 'Every search term (and your IP address) is sent directly to Giphy, not through your homeserver. Off by default.'
|
||||
: "GIF search isn't set up for this version of the app (no Giphy key in its configuration), so there is no GIF button even when this is on."
|
||||
}
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
value={gifPickerEnabled && gifAvailable}
|
||||
onChange={setGifPickerEnabled}
|
||||
disabled={!gifAvailable}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Show Hidden Events"
|
||||
title="Show hidden events"
|
||||
after={
|
||||
<Switch variant="Primary" value={showHiddenEvents} onChange={setShowHiddenEvents} />
|
||||
}
|
||||
@@ -2766,7 +2817,7 @@ function Messages() {
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Enforce Message Retention"
|
||||
title="Enforce message retention"
|
||||
description="Permanently delete your own messages once a room's retention window (Room Settings → Message Retention) has passed. Off by default; only affects your own messages."
|
||||
after={
|
||||
<Switch
|
||||
@@ -2783,7 +2834,7 @@ function Messages() {
|
||||
direction="Column"
|
||||
>
|
||||
<SettingTile
|
||||
title="Translate Messages Into"
|
||||
title="Translate messages into"
|
||||
description={
|
||||
translationSupported
|
||||
? 'Translate messages written in other languages into this one. Runs entirely on your device — message text never leaves your computer or touches a cloud service.'
|
||||
@@ -2801,7 +2852,7 @@ function Messages() {
|
||||
/>
|
||||
{translationSupported && (
|
||||
<SettingTile
|
||||
title="Auto-translate Incoming Messages"
|
||||
title="Auto-translate incoming messages"
|
||||
description="Automatically translate messages that aren’t already in your language. When off, translate individual messages from their menu. The first time a language is used, its model downloads once (a few MB)."
|
||||
after={<Switch variant="Primary" value={autoTranslate} onChange={setAutoTranslate} />}
|
||||
/>
|
||||
@@ -2962,9 +3013,9 @@ function AppUpdates() {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">App Updates</Text>
|
||||
<Text size="L400">App updates</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile title="Check for Updates" description={description} after={after} />
|
||||
<SettingTile title="Check for updates" description={description} after={after} />
|
||||
{packageUpdate && packageHelp && <PackageUpdate help={packageHelp} />}
|
||||
{status.state === 'error' && !packageUpdate && (
|
||||
<Text size="T200" priority="300" style={{ wordBreak: 'break-word' }}>
|
||||
|
||||
@@ -82,7 +82,7 @@ export function AllMessagesNotifications() {
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box alignItems="Center" justifyContent="SpaceBetween" gap="200">
|
||||
<Text size="L400">All Messages</Text>
|
||||
<Text size="L400">All messages</Text>
|
||||
<Box gap="100">
|
||||
<Text size="T200">Badge: </Text>
|
||||
<Badge radii="300" variant="Secondary" fill="Solid">
|
||||
@@ -97,7 +97,7 @@ export function AllMessagesNotifications() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="1-to-1 Chats"
|
||||
title="1-to-1 chats"
|
||||
after={<AllMessagesModeSwitcher pushRules={pushRules} ruleId={RuleId.DM} oneToOne />}
|
||||
/>
|
||||
</SequenceCard>
|
||||
@@ -108,7 +108,7 @@ export function AllMessagesNotifications() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="1-to-1 Chats (Encrypted)"
|
||||
title="1-to-1 chats (encrypted)"
|
||||
after={
|
||||
<AllMessagesModeSwitcher
|
||||
pushRules={pushRules}
|
||||
@@ -137,7 +137,7 @@ export function AllMessagesNotifications() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Rooms (Encrypted)"
|
||||
title="Rooms (encrypted)"
|
||||
after={
|
||||
<AllMessagesModeSwitcher
|
||||
pushRules={pushRules}
|
||||
|
||||
@@ -171,7 +171,7 @@ export function KeywordMessagesNotifications() {
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box alignItems="Center" justifyContent="SpaceBetween" gap="200">
|
||||
<Text size="L400">Keyword Messages</Text>
|
||||
<Text size="L400">Keyword messages</Text>
|
||||
<Box gap="100">
|
||||
<Text size="T200">Badge: </Text>
|
||||
<Badge radii="300" variant="Success" fill="Solid">
|
||||
@@ -186,7 +186,7 @@ export function KeywordMessagesNotifications() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Select Keyword"
|
||||
title="Add a keyword"
|
||||
description="Set a notification preference for message containing given keyword."
|
||||
>
|
||||
<KeywordInput />
|
||||
|
||||
@@ -9,7 +9,6 @@ import { KeywordMessagesNotifications } from './KeywordMessages';
|
||||
import { PushRuleEditor } from './PushRuleEditor';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../styles.css';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
import { settingsAtom, Settings } from '../../../state/settings';
|
||||
import { notificationSnoozeUntilAtom } from '../../../state/notificationSnooze';
|
||||
|
||||
@@ -81,7 +80,7 @@ function NotificationPresets() {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Quick Presets</Text>
|
||||
<Text size="L400">Quick presets</Text>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<Box gap="300" style={{ padding: config.space.S300, flexWrap: 'wrap' }}>
|
||||
{PRESETS.map((preset) => (
|
||||
@@ -150,17 +149,6 @@ export function Notifications({ requestClose }: NotificationsProps) {
|
||||
<SpecialMessagesNotifications />
|
||||
<KeywordMessagesNotifications />
|
||||
<PushRuleEditor />
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Block Messages</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile description='This option has been moved to "Account > Block Users" section.' />
|
||||
</SequenceCard>
|
||||
</Box>
|
||||
</Box>
|
||||
</PageContent>
|
||||
</Scroll>
|
||||
|
||||
@@ -333,10 +333,10 @@ export function PushRuleEditor() {
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Advanced Push Rules</Text>
|
||||
<RuleSection title="Override Rules" kind={PushRuleKind.Override} rules={overrideRules} />
|
||||
<Text size="L400">Advanced push rules</Text>
|
||||
<RuleSection title="Override rules" kind={PushRuleKind.Override} rules={overrideRules} />
|
||||
<RuleSection
|
||||
title="Room Rules"
|
||||
title="Room rules"
|
||||
kind={PushRuleKind.RoomSpecific}
|
||||
rules={roomRules}
|
||||
addForm={
|
||||
@@ -348,7 +348,7 @@ export function PushRuleEditor() {
|
||||
}
|
||||
/>
|
||||
<RuleSection
|
||||
title="Sender Rules"
|
||||
title="Sender rules"
|
||||
kind={PushRuleKind.SenderSpecific}
|
||||
rules={senderRules}
|
||||
addForm={
|
||||
@@ -359,7 +359,7 @@ export function PushRuleEditor() {
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<RuleSection title="Underride Rules" kind={PushRuleKind.Underride} rules={underrideRules} />
|
||||
<RuleSection title="Underride rules" kind={PushRuleKind.Underride} rules={underrideRules} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ export function SpecialMessagesNotifications() {
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box alignItems="Center" justifyContent="SpaceBetween" gap="200">
|
||||
<Text size="L400">Special Messages</Text>
|
||||
<Text size="L400">Special messages</Text>
|
||||
<Box gap="100">
|
||||
<Text size="T200">Badge: </Text>
|
||||
<Badge radii="300" variant="Success" fill="Solid">
|
||||
|
||||
@@ -63,7 +63,7 @@ function EmailNotification() {
|
||||
|
||||
return (
|
||||
<SettingTile
|
||||
title="Email Notification"
|
||||
title="Email notifications"
|
||||
description={
|
||||
<>
|
||||
{result && !result.email && (
|
||||
@@ -161,7 +161,7 @@ function PauseNotifications() {
|
||||
|
||||
return (
|
||||
<SettingTile
|
||||
title="Pause Notifications"
|
||||
title="Pause notifications"
|
||||
description={<span style={active ? { color: color.Warning.Main } : undefined}>{status}</span>}
|
||||
after={
|
||||
active ? (
|
||||
@@ -221,7 +221,7 @@ export function SystemNotification() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Desktop Notifications"
|
||||
title="Desktop notifications"
|
||||
description={
|
||||
notifPermission === 'denied' ? (
|
||||
<Text as="span" style={{ color: color.Critical.Main }} size="T200">
|
||||
@@ -230,7 +230,7 @@ export function SystemNotification() {
|
||||
: 'Notifications are not supported by the system.'}
|
||||
</Text>
|
||||
) : (
|
||||
<span>Show desktop notifications when message arrive.</span>
|
||||
<span>Show desktop notifications when messages arrive.</span>
|
||||
)
|
||||
}
|
||||
after={
|
||||
@@ -263,8 +263,8 @@ export function SystemNotification() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Notification Sound"
|
||||
description="Play sound when new message arrive."
|
||||
title="Notification sound"
|
||||
description="Play a sound when a new message arrives."
|
||||
after={<Switch value={isNotificationSounds} onChange={setIsNotificationSounds} />}
|
||||
/>
|
||||
{isNotificationSounds && (
|
||||
@@ -353,7 +353,7 @@ export function SystemNotification() {
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Quiet Hours"
|
||||
title="Quiet hours"
|
||||
description="Notifications are silenced between these times. Handles overnight (e.g. 11:00 PM – 8:00 AM)."
|
||||
after={<Switch value={quietHoursEnabled} onChange={setQuietHoursEnabled} />}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user