Fetched upstream

This commit is contained in:
ThaungThanHan
2023-08-22 21:45:23 +07:00
parent 353d533ba0
commit 387c839b48
4 changed files with 62480 additions and 11070 deletions
+51450
View File
File diff suppressed because it is too large Load Diff
+113 -30
View File
@@ -4,20 +4,58 @@ export const Threads = styled.div`
padding: 20px 0; padding: 20px 0;
text-align: center; text-align: center;
margin: 0; margin: 0;
overflow:hidden;
.thread { .thread {
width: 180px; width: 180px;
position:relative;
position:relative;
max-height: 320px; max-height: 320px;
vertical-align: top; vertical-align: top;
display: inline-block; display: inline-block;
word-wrap: break-word; word-wrap: break-word;
overflow: hidden;
margin-top: 5px; margin-top: 5px;
margin-bottom: 20px; margin-bottom: 20px;
padding: 5px 0 3px; padding: 5px 0 3px;
position: relative;
} }
.thread_popup{
display: inline-block;
height:auto;
background-color:black;
position:absolute;
margin-top:0px;
text-align:left;
z-index:10;
transform:none;
padding-left:5px;padding-right:5px;
border-radius:3px;
}
.thread_popup_content{
color: #dedede;
display: inline-block;
overflow: hidden;
white-space:nowrap;
font-size:13px;
}
.thread_popup_lastReply{
color: #bbbfbd;
display: block;
width: auto;
min-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
font-size:90%;
}
.thread_popup_title{
color:#a89baa
}
.thread_popup_author{
color:#519860;font-weight:bold
}
.thread_popup_authorAdmin{
color:#682071;
}
video, audio, img { video, audio, img {
max-width: 150px; max-width: 150px;
max-height: 150px; max-height: 150px;
@@ -91,20 +129,83 @@ export const Threads = styled.div`
.teaser { .teaser {
display: block; display: block;
padding: 0 15px; padding: 0 15px;
height:200px;
overflow:hidden;
} }
${({ selectedStyle }) => { ${({ selectedStyle }) => {
switch (selectedStyle) { switch (selectedStyle) {
case 'Tomorrow': case 'Yotsuba':
return ` return `
.file-thumb { .thread_popup_title{
background-color: rgba(255, 255, 255, 0.01) !important; color:#cc1105;
font-weight:700;
};
.thread_popup_author{
color:#00a550;font-weight:bold
}`;
case 'Yotsuba-B':
return `
.thread_popup_title{
color:#dedede;
font-weight:700;
};
.thread_popup_author{
color:#00a550;font-weight:bold
}`;
case 'Futaba':
return `
.thread_popup{
font-family: arial,helvetica,sans-serif;
} }
`; .thread_popup_title{
color:#cc1105;
font-weight:700;
};
.thread_popup_author{
color:#00a550;font-weight:700;
}`;
case 'Burichan':
return `
.thread_popup{
font-family: arial,helvetica,sans-serif;
}
.thread_popup_title{
color:#dedede;
font-weight:700;
};
.thread_popup_author{
color:#00a550;font-weight:700;
}`;
case 'Tomorrow':
return `
.thread_popup{
font-family: arial,helvetica,sans-serif;
}
.file-thumb {
background-color: rgba(255, 255, 255, 0.01) !important;
}
.thread_popup_title{
color:#b294bb;
font-weight:700;
};
.thread_popup_author{
color:#00a550;font-weight:700;
}`;
case 'Photon':
return `
.thread_popup{
font-family: arial,helvetica,sans-serif;
}
.thread_popup_title{
color:#dedede;
font-weight:700;
};
.thread_popup_author{
color:#00a550;font-weight:700;
}`;
default: default:
return ''; return '';
} }}}
}}
`; `;
export const PostMenuCatalog = styled.div` export const PostMenuCatalog = styled.div`
@@ -142,27 +243,9 @@ export const PostMenuCatalog = styled.div`
${({ selectedStyle }) => { ${({ selectedStyle }) => {
switch (selectedStyle) { switch (selectedStyle) {
case 'Yotsuba': case 'Yotsuba':
return `.highlighted, .highlighted-click, .highlighted-address { return `.thread_popup_title{
background-color: #f0c0b0 !important; color:red;
border: 1px solid #d99f91 !important; }`;
border-left: none !important;
border-top: none !important;
}
.post-menu-catalog {
border-right: 1px solid #d9bfb7;
border-bottom: 2px solid #d9bfb7;
li {
border: 1px solid #d9bfb7;
border-bottom: none;
background-color: #f0e0d6;
:hover {
background-color: #ffe;
}
}
}`;
case 'Yotsuba-B': case 'Yotsuba-B':
return `.highlighted, .highlighted-click, .highlighted-address { return `.highlighted, .highlighted-click, .highlighted-address {
+141 -9
View File
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import React, { useCallback,useLayoutEffect, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async'; import { Helmet } from 'react-helmet-async';
import { Link, useNavigate, useParams } from 'react-router-dom'; import { Link, useNavigate, useParams } from 'react-router-dom';
@@ -81,6 +81,67 @@ const CatalogPost = ({post}) => {
const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress}); const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress});
const account = useAccount(); const account = useAccount();
const popupRef = useRef(null);
const threadRefs = useRef([]);
const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null);
const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null);
const [isCalculationDone,setIsCalculationDone] = useState(false);
useLayoutEffect(() => {
setIsEnoughSpaceOnRight(null);
setIsEnoughSpaceOnLeft(null);
const calculateSpaceOnRight = () => {
if (thread.cid === isHoveringOnThread){
if(threadRefs.current[thread.cid] && popupRef.current) {
const threadRect = threadRefs.current[thread.cid].getBoundingClientRect();
const popupRect = popupRef.current.getBoundingClientRect();
// Get the width of the viewport area inside the browser window
const viewportWidth = document.documentElement.clientWidth;
// Calculate the space on the right side (relative to the viewport)
const spaceOnRight = viewportWidth - (threadRect.left + threadRect.width);
const spaceOnLeft = threadRect.left;
// Define the popup width
const popupWidth = popupRect.width;
// Check if there is enough space for the popup on the right side
const EnoughSpaceOnRight = spaceOnRight >= popupWidth + 10;
const EnoughSpaceOnLeft = spaceOnLeft >= popupWidth + 10;
setIsEnoughSpaceOnLeft(EnoughSpaceOnLeft);
setIsEnoughSpaceOnRight(EnoughSpaceOnRight);
return setIsCalculationDone(true);
}}
};
if(!isCalculationDone && isHoveringOnThread){
calculateSpaceOnRight();
}
}, [isHoveringOnThread]);
const timeElapsedCalc = (date) => {
const currentDateTime = new Date()
const targetToDate = new Date(date * 1000 ); // unix timestamp * 1000
const monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
const targetDateTime = new Date(`${monthNames[targetToDate.getMonth()]} ${targetToDate.getDate()} ${targetToDate.getFullYear()} ${targetToDate.getHours()}:${targetToDate.getMinutes()}:${targetToDate.getSeconds()}`)
const elapsedDateTime = currentDateTime - targetDateTime;
const elapsedDay = Math.floor(elapsedDateTime / (1000 * 60 * 60 * 24));
const elapsedHour = Math.floor((elapsedDateTime / (1000 * 60 * 60)) % 24);
const elapsedMinute = Math.floor((elapsedDateTime / (1000 * 60)) % 60);
if(elapsedDay > 0){
return `${elapsedDay} ${elapsedDay > 0 ? "days" : "day"}`;
}else if(elapsedHour > 0 ){
return `${elapsedHour} ${elapsedHour > 0 ? "hours" : "hour"}`;
}else if(elapsedMinute > 0){
return `${elapsedMinute} ${elapsedMinute > 0 ? "minutes" : "minute"}`
}
}
const handleMouseOnLeaveThread = () => {
setIsHoveringOnThread("");
setIsEnoughSpaceOnRight(null);
setIsCalculationDone(false);
}
const handleOutsideClick = useCallback((e) => { const handleOutsideClick = useCallback((e) => {
@@ -220,7 +281,6 @@ const CatalogPost = ({post}) => {
} }
}, [publishCommentEditOptions, triggerPublishCommentEdit, publishCommentEdit]); }, [publishCommentEditOptions, triggerPublishCommentEdit, publishCommentEdit]);
const getChallengeAnswersFromUser = async (challenges) => { const getChallengeAnswersFromUser = async (challenges) => {
setChallengesArray(challenges); setChallengesArray(challenges);
@@ -270,8 +330,22 @@ const CatalogPost = ({post}) => {
if (post.type === 'rules') { if (post.type === 'rules') {
return ( return (
<div className='thread' <div className='thread'
onMouseOver={() => setIsHoveringOnThread('rules')} onMouseOver={() => setIsHoveringOnThread("rules")}
onMouseLeave={() => setIsHoveringOnThread('')}> onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
{isHoveringOnThread == 'rules' ?
<div style={{left:"100%"}}
className={"thread_popup"}>
<p className="thread_popup_content" style={{color:"white"}}>
<span className="thread_popup_title">Rules </span>
by
<span className="thread_popup_authorAdmin"> ## Board Admins </span>
{timeElapsedCalc(subplebbit.createdAt)}</p>
<div>
<p className="thread_popup_content">Last reply by
<span className="thread_popup_authorAdmin"> Anonymous </span>
560 days ago</p>
</div>
</div> : null }
<BoardForm selectedStyle={selectedStyle} style={{all: 'unset'}}> <BoardForm selectedStyle={selectedStyle} style={{all: 'unset'}}>
<div className='meta' title="(R)eplies / (L)ink Replies"> <div className='meta' title="(R)eplies / (L)ink Replies">
R:&nbsp;<b>0</b>&nbsp;/&nbsp;L:&nbsp;<b>0</b> R:&nbsp;<b>0</b>&nbsp;/&nbsp;L:&nbsp;<b>0</b>
@@ -340,8 +414,23 @@ const CatalogPost = ({post}) => {
return ( return (
<> <>
<div className='thread' <div className='thread'
onMouseOver={() => setIsHoveringOnThread('description')} onMouseOver={() => setIsHoveringOnThread("description")}
onMouseLeave={() => setIsHoveringOnThread('')}> onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
{/* <!-- hovering div --> */}
{isHoveringOnThread == 'description' ?
<div style={{left:"100%"}}
className={"thread_popup"}>
<p className="thread_popup_content" style={{color:"white"}}>
<span className="thread_popup_title">Welcome to {subplebbit.title || subplebbit.address} </span>
by
<span className="thread_popup_authorAdmin"> ## Board Admins </span>
{timeElapsedCalc(subplebbit.createdAt)} ago</p>
<div>
<p className="thread_popup_content">Last reply by
<span className="thread_popup_authorAdmin"> Anonymous </span>
560 days ago</p>
</div>
</div> : null }
<Link style={{all: 'unset', cursor: 'pointer'}} to={`/p/${selectedAddress}/description`}> <Link style={{all: 'unset', cursor: 'pointer'}} to={`/p/${selectedAddress}/description`}>
{subplebbit.suggested?.avatarUrl ? ( {subplebbit.suggested?.avatarUrl ? (
<img className='card' <img className='card'
@@ -456,9 +545,38 @@ const CatalogPost = ({post}) => {
) )
} else { } else {
return ( return (
<div key={`thread-`} className="thread" <div key={`thread-`} className="thread">
onMouseOver={() => {setIsHoveringOnThread(thread.cid)}} {isHoveringOnThread === thread.cid ?
onMouseLeave={() => {setIsHoveringOnThread('')}}> <div ref={popupRef}
style={{
opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0,
left: isCalculationDone && isEnoughSpaceOnRight !== null && isEnoughSpaceOnRight ? '100%' : 'auto',
right: isCalculationDone && isEnoughSpaceOnRight !== null && !isEnoughSpaceOnRight ? '100%' : 'auto',}}
className="thread_popup">
<p
style={isEnoughSpaceOnLeft !== null && !isEnoughSpaceOnLeft
&& !isEnoughSpaceOnRight
?
{overflow:"visible",whiteSpace:"normal"}
: null
}
className="thread_popup_content">
<span className="thread_popup_title" >
{thread.title ? `${thread.title} ` : "Posted "}
</span>
by
<span className="thread_popup_author">
{thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
</span>
{thread.timestamp ? timeElapsedCalc(thread.timestamp) : null} ago</p>
<div>
{thread.replyCount > 0 ?
<p className="thread_popup_lastReply">
Last reply by <span className="thread_popup_author"> Anonymous </span>
{timeElapsedCalc(thread.lastReplyTimestamp)} ago</p>
: null}</div>
</div> : null }
{commentMediaInfo?.url ? ( {commentMediaInfo?.url ? (
<Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${selectedAddress}/c/${thread.cid}`} <Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${selectedAddress}/c/${thread.cid}`}
onClick={() => setSelectedThread(thread.cid)}> onClick={() => setSelectedThread(thread.cid)}>
@@ -467,6 +585,8 @@ const CatalogPost = ({post}) => {
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}> <span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
<img className="card" key={`img-`} <img className="card" key={`img-`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type} src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
onMouseOver={() => setIsHoveringOnThread(thread.cid)}
onMouseLeave={()=>{handleMouseOnLeaveThread()}}
onError={(e) => { onError={(e) => {
e.target.src = fallbackImgUrl e.target.src = fallbackImgUrl
e.target.onerror = null; e.target.onerror = null;
@@ -478,6 +598,8 @@ const CatalogPost = ({post}) => {
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}> <span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
<img className="card" key={`img-`} <img className="card" key={`img-`}
src={commentMediaInfo.url} alt={commentMediaInfo.type} src={commentMediaInfo.url} alt={commentMediaInfo.type}
onMouseOver={() => setIsHoveringOnThread(thread.cid)}
onMouseLeave={()=>{handleMouseOnLeaveThread()}}
onError={(e) => { onError={(e) => {
e.target.src = fallbackImgUrl e.target.src = fallbackImgUrl
e.target.onerror = null;}} /> e.target.onerror = null;}} />
@@ -486,6 +608,8 @@ const CatalogPost = ({post}) => {
{commentMediaInfo?.type === "video" ? ( {commentMediaInfo?.type === "video" ? (
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}> <span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
<video className="card" key={`fti-`} <video className="card" key={`fti-`}
onMouseOver={() => setIsHoveringOnThread(thread.cid)}
onMouseLeave={()=>{handleMouseOnLeaveThread()}}
src={commentMediaInfo.url} src={commentMediaInfo.url}
alt={commentMediaInfo.type} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} /> onError={(e) => e.target.src = fallbackImgUrl} />
@@ -496,6 +620,8 @@ const CatalogPost = ({post}) => {
key={`fti-`} key={`fti-`}
src={commentMediaInfo.url} src={commentMediaInfo.url}
alt={commentMediaInfo.type} alt={commentMediaInfo.type}
onMouseOver={() => setIsHoveringOnThread(thread.cid)}
onMouseLeave={()=>{handleMouseOnLeaveThread()}}
onError={(e) => e.target.src = fallbackImgUrl} /> onError={(e) => e.target.src = fallbackImgUrl} />
) : null} ) : null}
</Link> </Link>
@@ -684,9 +810,15 @@ const CatalogPost = ({post}) => {
<Link style={{all: "unset", cursor: "pointer"}} key={`link2-`} to={`/p/${selectedAddress}/c/${thread.cid}`} <Link style={{all: "unset", cursor: "pointer"}} key={`link2-`} to={`/p/${selectedAddress}/c/${thread.cid}`}
onClick={() => setSelectedThread(thread.cid)}> onClick={() => setSelectedThread(thread.cid)}>
<div key={`t-`} className="teaser"> <div key={`t-`} className="teaser">
<div style={{cursor:"text"}}
onMouseOver={() => {
!thread.thumbnailUrl && setIsHoveringOnThread(thread.cid)}}
onMouseLeave={()=>{handleMouseOnLeaveThread()}}
ref={(el) => (threadRefs.current[thread.cid] = el)}>
<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}
</div> </div>
</div>
</Link> </Link>
</div> </div>
) )
+10776 -11031
View File
File diff suppressed because it is too large Load Diff