diff --git a/src/components/board-buttons/board-buttons.module.css b/src/components/board-buttons/board-buttons.module.css index 69664298..ee4bbc79 100644 --- a/src/components/board-buttons/board-buttons.module.css +++ b/src/components/board-buttons/board-buttons.module.css @@ -79,6 +79,16 @@ padding-top: 15px; } +.filteredThreadsCount { + text-transform: none !important; +} + +.mobileBoardButtons .filteredThreadsCount { + display: block; + margin-top: 3px; + margin-bottom: 15px; +} + @media (max-width: 640px) { .desktopBoardButtons { display: none; diff --git a/src/components/board-buttons/board-buttons.tsx b/src/components/board-buttons/board-buttons.tsx index 2fa41cb7..c9deccc4 100644 --- a/src/components/board-buttons/board-buttons.tsx +++ b/src/components/board-buttons/board-buttons.tsx @@ -12,6 +12,8 @@ import Tooltip from '../tooltip'; import useCountLinksInReplies from '../../hooks/use-count-links-in-replies'; import _ from 'lodash'; import useIsMobile from '../../hooks/use-is-mobile'; +import useCatalogFiltersStore from '../../stores/use-catalog-filters-store'; +import { useEffect } from 'react'; interface BoardButtonsProps { address?: string | undefined; @@ -231,6 +233,14 @@ export const MobileBoardButtons = () => { const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any }); const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress; + const { filteredCount, resetFilteredCount } = useCatalogFiltersStore(); + + useEffect(() => { + if (subplebbitAddress) { + resetFilteredCount(); + } + }, [subplebbitAddress, resetFilteredCount]); + return (
{isInPostView || isInPendingPostPage ? ( @@ -252,6 +262,12 @@ export const MobileBoardButtons = () => { )} {!(isInAllView || isInSubscriptionsView) && } + {isInCatalogView && filteredCount > 0 && ( + + {' '} + — Filtered threads: {filteredCount} + + )} {isInCatalogView && ( <>
@@ -305,6 +321,14 @@ export const DesktopBoardButtons = () => { const isInPostView = isPostPageView(location.pathname, params); const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); + const { filteredCount, resetFilteredCount } = useCatalogFiltersStore(); + + useEffect(() => { + if (subplebbitAddress) { + resetFilteredCount(); + } + }, [subplebbitAddress, resetFilteredCount]); + return ( <>
@@ -336,6 +360,12 @@ export const DesktopBoardButtons = () => { )} [] + {isInCatalogView && filteredCount > 0 && ( + + {' '} + — Filtered threads: {filteredCount} + + )} {isInCatalogView && ( <> diff --git a/src/stores/use-catalog-filters-store.ts b/src/stores/use-catalog-filters-store.ts index 1ed9c862..921d1b5b 100644 --- a/src/stores/use-catalog-filters-store.ts +++ b/src/stores/use-catalog-filters-store.ts @@ -23,6 +23,8 @@ interface CatalogFiltersStore { filter: ((comment: Comment) => boolean) | undefined; updateFilter: () => void; initializeFilter: () => void; + filteredCount: number; + resetFilteredCount: () => void; } const useCatalogFiltersStore = create( @@ -30,7 +32,7 @@ const useCatalogFiltersStore = create( (set, get) => ({ showTextOnlyThreads: false, setShowTextOnlyThreads: (value: boolean) => { - set({ showTextOnlyThreads: value }); + set({ showTextOnlyThreads: value, filteredCount: 0 }); get().updateFilter(); }, showAdultBoards: false, @@ -46,33 +48,47 @@ const useCatalogFiltersStore = create( }, saveAndApplyFilters: (items: FilterItem[]) => { const nonEmptyItems = items.filter((item) => item.text.trim() !== ''); - set({ filterItems: nonEmptyItems }); + set({ filterItems: nonEmptyItems, filteredCount: 0 }); get().updateFilter(); }, filter: undefined, - updateFilter: () => + updateFilter: () => { + const filteredCids = new Set(); set((state) => ({ filter: (comment: Comment) => { const { showTextOnlyThreads, filterItems } = state; - if (!showTextOnlyThreads && !getHasThumbnail(getCommentMediaInfo(comment), comment?.link)) { - return false; + + const shouldShow = (() => { + if (!showTextOnlyThreads && !getHasThumbnail(getCommentMediaInfo(comment), comment?.link)) { + return false; + } + + 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 })); } - 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); - }); + return shouldShow; }, - })), + })); + }, initializeFilter: () => { const { updateFilter } = get(); updateFilter(); }, + filteredCount: 0, + resetFilteredCount: () => set({ filteredCount: 0 }), }), { name: 'catalog-filters-storage',