From 988416aa3da6b175361015b352d8b7fff0ce3858 Mon Sep 17 00:00:00 2001
From: Linus Rath <139418639+rathlinus@users.noreply.github.com>
Date: Mon, 19 Oct 2026 17:20:38 +0200
Subject: [PATCH] feat: add an advanced switch that hides power-user settings
until turned on
---
.../__tests__/advanced-settings.test.tsx | 61 +++++++++
components/settings/settings-app.tsx | 11 +-
components/settings/settings-section.tsx | 127 +++++++++++++++++-
locales/en/common.json | 28 ++--
stores/settings-store.ts | 5 +
5 files changed, 213 insertions(+), 19 deletions(-)
create mode 100644 components/settings/__tests__/advanced-settings.test.tsx
diff --git a/components/settings/__tests__/advanced-settings.test.tsx b/components/settings/__tests__/advanced-settings.test.tsx
new file mode 100644
index 000000000..c25c9cf5c
--- /dev/null
+++ b/components/settings/__tests__/advanced-settings.test.tsx
@@ -0,0 +1,61 @@
+import { render, screen, fireEvent, act } from '@testing-library/react';
+import { describe, it, expect, beforeEach } from 'vitest';
+import { AdvancedSettingsProvider, AdvancedSettingsSwitch, SettingItem, SettingsSection } from '../settings-section';
+import { useSettingsStore } from '@/stores/settings-store';
+
+function Page() {
+ return (
+
{description}
)} @@ -36,19 +140,30 @@ interface SettingItemProps { description?: string; children: ReactNode; locked?: boolean; + /** Hidden until the Advanced switch is on. */ + advanced?: boolean; + /** Indented under the row above it, for a sub-option of a toggle. */ + nested?: boolean; } -export function SettingItem({ label, description, children, locked }: SettingItemProps) { +export function SettingItem({ label, description, children, locked, advanced, nested }: SettingItemProps) { const labelId = useId(); + const visible = useAdvancedVisible(advanced); + if (!visible) return null; return ({description}
diff --git a/locales/en/common.json b/locales/en/common.json index 1516905e3..2cddb793b 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -1339,17 +1339,17 @@ "confirm_revoke_message_this": "This device will stop receiving background notifications immediately." }, "push_all": { - "title": "All accounts", - "description": "Turn push on or off for several accounts at once. One browser subscription serves them all.", - "select_all": "Select every connected account", - "state_on": "notifications on", - "state_off": "notifications off", - "enable_selected": "Enable for selected", - "disable_selected": "Disable for selected", - "result_enabled": "Notifications enabled for {count} accounts.", - "result_partial": "Enabled for {enabled} accounts; {failed} could not be enabled.", - "result_disabled": "Notifications disabled for {count} accounts." - }, + "title": "All accounts", + "description": "Turn push on or off for several accounts at once. One browser subscription serves them all.", + "select_all": "Select every connected account", + "state_on": "notifications on", + "state_off": "notifications off", + "enable_selected": "Enable for selected", + "disable_selected": "Disable for selected", + "result_enabled": "Notifications enabled for {count} accounts.", + "result_partial": "Enabled for {enabled} accounts; {failed} could not be enabled.", + "result_disabled": "Notifications disabled for {count} accounts." + }, "sound_selection": { "title": "Notification Sound", "description": "Choose which sound to play for notifications", @@ -2532,6 +2532,12 @@ "preview": { "label": "Preview" } + }, + "advanced_switch": { + "label": "Show advanced settings", + "badge": "Advanced", + "hidden_count": "{count, plural, one {1 advanced setting is hidden on this page.} other {# advanced settings are hidden on this page.}}", + "show": "Show advanced settings" } }, "errors": { diff --git a/stores/settings-store.ts b/stores/settings-store.ts index a44bc6006..9f77a1277 100644 --- a/stores/settings-store.ts +++ b/stores/settings-store.ts @@ -603,6 +603,9 @@ interface SettingsState { hideAccountSwitcher: boolean; showRailAccountList: boolean; proInterface: boolean; + // Settings marked `advanced` (power-user and integrator rows) stay hidden + // until this is on. Synced like the rest: it is a preference, not a device. + showAdvancedSettings: boolean; // Unified Mailbox enableUnifiedMailbox: boolean; @@ -889,6 +892,7 @@ const DEFAULT_SETTINGS = { hideAccountSwitcher: false, showRailAccountList: false, proInterface: false, + showAdvancedSettings: false, // Unified Mailbox enableUnifiedMailbox: false, @@ -1228,6 +1232,7 @@ export const useSettingsStore = create