refactor(react-doctor): raise score from 79 to 90

This commit is contained in:
plebeius
2026-02-24 15:15:44 +08:00
parent 5bd1dc0e71
commit e51f5b968c
36 changed files with 2372 additions and 1030 deletions
@@ -41,7 +41,18 @@ const BoardsFilterModal = () => {
return (
<>
<span ref={buttonRef} onClick={() => !showFilterModal && setShowFilterModal(true)}>
<span
ref={buttonRef}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
if (!showFilterModal) setShowFilterModal(true);
}
}}
onClick={() => !showFilterModal && setShowFilterModal(true)}
>
{t('filter')}
</span>
{showFilterModal && (
@@ -49,6 +60,15 @@ const BoardsFilterModal = () => {
{/* Always shown: Use Catalog */}
<div
className={`${styles.option} ${useCatalogLinks && styles.selected}`}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
setUseCatalogLinks(!useCatalogLinks);
setShowFilterModal(false);
}
}}
onClick={() => {
setUseCatalogLinks(!useCatalogLinks);
setShowFilterModal(false);
@@ -63,6 +83,15 @@ const BoardsFilterModal = () => {
<div className={styles.separator} />
<div
className={`${styles.option} ${boardFilter === 'all' && styles.selected}`}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
setBoardFilter('all');
setShowFilterModal(false);
}
}}
onClick={() => {
setBoardFilter('all');
setShowFilterModal(false);
@@ -72,6 +101,15 @@ const BoardsFilterModal = () => {
</div>
<div
className={`${styles.option} ${boardFilter === 'nsfw' && styles.selected}`}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
setBoardFilter('nsfw');
setShowFilterModal(false);
}
}}
onClick={() => {
setBoardFilter('nsfw');
setShowFilterModal(false);
@@ -81,6 +119,15 @@ const BoardsFilterModal = () => {
</div>
<div
className={`${styles.option} ${boardFilter === 'worksafe' && styles.selected}`}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
setBoardFilter('worksafe');
setShowFilterModal(false);
}
}}
onClick={() => {
setBoardFilter('worksafe');
setShowFilterModal(false);
+401 -97
View File
@@ -26,6 +26,34 @@ const NSFWBadge = () => {
);
};
interface BoardLinkProps {
boardName: string;
address: string | null;
getBoardLink: (address: string) => string;
onLinkClick: (e: React.MouseEvent<HTMLAnchorElement>, address: string) => void;
onPlaceholderClick: (e: React.MouseEvent<HTMLAnchorElement>) => void;
}
const BoardLink = ({ boardName, address, getBoardLink, onLinkClick, onPlaceholderClick }: BoardLinkProps) => {
if (address) {
return (
<li>
<Link to={getBoardLink(address)} onClick={(e) => onLinkClick(e, address)}>
{boardName}
</Link>
</li>
);
}
return (
<li>
<Link to='#' onClick={onPlaceholderClick} className={styles.placeholder}>
{boardName}
</Link>
</li>
);
};
const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
const { t } = useTranslation();
const navigate = useNavigate();
@@ -64,27 +92,10 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
return acc;
}, {});
const renderBoardLink = (boardName: string) => {
const address = boardAddressesByName[boardName];
const key = address ?? boardName;
if (address) {
return (
<li key={key}>
<Link to={getBoardLink(address)} onClick={(e) => handleLinkClick(e, address)}>
{boardName}
</Link>
</li>
);
}
return (
<li key={key}>
<Link to='#' onClick={handlePlaceholderClick} className={styles.placeholder}>
{boardName}
</Link>
</li>
);
const boardLinkProps = {
getBoardLink,
onLinkClick: handleLinkClick,
onPlaceholderClick: handlePlaceholderClick,
};
const errorMessage = error?.message;
@@ -122,20 +133,62 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
<ul>
{(showAll || showWorksafeOnly) && (
<>
{renderBoardLink('Anime & Manga')}
{renderBoardLink('Anime/Cute')}
{renderBoardLink('Anime/Wallpapers')}
{renderBoardLink('Mecha')}
{renderBoardLink('Cosplay & EGL')}
{renderBoardLink('Cute/Male')}
<BoardLink
key={boardAddressesByName['Anime & Manga'] ?? 'Anime & Manga'}
boardName='Anime & Manga'
address={boardAddressesByName['Anime & Manga'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Anime/Cute'] ?? 'Anime/Cute'}
boardName='Anime/Cute'
address={boardAddressesByName['Anime/Cute'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Anime/Wallpapers'] ?? 'Anime/Wallpapers'}
boardName='Anime/Wallpapers'
address={boardAddressesByName['Anime/Wallpapers'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Mecha'] ?? 'Mecha'} boardName='Mecha' address={boardAddressesByName['Mecha'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Cosplay & EGL'] ?? 'Cosplay & EGL'}
boardName='Cosplay & EGL'
address={boardAddressesByName['Cosplay & EGL'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Cute/Male'] ?? 'Cute/Male'}
boardName='Cute/Male'
address={boardAddressesByName['Cute/Male'] ?? null}
{...boardLinkProps}
/>
</>
)}
{(showAll || showNsfwOnly) && renderBoardLink('Flash')}
{(showAll || showNsfwOnly) && (
<BoardLink key={boardAddressesByName['Flash'] ?? 'Flash'} boardName='Flash' address={boardAddressesByName['Flash'] ?? null} {...boardLinkProps} />
)}
{(showAll || showWorksafeOnly) && (
<>
{renderBoardLink('Transportation')}
{renderBoardLink('Otaku Culture')}
{renderBoardLink('Virtual YouTubers')}
<BoardLink
key={boardAddressesByName['Transportation'] ?? 'Transportation'}
boardName='Transportation'
address={boardAddressesByName['Transportation'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Otaku Culture'] ?? 'Otaku Culture'}
boardName='Otaku Culture'
address={boardAddressesByName['Otaku Culture'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Virtual YouTubers'] ?? 'Virtual YouTubers'}
boardName='Virtual YouTubers'
address={boardAddressesByName['Virtual YouTubers'] ?? null}
{...boardLinkProps}
/>
</>
)}
</ul>
@@ -147,14 +200,54 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
<>
<h3>Video Games</h3>
<ul>
{renderBoardLink('Video Games')}
{renderBoardLink('Video Game Generals')}
{renderBoardLink('Video Games/Multiplayer')}
{renderBoardLink('Video Games/Mobile')}
{renderBoardLink('Pokémon')}
{renderBoardLink('Retro Games')}
{renderBoardLink('Video Games/RPG')}
{renderBoardLink('Video Games/Strategy')}
<BoardLink
key={boardAddressesByName['Video Games'] ?? 'Video Games'}
boardName='Video Games'
address={boardAddressesByName['Video Games'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Video Game Generals'] ?? 'Video Game Generals'}
boardName='Video Game Generals'
address={boardAddressesByName['Video Game Generals'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Video Games/Multiplayer'] ?? 'Video Games/Multiplayer'}
boardName='Video Games/Multiplayer'
address={boardAddressesByName['Video Games/Multiplayer'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Video Games/Mobile'] ?? 'Video Games/Mobile'}
boardName='Video Games/Mobile'
address={boardAddressesByName['Video Games/Mobile'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Pokémon'] ?? 'Pokémon'}
boardName='Pokémon'
address={boardAddressesByName['Pokémon'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Retro Games'] ?? 'Retro Games'}
boardName='Retro Games'
address={boardAddressesByName['Retro Games'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Video Games/RPG'] ?? 'Video Games/RPG'}
boardName='Video Games/RPG'
address={boardAddressesByName['Video Games/RPG'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Video Games/Strategy'] ?? 'Video Games/Strategy'}
boardName='Video Games/Strategy'
address={boardAddressesByName['Video Games/Strategy'] ?? null}
{...boardLinkProps}
/>
</ul>
</>
)}
@@ -166,21 +259,76 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
<div className={styles.boardsColumn}>
<h3>Interests</h3>
<ul>
{renderBoardLink('Comics & Cartoons')}
{renderBoardLink('Technology')}
{renderBoardLink('Television & Film')}
{renderBoardLink('Weapons')}
{renderBoardLink('Auto')}
{renderBoardLink('Animals & Nature')}
{renderBoardLink('Traditional Games')}
{renderBoardLink('Sports')}
{renderBoardLink('Extreme Sports')}
{renderBoardLink('Professional Wrestling')}
{renderBoardLink('Science & Math')}
{renderBoardLink('History & Humanities')}
{renderBoardLink('International')}
{renderBoardLink('Outdoors')}
{renderBoardLink('Toys')}
<BoardLink
key={boardAddressesByName['Comics & Cartoons'] ?? 'Comics & Cartoons'}
boardName='Comics & Cartoons'
address={boardAddressesByName['Comics & Cartoons'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Technology'] ?? 'Technology'}
boardName='Technology'
address={boardAddressesByName['Technology'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Television & Film'] ?? 'Television & Film'}
boardName='Television & Film'
address={boardAddressesByName['Television & Film'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Weapons'] ?? 'Weapons'} boardName='Weapons' address={boardAddressesByName['Weapons'] ?? null} {...boardLinkProps} />
<BoardLink key={boardAddressesByName['Auto'] ?? 'Auto'} boardName='Auto' address={boardAddressesByName['Auto'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Animals & Nature'] ?? 'Animals & Nature'}
boardName='Animals & Nature'
address={boardAddressesByName['Animals & Nature'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Traditional Games'] ?? 'Traditional Games'}
boardName='Traditional Games'
address={boardAddressesByName['Traditional Games'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Sports'] ?? 'Sports'} boardName='Sports' address={boardAddressesByName['Sports'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Extreme Sports'] ?? 'Extreme Sports'}
boardName='Extreme Sports'
address={boardAddressesByName['Extreme Sports'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Professional Wrestling'] ?? 'Professional Wrestling'}
boardName='Professional Wrestling'
address={boardAddressesByName['Professional Wrestling'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Science & Math'] ?? 'Science & Math'}
boardName='Science & Math'
address={boardAddressesByName['Science & Math'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['History & Humanities'] ?? 'History & Humanities'}
boardName='History & Humanities'
address={boardAddressesByName['History & Humanities'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['International'] ?? 'International'}
boardName='International'
address={boardAddressesByName['International'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Outdoors'] ?? 'Outdoors'}
boardName='Outdoors'
address={boardAddressesByName['Outdoors'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Toys'] ?? 'Toys'} boardName='Toys' address={boardAddressesByName['Toys'] ?? null} {...boardLinkProps} />
</ul>
</div>
)}
@@ -190,26 +338,82 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
<div className={styles.boardsColumn}>
<h3>Creative</h3>
<ul>
{(showAll || showNsfwOnly) && renderBoardLink('Oekaki')}
{(showAll || showNsfwOnly) && (
<BoardLink key={boardAddressesByName['Oekaki'] ?? 'Oekaki'} boardName='Oekaki' address={boardAddressesByName['Oekaki'] ?? null} {...boardLinkProps} />
)}
{(showAll || showWorksafeOnly) && (
<>
{renderBoardLink('Papercraft & Origami')}
{renderBoardLink('Photography')}
{renderBoardLink('Food & Cooking')}
<BoardLink
key={boardAddressesByName['Papercraft & Origami'] ?? 'Papercraft & Origami'}
boardName='Papercraft & Origami'
address={boardAddressesByName['Papercraft & Origami'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Photography'] ?? 'Photography'}
boardName='Photography'
address={boardAddressesByName['Photography'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Food & Cooking'] ?? 'Food & Cooking'}
boardName='Food & Cooking'
address={boardAddressesByName['Food & Cooking'] ?? null}
{...boardLinkProps}
/>
</>
)}
{(showAll || showNsfwOnly) && renderBoardLink('Artwork/Critique')}
{(showAll || showNsfwOnly) && renderBoardLink('Wallpapers/General')}
{(showAll || showNsfwOnly) && (
<BoardLink
key={boardAddressesByName['Artwork/Critique'] ?? 'Artwork/Critique'}
boardName='Artwork/Critique'
address={boardAddressesByName['Artwork/Critique'] ?? null}
{...boardLinkProps}
/>
)}
{(showAll || showNsfwOnly) && (
<BoardLink
key={boardAddressesByName['Wallpapers/General'] ?? 'Wallpapers/General'}
boardName='Wallpapers/General'
address={boardAddressesByName['Wallpapers/General'] ?? null}
{...boardLinkProps}
/>
)}
{(showAll || showWorksafeOnly) && (
<>
{renderBoardLink('Literature')}
{renderBoardLink('Music')}
{renderBoardLink('Fashion')}
{renderBoardLink('3DCG')}
{renderBoardLink('Graphic Design')}
{renderBoardLink('Do It Yourself')}
{renderBoardLink('Worksafe GIF')}
{renderBoardLink('Quests')}
<BoardLink
key={boardAddressesByName['Literature'] ?? 'Literature'}
boardName='Literature'
address={boardAddressesByName['Literature'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Music'] ?? 'Music'} boardName='Music' address={boardAddressesByName['Music'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Fashion'] ?? 'Fashion'}
boardName='Fashion'
address={boardAddressesByName['Fashion'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['3DCG'] ?? '3DCG'} boardName='3DCG' address={boardAddressesByName['3DCG'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Graphic Design'] ?? 'Graphic Design'}
boardName='Graphic Design'
address={boardAddressesByName['Graphic Design'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Do It Yourself'] ?? 'Do It Yourself'}
boardName='Do It Yourself'
address={boardAddressesByName['Do It Yourself'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Worksafe GIF'] ?? 'Worksafe GIF'}
boardName='Worksafe GIF'
address={boardAddressesByName['Worksafe GIF'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Quests'] ?? 'Quests'} boardName='Quests' address={boardAddressesByName['Quests'] ?? null} {...boardLinkProps} />
</>
)}
</ul>
@@ -224,16 +428,46 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
<>
<h3>Other</h3>
<ul>
{renderBoardLink('Business & Finance')}
{renderBoardLink('Travel')}
{renderBoardLink('Fitness')}
{renderBoardLink('Paranormal')}
{renderBoardLink('Advice')}
{renderBoardLink('LGBT')}
{renderBoardLink('Pony')}
{renderBoardLink('Current News')}
{renderBoardLink('Worksafe Requests')}
{renderBoardLink('Very Important Posts')}
<BoardLink
key={boardAddressesByName['Business & Finance'] ?? 'Business & Finance'}
boardName='Business & Finance'
address={boardAddressesByName['Business & Finance'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Travel'] ?? 'Travel'} boardName='Travel' address={boardAddressesByName['Travel'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Fitness'] ?? 'Fitness'}
boardName='Fitness'
address={boardAddressesByName['Fitness'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Paranormal'] ?? 'Paranormal'}
boardName='Paranormal'
address={boardAddressesByName['Paranormal'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Advice'] ?? 'Advice'} boardName='Advice' address={boardAddressesByName['Advice'] ?? null} {...boardLinkProps} />
<BoardLink key={boardAddressesByName['LGBT'] ?? 'LGBT'} boardName='LGBT' address={boardAddressesByName['LGBT'] ?? null} {...boardLinkProps} />
<BoardLink key={boardAddressesByName['Pony'] ?? 'Pony'} boardName='Pony' address={boardAddressesByName['Pony'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Current News'] ?? 'Current News'}
boardName='Current News'
address={boardAddressesByName['Current News'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Worksafe Requests'] ?? 'Worksafe Requests'}
boardName='Worksafe Requests'
address={boardAddressesByName['Worksafe Requests'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Very Important Posts'] ?? 'Very Important Posts'}
boardName='Very Important Posts'
address={boardAddressesByName['Very Important Posts'] ?? null}
{...boardLinkProps}
/>
</ul>
</>
)}
@@ -244,12 +478,37 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
<h3>Misc.</h3>
<NSFWBadge />
<ul>
{renderBoardLink('Random')}
{renderBoardLink('ROBOT9001')}
{renderBoardLink('Politically Incorrect')}
{renderBoardLink('International/Random')}
{renderBoardLink('Cams & Meetups')}
{renderBoardLink('Shit 5chan Says')}
<BoardLink key={boardAddressesByName['Random'] ?? 'Random'} boardName='Random' address={boardAddressesByName['Random'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['ROBOT9001'] ?? 'ROBOT9001'}
boardName='ROBOT9001'
address={boardAddressesByName['ROBOT9001'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Politically Incorrect'] ?? 'Politically Incorrect'}
boardName='Politically Incorrect'
address={boardAddressesByName['Politically Incorrect'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['International/Random'] ?? 'International/Random'}
boardName='International/Random'
address={boardAddressesByName['International/Random'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Cams & Meetups'] ?? 'Cams & Meetups'}
boardName='Cams & Meetups'
address={boardAddressesByName['Cams & Meetups'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Shit 5chan Says'] ?? 'Shit 5chan Says'}
boardName='Shit 5chan Says'
address={boardAddressesByName['Shit 5chan Says'] ?? null}
{...boardLinkProps}
/>
</ul>
</>
)}
@@ -262,19 +521,64 @@ const BoardsList = ({ multisub }: { multisub: DirectoryCommunity[] }) => {
<h3>Adult</h3>
<NSFWBadge />
<ul>
{renderBoardLink('Sexy Beautiful Women')}
{renderBoardLink('Hardcore')}
{renderBoardLink('Handsome Men')}
{renderBoardLink('Hentai')}
{renderBoardLink('Ecchi')}
{renderBoardLink('Yuri')}
{renderBoardLink('Hentai/Alternative')}
{renderBoardLink('Yaoi')}
{renderBoardLink('Torrents')}
{renderBoardLink('High Resolution')}
{renderBoardLink('Adult GIF')}
{renderBoardLink('Adult Cartoons')}
{renderBoardLink('Adult Requests')}
<BoardLink
key={boardAddressesByName['Sexy Beautiful Women'] ?? 'Sexy Beautiful Women'}
boardName='Sexy Beautiful Women'
address={boardAddressesByName['Sexy Beautiful Women'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Hardcore'] ?? 'Hardcore'}
boardName='Hardcore'
address={boardAddressesByName['Hardcore'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Handsome Men'] ?? 'Handsome Men'}
boardName='Handsome Men'
address={boardAddressesByName['Handsome Men'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Hentai'] ?? 'Hentai'} boardName='Hentai' address={boardAddressesByName['Hentai'] ?? null} {...boardLinkProps} />
<BoardLink key={boardAddressesByName['Ecchi'] ?? 'Ecchi'} boardName='Ecchi' address={boardAddressesByName['Ecchi'] ?? null} {...boardLinkProps} />
<BoardLink key={boardAddressesByName['Yuri'] ?? 'Yuri'} boardName='Yuri' address={boardAddressesByName['Yuri'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Hentai/Alternative'] ?? 'Hentai/Alternative'}
boardName='Hentai/Alternative'
address={boardAddressesByName['Hentai/Alternative'] ?? null}
{...boardLinkProps}
/>
<BoardLink key={boardAddressesByName['Yaoi'] ?? 'Yaoi'} boardName='Yaoi' address={boardAddressesByName['Yaoi'] ?? null} {...boardLinkProps} />
<BoardLink
key={boardAddressesByName['Torrents'] ?? 'Torrents'}
boardName='Torrents'
address={boardAddressesByName['Torrents'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['High Resolution'] ?? 'High Resolution'}
boardName='High Resolution'
address={boardAddressesByName['High Resolution'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Adult GIF'] ?? 'Adult GIF'}
boardName='Adult GIF'
address={boardAddressesByName['Adult GIF'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Adult Cartoons'] ?? 'Adult Cartoons'}
boardName='Adult Cartoons'
address={boardAddressesByName['Adult Cartoons'] ?? null}
{...boardLinkProps}
/>
<BoardLink
key={boardAddressesByName['Adult Requests'] ?? 'Adult Requests'}
boardName='Adult Requests'
address={boardAddressesByName['Adult Requests'] ?? null}
{...boardLinkProps}
/>
</ul>
</div>
)}
+46 -1
View File
@@ -29,13 +29,36 @@ const BoxModal = () => {
return (
<>
<span ref={buttonRef} onClick={() => !showFilterModal && setShowFilterModal(true)}>
<span
ref={buttonRef}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
if (!showFilterModal) setShowFilterModal(true);
}
}}
onClick={() => !showFilterModal && setShowFilterModal(true)}
>
{t('options')}
</span>
{showFilterModal && (
<div ref={modalRef} className={styles.filterModal}>
<div
className={`${styles.option} ${showWorksafeContentOnly && styles.selected}`}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
if (showNsfwContentOnly) {
setShowNsfwContentOnly(false);
}
setShowWorksafeContentOnly(!showWorksafeContentOnly);
setShowFilterModal(false);
}
}}
onClick={() => {
if (showNsfwContentOnly) {
setShowNsfwContentOnly(false);
@@ -48,6 +71,18 @@ const BoxModal = () => {
</div>
<div
className={`${styles.option} ${showNsfwContentOnly && styles.selected}`}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
if (showWorksafeContentOnly) {
setShowWorksafeContentOnly(false);
}
setShowNsfwContentOnly(!showNsfwContentOnly);
setShowFilterModal(false);
}
}}
onClick={() => {
if (showWorksafeContentOnly) {
setShowWorksafeContentOnly(false);
@@ -60,6 +95,16 @@ const BoxModal = () => {
</div>
<div
className={`${styles.option} ${!showWorksafeContentOnly && !showNsfwContentOnly && styles.selected}`}
role='button'
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
setShowWorksafeContentOnly(false);
setShowNsfwContentOnly(false);
setShowFilterModal(false);
}
}}
onClick={() => {
setShowWorksafeContentOnly(false);
setShowNsfwContentOnly(false);
+84 -92
View File
@@ -66,6 +66,72 @@ interface ModQueueActionState {
handleReject: () => Promise<void>;
}
interface ModQueueActionsProps {
status: 'approved' | 'rejected' | 'failed' | null;
errorMessage?: string;
isPublishing: boolean;
handleApprove: () => Promise<void>;
handleReject: () => Promise<void>;
variant: 'row' | 'card';
}
const ModQueueActions = ({ status, errorMessage, isPublishing, handleApprove, handleReject, variant }: ModQueueActionsProps) => {
const { t } = useTranslation();
if (status === 'approved') {
const content = <span className={`${styles.button} ${styles.approve}`}>{t('approved')}</span>;
return variant === 'card' ? <div className={styles.cardActions}>{content}</div> : content;
}
if (status === 'rejected') {
const content = <span className={`${styles.button} ${styles.reject}`}>{t('rejected')}</span>;
return variant === 'card' ? <div className={styles.cardActions}>{content}</div> : content;
}
if (status === 'failed') {
const content = (
<span className={`${styles.button} ${styles.reject}`}>
{t('failed')}
{errorMessage ? `: ${errorMessage}` : ''}
</span>
);
return variant === 'card' ? <div className={styles.cardActions}>{content}</div> : content;
}
if (isPublishing) {
const content = <LoadingEllipsis string={t('publishing')} />;
return variant === 'card' ? <div className={styles.cardActions}>{content}</div> : content;
}
const buttons =
variant === 'row' ? (
<div className={styles.actionButtons}>
<span className={styles.buttonWrapper}>
[
<button className={styles.button} onClick={handleApprove} disabled={isPublishing}>
{t('approve')}
</button>
]
</span>
<span className={styles.buttonWrapper}>
[
<button className={styles.button} onClick={handleReject} disabled={isPublishing}>
{t('reject')}
</button>
]
</span>
</div>
) : (
<div className={styles.cardActions}>
<button className={styles.button} onClick={handleApprove} disabled={isPublishing}>
{t('approve')}
</button>
<button className={styles.button} onClick={handleReject} disabled={isPublishing}>
{t('reject')}
</button>
</div>
);
return buttons;
};
const useModQueueActions = (comment: Comment): ModQueueActionState => {
const { t } = useTranslation();
const { cid, subplebbitAddress, approved, removed } = comment || {};
@@ -202,47 +268,6 @@ const ModQueueRow = ({ comment, isOdd = false }: ModQueueRowProps) => {
const threadTargetCid = threadCid || cid;
const postUrl = boardPath && threadTargetCid ? `/${boardPath}/thread/${threadTargetCid}` : undefined;
// Render the status or action buttons
const renderActions = () => {
// Check existing moderation state first (from API/previous sessions)
if (status === 'approved') {
return <span className={`${styles.button} ${styles.approve}`}>{t('approved')}</span>;
}
if (status === 'rejected') {
return <span className={`${styles.button} ${styles.reject}`}>{t('rejected')}</span>;
}
if (status === 'failed') {
return (
<span className={`${styles.button} ${styles.reject}`}>
{t('failed')}
{errorMessage ? `: ${errorMessage}` : ''}
</span>
);
}
if (isPublishing) {
return <LoadingEllipsis string={t('publishing')} />;
}
return (
<div className={styles.actionButtons}>
<span className={styles.buttonWrapper}>
[
<button className={styles.button} onClick={handleApprove} disabled={isPublishing}>
{t('approve')}
</button>
]
</span>
<span className={styles.buttonWrapper}>
[
<button className={styles.button} onClick={handleReject} disabled={isPublishing}>
{t('reject')}
</button>
]
</span>
</div>
);
};
return (
<div className={`${styles.row} ${isOdd ? styles.rowOdd : ''}`}>
<div className={styles.number}>{number ?? 'N/A'}</div>
@@ -266,19 +291,32 @@ const ModQueueRow = ({ comment, isOdd = false }: ModQueueRowProps) => {
) : // On desktop, show full date with tooltip
isAwaitingApproval && isOverThreshold ? (
<>
<Tooltip children={<span>{getFormattedDate(timestamp)}</span>} content={getFormattedTimeAgo(timestamp)} />
<Tooltip content={getFormattedTimeAgo(timestamp)}>
<span>{getFormattedDate(timestamp)}</span>
</Tooltip>
<span className={styles.alertWrapper}>
{' '}
(<span className={styles.alert}>{getFormattedTimeAgo(timestamp)}</span>)
</span>
</>
) : (
<Tooltip children={<span>{getFormattedDate(timestamp)}</span>} content={getFormattedTimeAgo(timestamp)} />
<Tooltip content={getFormattedTimeAgo(timestamp)}>
<span>{getFormattedDate(timestamp)}</span>
</Tooltip>
)}
</div>
<div className={styles.type}>{isReply ? capitalize(t('reply')) : capitalize(t('post'))}</div>
<div className={styles.image}>{hasThumbnail ? t('yes') : t('no')}</div>
<div className={styles.actions}>{renderActions()}</div>
<div className={styles.actions}>
<ModQueueActions
status={status}
errorMessage={errorMessage}
isPublishing={isPublishing}
handleApprove={handleApprove}
handleReject={handleReject}
variant='row'
/>
</div>
</div>
);
};
@@ -326,51 +364,6 @@ const ModQueueCard = ({ comment }: ModQueueCardProps) => {
const threadTargetCid = threadCid || cid;
const postUrl = boardPath && threadTargetCid ? `/${boardPath}/thread/${threadTargetCid}` : undefined;
const renderActions = () => {
if (status === 'approved') {
return (
<div className={styles.cardActions}>
<span className={`${styles.button} ${styles.approve}`}>{t('approved')}</span>
</div>
);
}
if (status === 'rejected') {
return (
<div className={styles.cardActions}>
<span className={`${styles.button} ${styles.reject}`}>{t('rejected')}</span>
</div>
);
}
if (status === 'failed') {
return (
<div className={styles.cardActions}>
<span className={`${styles.button} ${styles.reject}`}>
{t('failed')}
{errorMessage ? `: ${errorMessage}` : ''}
</span>
</div>
);
}
if (isPublishing) {
return (
<div className={styles.cardActions}>
<LoadingEllipsis string={t('publishing')} />
</div>
);
}
return (
<div className={styles.cardActions}>
<button className={styles.button} onClick={handleApprove} disabled={isPublishing}>
{t('approve')}
</button>
<button className={styles.button} onClick={handleReject} disabled={isPublishing}>
{t('reject')}
</button>
</div>
);
};
return (
<div className={styles.mobileCard}>
<div className={styles.cardHeader}>
@@ -396,7 +389,7 @@ const ModQueueCard = ({ comment }: ModQueueCardProps) => {
)}{' '}
/ {t('type')}: {isReply ? t('reply') : t('post')} / {capitalize(t('image'))}: {hasThumbnail ? lowerCase(t('yes')) : lowerCase(t('no'))}
</div>
{renderActions()}
<ModQueueActions status={status} errorMessage={errorMessage} isPublishing={isPublishing} handleApprove={handleApprove} handleReject={handleReject} variant='card' />
</div>
);
};
@@ -646,7 +639,7 @@ export const ModQueueButton = ({ boardIdentifier, isMobile }: ModQueueButtonProp
return <ModQueueButtonContent key={contentKey} feed={feed} alertThresholdSeconds={alertThresholdSeconds} boardIdentifier={boardIdentifier} isMobile={isMobile} />;
};
export const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueViewProps) => {
const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueViewProps) => {
const { t } = useTranslation();
const params = useParams();
const { selectedBoardFilter, viewMode } = useModQueueStore();
@@ -707,7 +700,6 @@ export const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueV
postsPerPage: 50,
});
// Register reset function with feed reset store so refresh button works
const setResetFunction = useFeedResetStore((state) => state.setResetFunction);
useEffect(() => {
setResetFunction(reset);