fix catalog popup positioning logic

This commit is contained in:
plebeius.eth
2023-09-07 15:50:27 +02:00
parent 6b53ce6f7c
commit 7ef7b1e17a
4 changed files with 203 additions and 138 deletions
@@ -20,17 +20,15 @@ export const Threads = styled.div`
.thread_popup { .thread_popup {
display: inline-block; display: inline-block;
height: auto;
background-color: black; background-color: black;
position: absolute; position: absolute;
margin-top: 0px; margin-top: 0px;
text-align: left; text-align: left;
z-index: 10; z-index: 10;
transform:none;
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
border-radius: 3px; border-radius: 3px;
white-space: nowrap; /* overflow-wrap: break-word; */
} }
.thread_popup_content { .thread_popup_content {
@@ -40,6 +38,7 @@ export const Threads = styled.div`
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
font-size: 13px; font-size: 13px;
white-space: normal;
} }
.thread_popup_lastReply { .thread_popup_lastReply {
@@ -47,7 +46,6 @@ export const Threads = styled.div`
color: #bbbfbd; color: #bbbfbd;
display: block; display: block;
min-width: 250px; min-width: 250px;
text-overflow: ellipsis;
font-size: 90%; font-size: 90%;
} }
+81 -52
View File
@@ -82,10 +82,14 @@ const CatalogPost = ({post}) => {
const imageRef = useRef(null); const imageRef = useRef(null);
const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null); const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null);
const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null); const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null);
const [spaceOnLeft,setSpaceOnLeft] = useState(null);
const [spaceOnRight,setSpaceOnRight] = useState(null);
const [isCalculationDone,setIsCalculationDone] = useState(false); const [isCalculationDone,setIsCalculationDone] = useState(false);
const [hoverTimeoutId, setHoverTimeoutId] = useState(null); const [hoverTimeoutId, setHoverTimeoutId] = useState(null);
const [isHoveringForMenu, setIsHoveringForMenu] = useState(false);
const textRect = textRef.current?.getBoundingClientRect(); const textRect = textRef.current?.getBoundingClientRect();
const imageRect = imageRef.current?.getBoundingClientRect(); const imageRect = imageRef.current?.getBoundingClientRect();
const popupRect = popupRef.current?.getBoundingClientRect();
const isMediaShowed = (thread.link && commentMediaInfo && ( const isMediaShowed = (thread.link && commentMediaInfo && (
commentMediaInfo.type === 'image' || commentMediaInfo.type === 'image' ||
commentMediaInfo.type === 'video' || commentMediaInfo.type === 'video' ||
@@ -95,31 +99,38 @@ const CatalogPost = ({post}) => {
commentMediaInfo.thumbnail))) ? true : false; commentMediaInfo.thumbnail))) ? true : false;
useLayoutEffect(() => { useLayoutEffect(() => {
const executeLayoutEffectLogic = () => { const executeLayoutEffectLogic = () => {
let ref; let ref;
ref = threadRefs.current[isHoveringOnThread]; if (isMediaShowed) {
ref = imageRef.current;
if (ref && popupRef.current) { } else {
const threadRect = ref.getBoundingClientRect(); ref = textRef.current;
const popupRect = popupRef.current.getBoundingClientRect(); }
const viewportWidth = document.documentElement.clientWidth;
const spaceOnRight = viewportWidth - (threadRect.left + threadRect.width); if (ref && popupRef.current) {
const spaceOnLeft = threadRect.left; const threadRect = ref.getBoundingClientRect();
const popupWidth = popupRect.width; const viewportWidth = document.documentElement.clientWidth;
setIsEnoughSpaceOnLeft(spaceOnLeft >= popupWidth + 10); const spaceRight = viewportWidth - (threadRect.left + threadRect.width);
setIsEnoughSpaceOnRight(spaceOnRight >= popupWidth + 10); const spaceLeft = threadRect.left;
setIsCalculationDone(true); setIsEnoughSpaceOnLeft(spaceLeft > 500);
setIsEnoughSpaceOnRight(spaceRight > 500);
setSpaceOnRight(spaceRight);
setSpaceOnLeft(spaceLeft);
setIsCalculationDone(true);
}
};
if (isHoveringOnThread) {
const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
return () => {
clearTimeout(timeoutId);
setIsCalculationDone(false);
};
} }
};
}, [isHoveringOnThread, isMediaShowed]);
if (isHoveringOnThread) {
const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
return () => clearTimeout(timeoutId);
}
}, [isHoveringOnThread]);
const handleMouseOnLeaveThread = () => { const handleMouseOnLeaveThread = () => {
if (hoverTimeoutId) { if (hoverTimeoutId) {
@@ -343,42 +354,45 @@ const CatalogPost = ({post}) => {
onMouseLeave={() => {handleMouseOnLeaveThread()}}> onMouseLeave={() => {handleMouseOnLeaveThread()}}>
{isHoveringOnThread === thread.cid ? {isHoveringOnThread === thread.cid ?
<div ref={popupRef} <div ref={popupRef}
className="thread_popup"
onMouseOver={() => handleMouseOnLeaveThread()} onMouseOver={() => handleMouseOnLeaveThread()}
style={{ style={{
opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0, opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0,
visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden', visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden',
left: isCalculationDone && isEnoughSpaceOnRight !== null && isEnoughSpaceOnRight left:
isCalculationDone && isEnoughSpaceOnRight !== null && popupRect.width < spaceOnRight
? isMediaShowed ? isMediaShowed
? `calc(50% + ${imageRect.width}px / 2 + 5px)` ? `calc(50% + ${imageRect.width}px / 2 + 5px)`
: `calc(50% + ${textRect.width}px / 2 + 5px)` : `calc(50% + ${textRect.width}px / 2 + 5px)`
: 'auto', : 'auto',
right: isCalculationDone && isEnoughSpaceOnRight !== null && !isEnoughSpaceOnRight right:
? isMediaShowed isCalculationDone && isEnoughSpaceOnRight !== null &&
? `calc(50% + ${imageRect.width}px / 2 + 5px)` (popupRect.width > spaceOnRight && spaceOnLeft > spaceOnRight)
: `calc(50% + ${textRect.width}px / 2 + 5px)` ? isMediaShowed
? `calc(50% + ${imageRect.width}px / 2 + 5px)`
: `calc(50% + ${textRect.width}px / 2 + 5px)`
: 'auto', : 'auto',
}} }}>
className="thread_popup">
<p <p
style={isEnoughSpaceOnLeft !== null && !isEnoughSpaceOnLeft className="thread_popup_content"
&& !isEnoughSpaceOnRight style={{ width: !isEnoughSpaceOnLeft && !isEnoughSpaceOnRight ? (
? spaceOnLeft > spaceOnRight ? `${spaceOnLeft}px` :
{overflow:"visible",whiteSpace:"normal"} spaceOnLeft < spaceOnRight ? `${spaceOnRight}px` : 'auto') : 'auto'
: null} }}>
className="thread_popup_content"> <span className="thread_popup_title" >
<span className="thread_popup_title" > {thread.title ? `${thread.title} ` : "Posted "}
{thread.title ? `${thread.title} ` : "Posted "} </span>
</span> by
by <span className="thread_popup_author">
<span className="thread_popup_author"> {thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
{thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "} </span>
</span>
{thread.timestamp ? getFormattedTime(thread.timestamp) : null} {thread.timestamp ? getFormattedTime(thread.timestamp) : null}
</p> </p>
<div> <div>
{thread.replyCount > 0 ? {thread.replyCount > 0 ?
<p className="thread_popup_lastReply"> <p className="thread_popup_lastReply">
Last reply by <span className="thread_popup_author"> Anonymous </span> Last reply by
<span className="thread_popup_author"> Anonymous </span>
{getFormattedTime(thread.lastReplyTimestamp)} {getFormattedTime(thread.lastReplyTimestamp)}
</p> </p>
: null} : null}
@@ -387,7 +401,12 @@ const CatalogPost = ({post}) => {
: null } : null }
{commentMediaInfo?.url ? ( {commentMediaInfo?.url ? (
<Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} <Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`}
onClick={() => setSelectedThread(thread.cid)} onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}> onClick={() => setSelectedThread(thread.cid)}
onMouseOver={() => {
setIsHoveringOnThread(thread.cid);
setIsHoveringForMenu(thread.cid);
}}
onMouseLeave={() => setIsHoveringForMenu(false)}>
{commentMediaInfo?.type === "webpage" ? ( {commentMediaInfo?.type === "webpage" ? (
thread.thumbnailUrl ? ( thread.thumbnailUrl ? (
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}> <span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
@@ -446,7 +465,12 @@ const CatalogPost = ({post}) => {
tooltipPlace="top" /> tooltipPlace="top" />
)} )}
</div> </div>
<BoardForm selectedStyle={selectedStyle} onMouseOver={() => handleMouseOnLeaveThread()} <BoardForm selectedStyle={selectedStyle}
onMouseOver={() => {
setIsHoveringForMenu(thread.cid);
handleMouseOnLeaveThread();
}}
onMouseLeave={() => setIsHoveringForMenu(false)}
style={{ all: "unset"}}> style={{ all: "unset"}}>
<div key={`meta-`} className="meta" title="(R)eplies / (L)ink Replies" > <div key={`meta-`} className="meta" title="(R)eplies / (L)ink Replies" >
R:&nbsp;<b key={`b-`}>{thread.replyCount}</b> R:&nbsp;<b key={`b-`}>{thread.replyCount}</b>
@@ -457,7 +481,7 @@ const CatalogPost = ({post}) => {
</> </>
) : null} ) : null}
<PostMenu <PostMenu
style={{ display: isHoveringOnThread === thread.cid ? 'inline-block' : 'none', style={{ display: isHoveringForMenu === thread.cid ? 'inline-block' : 'none',
position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none', position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none',
zIndex: '999'}} zIndex: '999'}}
key={`pmb-`} key={`pmb-`}
@@ -599,7 +623,12 @@ const CatalogPost = ({post}) => {
onClick={() => setSelectedThread(thread.cid)}> onClick={() => setSelectedThread(thread.cid)}>
<div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}} <div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}}
ref={(el) => (threadRefs.current[thread.cid] = el)}> ref={(el) => (threadRefs.current[thread.cid] = el)}>
<span key={`teaser-width${thread.cid}`} ref={textRef} onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}> <span key={`teaser-width${thread.cid}`} ref={textRef}
onMouseOver={() => {
setIsHoveringOnThread(thread.cid);
setIsHoveringForMenu(thread.cid);
}}
onMouseLeave={() => setIsHoveringForMenu(false)}>
<b key={`b2-`}>{thread.title ? `${thread.title}` : null}</b> <b key={`b2-`}>{thread.title ? `${thread.title}` : null}</b>
{thread.content ? `: ${thread.content}` : null} {thread.content ? `: ${thread.content}` : null}
</span> </span>
+40 -30
View File
@@ -90,11 +90,14 @@ const CatalogPost = ({post}) => {
const imageRef = useRef(null); const imageRef = useRef(null);
const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null); const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null);
const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null); const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null);
const [spaceOnLeft,setSpaceOnLeft] = useState(null);
const [spaceOnRight,setSpaceOnRight] = useState(null);
const [isCalculationDone,setIsCalculationDone] = useState(false); const [isCalculationDone,setIsCalculationDone] = useState(false);
const [hoverTimeoutId, setHoverTimeoutId] = useState(null); const [hoverTimeoutId, setHoverTimeoutId] = useState(null);
const [isHoveringForMenu, setIsHoveringForMenu] = useState(false); const [isHoveringForMenu, setIsHoveringForMenu] = useState(false);
const textRect = textRef.current?.getBoundingClientRect(); const textRect = textRef.current?.getBoundingClientRect();
const imageRect = imageRef.current?.getBoundingClientRect(); const imageRect = imageRef.current?.getBoundingClientRect();
const popupRect = popupRef.current?.getBoundingClientRect();
const isMediaShowed = (thread.link && commentMediaInfo && ( const isMediaShowed = (thread.link && commentMediaInfo && (
commentMediaInfo.type === 'image' || commentMediaInfo.type === 'image' ||
commentMediaInfo.type === 'video' || commentMediaInfo.type === 'video' ||
@@ -106,31 +109,34 @@ const CatalogPost = ({post}) => {
useLayoutEffect(() => { useLayoutEffect(() => {
const executeLayoutEffectLogic = () => { const executeLayoutEffectLogic = () => {
let ref; let ref;
if (isHoveringOnThread === 'rules' || isHoveringOnThread === 'description') { if (isMediaShowed) {
ref = popupRef.current; ref = imageRef.current;
} else { } else {
ref = threadRefs.current[isHoveringOnThread]; ref = textRef.current;
} }
if (ref && popupRef.current) { if (ref && popupRef.current) {
const threadRect = ref.getBoundingClientRect(); const threadRect = ref.getBoundingClientRect();
const popupRect = popupRef.current.getBoundingClientRect();
const viewportWidth = document.documentElement.clientWidth; const viewportWidth = document.documentElement.clientWidth;
const spaceOnRight = viewportWidth - (threadRect.left + threadRect.width); const spaceRight = viewportWidth - (threadRect.left + threadRect.width);
const spaceOnLeft = threadRect.left; const spaceLeft = threadRect.left;
const popupWidth = popupRect.width; setIsEnoughSpaceOnLeft(spaceLeft > 500);
setIsEnoughSpaceOnLeft(spaceOnLeft >= popupWidth + 10); setIsEnoughSpaceOnRight(spaceRight > 500);
setIsEnoughSpaceOnRight(spaceOnRight >= popupWidth + 10); setSpaceOnRight(spaceRight);
setSpaceOnLeft(spaceLeft);
setIsCalculationDone(true); setIsCalculationDone(true);
} }
}; };
if (isHoveringOnThread) { if (isHoveringOnThread) {
const timeoutId = setTimeout(executeLayoutEffectLogic, 250); const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
return () => clearTimeout(timeoutId); return () => {
clearTimeout(timeoutId);
setIsCalculationDone(false);
};
} }
}, [isHoveringOnThread]); }, [isHoveringOnThread, isMediaShowed]);
const handleMouseOnLeaveThread = () => { const handleMouseOnLeaveThread = () => {
@@ -588,30 +594,31 @@ const CatalogPost = ({post}) => {
onMouseLeave={()=>{handleMouseOnLeaveThread()}}> onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
{isHoveringOnThread === thread.cid ? {isHoveringOnThread === thread.cid ?
<div ref={popupRef} <div ref={popupRef}
className="thread_popup"
onMouseOver={() => handleMouseOnLeaveThread()} onMouseOver={() => handleMouseOnLeaveThread()}
style={{ style={{
opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0, opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0,
visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden', visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden',
left: isCalculationDone && isEnoughSpaceOnRight !== null && isEnoughSpaceOnRight left:
isCalculationDone && isEnoughSpaceOnRight !== null && popupRect.width < spaceOnRight
? isMediaShowed ? isMediaShowed
? `calc(50% + ${imageRect.width}px / 2 + 5px)` ? `calc(50% + ${imageRect.width}px / 2 + 5px)`
: `calc(50% + ${textRect.width}px / 2 + 5px)` : `calc(50% + ${textRect.width}px / 2 + 5px)`
: 'auto', : 'auto',
right: isCalculationDone && isEnoughSpaceOnRight !== null && !isEnoughSpaceOnRight right:
? isMediaShowed isCalculationDone && isEnoughSpaceOnRight !== null &&
? `calc(50% + ${imageRect.width}px / 2 + 5px)` (popupRect.width > spaceOnRight && spaceOnLeft > spaceOnRight)
: `calc(50% + ${textRect.width}px / 2 + 5px)` ? isMediaShowed
? `calc(50% + ${imageRect.width}px / 2 + 5px)`
: `calc(50% + ${textRect.width}px / 2 + 5px)`
: 'auto', : 'auto',
}} }}>
className="thread_popup">
<p <p
style={isEnoughSpaceOnLeft !== null && !isEnoughSpaceOnLeft className="thread_popup_content"
&& !isEnoughSpaceOnRight style={{ width: !isEnoughSpaceOnLeft && !isEnoughSpaceOnRight ? (
? spaceOnLeft > spaceOnRight ? `${spaceOnLeft}px` :
{overflow:"visible",whiteSpace:"normal"} spaceOnLeft < spaceOnRight ? `${spaceOnRight}px` : 'auto') : 'auto'
: null }}>
}
className="thread_popup_content">
<span className="thread_popup_title" > <span className="thread_popup_title" >
{thread.title ? `${thread.title} ` : "Posted "} {thread.title ? `${thread.title} ` : "Posted "}
</span> </span>
@@ -619,12 +626,15 @@ const CatalogPost = ({post}) => {
<span className="thread_popup_author"> <span className="thread_popup_author">
{thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "} {thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
</span> </span>
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}</p> {thread.timestamp ? getFormattedTime(thread.timestamp) : null}
</p>
<div> <div>
{thread.replyCount > 0 ? {thread.replyCount > 0 ?
<p className="thread_popup_lastReply"> <p className="thread_popup_lastReply">
Last reply by <span className="thread_popup_author"> Anonymous </span> Last reply by
{getFormattedTime(thread.lastReplyTimestamp)}</p> <span className="thread_popup_author"> Anonymous </span>
{getFormattedTime(thread.lastReplyTimestamp)}
</p>
: null} : null}
</div> </div>
</div> </div>
+80 -52
View File
@@ -82,10 +82,14 @@ const CatalogPost = ({post}) => {
const imageRef = useRef(null); const imageRef = useRef(null);
const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null); const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null);
const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null); const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null);
const [spaceOnLeft,setSpaceOnLeft] = useState(null);
const [spaceOnRight,setSpaceOnRight] = useState(null);
const [isCalculationDone,setIsCalculationDone] = useState(false); const [isCalculationDone,setIsCalculationDone] = useState(false);
const [hoverTimeoutId, setHoverTimeoutId] = useState(null); const [hoverTimeoutId, setHoverTimeoutId] = useState(null);
const [isHoveringForMenu, setIsHoveringForMenu] = useState(false);
const textRect = textRef.current?.getBoundingClientRect(); const textRect = textRef.current?.getBoundingClientRect();
const imageRect = imageRef.current?.getBoundingClientRect(); const imageRect = imageRef.current?.getBoundingClientRect();
const popupRect = popupRef.current?.getBoundingClientRect();
const isMediaShowed = (thread.link && commentMediaInfo && ( const isMediaShowed = (thread.link && commentMediaInfo && (
commentMediaInfo.type === 'image' || commentMediaInfo.type === 'image' ||
commentMediaInfo.type === 'video' || commentMediaInfo.type === 'video' ||
@@ -95,30 +99,37 @@ const CatalogPost = ({post}) => {
commentMediaInfo.thumbnail))) ? true : false; commentMediaInfo.thumbnail))) ? true : false;
useLayoutEffect(() => { useLayoutEffect(() => {
const executeLayoutEffectLogic = () => { const executeLayoutEffectLogic = () => {
let ref; let ref;
ref = threadRefs.current[isHoveringOnThread]; if (isMediaShowed) {
ref = imageRef.current;
if (ref && popupRef.current) { } else {
const threadRect = ref.getBoundingClientRect(); ref = textRef.current;
const popupRect = popupRef.current.getBoundingClientRect(); }
const viewportWidth = document.documentElement.clientWidth;
const spaceOnRight = viewportWidth - (threadRect.left + threadRect.width); if (ref && popupRef.current) {
const spaceOnLeft = threadRect.left; const threadRect = ref.getBoundingClientRect();
const popupWidth = popupRect.width; const viewportWidth = document.documentElement.clientWidth;
setIsEnoughSpaceOnLeft(spaceOnLeft >= popupWidth + 10); const spaceRight = viewportWidth - (threadRect.left + threadRect.width);
setIsEnoughSpaceOnRight(spaceOnRight >= popupWidth + 10); const spaceLeft = threadRect.left;
setIsCalculationDone(true); setIsEnoughSpaceOnLeft(spaceLeft > 500);
setIsEnoughSpaceOnRight(spaceRight > 500);
setSpaceOnRight(spaceRight);
setSpaceOnLeft(spaceLeft);
setIsCalculationDone(true);
}
};
if (isHoveringOnThread) {
const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
return () => {
clearTimeout(timeoutId);
setIsCalculationDone(false);
};
} }
};
}, [isHoveringOnThread, isMediaShowed]);
if (isHoveringOnThread) {
const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
return () => clearTimeout(timeoutId);
}
}, [isHoveringOnThread]);
const handleMouseOnLeaveThread = () => { const handleMouseOnLeaveThread = () => {
@@ -343,43 +354,45 @@ const CatalogPost = ({post}) => {
onMouseLeave={() => {handleMouseOnLeaveThread()}}> onMouseLeave={() => {handleMouseOnLeaveThread()}}>
{isHoveringOnThread === thread.cid ? {isHoveringOnThread === thread.cid ?
<div ref={popupRef} <div ref={popupRef}
className="thread_popup"
onMouseOver={() => handleMouseOnLeaveThread()} onMouseOver={() => handleMouseOnLeaveThread()}
style={{ style={{
opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0, opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0,
visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden', visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden',
left: isCalculationDone && isEnoughSpaceOnRight !== null && isEnoughSpaceOnRight left:
isCalculationDone && isEnoughSpaceOnRight !== null && popupRect.width < spaceOnRight
? isMediaShowed ? isMediaShowed
? `calc(50% + ${imageRect.width}px / 2 + 5px)` ? `calc(50% + ${imageRect.width}px / 2 + 5px)`
: `calc(50% + ${textRect.width}px / 2 + 5px)` : `calc(50% + ${textRect.width}px / 2 + 5px)`
: 'auto', : 'auto',
right: isCalculationDone && isEnoughSpaceOnRight !== null && !isEnoughSpaceOnRight right:
? isMediaShowed isCalculationDone && isEnoughSpaceOnRight !== null &&
? `calc(50% + ${imageRect.width}px / 2 + 5px)` (popupRect.width > spaceOnRight && spaceOnLeft > spaceOnRight)
: `calc(50% + ${textRect.width}px / 2 + 5px)` ? isMediaShowed
? `calc(50% + ${imageRect.width}px / 2 + 5px)`
: `calc(50% + ${textRect.width}px / 2 + 5px)`
: 'auto', : 'auto',
}} }}>
className="thread_popup">
<p <p
style={isEnoughSpaceOnLeft !== null && !isEnoughSpaceOnLeft className="thread_popup_content"
&& !isEnoughSpaceOnRight style={{ width: !isEnoughSpaceOnLeft && !isEnoughSpaceOnRight ? (
? spaceOnLeft > spaceOnRight ? `${spaceOnLeft}px` :
{overflow:"visible",whiteSpace:"normal"} spaceOnLeft < spaceOnRight ? `${spaceOnRight}px` : 'auto') : 'auto'
: null }}>
} <span className="thread_popup_title" >
className="thread_popup_content"> {thread.title ? `${thread.title} ` : "Posted "}
<span className="thread_popup_title" > </span>
{thread.title ? `${thread.title} ` : "Posted "} by
</span> <span className="thread_popup_author">
by {thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
<span className="thread_popup_author"> </span>
{thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
</span>
{thread.timestamp ? getFormattedTime(thread.timestamp) : null} {thread.timestamp ? getFormattedTime(thread.timestamp) : null}
</p> </p>
<div> <div>
{thread.replyCount > 0 ? {thread.replyCount > 0 ?
<p className="thread_popup_lastReply"> <p className="thread_popup_lastReply">
Last reply by <span className="thread_popup_author"> Anonymous </span> Last reply by
<span className="thread_popup_author"> Anonymous </span>
{getFormattedTime(thread.lastReplyTimestamp)} {getFormattedTime(thread.lastReplyTimestamp)}
</p> </p>
: null} : null}
@@ -388,7 +401,12 @@ const CatalogPost = ({post}) => {
: null } : null }
{commentMediaInfo?.url ? ( {commentMediaInfo?.url ? (
<Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} <Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`}
onClick={() => setSelectedThread(thread.cid)} onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}> onClick={() => setSelectedThread(thread.cid)}
onMouseOver={() => {
setIsHoveringOnThread(thread.cid);
setIsHoveringForMenu(thread.cid);
}}
onMouseLeave={() => setIsHoveringForMenu(false)}>
{commentMediaInfo?.type === "webpage" ? ( {commentMediaInfo?.type === "webpage" ? (
thread.thumbnailUrl ? ( thread.thumbnailUrl ? (
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}> <span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
@@ -447,7 +465,12 @@ const CatalogPost = ({post}) => {
tooltipPlace="top" /> tooltipPlace="top" />
)} )}
</div> </div>
<BoardForm selectedStyle={selectedStyle} onMouseOver={() => handleMouseOnLeaveThread()} <BoardForm selectedStyle={selectedStyle}
onMouseOver={() => {
setIsHoveringForMenu(thread.cid);
handleMouseOnLeaveThread();
}}
onMouseLeave={() => setIsHoveringForMenu(false)}
style={{ all: "unset"}}> style={{ all: "unset"}}>
<div key={`meta-`} className="meta" title="(R)eplies / (L)ink Replies" > <div key={`meta-`} className="meta" title="(R)eplies / (L)ink Replies" >
R:&nbsp;<b key={`b-`}>{thread.replyCount}</b> R:&nbsp;<b key={`b-`}>{thread.replyCount}</b>
@@ -458,7 +481,7 @@ const CatalogPost = ({post}) => {
</> </>
) : null} ) : null}
<PostMenu <PostMenu
style={{ display: isHoveringOnThread === thread.cid ? 'inline-block' : 'none', style={{ display: isHoveringForMenu === thread.cid ? 'inline-block' : 'none',
position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none', position: 'absolute', lineHeight: '1em', marginTop: '-1px', outline: 'none',
zIndex: '999'}} zIndex: '999'}}
key={`pmb-`} key={`pmb-`}
@@ -600,7 +623,12 @@ const CatalogPost = ({post}) => {
onClick={() => setSelectedThread(thread.cid)}> onClick={() => setSelectedThread(thread.cid)}>
<div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}} <div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}}
ref={(el) => (threadRefs.current[thread.cid] = el)}> ref={(el) => (threadRefs.current[thread.cid] = el)}>
<span key={`teaser-width${thread.cid}`} ref={textRef} onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}> <span key={`teaser-width${thread.cid}`} ref={textRef}
onMouseOver={() => {
setIsHoveringOnThread(thread.cid);
setIsHoveringForMenu(thread.cid);
}}
onMouseLeave={() => setIsHoveringForMenu(false)}>
<b key={`b2-`}>{thread.title ? `${thread.title}` : null}</b> <b key={`b2-`}>{thread.title ? `${thread.title}` : null}</b>
{thread.content ? `: ${thread.content}` : null} {thread.content ? `: ${thread.content}` : null}
</span> </span>