implement PostOnHover component

This commit is contained in:
Tom
2023-06-03 16:33:59 +02:00
parent 98f000b173
commit 97e95005d3
6 changed files with 495 additions and 72 deletions
+77 -24
View File
@@ -1,4 +1,4 @@
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate, useParams } from 'react-router-dom';
@@ -19,6 +19,7 @@ import ModerationModal from '../modals/ModerationModal';
import OfflineIndicator from '../OfflineIndicator';
import Post from '../Post';
import PostLoader from '../PostLoader';
import PostOnHover from '../PostOnHover';
import StateLabel from '../StateLabel';
import ReplyModal from '../modals/ReplyModal';
import SettingsModal from '../modals/SettingsModal';
@@ -74,8 +75,9 @@ const Board = () => {
const linkRef = useRef();
const threadMenuRefs = useRef({});
const replyMenuRefs = useRef({});
const postMenuRef = useRef(null);
const postMenuCatalogRef = useRef(null);
const threadBacklinkRefs = useRef({});
const postOnHoverRef = useRef(null);
const { feed, hasMore, loadMore } = useFeed({subplebbitAddresses: [`${selectedAddress}`], sortType: 'new'});
const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress});
@@ -97,6 +99,8 @@ const Board = () => {
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
const [openMenuCid, setOpenMenuCid] = useState(null);
const [outOfViewCid, setOutOfViewCid] = useState(null);
const [outOfViewPosition, setOutOfViewPosition] = useState({top: 0, left: 0});
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
const [errorMessage, setErrorMessage] = useState(null);
const [successMessage, setSuccessMessage] = useState(null);
@@ -122,10 +126,10 @@ const Board = () => {
};
const handleOutsideClick = useCallback((e) => {
if (openMenuCid !== null && !postMenuRef.current.contains(e.target) && !postMenuCatalogRef.current.contains(e.target)) {
if (openMenuCid !== null && !postMenuCatalogRef.current.contains(e.target)) {
setOpenMenuCid(null);
}
}, [openMenuCid, postMenuRef, postMenuCatalogRef]);
}, [openMenuCid, postMenuCatalogRef]);
useEffect(() => {
@@ -524,6 +528,13 @@ const Board = () => {
}
};
useLayoutEffect(() => {
if (postOnHoverRef.current) {
const rect = postOnHoverRef.current.getBoundingClientRect();
setPostOnHoverHeight(rect.height);
}
}, [outOfViewCid]);
return (
<>
@@ -872,8 +883,7 @@ const Board = () => {
key={`pmb-${index}`}
title="Post menu"
ref={el => {
threadMenuRefs.current[thread.cid] = el;
postMenuRef.current = el;
threadMenuRefs.current[thread.cid] = el;
}}
className='post-menu-button'
rotated={openMenuCid === thread.cid}
@@ -968,17 +978,31 @@ const Board = () => {
{thread.replies?.pages?.topAll.comments
.sort((a, b) => a.timestamp - b.timestamp)
.map((reply, index) => (
<div key={`div-${index}`} style={{display: 'inline-block'}}>
<Link key={`ql-${index}`}
to={() => {}} className="quote-link"
onClick={(event) => handleQuoteClick(reply, null, event)}
onMouseOver={() => handleQuoteHover(reply, null, (cid) => setOutOfViewCid(cid))}
onMouseLeave={() => {
removeHighlight();
setOutOfViewCid(null);
<div key={`div-${index}`} style={{display: 'inline-block'}}
ref={el => {
threadBacklinkRefs.current[reply.cid] = el;
}}>
c/{reply.shortCid}</Link>
&nbsp;
<Link key={`ql-${index}`}
to={() => {}}
className="quote-link"
onClick={(event) => handleQuoteClick(reply, null, event)}
onMouseOver={(event) => {
event.stopPropagation();
handleQuoteHover(reply, null, () => {
setOutOfViewCid(reply.cid);
const rect = threadBacklinkRefs.current[reply.cid].getBoundingClientRect();
setOutOfViewPosition({
top: rect.top + window.scrollY - rect.height / 2,
left: rect.left + rect.width + 5,
});
});
}}
onMouseLeave={() => {
removeHighlight();
setOutOfViewCid(null);
}}>
c/{reply.shortCid}</Link>
&nbsp;
</div>
))
}
@@ -1098,7 +1122,6 @@ const Board = () => {
title="Post menu"
ref={el => {
replyMenuRefs.current[reply.cid] = el;
postMenuRef.current = el;
}}
className='post-menu-button'
rotated={openMenuCid === reply.cid}
@@ -1189,16 +1212,29 @@ const Board = () => {
</div>
</PostMenuCatalog>, document.body
)}
<div id="backlink-id" className="backlink">
<div key={`bi-${index}`} id="backlink-id" className="backlink">
{reply.replies?.pages?.topAll.comments
.sort((a, b) => a.timestamp - b.timestamp)
.map((reply, index) => (
<div key={`div-${index}`} style={{display: 'inline-block'}}>
<Link to={() => {}} key={`ql-${index}`}
className="quote-link"
onClick={(event) => handleQuoteClick(reply, reply.shortCid, event)}
onMouseOver={() => handleQuoteHover(reply, reply.shortCid, (cid) => setOutOfViewCid(cid))}
onMouseLeave={() => {
<div key={`div-${index}`} style={{display: 'inline-block'}}
ref={el => {
threadBacklinkRefs.current[reply.cid] = el;
}}>
<Link key={`ql-${index}`}
to={() => {}} className="quote-link"
onClick={(event) => handleQuoteClick(reply, null, event)}
onMouseOver={(event) => {
event.stopPropagation();
handleQuoteHover(reply, null, () => {
setOutOfViewCid(reply.cid);
const rect = threadBacklinkRefs.current[reply.cid].getBoundingClientRect();
setOutOfViewPosition({
top: rect.top + window.scrollY - rect.height / 2,
left: rect.left + rect.width + 5,
});
});
}}
onMouseLeave={() => {
removeHighlight();
setOutOfViewCid(null);
}}>
@@ -1672,6 +1708,23 @@ const Board = () => {
) : (<PostLoader />)
)}
</div>
{createPortal(
<div
ref={postOnHoverRef}
style={{
display: outOfViewCid ? "block" : "none",
position: "absolute",
top: outOfViewPosition.top - postOnHoverHeight / 2 + 10,
left: outOfViewPosition.left,
}}
>
<PostOnHover
cid={outOfViewCid}
feed={feed}
/>
</div>
, document.body
)}
</BoardForm>
<Footer selectedStyle={selectedStyle}>
<Break id="break" selectedStyle={selectedStyle} style={{