From 664a33482f3e45f7f50f2c30b9e6118d6037d7cf Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Thu, 12 Sep 2024 21:22:22 +0200 Subject: [PATCH] move filters to interface settings, enable for all feeds --- .../interface-settings/interface-settings.tsx | 27 +++++++++++ src/hooks/use-catalog-feed-rows.ts | 30 +++--------- src/stores/use-catalog-filters-store.ts | 46 ++++++++----------- src/stores/use-interface-settings-store.ts | 29 ++++++++++++ src/views/board/board.tsx | 15 +++++- .../catalog-filters/catalog-filters.tsx | 35 +------------- src/views/catalog/catalog.tsx | 8 ++-- 7 files changed, 101 insertions(+), 89 deletions(-) create mode 100644 src/stores/use-interface-settings-store.ts diff --git a/src/components/settings-modal/interface-settings/interface-settings.tsx b/src/components/settings-modal/interface-settings/interface-settings.tsx index 9fccc550..e48bc1b0 100644 --- a/src/components/settings-modal/interface-settings/interface-settings.tsx +++ b/src/components/settings-modal/interface-settings/interface-settings.tsx @@ -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) => { setHideAvatars(e.target.checked); @@ -142,6 +146,29 @@ const InterfaceSettings = () => { {_.capitalize(t('hide_avatars'))} +
+ +
+
+ +
+
+ +
); }; diff --git a/src/hooks/use-catalog-feed-rows.ts b/src/hooks/use-catalog-feed-rows.ts index e7bdca87..2fe732dc 100644 --- a/src/hooks/use-catalog-feed-rows.ts +++ b/src/hooks/use-catalog-feed-rows.ts @@ -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 = []; diff --git a/src/stores/use-catalog-filters-store.ts b/src/stores/use-catalog-filters-store.ts index 921d1b5b..67db2ab9 100644 --- a/src/stores/use-catalog-filters-store.ts +++ b/src/stores/use-catalog-filters-store.ts @@ -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; }, })); }, diff --git a/src/stores/use-interface-settings-store.ts b/src/stores/use-interface-settings-store.ts new file mode 100644 index 00000000..a58bac1e --- /dev/null +++ b/src/stores/use-interface-settings-store.ts @@ -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( + (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; diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx index 80b1ce95..6483251a 100644 --- a/src/views/board/board.tsx +++ b/src/views/board/board.tsx @@ -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); diff --git a/src/views/catalog/catalog-filters/catalog-filters.tsx b/src/views/catalog/catalog-filters/catalog-filters.tsx index c44aa579..e82bfeab 100644 --- a/src/views/catalog/catalog-filters/catalog-filters.tsx +++ b/src/views/catalog/catalog-filters/catalog-filters.tsx @@ -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 }) => { {t('filters')} -
- {isInCatalogView && ( -
- -
- )} - {isInAllView && ( -
-
- -
-
- -
-
- )} -
- {isInCatalogView && } + ); diff --git a/src/views/catalog/catalog.tsx b/src/views/catalog/catalog.tsx index 5afc8eaa..05d9b444 100644 --- a/src/views/catalog/catalog.tsx +++ b/src/views/catalog/catalog.tsx @@ -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;