From 1c55a79581971b7d4348b787e552cc5ddd91f25e Mon Sep 17 00:00:00 2001 From: plebeius Date: Tue, 24 Feb 2026 20:41:47 +0800 Subject: [PATCH] Update settings-modal.tsx --- .../settings-modal/settings-modal.tsx | 109 ++++++++++-------- 1 file changed, 58 insertions(+), 51 deletions(-) diff --git a/src/components/settings-modal/settings-modal.tsx b/src/components/settings-modal/settings-modal.tsx index 8028ca9e..0ea59a8e 100644 --- a/src/components/settings-modal/settings-modal.tsx +++ b/src/components/settings-modal/settings-modal.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import styles from './settings-modal.module.css'; @@ -10,6 +10,14 @@ import MediaHostingSettings from './media-hosting-settings'; import AdvancedSettings from './advanced-settings'; import SubscriptionsSetting from './subscriptions-setting'; +const allSectionIds = ['interface-settings', 'media-hosting-settings', 'account-settings', 'subscriptions-settings', 'advanced-settings']; + +const hashToSection = (hash: string): string | null => { + if (hash === 'crypto-address-settings' || hash === 'crypto-wallet-settings') return 'account-settings'; + if (allSectionIds.includes(hash)) return hash; + return null; +}; + const SettingsModal = () => { const { t } = useTranslation(); const location = useLocation(); @@ -34,58 +42,57 @@ const SettingsModal = () => { }; }, [closeModal]); - const [expandAll, setExpandAll] = useState(false); + const [expandedSections, setExpandedSections] = useState>(() => { + const section = hashToSection(hash); + return section ? new Set([section]) : new Set(); + }); - const expandAccount = hash === 'account-settings' || hash === 'crypto-address-settings' || hash === 'crypto-wallet-settings'; - const showInterfaceSettings = expandAll || hash === 'interface-settings'; - const showMediaHostingSettings = expandAll || hash === 'media-hosting-settings'; - const showAccountSettings = expandAll || expandAccount; - const showSubscriptionsSettings = expandAll || hash === 'subscriptions-settings'; - const showAdvancedSettings = expandAll || hash === 'advanced-settings'; + const showInterfaceSettings = expandedSections.has('interface-settings'); + const showMediaHostingSettings = expandedSections.has('media-hosting-settings'); + const showAccountSettings = expandedSections.has('account-settings'); + const showSubscriptionsSettings = expandedSections.has('subscriptions-settings'); + const showAdvancedSettings = expandedSections.has('advanced-settings'); - const getExpandedCount = () => { - return ( - Number(showInterfaceSettings) + Number(showMediaHostingSettings) + Number(showAccountSettings) + Number(showSubscriptionsSettings) + Number(showAdvancedSettings) - ); - }; + const allExpanded = useMemo(() => allSectionIds.every((id) => expandedSections.has(id)), [expandedSections]); - const getExpandedCategoryId = (excludeCategoryId?: string) => { - if (showInterfaceSettings && 'interface-settings' !== excludeCategoryId) return 'interface-settings'; - if (showMediaHostingSettings && 'media-hosting-settings' !== excludeCategoryId) return 'media-hosting-settings'; - if (showAccountSettings && 'account-settings' !== excludeCategoryId) return 'account-settings'; - if (showSubscriptionsSettings && 'subscriptions-settings' !== excludeCategoryId) return 'subscriptions-settings'; - if (showAdvancedSettings && 'advanced-settings' !== excludeCategoryId) return 'advanced-settings'; - return null; - }; + const basePath = location.pathname; - const handleCategoryClick = (categoryId: string, isShowing: boolean) => { - const newState = !isShowing; - const currentPath = location.pathname; - const baseSettingsPath = currentPath.split('#')[0]; - const currentExpandedCount = getExpandedCount(); - - if (newState) { - if (currentExpandedCount === 0) { - navigate(`${baseSettingsPath}#${categoryId}`, { replace: true }); - } else { - navigate(baseSettingsPath, { replace: true }); - } - } else { - if (currentExpandedCount === 1) { - navigate(baseSettingsPath, { replace: true }); - } else if (currentExpandedCount === 2) { - const remainingCategory = getExpandedCategoryId(categoryId); - if (remainingCategory) { - navigate(`${baseSettingsPath}#${remainingCategory}`, { replace: true }); - } - } + useEffect(() => { + const section = hashToSection(hash); + if (section && !expandedSections.has(section)) { + setExpandedSections((prev) => new Set(prev).add(section)); } + }, [hash]); // eslint-disable-line react-hooks/exhaustive-deps + + const handleCategoryClick = (categoryId: string) => { + setExpandedSections((prev) => { + const next = new Set(prev); + const isOpening = !next.has(categoryId); + if (isOpening) { + next.add(categoryId); + } else { + next.delete(categoryId); + } + if (isOpening) { + navigate(`${basePath}#${categoryId}`, { replace: true }); + } else if (next.size === 1) { + const remaining = next.values().next().value; + navigate(`${basePath}#${remaining}`, { replace: true }); + } else { + navigate(basePath, { replace: true }); + } + return next; + }); }; const handleExpandAll = () => { - setExpandAll((prev) => !prev); - const baseSettingsPath = location.pathname.split('#')[0]; - navigate(baseSettingsPath, { replace: true }); + if (allExpanded) { + setExpandedSections(new Set()); + navigate(basePath, { replace: true }); + } else { + setExpandedSections(new Set(allSectionIds)); + navigate(basePath, { replace: true }); + } }; const handleKeyDown = (handler: () => void) => (e: React.KeyboardEvent) => { @@ -106,26 +113,26 @@ const SettingsModal = () => {
[ - {expandAll ? t('collapse_all_settings') : t('expand_all_settings')} + {allExpanded ? t('collapse_all_settings') : t('expand_all_settings')} ]
-
{showInterfaceSettings && }
-
{showMediaHostingSettings && }
-