mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf(homepage): isolate boards list from live hook churn
This commit is contained in:
@@ -60,8 +60,8 @@ vi.mock('../boards-list', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../popular-threads-box', () => ({
|
||||
default: ({ directories, communities }: { directories: unknown[]; communities: Record<string, unknown> }) =>
|
||||
createElement('div', { 'data-testid': 'popular-threads-box' }, `popular:${directories.length}:${Object.keys(communities).length}`),
|
||||
default: ({ directories, directoryAddresses }: { directories: unknown[]; directoryAddresses: string[] }) =>
|
||||
createElement('div', { 'data-testid': 'popular-threads-box' }, `popular:${directories.length}:${directoryAddresses.length}`),
|
||||
}));
|
||||
|
||||
vi.mock('../../../components/site-legal-meta', () => ({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAccountCommunityAddresses } from '../../../hooks/use-account-community-addresses';
|
||||
import { useDirectoriesState, useDirectories, DirectoryCommunity } from '../../../hooks/use-directories';
|
||||
import { useDirectoriesState, DirectoryCommunity } from '../../../hooks/use-directories';
|
||||
import { getBoardPath } from '../../../lib/utils/route-utils';
|
||||
import useDisclaimerModalStore from '../../../stores/use-disclaimer-modal-store';
|
||||
import useDirectoryModalStore from '../../../stores/use-directory-modal-store';
|
||||
@@ -55,20 +55,37 @@ const BoardLink = ({ boardName, address, getBoardLink, onLinkClick, onPlaceholde
|
||||
);
|
||||
};
|
||||
|
||||
const DirectoriesErrorMessage = () => {
|
||||
const error = useDirectoriesState().error;
|
||||
return error?.message ? <div className='red'>{error.message}</div> : null;
|
||||
};
|
||||
|
||||
const ModeratedBoardsLink = () => {
|
||||
const { t } = useTranslation();
|
||||
const accountCommunityAddresses = useAccountCommunityAddresses();
|
||||
|
||||
if (accountCommunityAddresses.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<li>
|
||||
<Link to='/mod'>{t('boards_you_moderate_nav')}</Link>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { error } = useDirectoriesState();
|
||||
const { showDisclaimerModal } = useDisclaimerModalStore();
|
||||
const { openDirectoryModal } = useDirectoryModalStore();
|
||||
const { useCatalogLinks, boardFilter } = useBoardsFilterStore();
|
||||
const directories = useDirectories();
|
||||
|
||||
const accountCommunityAddresses = useAccountCommunityAddresses();
|
||||
const showDisclaimerModal = useDisclaimerModalStore((state) => state.showDisclaimerModal);
|
||||
const openDirectoryModal = useDirectoryModalStore((state) => state.openDirectoryModal);
|
||||
const useCatalogLinks = useBoardsFilterStore((state) => state.useCatalogLinks);
|
||||
const boardFilter = useBoardsFilterStore((state) => state.boardFilter);
|
||||
|
||||
const handleLinkClick = (e: React.MouseEvent<HTMLAnchorElement>, address: string) => {
|
||||
e.preventDefault();
|
||||
const boardPath = getBoardPath(address, directories);
|
||||
const boardPath = getBoardPath(address, multisub);
|
||||
const targetPath = boardPath + (useCatalogLinks ? '/catalog' : '');
|
||||
showDisclaimerModal(address, navigate, targetPath);
|
||||
};
|
||||
@@ -76,7 +93,7 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
|
||||
// Helper to generate link URL with optional catalog suffix
|
||||
const getBoardLink = (address: string | null): string => {
|
||||
if (!address) return '#';
|
||||
const boardPath = getBoardPath(address, directories);
|
||||
const boardPath = getBoardPath(address, multisub);
|
||||
return `/${boardPath}${useCatalogLinks ? '/catalog' : ''}`;
|
||||
};
|
||||
|
||||
@@ -101,8 +118,6 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
|
||||
onPlaceholderClick: handlePlaceholderClick,
|
||||
};
|
||||
|
||||
const errorMessage = error?.message;
|
||||
|
||||
// Filtering logic: determine which categories to show
|
||||
const showAll = boardFilter === 'all';
|
||||
const showNsfwOnly = boardFilter === 'nsfw';
|
||||
@@ -125,7 +140,7 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
|
||||
<BoardsFilterModal />
|
||||
</div>
|
||||
<div className={`${styles.boxContent} ${styles.boardsContent}`}>
|
||||
{errorMessage && <div className='red'>{errorMessage}</div>}
|
||||
<DirectoriesErrorMessage />
|
||||
{/* Column 1: Japanese Culture + Video Games */}
|
||||
{(showJapaneseCulture || showVideoGames) && (
|
||||
<div className={styles.boardsColumn}>
|
||||
@@ -598,11 +613,7 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
|
||||
<li>
|
||||
<Link to='/subs'>Subscriptions</Link>
|
||||
</li>
|
||||
{accountCommunityAddresses.length > 0 && (
|
||||
<li>
|
||||
<Link to='/mod'>{t('boards_you_moderate_nav')}</Link>
|
||||
</li>
|
||||
)}
|
||||
<ModeratedBoardsLink />
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { useEffect, useMemo, useRef, FormEvent } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { useCommunities } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import styles from './home.module.css';
|
||||
import { useDirectories, useDirectoryAddresses } from '../../hooks/use-directories';
|
||||
import { useCommunityIdentifiers } from '../../hooks/use-community-identifiers';
|
||||
import { CommunityStatsCollector, useCommunitiesStatsStore } from '../../hooks/use-communities-stats';
|
||||
import PopularThreadsBox from './popular-threads-box';
|
||||
import BoardsList from './boards-list';
|
||||
@@ -190,8 +188,6 @@ export const HomeLogo = () => {
|
||||
const Home = () => {
|
||||
const directories = useDirectories();
|
||||
const directoryAddresses = useDirectoryAddresses();
|
||||
const directoryCommunities = useCommunityIdentifiers(directoryAddresses);
|
||||
const { communities } = useCommunities({ communities: directoryCommunities });
|
||||
const { closeDirectoryModal } = useDirectoryModalStore();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -214,7 +210,7 @@ const Home = () => {
|
||||
<SearchBar />
|
||||
<InfoBox />
|
||||
<BoardsList multisub={directories} />
|
||||
<PopularThreadsBox directories={directories} directoryAddresses={directoryAddresses} communities={communities} />
|
||||
<PopularThreadsBox directories={directories} directoryAddresses={directoryAddresses} />
|
||||
<Stats directoryAddresses={directoryAddresses} />
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { memo, useMemo } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Comment, Community } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import { Comment, useCommunities } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import styles from '../home.module.css';
|
||||
import usePopularPosts from '../../../hooks/use-popular-posts';
|
||||
import { useFeedStateString } from '../../../hooks/use-state-string';
|
||||
@@ -11,6 +11,7 @@ import { CatalogPostMedia } from '../../../components/catalog-row';
|
||||
import LoadingEllipsis from '../../../components/loading-ellipsis';
|
||||
import BoxModal from '../box-modal';
|
||||
import { DirectoryCommunity, findDirectoryByAddress } from '../../../hooks/use-directories';
|
||||
import { useCommunityIdentifiers } from '../../../hooks/use-community-identifiers';
|
||||
import { getBoardPath } from '../../../lib/utils/route-utils';
|
||||
import { removeMarkdown } from '../../../lib/utils/post-utils';
|
||||
|
||||
@@ -55,18 +56,12 @@ const PopularThreadCard = memo(
|
||||
(prevProps, nextProps) => prevProps.post?.cid === nextProps.post?.cid && prevProps.boardTitle === nextProps.boardTitle && prevProps.boardPath === nextProps.boardPath,
|
||||
);
|
||||
|
||||
const PopularThreadsBox = ({
|
||||
directories,
|
||||
directoryAddresses,
|
||||
communities,
|
||||
}: {
|
||||
directories: DirectoryCommunity[];
|
||||
directoryAddresses: string[];
|
||||
communities: Array<Community | undefined>;
|
||||
}) => {
|
||||
const PopularThreadsBox = ({ directories, directoryAddresses }: { directories: DirectoryCommunity[]; directoryAddresses: string[] }) => {
|
||||
const { t } = useTranslation();
|
||||
const { showWorksafeContentOnly, showNsfwContentOnly } = usePopularThreadsOptionsStore();
|
||||
const getCommentCommunityAddress = (post: Comment) => post.communityAddress || post.subplebbitAddress;
|
||||
const directoryCommunities = useCommunityIdentifiers(directoryAddresses);
|
||||
const { communities } = useCommunities({ communities: directoryCommunities });
|
||||
|
||||
const { filteredBoardAddresses, filteredCommunities } = useMemo(() => {
|
||||
const filteredEntries = directoryAddresses.flatMap((address, index) => {
|
||||
|
||||
Reference in New Issue
Block a user