mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat: highlight reply if visible, render it as floating preview if not visible
This commit is contained in:
@@ -287,7 +287,7 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
|
||||
<div key={index} className={styles.replyContainer} ref={(el) => (replyRefs.current[index] = el)}>
|
||||
<div className={styles.replyDesktop}>
|
||||
<div className={styles.sideArrows}>{'>>'}</div>
|
||||
<div className={`${styles.reply} ${isRouteLinkToReply && styles.highlight}`}>
|
||||
<div className={`${styles.reply} ${isRouteLinkToReply && styles.highlight}`} id={reply?.cid}>
|
||||
<PostInfo openReplyModal={openReplyModal} post={reply} roles={roles} />
|
||||
{reply.link && isValidURL(reply.link) && <PostMedia post={reply} />}
|
||||
{reply.content && <PostMessage post={reply} />}
|
||||
|
||||
@@ -232,7 +232,7 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
|
||||
<div key={index} className={styles.replyContainer} ref={(el) => (replyRefs.current[index] = el)}>
|
||||
<div className={styles.replyMobile}>
|
||||
<div className={styles.reply}>
|
||||
<div className={`${styles.replyContainer} ${isRouteLinkToReply && styles.highlight}`}>
|
||||
<div className={`${styles.replyContainer} ${isRouteLinkToReply && styles.highlight}`} id={reply?.cid}>
|
||||
<PostInfoAndMedia openReplyModal={openReplyModal} post={reply} roles={roles} />
|
||||
{reply.content && <PostMessageMobile post={reply} />}
|
||||
<ReplyBacklinks post={reply} />
|
||||
|
||||
@@ -15,8 +15,32 @@ interface ReplyQuotePreviewProps {
|
||||
quotelinkReply?: Comment;
|
||||
}
|
||||
|
||||
const handleQuoteHover = (cid: string, onElementOutOfView: () => void) => {
|
||||
const targetElement = document.getElementById(cid);
|
||||
|
||||
if (!targetElement) return;
|
||||
|
||||
const isInViewport = (element: HTMLElement) => {
|
||||
const bounding = element.getBoundingClientRect();
|
||||
return (
|
||||
bounding.top >= 0 &&
|
||||
bounding.left >= 0 &&
|
||||
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
||||
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
|
||||
);
|
||||
};
|
||||
|
||||
if (isInViewport(targetElement)) {
|
||||
targetElement.classList.add('highlight');
|
||||
} else {
|
||||
targetElement.classList.remove('highlight');
|
||||
onElementOutOfView();
|
||||
}
|
||||
};
|
||||
|
||||
const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQuotelinkReply }: ReplyQuotePreviewProps) => {
|
||||
const [hoveredCid, setHoveredCid] = useState<string | null>(null);
|
||||
const [outOfViewCid, setOutOfViewCid] = useState<string | null>(null);
|
||||
const placementRef = useRef<Placement>('right');
|
||||
const availableWidthRef = useRef<number>(0);
|
||||
|
||||
@@ -56,18 +80,37 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i
|
||||
};
|
||||
}, [update]);
|
||||
|
||||
const handleMouseOver = (cid: string | undefined) => {
|
||||
if (!cid) return;
|
||||
|
||||
handleQuoteHover(cid, () => setOutOfViewCid(cid));
|
||||
setHoveredCid(cid);
|
||||
};
|
||||
|
||||
const handleMouseLeave = (cid: string | null) => {
|
||||
if (cid) {
|
||||
const targetElement = document.getElementById(cid);
|
||||
if (targetElement) {
|
||||
targetElement.classList.remove('highlight');
|
||||
}
|
||||
}
|
||||
setHoveredCid(null);
|
||||
setOutOfViewCid(null);
|
||||
};
|
||||
|
||||
const replyBacklink = (
|
||||
<>
|
||||
<Link
|
||||
className={styles.backlink}
|
||||
to={`/p/${backlinkReply?.subplebbitAddress}/c/${backlinkReply?.cid}`}
|
||||
ref={refs.setReference}
|
||||
onMouseOver={() => setHoveredCid(backlinkReply?.cid)}
|
||||
onMouseLeave={() => setHoveredCid(null)}
|
||||
onMouseOver={() => handleMouseOver(backlinkReply?.cid)}
|
||||
onMouseLeave={() => handleMouseLeave(backlinkReply?.cid)}
|
||||
>
|
||||
c/{backlinkReply?.shortCid}
|
||||
</Link>
|
||||
{hoveredCid === backlinkReply?.cid &&
|
||||
outOfViewCid === backlinkReply?.cid &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={backlinkReply} showReplies={false} />
|
||||
@@ -83,13 +126,14 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i
|
||||
to={`/p/${quotelinkReply?.subplebbitAddress}/c/${quotelinkReply?.cid}`}
|
||||
ref={refs.setReference}
|
||||
className={styles.quoteLink}
|
||||
onMouseOver={() => setHoveredCid(quotelinkReply?.cid)}
|
||||
onMouseLeave={() => setHoveredCid(null)}
|
||||
onMouseOver={() => handleMouseOver(quotelinkReply?.cid)}
|
||||
onMouseLeave={() => handleMouseLeave(quotelinkReply?.cid)}
|
||||
>
|
||||
{`c/${quotelinkReply?.cid && Plebbit.getShortCid(quotelinkReply.cid)}`}
|
||||
</Link>
|
||||
<br />
|
||||
{hoveredCid === quotelinkReply?.cid &&
|
||||
outOfViewCid === quotelinkReply?.cid &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={quotelinkReply} showReplies={false} />
|
||||
@@ -104,6 +148,7 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i
|
||||
|
||||
const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQuotelinkReply }: ReplyQuotePreviewProps) => {
|
||||
const [hoveredCid, setHoveredCid] = useState<string | null>(null);
|
||||
const [outOfViewCid, setOutOfViewCid] = useState<string | null>(null);
|
||||
|
||||
const { refs, floatingStyles, update } = useFloating({
|
||||
placement: 'bottom',
|
||||
@@ -118,15 +163,39 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is
|
||||
};
|
||||
}, [update]);
|
||||
|
||||
const handleMouseOver = (cid: string | undefined) => {
|
||||
if (!cid) return;
|
||||
|
||||
handleQuoteHover(cid, () => setOutOfViewCid(cid));
|
||||
setHoveredCid(cid);
|
||||
};
|
||||
|
||||
const handleMouseLeave = (cid: string | null) => {
|
||||
if (cid) {
|
||||
const targetElement = document.getElementById(cid);
|
||||
if (targetElement) {
|
||||
targetElement.classList.remove('highlight');
|
||||
}
|
||||
}
|
||||
setHoveredCid(null);
|
||||
setOutOfViewCid(null);
|
||||
};
|
||||
|
||||
const replyBacklink = (
|
||||
<>
|
||||
<span className={styles.backlink} ref={refs.setReference} onMouseOver={() => setHoveredCid(backlinkReply?.cid)} onMouseLeave={() => setHoveredCid(null)}>
|
||||
<span
|
||||
className={styles.backlink}
|
||||
ref={refs.setReference}
|
||||
onMouseOver={() => handleMouseOver(backlinkReply?.cid)}
|
||||
onMouseLeave={() => handleMouseLeave(backlinkReply?.cid)}
|
||||
>
|
||||
c/{backlinkReply?.shortCid}{' '}
|
||||
</span>
|
||||
<Link to={`/p/${backlinkReply?.subplebbitAddress}/c/${backlinkReply?.cid}`} className={styles.backlinkHash}>
|
||||
#
|
||||
</Link>
|
||||
{hoveredCid === backlinkReply?.cid &&
|
||||
outOfViewCid === backlinkReply?.cid &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={backlinkReply} showReplies={false} />
|
||||
@@ -138,7 +207,12 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is
|
||||
|
||||
const replyQuotelink = (
|
||||
<>
|
||||
<span ref={refs.setReference} className={styles.quoteLink} onMouseOver={() => setHoveredCid(quotelinkReply?.cid)} onMouseLeave={() => setHoveredCid(null)}>
|
||||
<span
|
||||
ref={refs.setReference}
|
||||
className={styles.quoteLink}
|
||||
onMouseOver={() => handleMouseOver(quotelinkReply?.cid)}
|
||||
onMouseLeave={() => handleMouseLeave(quotelinkReply?.cid)}
|
||||
>
|
||||
c/{quotelinkReply?.shortCid}{' '}
|
||||
</span>
|
||||
<Link className={styles.quoteLink} to={`/p/${quotelinkReply?.subplebbitAddress}/c/${quotelinkReply?.cid}`}>
|
||||
@@ -146,6 +220,7 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is
|
||||
</Link>
|
||||
<br />
|
||||
{hoveredCid === quotelinkReply?.cid &&
|
||||
outOfViewCid === quotelinkReply?.cid &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={quotelinkReply} showReplies={false} />
|
||||
|
||||
@@ -26,6 +26,10 @@ hr {
|
||||
color: var(--post-greentext-color);
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background: var(--reply-highlight-background-color) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.button {
|
||||
font-size: var(--button-font-size-mobile);
|
||||
|
||||
Reference in New Issue
Block a user