refactor: rebrand default subplebbits to 5chan directories

This commit is contained in:
plebeius
2026-01-28 16:51:27 +08:00
parent 7c8a7b8df8
commit 63ee8aa168
33 changed files with 329 additions and 348 deletions
+7 -7
View File
@@ -1,6 +1,6 @@
import { Link, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useDefaultSubplebbitsState, useDefaultSubplebbits, MultisubSubplebbit } from '../../../hooks/use-default-subplebbits';
import { useDirectoriesState, useDirectories, 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';
@@ -9,7 +9,7 @@ import BoardsFilterModal from './boards-filter-modal';
import styles from '../home.module.css';
// Helper function to find board address by matching title pattern
const findBoardAddress = (multisub: MultisubSubplebbit[], titlePattern: string): string | null => {
const findBoardAddress = (multisub: DirectoryCommunity[], titlePattern: string): string | null => {
const entry = multisub.find((ms) => ms.title === titlePattern);
return entry?.address || null;
};
@@ -27,25 +27,25 @@ const NSFWBadge = () => {
);
};
const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => {
const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
const { t } = useTranslation();
const navigate = useNavigate();
const { error } = useDefaultSubplebbitsState();
const { error } = useDirectoriesState();
const { showDisclaimerModal } = useDisclaimerModalStore();
const { openDirectoryModal } = useDirectoryModalStore();
const { useCatalogLinks, boardFilter } = useBoardsFilterStore();
const defaultSubplebbits = useDefaultSubplebbits();
const directories = useDirectories();
const handleLinkClick = (e: React.MouseEvent<HTMLAnchorElement>, address: string) => {
e.preventDefault();
const boardPath = getBoardPath(address, defaultSubplebbits);
const boardPath = getBoardPath(address, directories);
showDisclaimerModal(address, navigate, boardPath);
};
// Helper to generate link URL with optional catalog suffix
const getBoardLink = (address: string | null): string => {
if (!address) return '#';
const boardPath = getBoardPath(address, defaultSubplebbits);
const boardPath = getBoardPath(address, directories);
return `/${boardPath}${useCatalogLinks ? '/catalog' : ''}`;
};
+14 -14
View File
@@ -3,7 +3,7 @@ import { Link, useNavigate } from 'react-router-dom';
import { Trans, useTranslation } from 'react-i18next';
import { useSubplebbits } from '@plebbit/plebbit-react-hooks';
import styles from './home.module.css';
import { useDefaultSubplebbits, useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import { useDirectories, useDirectoryAddresses } from '../../hooks/use-directories';
import { SubplebbitStatsCollector, useSubplebbitsStatsStore } from '../../hooks/use-subplebbits-stats';
import PopularThreadsBox from './popular-threads-box';
import BoardsList from './boards-list';
@@ -14,19 +14,19 @@ import DirectoryModal from '../../components/directory-modal';
import { getBoardPath } from '../../lib/utils/route-utils';
import _ from 'lodash';
// https://github.com/plebbit/lists/blob/master/5chan-multisub.json
// https://github.com/plebbit/lists/blob/master/5chan-directories.json
const SearchBar = () => {
const searchInputRef = useRef<HTMLInputElement>(null);
const { t } = useTranslation();
const navigate = useNavigate();
const defaultSubplebbits = useDefaultSubplebbits();
const directories = useDirectories();
const handleSearchSubmit = (e: FormEvent) => {
e.preventDefault();
const searchInput = searchInputRef.current?.value;
if (searchInput) {
const boardPath = getBoardPath(searchInput, defaultSubplebbits);
const boardPath = getBoardPath(searchInput, directories);
navigate(`/${boardPath}`);
}
};
@@ -73,7 +73,7 @@ const InfoBox = () => {
);
};
const Stats = ({ subplebbitAddresses }: { subplebbitAddresses: string[] }) => {
const Stats = ({ directoryAddresses }: { directoryAddresses: string[] }) => {
const { t } = useTranslation();
const subplebbitsStats = useSubplebbitsStatsStore((state) => state.subplebbitsStats);
@@ -82,7 +82,7 @@ const Stats = ({ subplebbitAddresses }: { subplebbitAddresses: string[] }) => {
let currentUsers = 0;
let boardsTracked = 0;
subplebbitAddresses.forEach((address) => {
directoryAddresses.forEach((address) => {
const stat = subplebbitsStats[address];
if (stat) {
totalPosts += stat.allPostCount || 0;
@@ -92,12 +92,12 @@ const Stats = ({ subplebbitAddresses }: { subplebbitAddresses: string[] }) => {
});
return { totalPosts, currentUsers, boardsTracked };
}, [subplebbitsStats, subplebbitAddresses]);
}, [subplebbitsStats, directoryAddresses]);
return (
<>
{/* Render collectors to fetch stats for each subplebbit */}
{subplebbitAddresses.map((address) => (
{directoryAddresses.map((address) => (
<SubplebbitStatsCollector key={address} subplebbitAddress={address} />
))}
<div className={styles.box}>
@@ -192,9 +192,9 @@ export const HomeLogo = () => {
};
const Home = () => {
const defaultSubplebbits = useDefaultSubplebbits();
const subplebbitAddresses = useDefaultSubplebbitAddresses();
const { subplebbits } = useSubplebbits({ subplebbitAddresses });
const directories = useDirectories();
const directoryAddresses = useDirectoryAddresses();
const { subplebbits } = useSubplebbits({ subplebbitAddresses: directoryAddresses });
const { closeDirectoryModal } = useDirectoryModalStore();
useEffect(() => {
@@ -216,9 +216,9 @@ const Home = () => {
<HomeLogo />
<SearchBar />
<InfoBox />
<BoardsList multisub={defaultSubplebbits} />
<PopularThreadsBox multisub={defaultSubplebbits} subplebbits={subplebbits} />
<Stats subplebbitAddresses={subplebbitAddresses} />
<BoardsList multisub={directories} />
<PopularThreadsBox directories={directories} subplebbits={subplebbits} />
<Stats directoryAddresses={directoryAddresses} />
<Footer />
</div>
</>
@@ -9,13 +9,13 @@ import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
import { CatalogPostMedia } from '../../../components/catalog-row';
import LoadingEllipsis from '../../../components/loading-ellipsis';
import BoxModal from '../box-modal';
import { MultisubSubplebbit, useDefaultSubplebbits } from '../../../hooks/use-default-subplebbits';
import { DirectoryCommunity } from '../../../hooks/use-directories';
import { getBoardPath } from '../../../lib/utils/route-utils';
import { removeMarkdown } from '../../../lib/utils/post-utils';
interface PopularThreadProps {
post: Comment;
multisub: MultisubSubplebbit[];
directories: DirectoryCommunity[];
}
export const ContentPreview = ({ content, maxLength = 99 }: { content: string; maxLength?: number }) => {
@@ -27,15 +27,14 @@ export const ContentPreview = ({ content, maxLength = 99 }: { content: string; m
// Memoize to prevent rerenders when parent rerenders due to updatingState
const PopularThreadCard = memo(
({ post, multisub }: PopularThreadProps) => {
({ post, directories }: PopularThreadProps) => {
const { cid, content, link, linkHeight, linkWidth, subplebbitAddress, thumbnailUrl, title } = post || {};
const commentMediaInfo = getCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight);
const defaultSubplebbits = useDefaultSubplebbits();
// Find the matching MultisubSubplebbit entry and get its title
const multisubEntry = multisub.find((ms) => ms?.address === subplebbitAddress);
const boardTitle = multisubEntry?.title?.replace(/^\/[^/]+\/\s*-\s*/, '') || '';
const boardPath = subplebbitAddress ? getBoardPath(subplebbitAddress, defaultSubplebbits) : '';
// Find the matching DirectoryCommunity entry and get its title
const directoriesEntry = directories.find((ms) => ms?.address === subplebbitAddress);
const boardTitle = directoriesEntry?.title?.replace(/^\/[^/]+\/\s*-\s*/, '') || '';
const boardPath = subplebbitAddress ? getBoardPath(subplebbitAddress, directories) : '';
return (
<div className={styles.popularThread} key={cid}>
@@ -57,37 +56,37 @@ const PopularThreadCard = memo(
</div>
);
},
// Custom equality: rerender if post.cid or multisub entry title changes
// Custom equality: rerender if post.cid or directories entry title changes
(prevProps, nextProps) => {
if (prevProps.post?.cid !== nextProps.post?.cid) return false;
// Compare the relevant multisub entry for this post's subplebbitAddress
const prevEntry = prevProps.multisub.find((ms) => ms?.address === prevProps.post?.subplebbitAddress);
const nextEntry = nextProps.multisub.find((ms) => ms?.address === nextProps.post?.subplebbitAddress);
// Compare the relevant directories entry for this post's subplebbitAddress
const prevEntry = prevProps.directories.find((ms) => ms?.address === prevProps.post?.subplebbitAddress);
const nextEntry = nextProps.directories.find((ms) => ms?.address === nextProps.post?.subplebbitAddress);
return prevEntry?.title === nextEntry?.title;
},
);
const PopularThreadsBox = ({ multisub, subplebbits }: { multisub: MultisubSubplebbit[]; subplebbits: any }) => {
const PopularThreadsBox = ({ directories, subplebbits }: { directories: DirectoryCommunity[]; subplebbits: any }) => {
const { t } = useTranslation();
const { showWorksafeContentOnly, showNsfwContentOnly } = usePopularThreadsOptionsStore();
const getFilteredSubplebbits = () => {
if (showWorksafeContentOnly) {
return subplebbits.filter((sub: Subplebbit) => {
const multisubEntry = multisub.find((ms) => ms?.address === sub?.address);
return multisubEntry ? !multisubEntry.nsfw : true;
const directoriesEntry = directories.find((ms) => ms?.address === sub?.address);
return directoriesEntry ? !directoriesEntry.nsfw : true;
});
}
if (showNsfwContentOnly) {
return subplebbits.filter((sub: Subplebbit) => {
const multisubEntry = multisub.find((ms) => ms?.address === sub?.address);
return multisubEntry ? multisubEntry.nsfw : false;
const directoriesEntry = directories.find((ms) => ms?.address === sub?.address);
return directoriesEntry ? directoriesEntry.nsfw : false;
});
}
return subplebbits;
};
const filteredSubplebbits = useMemo(getFilteredSubplebbits, [subplebbits, showWorksafeContentOnly, showNsfwContentOnly, multisub]);
const filteredSubplebbits = useMemo(getFilteredSubplebbits, [subplebbits, showWorksafeContentOnly, showNsfwContentOnly, directories]);
const { popularPosts } = usePopularPosts(filteredSubplebbits);
const isLoading = popularPosts.length === 0;
@@ -98,7 +97,11 @@ const PopularThreadsBox = ({ multisub, subplebbits }: { multisub: MultisubSubple
<BoxModal />
</div>
<div className={`${styles.boxContent} ${styles.popularThreads} ${isLoading ? styles.popularThreadsLoading : ''}`}>
{isLoading ? <LoadingEllipsis string={t('loading')} /> : popularPosts.map((post: any) => <PopularThreadCard key={post.cid} post={post} multisub={multisub} />)}
{isLoading ? (
<LoadingEllipsis string={t('loading')} />
) : (
popularPosts.map((post: any) => <PopularThreadCard key={post.cid} post={post} directories={directories} />)
)}
</div>
</div>
);