move filters to interface settings, enable for all feeds

This commit is contained in:
Tom (plebeius.eth)
2024-09-12 21:22:22 +02:00
parent f9c82bccfd
commit 664a33482f
7 changed files with 101 additions and 89 deletions
@@ -5,6 +5,8 @@ import useTheme from '../../../hooks/use-theme';
import packageJson from '../../../../package.json';
import styles from './interface-settings.module.css';
import _ from 'lodash';
import useInterfaceSettingsStore from '../../../stores/use-interface-settings-store';
import useCatalogFiltersStore from '../../../stores/use-catalog-filters-store';
const commitRef = process.env.REACT_APP_COMMIT_REF;
const isElectron = window.isElectron === true;
@@ -110,6 +112,8 @@ const InterfaceLanguage = () => {
const InterfaceSettings = () => {
const { t } = useTranslation();
const { hideAvatars, setHideAvatars } = useAvatarVisibilityStore();
const { hideGoreBoards, setHideGoreBoards, hideAdultBoards, setHideAdultBoards, hideThreadsWithoutImages, setHideThreadsWithoutImages } = useInterfaceSettingsStore();
const { setShowTextOnlyThreads } = useCatalogFiltersStore();
const handleHideAvatarsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setHideAvatars(e.target.checked);
@@ -142,6 +146,29 @@ const InterfaceSettings = () => {
<input type='checkbox' checked={hideAvatars} onChange={handleHideAvatarsChange} /> {_.capitalize(t('hide_avatars'))}
</label>
</div>
<div className={styles.setting}>
<label>
<input type='checkbox' checked={hideGoreBoards} onChange={(e) => setHideGoreBoards(e.target.checked)} /> {_.capitalize(t('hide_gore_boards'))}
</label>
</div>
<div className={styles.setting}>
<label>
<input type='checkbox' checked={hideAdultBoards} onChange={(e) => setHideAdultBoards(e.target.checked)} /> {_.capitalize(t('hide_adult_boards'))}
</label>
</div>
<div className={styles.setting}>
<label>
<input
type='checkbox'
checked={hideThreadsWithoutImages}
onChange={(e) => {
setHideThreadsWithoutImages(e.target.checked);
setShowTextOnlyThreads(!e.target.checked);
}}
/>
{_.capitalize(t('hide_threads_without_images'))}
</label>
</div>
</div>
);
};
+7 -23
View File
@@ -2,17 +2,17 @@ import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams, useLocation } from 'react-router-dom';
import { useAccountComments, Subplebbit } from '@plebbit/plebbit-react-hooks';
import useInterfaceSettingsStore from '../stores/use-interface-settings-store';
import { getCommentMediaInfo, getHasThumbnail } from '../lib/utils/media-utils';
import { isAllView } from '../lib/utils/view-utils';
import { useMultisubMetadata } from './use-default-subplebbits';
import useCatalogFiltersStore from '../stores/use-catalog-filters-store';
import _ from 'lodash';
import { getCommentMediaInfo, getHasThumbnail } from '../lib/utils/media-utils';
const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolean, subplebbit: Subplebbit) => {
const { t } = useTranslation();
const { address, createdAt, description, rules, shortAddress, suggested, title } = subplebbit || {};
const { avatarUrl } = suggested || {};
const { showTextOnlyThreads } = useCatalogFiltersStore();
const { hideThreadsWithoutImages } = useInterfaceSettingsStore();
const location = useLocation();
const isInAllView = isAllView(location.pathname, useParams());
@@ -41,7 +41,7 @@ const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolea
!deleted &&
!removed &&
state === 'succeeded' &&
(showTextOnlyThreads || (!showTextOnlyThreads && isMediaShowed)) &&
(!hideThreadsWithoutImages || (hideThreadsWithoutImages && isMediaShowed)) &&
cid &&
cid === postCid &&
subplebbitAddress === address &&
@@ -63,7 +63,7 @@ const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolea
}
// add subplebbit description and rules as fake posts at the top of the feed
if ((description && description.length > 0 && (showTextOnlyThreads || (!showTextOnlyThreads && suggested?.avatarUrl))) || (isInAllView && showTextOnlyThreads)) {
if (description && description.length > 0) {
_feed.unshift({
isDescription: true,
subplebbitAddress: address,
@@ -77,7 +77,7 @@ const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolea
});
}
if (rules && rules.length > 0 && showTextOnlyThreads) {
if (rules && rules.length > 0) {
_feed.unshift({
isRules: true,
subplebbitAddress: address,
@@ -91,23 +91,7 @@ const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolea
}
return _feed;
}, [
accountComments,
feed,
description,
rules,
address,
isFeedLoaded,
createdAt,
title,
shortAddress,
avatarUrl,
t,
isInAllView,
multisub,
showTextOnlyThreads,
suggested?.avatarUrl,
]);
}, [accountComments, feed, description, rules, address, isFeedLoaded, createdAt, title, shortAddress, avatarUrl, t, isInAllView, multisub, hideThreadsWithoutImages]);
const rows = useMemo(() => {
const rows = [];
+19 -27
View File
@@ -9,10 +9,6 @@ interface FilterItem {
}
interface CatalogFiltersStore {
showAdultBoards: boolean;
setShowAdultBoards: (value: boolean) => void;
showGoreBoards: boolean;
setShowGoreBoards: (value: boolean) => void;
showTextOnlyThreads: boolean;
setShowTextOnlyThreads: (value: boolean) => void;
filterText: string;
@@ -35,10 +31,6 @@ const useCatalogFiltersStore = create(
set({ showTextOnlyThreads: value, filteredCount: 0 });
get().updateFilter();
},
showAdultBoards: false,
setShowAdultBoards: (value: boolean) => set({ showAdultBoards: value }),
showGoreBoards: false,
setShowGoreBoards: (value: boolean) => set({ showGoreBoards: value }),
filterText: '',
setFilterText: (value: string) => set({ filterText: value }),
filterItems: [],
@@ -58,28 +50,28 @@ const useCatalogFiltersStore = create(
filter: (comment: Comment) => {
const { showTextOnlyThreads, filterItems } = state;
const shouldShow = (() => {
if (!showTextOnlyThreads && !getHasThumbnail(getCommentMediaInfo(comment), comment?.link)) {
return false;
const hasThumbnail = getHasThumbnail(getCommentMediaInfo(comment), comment?.link);
const title = comment?.title?.toLowerCase() || '';
const content = comment?.content?.toLowerCase() || '';
const matchesFilterItems = filterItems
.filter((item) => item.enabled)
.some((item) => {
const text = item.text.toLowerCase();
return title.includes(text) || content.includes(text);
});
const shouldShow = showTextOnlyThreads || hasThumbnail;
if (!shouldShow || matchesFilterItems) {
if (matchesFilterItems && !filteredCids.has(comment.cid)) {
filteredCids.add(comment.cid);
set((state) => ({ filteredCount: state.filteredCount + 1 }));
}
const title = comment?.title?.toLowerCase() || '';
const content = comment?.content?.toLowerCase() || '';
return !filterItems
.filter((item) => item.enabled)
.some((item) => {
const text = item.text.toLowerCase();
return title.includes(text) || content.includes(text);
});
})();
if (!shouldShow && !filteredCids.has(comment.cid)) {
filteredCids.add(comment.cid);
set((state) => ({ filteredCount: state.filteredCount + 1 }));
return false;
}
return shouldShow;
return true;
},
}));
},
@@ -0,0 +1,29 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
interface InterfaceSettingsStore {
hideGoreBoards: boolean;
setHideGoreBoards: (value: boolean) => void;
hideAdultBoards: boolean;
setHideAdultBoards: (value: boolean) => void;
hideThreadsWithoutImages: boolean;
setHideThreadsWithoutImages: (value: boolean) => void;
}
const useInterfaceSettingsStore = create(
persist<InterfaceSettingsStore>(
(set) => ({
hideGoreBoards: true,
setHideGoreBoards: (value: boolean) => set({ hideGoreBoards: value }),
hideAdultBoards: true,
setHideAdultBoards: (value: boolean) => set({ hideAdultBoards: value }),
hideThreadsWithoutImages: true,
setHideThreadsWithoutImages: (value: boolean) => set({ hideThreadsWithoutImages: value }),
}),
{
name: 'interface-settings-storage',
},
),
);
export default useInterfaceSettingsStore;
+13 -2
View File
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { useAccount, useAccountComments, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import { Comment, useAccount, useAccountComments, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { useTranslation } from 'react-i18next';
import styles from './board.module.css';
@@ -17,13 +17,23 @@ import ReplyModal from '../../components/reply-modal';
import SettingsModal from '../../components/settings-modal';
import SubplebbitDescription from '../../components/subplebbit-description';
import SubplebbitRules from '../../components/subplebbit-rules';
import useInterfaceSettingsStore from '../../stores/use-interface-settings-store';
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
const threadsWithoutImagesFilter = (comment: Comment) => {
if (!getHasThumbnail(getCommentMediaInfo(comment), comment?.link)) {
return false;
}
return true;
};
const Board = () => {
const { t } = useTranslation();
const location = useLocation();
const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>();
const { hideThreadsWithoutImages } = useInterfaceSettingsStore();
const isInAllView = isAllView(location.pathname, useParams());
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
@@ -51,8 +61,9 @@ const Board = () => {
sortType,
postsPerPage: isInAllView || isInSubscriptionsView ? 5 : 25,
...(isInAllView || isInSubscriptionsView ? { newerThan: timeFilterSeconds } : {}),
filter: hideThreadsWithoutImages ? threadsWithoutImagesFilter : undefined,
}),
[subplebbitAddresses, sortType, timeFilterSeconds, isInAllView, isInSubscriptionsView],
[subplebbitAddresses, sortType, timeFilterSeconds, isInAllView, isInSubscriptionsView, hideThreadsWithoutImages],
);
const { feed, hasMore, loadMore, reset } = useFeed(feedOptions);
@@ -1,7 +1,5 @@
import { useState, useCallback } 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';
@@ -100,11 +98,6 @@ const FiltersTable = ({ onSave }: { onSave: () => void }) => {
const FiltersModal = ({ closeModal }: { closeModal: () => void }) => {
const { t } = useTranslation();
const { showAdultBoards, setShowAdultBoards, showGoreBoards, setShowGoreBoards, showTextOnlyThreads, setShowTextOnlyThreads } = useCatalogFiltersStore();
const location = useLocation();
const params = useParams();
const isInCatalogView = isCatalogView(location.pathname, params);
const isInAllView = isAllView(location.pathname, params);
return (
<>
@@ -114,33 +107,7 @@ const FiltersModal = ({ closeModal }: { closeModal: () => void }) => {
<span className={styles.title}>{t('filters')}</span>
<span className={styles.closeButton} title='close' onClick={closeModal} />
</div>
<div className={styles.filters}>
{isInCatalogView && (
<div>
<label className='capitalize'>
<input type='checkbox' checked={!showTextOnlyThreads} onChange={(e) => setShowTextOnlyThreads(!e.target.checked)} />
{t('hide_threads_without_images')}
</label>
</div>
)}
{isInAllView && (
<div className={styles.nsfwLabels}>
<div>
<label>
<input type='checkbox' checked={!showGoreBoards} onChange={(e) => setShowGoreBoards(!e.target.checked)} />
hide gore content
</label>
</div>
<div>
<label>
<input type='checkbox' checked={!showAdultBoards} onChange={(e) => setShowAdultBoards(!e.target.checked)} />
hide adult content
</label>
</div>
</div>
)}
</div>
{isInCatalogView && <FiltersTable onSave={closeModal} />}
<FiltersTable onSave={closeModal} />
</div>
</>
);
+5 -3
View File
@@ -17,6 +17,7 @@ import CatalogRow from '../../components/catalog-row';
import LoadingEllipsis from '../../components/loading-ellipsis';
import SettingsModal from '../../components/settings-modal';
import styles from './catalog.module.css';
import useInterfaceSettingsStore from '../../stores/use-interface-settings-store';
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
@@ -27,7 +28,8 @@ const Catalog = () => {
const isInAllView = isAllView(location.pathname, useParams());
const defaultSubplebbits = useDefaultSubplebbits();
const { filter, showAdultBoards, showGoreBoards } = useCatalogFiltersStore();
const { hideAdultBoards, hideGoreBoards } = useInterfaceSettingsStore();
const { filter } = useCatalogFiltersStore();
const account = useAccount();
const subscriptions = account?.subscriptions;
@@ -40,7 +42,7 @@ const Catalog = () => {
const hasGoreTag = tags?.includes('gore');
const hasAdultTag = tags?.includes('adult');
if ((hasGoreTag && !showGoreBoards) || (hasAdultTag && !showAdultBoards)) {
if ((hasGoreTag && hideGoreBoards) || (hasAdultTag && hideAdultBoards)) {
return false;
}
return true;
@@ -54,7 +56,7 @@ const Catalog = () => {
return subscriptions || [];
}
return [subplebbitAddress];
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, showAdultBoards, showGoreBoards]);
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, hideAdultBoards, hideGoreBoards]);
const { imageSize } = useCatalogStyleStore();
const columnWidth = imageSize === 'Large' ? 270 : 180;