From 75602b6a001083b0fb657dffa43cc9670dd55ccc Mon Sep 17 00:00:00 2001 From: dealerweb Date: Wed, 3 Jun 2026 14:34:13 +0200 Subject: [PATCH] Fix: Settings section gears permanently hijacked the active tab The folder and tag section gears in the sidebar deep-linked into Settings by writing the persisted `settings-active-tab` localStorage key, so the chosen section became the permanent default the main Settings button opened on - indefinitely. Compounding it, the desktop Settings tab list called setActiveTab directly without persisting, so normal navigation never updated the default and the hijacked value could never self-correct. Fix: section gears now write a one-shot sessionStorage key that is consumed on mount (transient deep-link, no persistence); desktop tab clicks go through handleTabSelect like the mobile list, so the last-used tab is saved consistently. Stale/removed tab IDs are still caught by the existing effectiveActiveTab fallback. --- app/(main)/[locale]/settings/page.tsx | 15 ++++++++++++++- components/layout/sidebar.tsx | 4 ++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/(main)/[locale]/settings/page.tsx b/app/(main)/[locale]/settings/page.tsx index ab7dcad7..efe8d476 100644 --- a/app/(main)/[locale]/settings/page.tsx +++ b/app/(main)/[locale]/settings/page.tsx @@ -335,6 +335,14 @@ const LEGACY_TAB_MAP: Record = { function readPersistedTab(): Tab { try { + // One-shot deep link from the sidebar section gears (Folders / Tags). + // Used only as the initial tab and intentionally NOT written to + // 'settings-active-tab', so a gear click never becomes the persisted + // default that the regular Settings button lands on. Cleared on mount. + const deepLink = sessionStorage.getItem('settings-deep-link-tab'); + if (deepLink) { + return (deepLink in LEGACY_TAB_MAP ? LEGACY_TAB_MAP[deepLink] : deepLink) as Tab; + } const saved = localStorage.getItem('settings-active-tab'); if (!saved) return 'appearance'; if (saved in LEGACY_TAB_MAP) { @@ -360,6 +368,11 @@ export default function SettingsPage() { const { stalwartFeaturesEnabled } = useConfig(); const { isFeatureEnabled } = usePolicyStore(); const [activeTab, setActiveTab] = useState(readPersistedTab); + // Consume the one-shot deep-link key so a section gear only steers this one + // open, never the persisted default for future Settings-button clicks. + useEffect(() => { + try { sessionStorage.removeItem('settings-deep-link-tab'); } catch { /* ignore */ } + }, []); const [mobileShowContent, setMobileShowContent] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [pendingHighlight, setPendingHighlight] = useState<{ tab: Tab; label: string; pluginId?: string } | null>(null); @@ -933,7 +946,7 @@ export default function SettingsPage() { return (