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