From c21d512958fbda8bac95c9ed3f6f2850bcbd3f7b Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Thu, 23 Jan 2025 15:08:40 +0100 Subject: [PATCH] feat(account settings): add hash-based routing for settings categories Each settings category now has a dedicated URL hash that expands only that category when accessed directly. The URL updates dynamically based on which category is expanded. --- .../account-settings/account-settings.tsx | 8 ++ .../settings-modal/settings-modal.tsx | 96 ++++++++++++++++--- 2 files changed, 89 insertions(+), 15 deletions(-) diff --git a/src/components/settings-modal/account-settings/account-settings.tsx b/src/components/settings-modal/account-settings/account-settings.tsx index dbbe8536..94e59ff2 100644 --- a/src/components/settings-modal/account-settings/account-settings.tsx +++ b/src/components/settings-modal/account-settings/account-settings.tsx @@ -5,6 +5,7 @@ import stringify from 'json-stringify-pretty-compact'; import styles from './account-settings.module.css'; import useAnonModeStore from '../../../stores/use-anon-mode-store'; import { Capacitor } from '@capacitor/core'; +import { useLocation, useNavigate } from 'react-router-dom'; const isAndroid = Capacitor.getPlatform() === 'android'; @@ -25,6 +26,7 @@ const AnonMode = () => { const AccountSettings = () => { const { t } = useTranslation(); + const location = useLocation(); const account = useAccount(); const [text, setText] = useState(''); @@ -39,6 +41,7 @@ const AccountSettings = () => { const { accounts } = useAccounts(); const switchToNewAccountRef = useRef(false); + const navigate = useNavigate(); useEffect(() => { if (switchToNewAccountRef.current && accounts.length > 0) { @@ -160,6 +163,11 @@ const AccountSettings = () => { } alert(`Imported ${newAccount.account?.name}`); + + const currentPath = location.pathname; + if (!currentPath.includes('/settings#account-settings')) { + navigate(`${currentPath}#account-settings`, { replace: true }); + } window.location.reload(); } catch (error) { if (error instanceof Error) { diff --git a/src/components/settings-modal/settings-modal.tsx b/src/components/settings-modal/settings-modal.tsx index afb76cbc..01ff2a3b 100644 --- a/src/components/settings-modal/settings-modal.tsx +++ b/src/components/settings-modal/settings-modal.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import styles from './settings-modal.module.css'; @@ -14,6 +14,7 @@ const SettingsModal = () => { const { t } = useTranslation(); const location = useLocation(); const navigate = useNavigate(); + const hash = location.hash.slice(1); const closeModal = () => { const newPath = location.pathname.replace(/\/settings$/, ''); @@ -29,6 +30,68 @@ const SettingsModal = () => { const [showPlebbitOptionsSettings, setShowPlebbitOptionsSettings] = useState(false); const [expandAll, setExpandAll] = useState(false); + const getExpandedCount = () => { + return ( + Number(showInterfaceSettings) + + Number(showAccountSettings) + + Number(showAvatarSettings) + + Number(showCryptoAddressSetting) + + Number(showCryptoWalletSettings) + + Number(showBlockedAddressesSetting) + + Number(showPlebbitOptionsSettings) + ); + }; + + const getExpandedCategoryId = (excludeCategoryId?: string) => { + if (showInterfaceSettings && 'interface-settings' !== excludeCategoryId) return 'interface-settings'; + if (showAccountSettings && 'account-settings' !== excludeCategoryId) return 'account-settings'; + if (showAvatarSettings && 'avatar-settings' !== excludeCategoryId) return 'avatar-settings'; + if (showCryptoAddressSetting && 'crypto-address-settings' !== excludeCategoryId) return 'crypto-address-settings'; + if (showCryptoWalletSettings && 'crypto-wallet-settings' !== excludeCategoryId) return 'crypto-wallet-settings'; + if (showBlockedAddressesSetting && 'blocked-addresses-settings' !== excludeCategoryId) return 'blocked-addresses-settings'; + if (showPlebbitOptionsSettings && 'plebbit-options-settings' !== excludeCategoryId) return 'plebbit-options-settings'; + return null; + }; + + const handleCategoryClick = (categoryId: string, isShowing: boolean, setShowing: (value: boolean) => void) => { + const newState = !isShowing; + setShowing(newState); + + 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(() => { + if (hash) { + setShowInterfaceSettings(hash === 'interface-settings'); + setShowAccountSettings(hash === 'account-settings'); + setShowAvatarSettings(hash === 'avatar-settings'); + setShowCryptoAddressSetting(hash === 'crypto-address-settings'); + setShowCryptoWalletSettings(hash === 'crypto-wallet-settings'); + setShowBlockedAddressesSetting(hash === 'blocked-addresses-settings'); + setShowPlebbitOptionsSettings(hash === 'plebbit-options-settings'); + } + }, [hash]); + const handleExpandAll = () => { const newExpandState = !expandAll; setExpandAll(newExpandState); @@ -39,6 +102,9 @@ const SettingsModal = () => { setShowCryptoWalletSettings(newExpandState); setShowBlockedAddressesSetting(newExpandState); setShowPlebbitOptionsSettings(newExpandState); + + const baseSettingsPath = location.pathname.split('#')[0]; + navigate(baseSettingsPath, { replace: true }); }; return ( @@ -52,50 +118,50 @@ const SettingsModal = () => {
[{expandAll ? t('collapse_all_settings') : t('expand_all_settings')}]
-
-