diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx
index 92588def..3f87f6be 100644
--- a/src/components/post-desktop/post-desktop.tsx
+++ b/src/components/post-desktop/post-desktop.tsx
@@ -1,14 +1,15 @@
import { useEffect, useRef, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { Link, useLocation, useParams } from 'react-router-dom';
-import { Comment, useAccount, useBlock, useComment } from '@plebbit/plebbit-react-hooks';
+import { Comment, useAccount, useComment } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import styles from '../../views/post/post.module.css';
import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../lib/utils/media-utils';
import { isValidURL } from '../../lib/utils/url-utils';
import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
-import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
import useEditCommentPrivileges from '../../hooks/use-author-privileges';
+import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
+import useHide from '../../hooks/use-hide';
import useReplies from '../../hooks/use-replies';
import useStateString from '../../hooks/use-state-string';
import CommentMedia from '../comment-media';
@@ -220,8 +221,8 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
const isInPendingPostView = isPendingPostView(location.pathname, params);
const isInPostPageView = isPostPageView(location.pathname, params);
- const { blocked, unblock, block } = useBlock({ cid });
- const isHidden = blocked && !isInPostPageView;
+ const { hidden, unhide, hide } = useHide({ cid });
+ const isHidden = hidden && !isInPostPageView;
const replies = useReplies(post);
const visiblelinksCount = useCountLinksInReplies(post, 5);
@@ -250,7 +251,7 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
{!isInPostPageView && !isDescription && !isRules && showReplies && (
-
+
)}
{link && !isHidden && isValidURL(link) &&
}
diff --git a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx
index 974f34e1..e305831b 100644
--- a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx
+++ b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx
@@ -8,6 +8,7 @@ import styles from './post-menu-desktop.module.css';
import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
import { copyShareLinkToClipboard, isValidURL } from '../../../lib/utils/url-utils';
import { isAllView, isCatalogView, isPostPageView, isSubscriptionsView } from '../../../lib/utils/view-utils';
+import useHide from '../../../hooks/use-hide';
import _ from 'lodash';
interface PostMenuDesktopProps {
@@ -102,14 +103,34 @@ const ViewOnButton = ({ cid, isDescription, isInAllView, isInSubscriptionsView,
);
};
+const BlockUserButton = ({ address }: { address: string }) => {
+ const { blocked, unblock, block } = useBlock({ address });
+
+ return (
+
+ {blocked ? 'Unblock' : 'Block'} user
+
+ );
+};
+
+const BlockBoardButton = ({ address }: { address: string }) => {
+ const { blocked, unblock, block } = useBlock({ address });
+
+ return (
+
+ {blocked ? 'Unblock' : 'Block'} board
+
+ );
+};
+
const PostMenuDesktop = ({ post }: { post: Comment }) => {
const { t } = useTranslation();
- const { cid, isDescription, isRules, link, postCid, subplebbitAddress } = post || {};
+ const { author, cid, isDescription, isRules, link, postCid, subplebbitAddress } = post || {};
const commentMediaInfo = getCommentMediaInfo(post);
const { thumbnail, type, url } = commentMediaInfo || {};
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
- const { blocked, unblock, block } = useBlock({ cid });
+ const { hidden, unhide, hide } = useHide({ cid });
const location = useLocation();
const params = useParams();
@@ -154,11 +175,11 @@ const PostMenuDesktop = ({ post }: { post: Comment }) => {
{
- blocked ? unblock() : block();
+ hidden ? unhide() : hide();
handleClose();
}}
>
- {blocked ? (postCid === cid ? t('unhide_thread') : t('unhide_post')) : postCid === cid ? t('hide_thread') : t('hide_post')}
+ {hidden ? (postCid === cid ? t('unhide_thread') : t('unhide_post')) : postCid === cid ? t('hide_thread') : t('hide_post')}
)}
{link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url &&
}
@@ -171,6 +192,8 @@ const PostMenuDesktop = ({ post }: { post: Comment }) => {
subplebbitAddress={subplebbitAddress}
onClose={handleClose}
/>
+
+ {(isInAllView || isInSubscriptionsView) &&
}
,
document.body,
diff --git a/src/hooks/use-hide.ts b/src/hooks/use-hide.ts
index 9faef7c3..2f19c039 100644
--- a/src/hooks/use-hide.ts
+++ b/src/hooks/use-hide.ts
@@ -1 +1,63 @@
+import { useEffect, useCallback } from 'react';
+import { create } from 'zustand';
import localForageLru from '@plebbit/plebbit-react-hooks/dist/lib/localforage-lru/index.js';
+
+interface HideStoreState {
+ hiddenCids: { [key: string]: boolean };
+ hide: (cid: string) => void;
+ unhide: (cid: string) => void;
+}
+
+const hideStore = localForageLru.createInstance({
+ name: 'hideStore',
+ size: 1000,
+});
+
+const useHideStore = create((set) => ({
+ hiddenCids: {},
+ hide: (cid: string) => {
+ set((state) => ({
+ hiddenCids: { ...state.hiddenCids, [cid]: true },
+ }));
+ hideStore.setItem(cid, true);
+ },
+ unhide: (cid: string) => {
+ set((state) => {
+ const newHiddenCids = { ...state.hiddenCids };
+ delete newHiddenCids[cid];
+ return { hiddenCids: newHiddenCids };
+ });
+ hideStore.removeItem(cid);
+ },
+}));
+
+const initializeHideStore = async () => {
+ const entries: [string, boolean][] = await hideStore.entries();
+ const hiddenCids: { [key: string]: boolean } = {};
+ entries.forEach(([key, value]) => {
+ hiddenCids[key] = value;
+ });
+
+ useHideStore.setState((state) => ({
+ hiddenCids: { ...hiddenCids, ...state.hiddenCids },
+ }));
+};
+
+const useHide = ({ cid }: { cid: string }) => {
+ const hiddenCids = useHideStore((state) => state.hiddenCids);
+ const hide = useHideStore((state) => state.hide);
+ const unhide = useHideStore((state) => state.unhide);
+
+ const hidden = !!hiddenCids[cid];
+
+ useEffect(() => {
+ initializeHideStore();
+ }, []);
+
+ const hideCallback = useCallback(() => hide(cid), [hide, cid]);
+ const unhideCallback = useCallback(() => unhide(cid), [unhide, cid]);
+
+ return { hidden, hide: hideCallback, unhide: unhideCallback };
+};
+
+export default useHide;
diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx
index 9a74c93e..b4f74a81 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, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
+import { useAccount, 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';
@@ -87,15 +87,40 @@ const Board = () => {
);
+ const { blocked, unblock } = useBlock({ address: subplebbitAddress });
+
const Footer = () => {
let footerContent;
if (feed.length === 0) {
- footerContent = t('no_posts');
+ if (blocked) {
+ footerContent = 'you have blocked this board';
+ } else {
+ footerContent = t('no_posts');
+ }
}
if (hasMore || subplebbitAddresses.length === 0) {
footerContent = loadingString;
}
- return {footerContent}
;
+ return (
+
+ {footerContent}
+ {blocked && (
+ <>
+ [
+ {
+ unblock();
+ reset();
+ }}
+ >
+ Unblock
+
+ ]
+ >
+ )}
+
+ );
};
// save the last Virtuoso state to restore it when navigating back