mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
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.
This commit is contained in:
@@ -5,6 +5,7 @@ import stringify from 'json-stringify-pretty-compact';
|
|||||||
import styles from './account-settings.module.css';
|
import styles from './account-settings.module.css';
|
||||||
import useAnonModeStore from '../../../stores/use-anon-mode-store';
|
import useAnonModeStore from '../../../stores/use-anon-mode-store';
|
||||||
import { Capacitor } from '@capacitor/core';
|
import { Capacitor } from '@capacitor/core';
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
const isAndroid = Capacitor.getPlatform() === 'android';
|
const isAndroid = Capacitor.getPlatform() === 'android';
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ const AnonMode = () => {
|
|||||||
|
|
||||||
const AccountSettings = () => {
|
const AccountSettings = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const location = useLocation();
|
||||||
const account = useAccount();
|
const account = useAccount();
|
||||||
const [text, setText] = useState('');
|
const [text, setText] = useState('');
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ const AccountSettings = () => {
|
|||||||
|
|
||||||
const { accounts } = useAccounts();
|
const { accounts } = useAccounts();
|
||||||
const switchToNewAccountRef = useRef(false);
|
const switchToNewAccountRef = useRef(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (switchToNewAccountRef.current && accounts.length > 0) {
|
if (switchToNewAccountRef.current && accounts.length > 0) {
|
||||||
@@ -160,6 +163,11 @@ const AccountSettings = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
alert(`Imported ${newAccount.account?.name}`);
|
alert(`Imported ${newAccount.account?.name}`);
|
||||||
|
|
||||||
|
const currentPath = location.pathname;
|
||||||
|
if (!currentPath.includes('/settings#account-settings')) {
|
||||||
|
navigate(`${currentPath}#account-settings`, { replace: true });
|
||||||
|
}
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import styles from './settings-modal.module.css';
|
import styles from './settings-modal.module.css';
|
||||||
@@ -14,6 +14,7 @@ const SettingsModal = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const hash = location.hash.slice(1);
|
||||||
|
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
const newPath = location.pathname.replace(/\/settings$/, '');
|
const newPath = location.pathname.replace(/\/settings$/, '');
|
||||||
@@ -29,6 +30,68 @@ const SettingsModal = () => {
|
|||||||
const [showPlebbitOptionsSettings, setShowPlebbitOptionsSettings] = useState(false);
|
const [showPlebbitOptionsSettings, setShowPlebbitOptionsSettings] = useState(false);
|
||||||
const [expandAll, setExpandAll] = 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 handleExpandAll = () => {
|
||||||
const newExpandState = !expandAll;
|
const newExpandState = !expandAll;
|
||||||
setExpandAll(newExpandState);
|
setExpandAll(newExpandState);
|
||||||
@@ -39,6 +102,9 @@ const SettingsModal = () => {
|
|||||||
setShowCryptoWalletSettings(newExpandState);
|
setShowCryptoWalletSettings(newExpandState);
|
||||||
setShowBlockedAddressesSetting(newExpandState);
|
setShowBlockedAddressesSetting(newExpandState);
|
||||||
setShowPlebbitOptionsSettings(newExpandState);
|
setShowPlebbitOptionsSettings(newExpandState);
|
||||||
|
|
||||||
|
const baseSettingsPath = location.pathname.split('#')[0];
|
||||||
|
navigate(baseSettingsPath, { replace: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -52,50 +118,50 @@ const SettingsModal = () => {
|
|||||||
<div className={styles.expandAllSettings}>
|
<div className={styles.expandAllSettings}>
|
||||||
[<span onClick={handleExpandAll}>{expandAll ? t('collapse_all_settings') : t('expand_all_settings')}</span>]
|
[<span onClick={handleExpandAll}>{expandAll ? t('collapse_all_settings') : t('expand_all_settings')}</span>]
|
||||||
</div>
|
</div>
|
||||||
<div className={`${styles.setting} ${styles.category}`}>
|
<div id='interface-settings' className={`${styles.setting} ${styles.category}`}>
|
||||||
<label onClick={() => setShowInterfaceSettings(!showInterfaceSettings)}>
|
<label onClick={() => handleCategoryClick('interface-settings', showInterfaceSettings, setShowInterfaceSettings)}>
|
||||||
<span className={showInterfaceSettings ? styles.hideButton : styles.showButton} />
|
<span className={showInterfaceSettings ? styles.hideButton : styles.showButton} />
|
||||||
{t('interface')}
|
{t('interface')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{showInterfaceSettings && <InterfaceSettings />}
|
{showInterfaceSettings && <InterfaceSettings />}
|
||||||
<div className={`${styles.setting} ${styles.category}`}>
|
<div id='account-settings' className={`${styles.setting} ${styles.category}`}>
|
||||||
<label onClick={() => setShowAccountSettings(!showAccountSettings)}>
|
<label onClick={() => handleCategoryClick('account-settings', showAccountSettings, setShowAccountSettings)}>
|
||||||
<span className={showAccountSettings ? styles.hideButton : styles.showButton} />
|
<span className={showAccountSettings ? styles.hideButton : styles.showButton} />
|
||||||
{t('plebbit_account')}
|
{t('plebbit_account')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{showAccountSettings && <AccountSettings />}
|
{showAccountSettings && <AccountSettings />}
|
||||||
<div className={`${styles.setting} ${styles.category}`}>
|
<div id='avatar-settings' className={`${styles.setting} ${styles.category}`}>
|
||||||
<label onClick={() => setShowAvatarSettings(!showAvatarSettings)}>
|
<label onClick={() => handleCategoryClick('avatar-settings', showAvatarSettings, setShowAvatarSettings)}>
|
||||||
<span className={showAvatarSettings ? styles.hideButton : styles.showButton} />
|
<span className={showAvatarSettings ? styles.hideButton : styles.showButton} />
|
||||||
{t('avatar')}
|
{t('avatar')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{showAvatarSettings && <AvatarSettings />}
|
{showAvatarSettings && <AvatarSettings />}
|
||||||
<div className={`${styles.setting} ${styles.category}`}>
|
<div id='crypto-address-settings' className={`${styles.setting} ${styles.category}`}>
|
||||||
<label onClick={() => setShowCryptoAddressSetting(!showCryptoAddressSetting)}>
|
<label onClick={() => handleCategoryClick('crypto-address-settings', showCryptoAddressSetting, setShowCryptoAddressSetting)}>
|
||||||
<span className={showCryptoAddressSetting ? styles.hideButton : styles.showButton} />
|
<span className={showCryptoAddressSetting ? styles.hideButton : styles.showButton} />
|
||||||
{t('crypto_address')}
|
{t('crypto_address')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{showCryptoAddressSetting && <CryptoAddressSetting />}
|
{showCryptoAddressSetting && <CryptoAddressSetting />}
|
||||||
<div className={`${styles.setting} ${styles.category}`}>
|
<div id='crypto-wallet-settings' className={`${styles.setting} ${styles.category}`}>
|
||||||
<label onClick={() => setShowCryptoWalletSettings(!showCryptoWalletSettings)}>
|
<label onClick={() => handleCategoryClick('crypto-wallet-settings', showCryptoWalletSettings, setShowCryptoWalletSettings)}>
|
||||||
<span className={showCryptoWalletSettings ? styles.hideButton : styles.showButton} />
|
<span className={showCryptoWalletSettings ? styles.hideButton : styles.showButton} />
|
||||||
{t('crypto_wallets')}
|
{t('crypto_wallets')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{showCryptoWalletSettings && <CryptoWalletsSetting />}
|
{showCryptoWalletSettings && <CryptoWalletsSetting />}
|
||||||
<div className={`${styles.setting} ${styles.category}`}>
|
<div id='blocked-addresses-settings' className={`${styles.setting} ${styles.category}`}>
|
||||||
<label onClick={() => setShowBlockedAddressesSetting(!showBlockedAddressesSetting)}>
|
<label onClick={() => handleCategoryClick('blocked-addresses-settings', showBlockedAddressesSetting, setShowBlockedAddressesSetting)}>
|
||||||
<span className={showBlockedAddressesSetting ? styles.hideButton : styles.showButton} />
|
<span className={showBlockedAddressesSetting ? styles.hideButton : styles.showButton} />
|
||||||
{t('blocked_addresses')}
|
{t('blocked_addresses')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{showBlockedAddressesSetting && <BlockedAddressesSetting />}
|
{showBlockedAddressesSetting && <BlockedAddressesSetting />}
|
||||||
<div className={`${styles.setting} ${styles.category}`}>
|
<div id='plebbit-options-settings' className={`${styles.setting} ${styles.category}`}>
|
||||||
<label onClick={() => setShowPlebbitOptionsSettings(!showPlebbitOptionsSettings)}>
|
<label onClick={() => handleCategoryClick('plebbit-options-settings', showPlebbitOptionsSettings, setShowPlebbitOptionsSettings)}>
|
||||||
<span className={showPlebbitOptionsSettings ? styles.hideButton : styles.showButton} />
|
<span className={showPlebbitOptionsSettings ? styles.hideButton : styles.showButton} />
|
||||||
{t('plebbit_options')}
|
{t('plebbit_options')}
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user