diff --git a/src/components/styled/views/Board.styled.jsx b/src/components/styled/views/Board.styled.jsx
index 1f586bf1..ae9f426b 100644
--- a/src/components/styled/views/Board.styled.jsx
+++ b/src/components/styled/views/Board.styled.jsx
@@ -4091,4 +4091,133 @@ export const PostMenu = styled.div`
cursor: pointer;
transition: transform 0.1s;
transform: ${props => props.rotated ? 'rotate(90deg)' : 'none'};
+`;
+
+export const PostMenuMobile = styled.div`
+ font-size: 16px;
+ line-height: 2.5em;
+ width: 216px;
+
+
+ ul {
+ border-right-width: 2px !important;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ white-space: nowrap;
+ }
+
+ li {
+ cursor: pointer;
+ position: relative;
+ padding: 2px 4px;
+ vertical-align: middle;
+ }
+
+ ${({ selectedStyle }) => {
+ switch (selectedStyle) {
+ case 'Yotsuba':
+ return `
+ ul {
+ border: 1px solid #d9bfb7;
+ }
+
+ li {
+ background-color: #f0e0d6;
+ border-bottom: 1px solid #d9bfb7;
+
+ :hover {
+ background-color: #ffe;
+ color: #d00;
+ }
+ }
+ `;
+
+ case 'Yotsuba-B':
+ return `
+ ul {
+ border: 1px solid #b7c5d9;
+ }
+
+ li {
+ background-color: #d6daf0;
+ border-bottom: 1px solid #b7c5d9;
+
+ :hover {
+ background-color: #eef2ff;
+ color: #d00;
+ }
+ }
+ `;
+
+ case 'Futaba':
+ return `
+ ul {
+ border: 1px solid #d9bfb7;
+ }
+
+ li {
+ background-color: #f0e0d6;
+ border-bottom: 1px solid #d9bfb7;
+
+ :hover {
+ background-color: #ffe;
+ color: #d00;
+ }
+ }
+ `;
+
+ case 'Burichan':
+ return `
+ ul {
+ border: 1px solid #b7c5d9;
+ }
+
+ li {
+ background-color: #d6daf0;
+ border-bottom: 1px solid #b7c5d9;
+
+ :hover {
+ background-color: #eef2ff;
+ color: #d00;
+ }
+ }
+ `;
+
+ case 'Tomorrow':
+ return `
+ ul {
+ border: 1px solid #282a2e;
+ }
+
+ li {
+ background-color: #1d1f21;
+ border-bottom: 1px solid #282a2e;
+
+ :hover {
+ background-color: #1b1c1e;
+ }
+ }
+ `;
+
+ case 'Photon':
+ return `
+ ul {
+ border: 1px solid #ccc;
+ }
+
+ li {
+ background-color: #ddd;
+ border-bottom: 1px solid #ccc;
+
+ :hover {
+ background-color: #eee;
+ }
+ }
+ `;
+
+ default:
+ return '';
+ }}
+ }
`;
\ No newline at end of file
diff --git a/src/components/views/All.jsx b/src/components/views/All.jsx
index d1d9ddd0..123cfd03 100755
--- a/src/components/views/All.jsx
+++ b/src/components/views/All.jsx
@@ -8,7 +8,7 @@ import { Virtuoso } from 'react-virtuoso';
import { useAccount, useAccountComments, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
import { debounce } from 'lodash';
-import { Container, NavBar, Header, Break, TopBar, BoardForm, PostMenu } from '../styled/views/Board.styled';
+import { Container, NavBar, Header, Break, TopBar, BoardForm, PostMenu, PostMenuMobile } from '../styled/views/Board.styled';
import { Footer } from '../styled/views/Thread.styled';
import { PostMenuCatalog } from '../styled/views/Catalog.styled';
import { AlertModal } from '../styled/modals/AlertModal.styled';
@@ -85,8 +85,11 @@ const All = () => {
const [, setNewSuccessMessage] = useSuccess();
const threadMenuRefs = useRef({});
+ const threadMenuRefsMobile = useRef({});
const replyMenuRefs = useRef({});
+ const replyMenuRefsMobile = useRef({});
const postMenuCatalogRef = useRef(null);
+ const postMenuMobileRef = useRef(null);
const backlinkRefs = useRef({});
const quoteRefs = useRef({});
const postRefs = useRef({});
@@ -105,8 +108,10 @@ const All = () => {
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
const [commentCid, setCommentCid] = useState(null);
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
+ const [mobileMenuPosition, setMobileMenuPosition] = useState({top: 0, left: 0});
const [triggerPublishCommentEdit, setTriggerPublishCommentEdit] = useState(false);
const [openMenuCid, setOpenMenuCid] = useState(null);
+ const [openMobileMenuCid, setOpenMobileMenuCid] = useState(null);
const [outOfViewCid, setOutOfViewCid] = useState(null);
const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0});
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
@@ -196,12 +201,22 @@ const All = () => {
setOpenMenuCid(null);
};
+ const handleMobileOptionClick = () => {
+ setOpenMobileMenuCid(null);
+ };
+
const handleOutsideClick = useCallback((e) => {
if (openMenuCid !== null && !postMenuCatalogRef.current.contains(e.target)) {
setOpenMenuCid(null);
}
}, [openMenuCid, postMenuCatalogRef]);
+
+ const handleMobileOutsideClick = useCallback((e) => {
+ if (openMobileMenuCid !== null && !postMenuMobileRef.current.contains(e.target)) {
+ setOpenMobileMenuCid(null);
+ }
+ }, [openMobileMenuCid, postMenuMobileRef]);
useEffect(() => {
@@ -217,6 +232,19 @@ const All = () => {
}, [openMenuCid, handleOutsideClick]);
+ useEffect(() => {
+ if (openMobileMenuCid !== null) {
+ document.addEventListener('click', handleMobileOutsideClick);
+ } else {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ }
+
+ return () => {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ };
+ }, [openMobileMenuCid, handleMobileOutsideClick]);
+
+
useEffect(() => {
if (postOnHoverRef.current) {
const rect = postOnHoverRef.current.getBoundingClientRect();
@@ -1321,7 +1349,7 @@ const All = () => {
handleOptionClick(reply.cid)}>
Yandex
@@ -1748,7 +1776,96 @@ const All = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === thread.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(thread.cid);
+ handleShareClick(selectedAddress, thread.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(thread)}>Edit post
+ - handleAuthorDeleteClick(thread)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(thread.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(thread.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(commentMediaInfo && (
+ commentMediaInfo.type === 'image' ||
+ (commentMediaInfo.type === 'webpage' &&
+ commentMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{thread.author.displayName
? thread.author.displayName.length > 20
@@ -1985,7 +2102,96 @@ const All = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === reply.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(reply.cid);
+ handleShareClick(selectedAddress, reply.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(reply)}>Edit post
+ - handleAuthorDeleteClick(reply)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(replyMediaInfo && (
+ replyMediaInfo.type === 'image' ||
+ (replyMediaInfo.type === 'webpage' &&
+ replyMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{reply.author.displayName
? reply.author.displayName.length > 20
diff --git a/src/components/views/Board.jsx b/src/components/views/Board.jsx
index 1e687ce6..f279d2d9 100755
--- a/src/components/views/Board.jsx
+++ b/src/components/views/Board.jsx
@@ -8,7 +8,7 @@ import { Virtuoso } from 'react-virtuoso';
import { useAccount, useAccountComments, useFeed, usePublishComment, usePublishCommentEdit, useSubplebbit, useSubscribe } from '@plebbit/plebbit-react-hooks';
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
import { debounce } from 'lodash';
-import { Container, NavBar, Header, Break, PostFormLink, PostFormTable, PostForm, TopBar, BoardForm, PostMenu } from '../styled/views/Board.styled';
+import { Container, NavBar, Header, Break, PostFormLink, PostFormTable, PostForm, TopBar, BoardForm, PostMenu, PostMenuMobile } from '../styled/views/Board.styled';
import { Footer } from '../styled/views/Thread.styled';
import { AlertModal } from '../styled/modals/AlertModal.styled';
import { PostMenuCatalog } from '../styled/views/Catalog.styled';
@@ -105,8 +105,11 @@ const Board = () => {
const commentRef = useRef();
const linkRef = useRef();
const threadMenuRefs = useRef({});
+ const threadMenuRefsMobile = useRef({});
const replyMenuRefs = useRef({});
+ const replyMenuRefsMobile = useRef({});
const postMenuCatalogRef = useRef(null);
+ const postMenuMobileRef = useRef(null);
const backlinkRefs = useRef({});
const quoteRefs = useRef({});
const postRefs = useRef({});
@@ -136,7 +139,9 @@ const Board = () => {
const [isModerator, setIsModerator] = useState(false);
const [commentCid, setCommentCid] = useState(null);
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
+ const [mobileMenuPosition, setMobileMenuPosition] = useState({top: 0, left: 0});
const [openMenuCid, setOpenMenuCid] = useState(null);
+ const [openMobileMenuCid, setOpenMobileMenuCid] = useState(null);
const [outOfViewCid, setOutOfViewCid] = useState(null);
const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0});
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
@@ -210,12 +215,22 @@ const Board = () => {
setOpenMenuCid(null);
};
+ const handleMobileOptionClick = () => {
+ setOpenMobileMenuCid(null);
+ };
+
const handleOutsideClick = useCallback((e) => {
if (openMenuCid !== null && !postMenuCatalogRef.current.contains(e.target)) {
setOpenMenuCid(null);
}
}, [openMenuCid, postMenuCatalogRef]);
+
+ const handleMobileOutsideClick = useCallback((e) => {
+ if (openMobileMenuCid !== null && !postMenuMobileRef.current.contains(e.target)) {
+ setOpenMobileMenuCid(null);
+ }
+ }, [openMobileMenuCid, postMenuMobileRef]);
useEffect(() => {
@@ -231,6 +246,19 @@ const Board = () => {
}, [openMenuCid, handleOutsideClick]);
+ useEffect(() => {
+ if (openMobileMenuCid !== null) {
+ document.addEventListener('click', handleMobileOutsideClick);
+ } else {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ }
+
+ return () => {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ };
+ }, [openMobileMenuCid, handleMobileOutsideClick]);
+
+
useEffect(() => {
if (postOnHoverRef.current) {
const rect = postOnHoverRef.current.getBoundingClientRect();
@@ -1038,7 +1066,32 @@ const Board = () => {
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === "rules" ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick("rules");
+ handleShareClick(selectedAddress, "rules")
+ }}>Share board
+
+ , document.body
+ )}
{
-
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === "rules" ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick("rules");
+ handleShareClick(selectedAddress, "rules")
+ }}>Share board
+
+ , document.body
+ )}
{
-
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === "description" ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick("description");
+ handleShareClick(selectedAddress, "description")
+ }}>Share board
+
+ , document.body
+ )}
{
handleOptionClick(reply.cid)}>
Yandex
@@ -2439,7 +2542,96 @@ const Board = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === thread.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(thread.cid);
+ handleShareClick(selectedAddress, thread.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(thread)}>Edit post
+ - handleAuthorDeleteClick(thread)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(thread.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(thread.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(commentMediaInfo && (
+ commentMediaInfo.type === 'image' ||
+ (commentMediaInfo.type === 'webpage' &&
+ commentMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{thread.author.displayName
? thread.author.displayName.length > 20
@@ -2677,7 +2869,96 @@ const Board = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === reply.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(reply.cid);
+ handleShareClick(selectedAddress, reply.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(reply)}>Edit post
+ - handleAuthorDeleteClick(reply)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(replyMediaInfo && (
+ replyMediaInfo.type === 'image' ||
+ (replyMediaInfo.type === 'webpage' &&
+ replyMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{reply.author.displayName
? reply.author.displayName.length > 20
diff --git a/src/components/views/Subscriptions.jsx b/src/components/views/Subscriptions.jsx
index b7bb60d1..85302afa 100755
--- a/src/components/views/Subscriptions.jsx
+++ b/src/components/views/Subscriptions.jsx
@@ -9,7 +9,7 @@ import { useAccount, useAccountComments, useFeed, usePublishCommentEdit, useSubp
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
import { debounce } from 'lodash';
import useGeneralStore from '../../hooks/stores/useGeneralStore';
-import { Container, NavBar, Header, Break, TopBar, BoardForm, PostMenu } from '../styled/views/Board.styled';
+import { Container, NavBar, Header, Break, TopBar, BoardForm, PostMenu, PostMenuMobile } from '../styled/views/Board.styled';
import { Footer } from '../styled/views/Thread.styled';
import { AlertModal } from '../styled/modals/AlertModal.styled';
import { PostMenuCatalog } from '../styled/views/Catalog.styled';
@@ -85,8 +85,11 @@ const Subscriptions = () => {
const [, setNewSuccessMessage] = useSuccess();
const threadMenuRefs = useRef({});
+ const threadMenuRefsMobile = useRef({});
const replyMenuRefs = useRef({});
+ const replyMenuRefsMobile = useRef({});
const postMenuCatalogRef = useRef(null);
+ const postMenuMobileRef = useRef(null);
const backlinkRefs = useRef({});
const quoteRefs = useRef({});
const postRefs = useRef({});
@@ -105,8 +108,10 @@ const Subscriptions = () => {
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
const [commentCid, setCommentCid] = useState(null);
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
+ const [mobileMenuPosition, setMobileMenuPosition] = useState({top: 0, left: 0});
const [triggerPublishCommentEdit, setTriggerPublishCommentEdit] = useState(false);
const [openMenuCid, setOpenMenuCid] = useState(null);
+ const [openMobileMenuCid, setOpenMobileMenuCid] = useState(null);
const [outOfViewCid, setOutOfViewCid] = useState(null);
const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0});
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
@@ -196,12 +201,22 @@ const Subscriptions = () => {
setOpenMenuCid(null);
};
-
+ const handleMobileOptionClick = () => {
+ setOpenMobileMenuCid(null);
+ };
+
+
const handleOutsideClick = useCallback((e) => {
if (openMenuCid !== null && !postMenuCatalogRef.current.contains(e.target)) {
setOpenMenuCid(null);
}
}, [openMenuCid, postMenuCatalogRef]);
+
+ const handleMobileOutsideClick = useCallback((e) => {
+ if (openMobileMenuCid !== null && !postMenuMobileRef.current.contains(e.target)) {
+ setOpenMobileMenuCid(null);
+ }
+ }, [openMobileMenuCid, postMenuMobileRef]);
useEffect(() => {
@@ -217,6 +232,19 @@ const Subscriptions = () => {
}, [openMenuCid, handleOutsideClick]);
+ useEffect(() => {
+ if (openMobileMenuCid !== null) {
+ document.addEventListener('click', handleMobileOutsideClick);
+ } else {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ }
+
+ return () => {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ };
+ }, [openMobileMenuCid, handleMobileOutsideClick]);
+
+
useEffect(() => {
if (postOnHoverRef.current) {
const rect = postOnHoverRef.current.getBoundingClientRect();
@@ -1329,7 +1357,7 @@ const Subscriptions = () => {
handleOptionClick(reply.cid)}>
Yandex
@@ -1756,7 +1784,96 @@ const Subscriptions = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === thread.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(thread.cid);
+ handleShareClick(selectedAddress, thread.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(thread)}>Edit post
+ - handleAuthorDeleteClick(thread)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(thread.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(thread.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(thread.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(commentMediaInfo && (
+ commentMediaInfo.type === 'image' ||
+ (commentMediaInfo.type === 'webpage' &&
+ commentMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(thread.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{thread.author.displayName
? thread.author.displayName.length > 20
@@ -1993,7 +2110,96 @@ const Subscriptions = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === reply.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(reply.cid);
+ handleShareClick(selectedAddress, reply.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(reply)}>Edit post
+ - handleAuthorDeleteClick(reply)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(replyMediaInfo && (
+ replyMediaInfo.type === 'image' ||
+ (replyMediaInfo.type === 'webpage' &&
+ replyMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{reply.author.displayName
? reply.author.displayName.length > 20
diff --git a/src/components/views/Thread.jsx b/src/components/views/Thread.jsx
index f79be8b0..1f489c4f 100755
--- a/src/components/views/Thread.jsx
+++ b/src/components/views/Thread.jsx
@@ -7,7 +7,7 @@ import { Tooltip } from 'react-tooltip';
import { useAccount, useAccountComments, useComment, usePublishComment, usePublishCommentEdit, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
import { debounce } from 'lodash';
-import { Container, NavBar, Header, Break, PostForm, PostFormTable, PostMenu } from '../styled/views/Board.styled';
+import { Container, NavBar, Header, Break, PostForm, PostFormTable, PostMenu, PostMenuMobile } from '../styled/views/Board.styled';
import { ReplyFormLink, TopBar, BottomBar, BoardForm, Footer } from '../styled/views/Thread.styled';
import { AlertModal } from '../styled/modals/AlertModal.styled';
import { PostMenuCatalog } from '../styled/views/Catalog.styled';
@@ -91,8 +91,11 @@ const Thread = () => {
const commentRef = useRef();
const linkRef = useRef();
const threadMenuRefs = useRef({});
+ const threadMenuRefsMobile = useRef({});
const replyMenuRefs = useRef({});
+ const replyMenuRefsMobile = useRef({});
const postMenuRef = useRef(null);
+ const postMenuMobileRef = useRef(null);
const postMenuCatalogRef = useRef(null);
const backlinkRefs = useRef({});
const quoteRefs = useRef({});
@@ -114,7 +117,9 @@ const Thread = () => {
const [isModerator, setIsModerator] = useState(false);
const [commentCid, setCommentCid] = useState(null);
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
+ const [mobileMenuPosition, setMobileMenuPosition] = useState({top: 0, left: 0});
const [openMenuCid, setOpenMenuCid] = useState(null);
+ const [openMobileMenuCid, setOpenMobileMenuCid] = useState(null);
const [outOfViewCid, setOutOfViewCid] = useState(null);
const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0});
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
@@ -189,12 +194,22 @@ const Thread = () => {
setOpenMenuCid(null);
};
+ const handleMobileOptionClick = () => {
+ setOpenMobileMenuCid(null);
+ };
+
const handleOutsideClick = useCallback((e) => {
if (openMenuCid !== null && !postMenuRef.current.contains(e.target) && !postMenuCatalogRef.current.contains(e.target)) {
setOpenMenuCid(null);
}
}, [openMenuCid, postMenuRef, postMenuCatalogRef]);
+ const handleMobileOutsideClick = useCallback((e) => {
+ if (openMobileMenuCid !== null && !postMenuMobileRef.current.contains(e.target)) {
+ setOpenMobileMenuCid(null);
+ }
+ }, [openMobileMenuCid, postMenuMobileRef]);
+
useEffect(() => {
if (openMenuCid !== null) {
document.addEventListener('click', handleOutsideClick);
@@ -208,6 +223,20 @@ const Thread = () => {
}, [openMenuCid, handleOutsideClick]);
+ useEffect(() => {
+ if (openMobileMenuCid !== null) {
+ document.addEventListener('click', handleMobileOutsideClick);
+ } else {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ }
+
+ return () => {
+ document.removeEventListener('click', handleMobileOutsideClick);
+ };
+ }, [openMobileMenuCid, handleMobileOutsideClick]);
+
+
+
useEffect(() => {
if (postOnHoverRef.current) {
const rect = postOnHoverRef.current.getBoundingClientRect();
@@ -1423,7 +1452,7 @@ const Thread = () => {
handleOptionClick(reply.cid)}>
Yandex
@@ -1737,7 +1766,96 @@ const Thread = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === comment.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(comment.cid);
+ handleShareClick(selectedAddress, comment.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(comment)}>Edit post
+ - handleAuthorDeleteClick(comment)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(comment.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(comment.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(comment.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(comment.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(commentMediaInfo && (
+ commentMediaInfo.type === 'image' ||
+ (commentMediaInfo.type === 'webpage' &&
+ commentMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(comment.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(comment.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(comment.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{comment?.author?.displayName
? comment?.author?.displayName.length > 15
@@ -1940,7 +2058,96 @@ const Thread = () => {
-
+
+ {createPortal(
+
{postMenuMobileRef.current = el}}
+ onClick={(event) => event.stopPropagation()}
+ style={{position: "absolute",
+ display: openMobileMenuCid === reply.cid ? "block" : "none",
+ top: mobileMenuPosition.top + 20,
+ left: mobileMenuPosition.left}}>
+
+ - {
+ handleMobileOptionClick(reply.cid);
+ handleShareClick(selectedAddress, reply.cid)
+ }}>Share thread
+ {({ authorAddress }) => (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ <>
+ - handleAuthorEditClick(reply)}>Edit post
+ - handleAuthorDeleteClick(reply)}>Delete post
+ >
+ ) : null}
+ {isModerator ? (
+ <>
+ {authorAddress === account?.author.address ||
+ authorAddress === account?.signer.address ? (
+ null
+ ) : (
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ setDeletePost(true);
+ }}>
+ Delete post
+
+ )}
+ - {
+ setModeratingCommentCid(reply.cid)
+ setIsModerationOpen(true);
+ handleMobileOptionClick(reply.cid);
+ }}>
+ Mod tools
+
+ >
+ ) : null}
+ >
+ )}
+ {(replyMediaInfo && (
+ replyMediaInfo.type === 'image' ||
+ (replyMediaInfo.type === 'webpage' &&
+ replyMediaInfo.thumbnail))) ? (
+ <>
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Google
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on Yandex
+
+ - handleMobileOptionClick(reply.cid)}>
+ Search image on SauceNAO
+
+ >
+ ) : null
+ }
+
+ , document.body
+ )}
{reply.author?.displayName
? reply.author?.displayName.length > 12