mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf(settings): speed up board settings navigation (#1191)
* perf(settings): speed up board settings navigation * perf(settings): parallelize account section loading
This commit is contained in:
+1
-1
@@ -56,6 +56,7 @@ import BoardBlotter from './components/board-blotter/board-blotter';
|
||||
import BoardsBar from './components/boards-bar/boards-bar';
|
||||
import ExternalQuoteStatus from './components/external-quote-status/external-quote-status';
|
||||
import ModEmptyState from './components/mod-empty-state/mod-empty-state';
|
||||
import SettingsModal from './components/settings-modal';
|
||||
|
||||
const AccountDataEditor = lazy(() => import('./views/account-data-editor'));
|
||||
const BoardsBarEditModal = lazy(() => import('./components/boards-bar-edit-modal'));
|
||||
@@ -64,7 +65,6 @@ const ChallengeModal = lazy(() => import('./components/challenge-modal'));
|
||||
const DirectoryModal = lazy(() => import('./components/directory-modal'));
|
||||
const DisclaimerModal = lazy(() => import('./components/disclaimer-modal'));
|
||||
const ReplyModal = lazy(() => import('./components/reply-modal'));
|
||||
const SettingsModal = lazy(() => import('./components/settings-modal'));
|
||||
const SettingsUpgradeModal = lazy(() => import('./components/settings-upgrade-modal'));
|
||||
|
||||
// Preload all theme assets (buttons, backgrounds) immediately on app load
|
||||
|
||||
@@ -76,8 +76,8 @@ const LocationProbe = () => {
|
||||
let root: Root;
|
||||
let container: HTMLDivElement;
|
||||
|
||||
const render = (initialEntry = '/all/settings') => {
|
||||
act(() => {
|
||||
const render = async (initialEntry = '/all/settings') => {
|
||||
await act(async () => {
|
||||
root.render(
|
||||
createElement(MemoryRouter, { initialEntries: [initialEntry] }, createElement(React.Fragment, {}, createElement(SettingsModal), createElement(LocationProbe))),
|
||||
);
|
||||
@@ -123,8 +123,8 @@ describe('SettingsModal', () => {
|
||||
container.remove();
|
||||
});
|
||||
|
||||
it('opens the account section for crypto subsection hashes', () => {
|
||||
render('/all/settings#crypto-wallet-settings');
|
||||
it('opens the account section for crypto subsection hashes', async () => {
|
||||
await render('/all/settings#crypto-wallet-settings');
|
||||
|
||||
expect(container.querySelector('[data-testid="account-settings"]')).not.toBeNull();
|
||||
expect(container.querySelector('[data-testid="crypto-address-setting"]')).not.toBeNull();
|
||||
@@ -132,7 +132,7 @@ describe('SettingsModal', () => {
|
||||
});
|
||||
|
||||
it('updates the section query when sections open and close', async () => {
|
||||
render('/all/settings?section=account-settings');
|
||||
await render('/all/settings?section=account-settings');
|
||||
|
||||
expect(getLocationText()).toBe('/all/settings?section=account-settings');
|
||||
|
||||
@@ -160,7 +160,7 @@ describe('SettingsModal', () => {
|
||||
});
|
||||
|
||||
it('expands and collapses all settings sections', async () => {
|
||||
render('/all/settings');
|
||||
await render('/all/settings');
|
||||
|
||||
const expandAllControl = Array.from(container.querySelectorAll('button')).find((candidate) => (candidate.textContent ?? '').includes('expand_all_settings'));
|
||||
if (!expandAllControl) {
|
||||
@@ -208,7 +208,7 @@ describe('SettingsModal', () => {
|
||||
};
|
||||
useSettingsUpgradeReviewStore.getState().dismissUpgradeKeys([upgradeKey]);
|
||||
|
||||
render('/all/settings');
|
||||
await render('/all/settings');
|
||||
|
||||
expect(container.textContent).toContain('settings_upgrade_review_notice');
|
||||
const reviewButton = Array.from(container.querySelectorAll('button')).find((candidate) => candidate.textContent === 'settings_upgrade_review_button');
|
||||
@@ -233,14 +233,14 @@ describe('SettingsModal', () => {
|
||||
expect(useSettingsUpgradeReviewStore.getState().reviewRequestId).toBe(1);
|
||||
});
|
||||
|
||||
it.each(['/all/settings?section=p2p-stats-settings', '/all/settings#p2p-stats-settings'])('opens the p2p stats section from route %s', (route) => {
|
||||
render(route);
|
||||
it.each(['/all/settings?section=p2p-stats-settings', '/all/settings#p2p-stats-settings'])('opens the p2p stats section from route %s', async (route) => {
|
||||
await render(route);
|
||||
|
||||
expect(container.querySelector('[data-testid="p2p-stats-settings-panel"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('closes the modal when the overlay is clicked', async () => {
|
||||
render('/all/settings#interface-settings');
|
||||
await render('/all/settings#interface-settings');
|
||||
|
||||
const overlay = container.querySelector('button');
|
||||
if (!overlay) {
|
||||
@@ -255,7 +255,7 @@ describe('SettingsModal', () => {
|
||||
});
|
||||
|
||||
it('closes the modal when Escape is pressed', async () => {
|
||||
render('/all/settings');
|
||||
await render('/all/settings');
|
||||
|
||||
await act(async () => {
|
||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { lazy, Suspense, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useAccount, usePkcRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from './settings-modal.module.css';
|
||||
import AccountSettings from './account-settings/account-settings';
|
||||
import CryptoAddressSetting from './crypto-address-setting/crypto-address-setting';
|
||||
import CryptoWalletsSetting from './crypto-wallets-setting/crypto-wallets-setting';
|
||||
import InterfaceSettings from './interface-settings/interface-settings';
|
||||
import MediaHostingSettings from './media-hosting-settings/media-hosting-settings';
|
||||
import AdvancedSettings from './advanced-settings/advanced-settings';
|
||||
import SubscriptionsSetting from './subscriptions-setting/subscriptions-setting';
|
||||
import TrustedBoardLinksSetting from './trusted-board-links-setting/trusted-board-links-setting';
|
||||
import P2PStatsSettings from './p2p-stats-settings/p2p-stats-settings';
|
||||
import { P2P_STATS_SECTION_ID, shouldShowP2PSettingsSection } from '../../lib/p2p-runtime';
|
||||
import { getReviewableSettingsUpgrades, getSettingsUpgradeKey, type SettingsUpgradeAccount } from '../../lib/settings-upgrades';
|
||||
import useSettingsUpgradeReviewStore from '../../stores/use-settings-upgrade-review-store';
|
||||
import { getSettingsSectionPath } from '../../lib/utils/route-utils';
|
||||
|
||||
const AccountSettings = lazy(() => import('./account-settings/account-settings'));
|
||||
const CryptoAddressSetting = lazy(() => import('./crypto-address-setting/crypto-address-setting'));
|
||||
const CryptoWalletsSetting = lazy(() => import('./crypto-wallets-setting/crypto-wallets-setting'));
|
||||
const InterfaceSettings = lazy(() => import('./interface-settings/interface-settings'));
|
||||
const MediaHostingSettings = lazy(() => import('./media-hosting-settings/media-hosting-settings'));
|
||||
const AdvancedSettings = lazy(() => import('./advanced-settings/advanced-settings'));
|
||||
const SubscriptionsSetting = lazy(() => import('./subscriptions-setting/subscriptions-setting'));
|
||||
const TrustedBoardLinksSetting = lazy(() => import('./trusted-board-links-setting/trusted-board-links-setting'));
|
||||
const P2PStatsSettings = lazy(() => import('./p2p-stats-settings/p2p-stats-settings'));
|
||||
|
||||
const allSectionIds = [
|
||||
'interface-settings',
|
||||
'media-hosting-settings',
|
||||
@@ -164,14 +165,22 @@ const SettingsModal = () => {
|
||||
{t('interface')}
|
||||
</button>
|
||||
</div>
|
||||
{showInterfaceSettings && <InterfaceSettings />}
|
||||
{showInterfaceSettings && (
|
||||
<Suspense fallback={null}>
|
||||
<InterfaceSettings />
|
||||
</Suspense>
|
||||
)}
|
||||
<div id='media-hosting-settings' className={`${styles.setting} ${styles.category}`}>
|
||||
<button type='button' className={styles.categoryButton} onClick={() => handleCategoryClick('media-hosting-settings')}>
|
||||
<span className={showMediaHostingSettings ? styles.hideButton : styles.showButton} />
|
||||
{t('media_hosting')}
|
||||
</button>
|
||||
</div>
|
||||
{showMediaHostingSettings && <MediaHostingSettings />}
|
||||
{showMediaHostingSettings && (
|
||||
<Suspense fallback={null}>
|
||||
<MediaHostingSettings />
|
||||
</Suspense>
|
||||
)}
|
||||
<div id='account-settings' className={`${styles.setting} ${styles.category}`}>
|
||||
<button type='button' className={styles.categoryButton} onClick={() => handleCategoryClick('account-settings')}>
|
||||
<span className={showAccountSettings ? styles.hideButton : styles.showButton} />
|
||||
@@ -180,11 +189,17 @@ const SettingsModal = () => {
|
||||
</div>
|
||||
{showAccountSettings && (
|
||||
<>
|
||||
<AccountSettings />
|
||||
<Suspense fallback={null}>
|
||||
<AccountSettings />
|
||||
</Suspense>
|
||||
<div className={styles.subSectionHeader}>{t('crypto_address')}</div>
|
||||
<CryptoAddressSetting />
|
||||
<Suspense fallback={null}>
|
||||
<CryptoAddressSetting />
|
||||
</Suspense>
|
||||
<div className={styles.subSectionHeader}>{t('crypto_wallets')}</div>
|
||||
<CryptoWalletsSetting />
|
||||
<Suspense fallback={null}>
|
||||
<CryptoWalletsSetting />
|
||||
</Suspense>
|
||||
</>
|
||||
)}
|
||||
<div id='subscriptions-settings' className={`${styles.setting} ${styles.category}`}>
|
||||
@@ -193,21 +208,33 @@ const SettingsModal = () => {
|
||||
{t('board_subscriptions')}
|
||||
</button>
|
||||
</div>
|
||||
{showSubscriptionsSettings && <SubscriptionsSetting />}
|
||||
{showSubscriptionsSettings && (
|
||||
<Suspense fallback={null}>
|
||||
<SubscriptionsSetting />
|
||||
</Suspense>
|
||||
)}
|
||||
<div id='board-link-permissions-settings' className={`${styles.setting} ${styles.category}`}>
|
||||
<button type='button' className={styles.categoryButton} onClick={() => handleCategoryClick('board-link-permissions-settings')}>
|
||||
<span className={showBoardLinkPermissionsSettings ? styles.hideButton : styles.showButton} />
|
||||
{t('board_link_permissions')}
|
||||
</button>
|
||||
</div>
|
||||
{showBoardLinkPermissionsSettings && <TrustedBoardLinksSetting />}
|
||||
{showBoardLinkPermissionsSettings && (
|
||||
<Suspense fallback={null}>
|
||||
<TrustedBoardLinksSetting />
|
||||
</Suspense>
|
||||
)}
|
||||
<div id='advanced-settings' className={`${styles.setting} ${styles.category}`}>
|
||||
<button type='button' className={styles.categoryButton} onClick={() => handleCategoryClick('advanced-settings')}>
|
||||
<span className={showAdvancedSettings ? styles.hideButton : styles.showButton} />
|
||||
{t('advanced_settings')}
|
||||
</button>
|
||||
</div>
|
||||
{showAdvancedSettings && <AdvancedSettings />}
|
||||
{showAdvancedSettings && (
|
||||
<Suspense fallback={null}>
|
||||
<AdvancedSettings />
|
||||
</Suspense>
|
||||
)}
|
||||
{sectionIds.includes(P2P_STATS_SECTION_ID) && (
|
||||
<>
|
||||
<div id={P2P_STATS_SECTION_ID} className={`${styles.setting} ${styles.category}`}>
|
||||
@@ -216,7 +243,11 @@ const SettingsModal = () => {
|
||||
{t('p2p_stats')}
|
||||
</button>
|
||||
</div>
|
||||
{showP2PStatsSettings && <P2PStatsSettings />}
|
||||
{showP2PStatsSettings && (
|
||||
<Suspense fallback={null}>
|
||||
<P2PStatsSettings />
|
||||
</Suspense>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{showSettingsUpgradeReview && (
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ const renderRoot = async () => {
|
||||
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<Router>
|
||||
<Router useTransitions={false}>
|
||||
<AppUpdateRegistration />
|
||||
<App />
|
||||
{Analytics && <Analytics />}
|
||||
|
||||
Reference in New Issue
Block a user