mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat: implement 5chan-specific default board list
This commit is contained in:
@@ -129,7 +129,7 @@ const Catalog = () => {
|
||||
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const defaultSubplebbits = useDefaultSubplebbits();
|
||||
const { hideAdultBoards, hideGoreBoards } = useInterfaceSettingsStore();
|
||||
const { hideAdultBoards } = useInterfaceSettingsStore();
|
||||
const { showTextOnlyThreads, filterItems, searchText, clearMatchedFilters } = useCatalogFiltersStore();
|
||||
|
||||
const account = useAccount();
|
||||
@@ -139,11 +139,8 @@ const Catalog = () => {
|
||||
const subplebbitAddresses = useMemo(() => {
|
||||
const filteredDefaultSubplebbits = defaultSubplebbits
|
||||
.filter((subplebbit) => {
|
||||
const { tags } = subplebbit;
|
||||
const hasGoreTag = tags?.includes('gore');
|
||||
const hasAdultTag = tags?.includes('adult');
|
||||
|
||||
if ((hasGoreTag && hideGoreBoards) || (hasAdultTag && hideAdultBoards)) {
|
||||
// Hide NSFW boards if hideAdultBoards is enabled (treating NSFW as adult content)
|
||||
if (subplebbit.nsfw && hideAdultBoards) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -159,7 +156,7 @@ const Catalog = () => {
|
||||
}
|
||||
// Only include subplebbitAddress if it's defined
|
||||
return subplebbitAddress ? [subplebbitAddress] : [];
|
||||
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, hideAdultBoards, hideGoreBoards]);
|
||||
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, hideAdultBoards]);
|
||||
|
||||
const { imageSize } = useCatalogStyleStore();
|
||||
const columnWidth = imageSize === 'Large' ? 270 : 180;
|
||||
|
||||
@@ -1,95 +1,38 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { Subplebbit, useSubplebbitStats } from '@plebbit/plebbit-react-hooks';
|
||||
import useSubplebbitsStore from '@plebbit/plebbit-react-hooks/dist/stores/subplebbits';
|
||||
import { useDefaultSubplebbitsState, useDefaultSubplebbitTags } from '../../../hooks/use-default-subplebbits';
|
||||
import { useDefaultSubplebbitsState, MultisubSubplebbit } from '../../../hooks/use-default-subplebbits';
|
||||
import useIsMobile from '../../../hooks/use-is-mobile';
|
||||
import useIsSubplebbitOffline from '../../../hooks/use-is-subplebbit-offline';
|
||||
import LoadingEllipsis from '../../../components/loading-ellipsis';
|
||||
import Tooltip from '../../../components/tooltip';
|
||||
import styles from './boards-list.module.css';
|
||||
import { nsfwTags } from '../../../constants/nsfwTags';
|
||||
|
||||
const Board = ({ subplebbit, isMobile }: { subplebbit: Subplebbit; isMobile: boolean }) => {
|
||||
const Board = ({ subplebbit, isMobile }: { subplebbit: MultisubSubplebbit; isMobile: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, tags } = subplebbit || {};
|
||||
const nsfwTag = tags?.find((tag: string) => nsfwTags.includes(tag));
|
||||
|
||||
let stats = useSubplebbitStats({ subplebbitAddress: address });
|
||||
|
||||
const subplebbitData = useSubplebbitsStore((state) => state.subplebbits[address]);
|
||||
const { isOffline, isOnlineStatusLoading, offlineIconClass, offlineTitle } = useIsSubplebbitOffline(subplebbitData);
|
||||
|
||||
const { address, title, nsfw } = subplebbit || {};
|
||||
const displayAddress = address && Plebbit.getShortAddress(address);
|
||||
const showOfflineIcon = address && (isOffline || isOnlineStatusLoading);
|
||||
|
||||
const title =
|
||||
subplebbitData?.title ||
|
||||
(subplebbitData?.updatedAt ? (
|
||||
displayAddress.endsWith('.eth') || displayAddress.endsWith('.sol') ? (
|
||||
displayAddress.slice(0, -4)
|
||||
) : (
|
||||
displayAddress
|
||||
)
|
||||
) : (
|
||||
<span className={styles.loadingBoardCellValue}>{isOffline ? t('board_not_reachable') : t('loading_board')}</span>
|
||||
));
|
||||
|
||||
return (
|
||||
<tr key={address}>
|
||||
<td>
|
||||
<p className={styles.boardCell}>
|
||||
<Link to={`/p/${address}`}>{displayAddress}</Link>
|
||||
{nsfwTag && <span className={styles.nsfw}> ({t(nsfwTag)})</span>}
|
||||
{showOfflineIcon && (
|
||||
<span className={styles.offlineIconContainer}>
|
||||
<Tooltip content={offlineTitle}>
|
||||
<span className={`${styles.offlineIcon} ${offlineIconClass}`} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
{nsfw && <span className={styles.nsfw}> ({t('nsfw')})</span>}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p className={styles.boardCell}>{title}</p>
|
||||
<p className={styles.boardCell}>{title || displayAddress}</p>
|
||||
</td>
|
||||
{!isMobile && (
|
||||
<>
|
||||
<td className={styles.boardPPH}>
|
||||
<p className={styles.boardCell}>{stats.hourPostCount ?? <span className={styles.loadingBoardCellValue}>?</span>}</p>
|
||||
</td>
|
||||
<td className={styles.boardTags}>
|
||||
<p className={styles.boardCell}>
|
||||
{tags.map((tag: string, index: number) => (
|
||||
<span key={tag}>
|
||||
<Link to={`/${tag}`}>{tag}</Link>
|
||||
{index < tags.length - 1 && ', '}
|
||||
</span>
|
||||
))}
|
||||
</p>
|
||||
</td>
|
||||
</>
|
||||
)}
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
|
||||
const BoardsList = ({ multisub }: { multisub: Subplebbit[] }) => {
|
||||
const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const [displayCount, setDisplayCount] = useState(15);
|
||||
const isMobile = useIsMobile();
|
||||
const { loading, error } = useDefaultSubplebbitsState();
|
||||
|
||||
const currentTag = location.pathname.split('/').filter(Boolean)[0];
|
||||
const tags = useDefaultSubplebbitTags(multisub);
|
||||
|
||||
useEffect(() => {
|
||||
setDisplayCount(15);
|
||||
}, [currentTag]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className={styles.boardsBox}>
|
||||
@@ -108,12 +51,9 @@ const BoardsList = ({ multisub }: { multisub: Subplebbit[] }) => {
|
||||
);
|
||||
}
|
||||
|
||||
const filteredBoards = (currentTag && tags.includes(currentTag) ? multisub.filter((sub) => sub?.tags?.includes(currentTag)) : multisub).slice(0, displayCount);
|
||||
|
||||
const totalBoardCount = currentTag && tags.includes(currentTag) ? multisub.filter((sub) => sub?.tags?.includes(currentTag)).length : multisub.length;
|
||||
|
||||
const hasMoreBoards =
|
||||
currentTag && tags.includes(currentTag) ? displayCount < multisub.filter((sub) => sub?.tags?.includes(currentTag)).length : displayCount < multisub.length;
|
||||
const filteredBoards = multisub.slice(0, displayCount);
|
||||
const totalBoardCount = multisub.length;
|
||||
const hasMoreBoards = displayCount < multisub.length;
|
||||
|
||||
return (
|
||||
<div className={styles.boardsBox}>
|
||||
@@ -126,12 +66,6 @@ const BoardsList = ({ multisub }: { multisub: Subplebbit[] }) => {
|
||||
<tr>
|
||||
<th>{t('board')}</th>
|
||||
<th>{t('title')}</th>
|
||||
{!isMobile && (
|
||||
<th className={styles.boardPPH} title={t('pph')}>
|
||||
PPH
|
||||
</th>
|
||||
)}
|
||||
{!isMobile && <th>{t('tags')}</th>}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -141,14 +75,7 @@ const BoardsList = ({ multisub }: { multisub: Subplebbit[] }) => {
|
||||
</tbody>
|
||||
</table>
|
||||
<div className={styles.displayCount}>
|
||||
{currentTag && tags.includes(currentTag)
|
||||
? t('displaying_boards_with_tag', {
|
||||
filteredBoardsCount: filteredBoards.length,
|
||||
totalBoardCount: totalBoardCount,
|
||||
currentTag: `"${currentTag}"`,
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
: t('displaying_boards', { filteredBoardsCount: filteredBoards.length, totalBoardCount: totalBoardCount, interpolation: { escapeValue: false } })}
|
||||
{t('displaying_boards', { filteredBoardsCount: filteredBoards.length, totalBoardCount: totalBoardCount, interpolation: { escapeValue: false } })}
|
||||
</div>
|
||||
{hasMoreBoards && (
|
||||
<div className={styles.loadMoreButton}>
|
||||
|
||||
@@ -10,7 +10,7 @@ import BoardsList from './boards-list';
|
||||
import Version from '../../components/version';
|
||||
import _ from 'lodash';
|
||||
|
||||
// https://github.com/plebbit/temporary-default-subplebbits/blob/master/README.md
|
||||
// https://github.com/plebbit/lists/blob/master/5chan-multisub.json
|
||||
|
||||
const SearchBar = () => {
|
||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -9,7 +9,7 @@ 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 { nsfwTags } from '../../../constants/nsfwTags';
|
||||
import { MultisubSubplebbit } from '../../../hooks/use-default-subplebbits';
|
||||
import { removeMarkdown } from '../../../lib/utils/post-utils';
|
||||
|
||||
interface PopularThreadProps {
|
||||
@@ -50,7 +50,7 @@ const PopularThreadCard = ({ post, boardTitle, boardShortAddress }: PopularThrea
|
||||
);
|
||||
};
|
||||
|
||||
const PopularThreadsBox = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subplebbits: any }) => {
|
||||
const PopularThreadsBox = ({ multisub, subplebbits }: { multisub: MultisubSubplebbit[]; subplebbits: any }) => {
|
||||
const { t } = useTranslation();
|
||||
const { showWorksafeContentOnly, showNsfwContentOnly } = usePopularThreadsOptionsStore();
|
||||
|
||||
@@ -58,13 +58,13 @@ const PopularThreadsBox = ({ multisub, subplebbits }: { multisub: Subplebbit[];
|
||||
if (showWorksafeContentOnly) {
|
||||
return subplebbits.filter((sub: Subplebbit) => {
|
||||
const multisubEntry = multisub.find((ms) => ms?.address === sub?.address);
|
||||
return multisubEntry ? !multisubEntry.tags.some((tag: string) => nsfwTags.includes(tag)) : true;
|
||||
return multisubEntry ? !multisubEntry.nsfw : true;
|
||||
});
|
||||
}
|
||||
if (showNsfwContentOnly) {
|
||||
return subplebbits.filter((sub: Subplebbit) => {
|
||||
const multisubEntry = multisub.find((ms) => ms?.address === sub?.address);
|
||||
return multisubEntry ? multisubEntry.tags.some((tag: string) => nsfwTags.includes(tag)) : false;
|
||||
return multisubEntry ? multisubEntry.nsfw : false;
|
||||
});
|
||||
}
|
||||
return subplebbits;
|
||||
|
||||
Reference in New Issue
Block a user