feat(catalog): add filters modal for text-only posts, nsfw boards in p/all

This commit is contained in:
Tom (plebeius.eth)
2024-06-15 16:42:30 +02:00
parent 60ab84efd1
commit aa63ab0f1b
8 changed files with 210 additions and 24 deletions
@@ -0,0 +1,99 @@
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.25);
z-index: 4;
}
.button {
text-transform: capitalize;
color: var(--button-desktop-text-color);
text-decoration: var(--button-text-decoration);
}
.button:hover {
color: var(--button-desktop-text-color-hover);
cursor: pointer;
}
.modal label, .modal button, .modal select {
cursor: pointer;
}
.modal button {
text-transform: capitalize;
}
.modal {
top: 60px;
left: 50%;
transform: translateX(-50%);
width: 340px;
height: auto;
max-height: 80%;
overflow-y: auto;
position: fixed;
z-index: 5;
padding: 2px;
font-size: var(--settings-modal-font-size);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
background-color: var(--settings-modal-background-color);
border-top: var(--settings-modal-border-top);
border-right: var(--settings-modal-border-right);
border-bottom: var(--settings-modal-border-bottom);
border-left: var(--settings-modal-border-left);
}
.header {
font-size: 16px;
font-weight: 700;
margin-bottom: 5px;
margin-top: 5px;
padding-bottom: 5px;
text-align: center;
line-height: 14px;
border-bottom: var(--settings-modal-header-border-bottom);
}
.title {
text-transform: capitalize;
}
.closeButton {
right: 5px;
width: 18px;
height: 18px;
display: block;
background-size: 100%;
position: absolute;
top: 5px;
image-rendering: pixelated;
background-image: var(--settings-modal-close-button-background-image);
}
.filters {
padding: 5px;
}
.filters label {
display: block;
margin-bottom: 7px;
}
.filters label input[type='checkbox'] {
margin-right: 5px;
}
.categoryTitle {
font-size: 14px;
font-weight: 700;
padding-bottom: 5px;
}
.paddingBottom {
padding-bottom: 5px;
}
@@ -0,0 +1,67 @@
import { useState } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { isAllView, isCatalogView } from '../../../lib/utils/view-utils';
import useCatalogFiltersStore from '../../../stores/use-catalog-filters-store';
import styles from './catalog-filters.module.css';
const FiltersModal = ({ closeModal }: { closeModal: () => void }) => {
const { t } = useTranslation();
const { showAdultBoards, setShowAdultBoards, showGoreBoards, setShowGoreBoards, showTextOnlyThreads, setShowTextOnlyThreads } = useCatalogFiltersStore();
const location = useLocation();
const isInCatalogView = isCatalogView(location.pathname, useParams());
const isInAllView = isAllView(location.pathname);
return (
<>
<div className={styles.overlay} onClick={closeModal} />
<div className={styles.modal}>
<div className={styles.header}>
<span className={styles.title}>{t('filters')}</span>
<span className={styles.closeButton} title='close' onClick={closeModal} />
</div>
<div className={styles.filters}>
{isInCatalogView && (
<label className={styles.paddingBottom}>
<input type='checkbox' checked={!showTextOnlyThreads} onChange={(e) => setShowTextOnlyThreads(!e.target.checked)} />
Hide Text-Only Posts
</label>
)}
{isInAllView && (
<div className={styles.nsfwLabels}>
<div className={styles.categoryTitle}>NSFW Boards</div>
<label>
<input type='checkbox' checked={!showGoreBoards} onChange={(e) => setShowGoreBoards(!e.target.checked)} />
Hide Gore Boards
</label>
<label>
<input type='checkbox' checked={!showAdultBoards} onChange={(e) => setShowAdultBoards(!e.target.checked)} />
Hide Adult Boards
</label>
</div>
)}
</div>
</div>
</>
);
};
const CatalogFilters = () => {
const [showModal, setShowModal] = useState(false);
const closeModal = () => {
setShowModal(false);
};
return (
<>
[
<span className={styles.button} onClick={() => setShowModal(true)}>
Filters
</span>
]{showModal && <FiltersModal closeModal={closeModal} />}
</>
);
};
export default CatalogFilters;
@@ -0,0 +1 @@
export { default } from './catalog-filters';
+22 -4
View File
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
import { useAccount, Subplebbit, useFeed, useSubplebbit, Comment } from '@plebbit/plebbit-react-hooks';
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import useDefaultSubplebbits from '../../hooks/use-default-subplebbits';
import useFeedStateString from '../../hooks/use-feed-state-string';
import { useMultisubMetadata } from '../../hooks/use-default-subplebbits';
import useTimeFilter from '../../hooks/use-time-filter';
@@ -91,21 +91,39 @@ const Catalog = () => {
const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>();
const isInAllView = isAllView(location.pathname);
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
const defaultSubplebbits = useDefaultSubplebbits();
const { showAdultBoards, showGoreBoards } = useCatalogFiltersStore();
const account = useAccount();
const subscriptions = account?.subscriptions;
const isInSubscriptionsView = isSubscriptionsView(location.pathname);
const subplebbitAddresses = useMemo(() => {
const filteredDefaultSubplebbits = defaultSubplebbits
.filter((subplebbit) => {
const { tags } = subplebbit;
const hasGoreTag = tags?.includes('gore');
const hasAdultTag = tags?.includes('adult');
if ((hasGoreTag && !showGoreBoards) || (hasAdultTag && !showAdultBoards)) {
return false;
}
return true;
})
.map((subplebbit) => subplebbit.address);
if (isInAllView) {
return defaultSubplebbitAddresses;
return filteredDefaultSubplebbits;
}
if (isInSubscriptionsView) {
return subscriptions || [];
}
return [subplebbitAddress];
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbitAddresses, subscriptions]);
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, showAdultBoards, showGoreBoards]);
useEffect(() => {
console.log(showAdultBoards, showGoreBoards);
}, [showAdultBoards, showGoreBoards]);
const columnCount = Math.floor(useWindowWidth() / columnWidth);
// postPerPage based on columnCount for optimized feed, dont change value after first render