mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'master' of github.com:plebbit/plebchan
This commit is contained in:
+2
-2
@@ -3,13 +3,13 @@
|
||||
"version": "0.1.11",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@capacitor/app": "1.1.1",
|
||||
"@babel/core": "7.21.3",
|
||||
"@babel/plugin-syntax-flow": "7.18.6",
|
||||
"@babel/plugin-transform-react-jsx": "7.21.0",
|
||||
"@capacitor/android": "3.6.0",
|
||||
"@capacitor/app": "1.1.1",
|
||||
"@capacitor/core": "3.6.0",
|
||||
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#e741b0dad5bba65cf1f0896053f25cd91ed55cf1",
|
||||
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#55b6e1dc3f11f19fb0b71f5770909d7904cb29c0",
|
||||
"@testing-library/dom": "9.0.1",
|
||||
"@testing-library/jest-dom": "5.14.1",
|
||||
"@testing-library/react": "14.0.0",
|
||||
|
||||
@@ -20,7 +20,7 @@ const BoardStats = ({ subplebbitAddress }) => {
|
||||
const date = new Date(timestamp * 1000);
|
||||
const month = ('0' + (date.getMonth() + 1)).slice(-2);
|
||||
const day = ('0' + date.getDate()).slice(-2);
|
||||
const year = date.getFullYear();
|
||||
const year = date.getFullYear().toString().slice(-2);
|
||||
return month + '/' + day + '/' + year;
|
||||
};
|
||||
|
||||
@@ -33,13 +33,13 @@ const BoardStats = ({ subplebbitAddress }) => {
|
||||
{showStats && (
|
||||
<tbody id="blotter-msgs">
|
||||
<tr>
|
||||
<td>In the past hour, <span id="stat-number">{stats.hourActiveUserCount}</span> {pluralize(stats.hourActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.hourPostCount}</span> {pluralize(stats.hourPostCount, 'post', 'posts')} — In the past day, <span id="stat-number">{stats.dayActiveUserCount}</span> {pluralize(stats.dayActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.dayPostCount}</span> {pluralize(stats.dayPostCount, 'post', 'posts')}</td>
|
||||
<td>In the past hour, <span id="stat-number">{stats.hourActiveUserCount}</span> {pluralize(stats.hourActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.hourPostCount}</span> {pluralize(stats.hourPostCount, 'post', 'posts')} — in the past day, <span id="stat-number">{stats.dayActiveUserCount}</span> {pluralize(stats.dayActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.dayPostCount}</span> {pluralize(stats.dayPostCount, 'post', 'posts')}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>In the past week, <span id="stat-number">{stats.weekActiveUserCount}</span> {pluralize(stats.weekActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.weekPostCount}</span> {pluralize(stats.weekPostCount, 'post', 'posts')} — In the past month, <span id="stat-number">{stats.monthActiveUserCount}</span> {pluralize(stats.monthActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.monthPostCount}</span> {pluralize(stats.monthPostCount, 'post', 'posts')}</td>
|
||||
<td>In the past week, <span id="stat-number">{stats.weekActiveUserCount}</span> {pluralize(stats.weekActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.weekPostCount}</span> {pluralize(stats.weekPostCount, 'post', 'posts')} — in the past month, <span id="stat-number">{stats.monthActiveUserCount}</span> {pluralize(stats.monthActiveUserCount, 'user', 'users')} made <span id="stat-number">{stats.monthPostCount}</span> {pluralize(stats.monthPostCount, 'post', 'posts')}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{unixToMMDDYYYY(subplebbit.createdAt)} board created, since then <span id="stat-number">{stats.allActiveUserCount}</span> {pluralize(stats.allActiveUserCount, 'user', 'users')} have made <span id="stat-number">{stats.allPostCount}</span> {pluralize(stats.allPostCount, 'post', 'posts')}</td>
|
||||
<td>{unixToMMDDYYYY(subplebbit.createdAt)} board created — since then, <span id="stat-number">{stats.allActiveUserCount}</span> {pluralize(stats.allActiveUserCount, 'user', 'users')} have made <span id="stat-number">{stats.allPostCount}</span> {pluralize(stats.allPostCount, 'post', 'posts')}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
)}
|
||||
|
||||
@@ -461,7 +461,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
|
||||
</label>
|
||||
</li>
|
||||
<li className="settings-tip anon-tip">
|
||||
Automatically use a different u/address per thread to post.
|
||||
Use a newly generated u/address per thread to post.
|
||||
</li>
|
||||
<li className="settings-option disc">
|
||||
Account Data
|
||||
|
||||
@@ -10,11 +10,13 @@ export const BoardStatsContainer = styled.div`
|
||||
width: 468px;
|
||||
margin: auto;
|
||||
line-height: 1;
|
||||
margin-top: -1px;
|
||||
|
||||
table {
|
||||
border-spacing: 0px;
|
||||
width: 100%;
|
||||
margin-top: -1px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
tr {
|
||||
|
||||
@@ -12,55 +12,11 @@ export const Threads = styled.div`
|
||||
max-height: 320px;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
word-wrap: break-word;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 20px;
|
||||
padding: 5px 0 3px;
|
||||
}
|
||||
|
||||
.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 {
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
@@ -125,7 +81,6 @@ export const Threads = styled.div`
|
||||
}
|
||||
|
||||
.meta {
|
||||
cursor: help;
|
||||
font-size: 11px;
|
||||
line-height: 8px;
|
||||
margin-top: 2px;
|
||||
@@ -136,82 +91,162 @@ export const Threads = styled.div`
|
||||
display: block;
|
||||
padding: 0 15px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
return ``;
|
||||
|
||||
case 'Yotsuba-B':
|
||||
return ``;
|
||||
|
||||
case 'Futaba':
|
||||
return ``;
|
||||
|
||||
case 'Burichan':
|
||||
return ``;
|
||||
|
||||
case 'Tomorrow':
|
||||
return `
|
||||
.file-thumb {
|
||||
background-color: rgba(255, 255, 255, 0.01) !important;
|
||||
}`;
|
||||
|
||||
case 'Photon':
|
||||
return ``;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
export const PostPreview = styled.div`
|
||||
.post-preview {
|
||||
position: absolute;
|
||||
background-color: #000;
|
||||
border-radius: 3px;
|
||||
padding: 5px 8px 4px;
|
||||
z-index: 100000;
|
||||
word-wrap: break-word;
|
||||
white-space: normal;
|
||||
max-width: 500px;
|
||||
width: fit-content;
|
||||
color: #dedede;
|
||||
font-size: 10pt;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.post-author {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.post-last {
|
||||
margin-top: 3px;
|
||||
color: #bbbfbd;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.post-author-admin {
|
||||
color: purple;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
return `
|
||||
.thread_popup_title{
|
||||
.post-subject{
|
||||
color:#cc1105;
|
||||
font-weight:700;
|
||||
};
|
||||
.thread_popup_author{
|
||||
|
||||
.post-author{
|
||||
color:#00a550;font-weight:bold
|
||||
}`;
|
||||
|
||||
case 'Yotsuba-B':
|
||||
return `
|
||||
.thread_popup_title{
|
||||
.post-subject{
|
||||
color:#dedede;
|
||||
font-weight:700;
|
||||
};
|
||||
.thread_popup_author{
|
||||
|
||||
.post-author{
|
||||
color:#00a550;font-weight:bold
|
||||
}`;
|
||||
|
||||
case 'Futaba':
|
||||
return `
|
||||
.thread_popup{
|
||||
.post-preview{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
}
|
||||
.thread_popup_title{
|
||||
|
||||
.post-subject{
|
||||
color:#cc1105;
|
||||
font-weight:700;
|
||||
};
|
||||
.thread_popup_author{
|
||||
|
||||
.post-author{
|
||||
color:#00a550;font-weight:700;
|
||||
}`;
|
||||
|
||||
case 'Burichan':
|
||||
return `
|
||||
.thread_popup{
|
||||
.post-preview{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
}
|
||||
.thread_popup_title{
|
||||
|
||||
.post-subject{
|
||||
color:#dedede;
|
||||
font-weight:700;
|
||||
};
|
||||
.thread_popup_author{
|
||||
|
||||
.post-author{
|
||||
color:#00a550;font-weight:700;
|
||||
}`;
|
||||
|
||||
case 'Tomorrow':
|
||||
return `
|
||||
.thread_popup{
|
||||
.post-preview{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
}
|
||||
|
||||
.file-thumb {
|
||||
background-color: rgba(255, 255, 255, 0.01) !important;
|
||||
}
|
||||
.thread_popup_title{
|
||||
|
||||
.post-subject{
|
||||
color:#b294bb;
|
||||
font-weight:700;
|
||||
};
|
||||
.thread_popup_author{
|
||||
|
||||
.post-author{
|
||||
color:#00a550;font-weight:700;
|
||||
}`;
|
||||
|
||||
case 'Photon':
|
||||
return `
|
||||
.thread_popup{
|
||||
.post-preview{
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
}
|
||||
.thread_popup_title{
|
||||
|
||||
.post-subject{
|
||||
color:#dedede;
|
||||
font-weight:700;
|
||||
};
|
||||
.thread_popup_author{
|
||||
color:#00a550;font-weight:700;
|
||||
|
||||
.post-author{
|
||||
color:#dedede;font-weight:700;
|
||||
}`;
|
||||
default:
|
||||
return '';
|
||||
}}}
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
export const PostMenuCatalog = styled.div`
|
||||
@@ -249,7 +284,7 @@ export const PostMenuCatalog = styled.div`
|
||||
${({ selectedStyle }) => {
|
||||
switch (selectedStyle) {
|
||||
case 'Yotsuba':
|
||||
return `.thread_popup_title{
|
||||
return `.post-subject{
|
||||
color:red;
|
||||
}`;
|
||||
|
||||
|
||||
@@ -718,7 +718,7 @@ const All = () => {
|
||||
commentMediaInfo?.url.slice(0, 30) + "(...)" :
|
||||
commentMediaInfo?.url
|
||||
}</a> ({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
|
||||
{isThreadThumbnailClicked[index] ? (
|
||||
{isThreadThumbnailClicked[index] && commentMediaInfo.type !== "image" ? (
|
||||
<span>
|
||||
-[
|
||||
<span className='reply-link'
|
||||
@@ -927,7 +927,7 @@ const All = () => {
|
||||
<ul className="post-menu-catalog">
|
||||
<li onClick={() => {
|
||||
handleOptionClick(thread.cid);
|
||||
handleShareClick(selectedAddress, thread.cid);
|
||||
handleShareClick(thread.subplebbitAddress, thread.cid);
|
||||
}}>Share thread</li>
|
||||
<VerifiedAuthor commentCid={thread.cid}>{({ authorAddress }) => (
|
||||
<>
|
||||
@@ -1007,19 +1007,19 @@ const All = () => {
|
||||
style={{display: isClientRedirectMenuOpen ? 'block': 'none'}}>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://plebbitapp.eth.limo/#/p/${selectedAddress}/c/${thread.cid}`}
|
||||
href={`https://plebbitapp.eth.limo/#/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebbit</a>
|
||||
</li>
|
||||
{/* <li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://seedit.eth.limo/#/p/${selectedAddress}/c/${thread.cid}`}
|
||||
href={`https://seedit.eth.limo/#/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Seedit</a>
|
||||
</li> */}
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://plebones.netlify.app/#/p/${selectedAddress}/c/${thread.cid}`}
|
||||
href={`https://plebones.netlify.app/#/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebones</a>
|
||||
</li>
|
||||
@@ -1099,7 +1099,7 @@ const All = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`ttl-s-br2${index}`} />
|
||||
Post too long.
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view.
|
||||
</span>
|
||||
</blockquote>
|
||||
@@ -1262,7 +1262,7 @@ const All = () => {
|
||||
<ul className="post-menu-catalog">
|
||||
<li onClick={() => {
|
||||
handleOptionClick(reply.cid);
|
||||
handleShareClick(selectedAddress, thread.cid);
|
||||
handleShareClick(thread.subplebbitAddress, thread.cid);
|
||||
}}>Share thread</li>
|
||||
<VerifiedAuthor commentCid={reply.cid}>{({ authorAddress }) => (
|
||||
<>
|
||||
@@ -1342,19 +1342,19 @@ const All = () => {
|
||||
style={{display: isClientRedirectMenuOpen ? 'block': 'none'}}>
|
||||
<li onClick={() => handleOptionClick(reply.cid)}>
|
||||
<a
|
||||
href={`https://plebbitapp.eth.limo/#/p/${selectedAddress}/c/${reply.cid}`}
|
||||
href={`https://plebbitapp.eth.limo/#/p/${thread.subplebbitAddress}/c/${reply.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebbit</a>
|
||||
</li>
|
||||
{/* <li onClick={() => handleOptionClick(reply.cid)}>
|
||||
<a
|
||||
href={`https://seedit.eth.limo/#/p/${selectedAddress}/c/${reply.cid}`}
|
||||
href={`https://seedit.eth.limo/#/p/${thread.subplebbitAddress}/c/${reply.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Seedit</a>
|
||||
</li> */}
|
||||
<li onClick={() => handleOptionClick(reply.cid)}>
|
||||
<a
|
||||
href={`https://plebones.netlify.app/#/p/${selectedAddress}/c/${reply.cid}`}
|
||||
href={`https://plebones.netlify.app/#/p/${thread.subplebbitAddress}/c/${reply.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebones</a>
|
||||
</li>
|
||||
@@ -1430,7 +1430,7 @@ const All = () => {
|
||||
replyMediaInfo?.url.slice(0, 30) + "(...)" :
|
||||
replyMediaInfo?.url
|
||||
}</a> ({replyMediaInfo?.type})
|
||||
{replyMediaInfo?.type === "video" || "iframe" ? (
|
||||
{replyMediaInfo?.type === "video" || replyMediaInfo?.type === "iframe" ? (
|
||||
isReplyThumbnailClicked[index] ? (
|
||||
<span>
|
||||
-[
|
||||
@@ -1608,7 +1608,7 @@ const All = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`ttl-s-br2${index}`} />
|
||||
Comment too long.
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view. </span>
|
||||
</blockquote>
|
||||
</Fragment>
|
||||
@@ -1842,7 +1842,7 @@ const All = () => {
|
||||
style={{cursor: "pointer"}}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -1899,7 +1899,7 @@ const All = () => {
|
||||
onError={(e) => e.target.src = fallbackImgUrl}
|
||||
/>
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -1936,7 +1936,7 @@ const All = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`mob-ttl-s-br2${thread.cid}`} />
|
||||
Post too long.
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view. </span>
|
||||
</blockquote>
|
||||
</Fragment>
|
||||
@@ -2215,7 +2215,7 @@ const All = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`mob-ttl-s-br2${reply.cid}`} />
|
||||
Comment too long.
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view. </span>
|
||||
</blockquote>
|
||||
</Fragment>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Virtuoso } from 'react-virtuoso';
|
||||
import { useAccount, useFeed, usePublishCommentEdit, useSubplebbit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import { debounce } from 'lodash';
|
||||
import { Container, NavBar, Header, Break, PostMenu, BoardForm } from '../styled/views/Board.styled';
|
||||
import { Threads, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { Threads, PostPreview, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { TopBar, Footer } from '../styled/views/Thread.styled';
|
||||
import { AlertModal } from '../styled/modals/AlertModal.styled';
|
||||
import CatalogLoader from '../CatalogLoader';
|
||||
@@ -61,6 +61,7 @@ const CatalogPost = ({post}) => {
|
||||
const fallbackImgUrl = "assets/filedeleted-res.gif";
|
||||
const [isHoveringOnThread, setIsHoveringOnThread] = useState(false);
|
||||
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
|
||||
const [popupPosition, setPopupPosition] = useState({top: 0, left: 0});
|
||||
const [openMenuCid, setOpenMenuCid] = useState(null);
|
||||
const [triggerPublishCommentEdit, setTriggerPublishCommentEdit] = useState(false);
|
||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||
@@ -74,40 +75,73 @@ const CatalogPost = ({post}) => {
|
||||
const account = useAccount();
|
||||
const subplebbit = useSubplebbit({subplebbitAddress: thread.subplebbitAddress});
|
||||
const threadMenuRefs = useRef({});
|
||||
const threadRefs = useRef({});
|
||||
const postMenuRef = useRef(null);
|
||||
const postMenuCatalogRef = useRef(null);
|
||||
const popupRef = useRef(null);
|
||||
const threadRefs = useRef([]);
|
||||
const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null);
|
||||
const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null);
|
||||
const textRef = useRef(null);
|
||||
const imageRef = useRef(null);
|
||||
const [spaceOnRight, setSpaceOnRight] = useState(null);
|
||||
const [isCalculationDone,setIsCalculationDone] = useState(false);
|
||||
const [hoverTimeoutId, setHoverTimeoutId] = useState(null);
|
||||
const [isHoveringForMenu, setIsHoveringForMenu] = useState(false);
|
||||
const textRect = textRef.current?.getBoundingClientRect();
|
||||
const imageRect = imageRef.current?.getBoundingClientRect();
|
||||
const popupRect = popupRef.current?.getBoundingClientRect();
|
||||
const isMediaShowed = (thread.link && commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail) ||
|
||||
(commentMediaInfo.type === 'iframe' &&
|
||||
commentMediaInfo.thumbnail))) ? true : false;
|
||||
|
||||
|
||||
const { left: textLeft, right: textRight, width: textWidth } = textRef.current?.getBoundingClientRect() || {};
|
||||
const { left: imageLeft, right: imageRight, width: imageWidth } = imageRef.current?.getBoundingClientRect() || {};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const executeLayoutEffectLogic = () => {
|
||||
let ref;
|
||||
ref = threadRefs.current[isHoveringOnThread];
|
||||
|
||||
if (isMediaShowed) {
|
||||
ref = imageRef.current;
|
||||
} else {
|
||||
ref = textRef.current;
|
||||
}
|
||||
|
||||
if (ref && popupRef.current) {
|
||||
const threadRect = ref.getBoundingClientRect();
|
||||
const popupRect = popupRef.current.getBoundingClientRect();
|
||||
const rect = ref.getBoundingClientRect();
|
||||
const viewportWidth = document.documentElement.clientWidth;
|
||||
const spaceOnRight = viewportWidth - (threadRect.left + threadRect.width);
|
||||
const spaceOnLeft = threadRect.left;
|
||||
const popupWidth = popupRect.width;
|
||||
setIsEnoughSpaceOnLeft(spaceOnLeft >= popupWidth + 10);
|
||||
setIsEnoughSpaceOnRight(spaceOnRight >= popupWidth + 10);
|
||||
const spaceRight = viewportWidth - (rect.left + rect.width);
|
||||
const spaceLeft = rect.left;
|
||||
|
||||
if (spaceRight < 200 && spaceLeft > spaceRight && spaceLeft < 500) {
|
||||
popupRef.current.style.maxWidth = `calc(
|
||||
100vw -
|
||||
${isMediaShowed ? imageWidth : textWidth}px
|
||||
- ${spaceRight + 40}px
|
||||
)`;
|
||||
} else if (spaceRight < 200 && spaceLeft < spaceRight) {
|
||||
popupRef.current.style.maxWidth = `calc(100vw - ${isMediaShowed ? imageWidth : textWidth}px)`;
|
||||
} else {
|
||||
popupRef.current.style.maxWidth = `500px`;
|
||||
}
|
||||
|
||||
setSpaceOnRight(spaceRight);
|
||||
setIsCalculationDone(true);
|
||||
}
|
||||
};
|
||||
|
||||
if (isHoveringOnThread) {
|
||||
const timeoutId = setTimeout(executeLayoutEffectLogic, 500);
|
||||
return () => clearTimeout(timeoutId);
|
||||
const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
setIsCalculationDone(false);
|
||||
};
|
||||
}
|
||||
|
||||
}, [isHoveringOnThread]);
|
||||
}, [isHoveringOnThread, isMediaShowed, textLeft, textRight, imageLeft, imageRight, textWidth, imageWidth]);
|
||||
|
||||
|
||||
const handleMouseOnLeaveThread = () => {
|
||||
@@ -117,7 +151,6 @@ const CatalogPost = ({post}) => {
|
||||
setIsHoveringOnThread("")
|
||||
} else if (isHoveringOnThread !== "") {
|
||||
setIsHoveringOnThread("");
|
||||
setIsEnoughSpaceOnRight(null);
|
||||
setIsCalculationDone(false);
|
||||
}
|
||||
};
|
||||
@@ -328,48 +361,63 @@ const CatalogPost = ({post}) => {
|
||||
|
||||
|
||||
return (
|
||||
<div key={`thread-`} className="thread"
|
||||
onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}
|
||||
onMouseLeave={() => {handleMouseOnLeaveThread()}}>
|
||||
<>
|
||||
{isHoveringOnThread === thread.cid ?
|
||||
createPortal(
|
||||
<PostPreview selectedStyle={selectedStyle}>
|
||||
<div ref={popupRef}
|
||||
className="post-preview"
|
||||
onMouseOver={() => handleMouseOnLeaveThread()}
|
||||
style={{
|
||||
opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0,
|
||||
visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden',
|
||||
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" >
|
||||
visibility: isCalculationDone ? 'visible' : 'hidden',
|
||||
left:
|
||||
isCalculationDone && spaceOnRight > 250
|
||||
? isMediaShowed ? imageRect.right + 5 : textRect.right + 5 :
|
||||
isCalculationDone && spaceOnRight < 250
|
||||
? isMediaShowed ? imageRect.left - popupRect.width - 5 : textRect.left - popupRect.width - 5
|
||||
: 'auto',
|
||||
top: popupPosition.top + 5,
|
||||
}}>
|
||||
<span className="post-subject" >
|
||||
{thread.title ? `${thread.title} ` : "Posted "}
|
||||
</span>
|
||||
by
|
||||
<span className="thread_popup_author">
|
||||
<span className="post-author">
|
||||
{thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
|
||||
</span>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}</p>
|
||||
<div>
|
||||
<span className='post-ago'>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}
|
||||
</span>
|
||||
{thread.replyCount > 0 ?
|
||||
<p className="thread_popup_lastReply">
|
||||
Last reply by <span className="thread_popup_author"> Anonymous </span>
|
||||
{getFormattedTime(thread.lastReplyTimestamp)}</p>
|
||||
: null}</div>
|
||||
</div> : null }
|
||||
<div className='post-last'>
|
||||
Last reply by
|
||||
<span className="post-author"> Anonymous </span>
|
||||
<span className='post-ago'>{getFormattedTime(thread.lastReplyTimestamp)}</span>
|
||||
</div>
|
||||
: null}
|
||||
</div>
|
||||
</PostPreview>, document.body
|
||||
)
|
||||
: null }
|
||||
<div key={`thread-`} className="thread"
|
||||
ref={el => {
|
||||
threadRefs.current[thread.cid] = el;
|
||||
}}
|
||||
onMouseLeave={() => {handleMouseOnLeaveThread()}}>
|
||||
{commentMediaInfo?.url ? (
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
onClick={() => setSelectedThread(thread.cid)}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread(thread.cid);
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
const rect = threadRefs.current[thread.cid].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
{commentMediaInfo?.type === "webpage" ? (
|
||||
thread.thumbnailUrl ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" key={`img-`}
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
@@ -378,9 +426,16 @@ const CatalogPost = ({post}) => {
|
||||
</span>
|
||||
) : null
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "iframe" && (thread.thumbnailUrl || commentMediaInfo.thumbnail) ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => { e.target.src = fallbackImgUrl }} />
|
||||
</span>
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "image" ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" key={`img-`}
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.url} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
@@ -389,14 +444,14 @@ const CatalogPost = ({post}) => {
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "video" ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<video className="card" key={`fti-`}
|
||||
<video className="card" ref={imageRef} key={`fti-`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
</span>
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "audio" ? (
|
||||
<audio className="card" controls
|
||||
<audio className="card" ref={imageRef} controls
|
||||
key={`fti-`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
@@ -405,11 +460,7 @@ const CatalogPost = ({post}) => {
|
||||
</Link>
|
||||
) : null}
|
||||
<div key={`ti-`} className="thread-icons" >
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? (
|
||||
{isMediaShowed ? (
|
||||
<OfflineIndicator
|
||||
address={thread.subplebbitAddress}
|
||||
className="thread-icon offline-icon"
|
||||
@@ -422,6 +473,11 @@ const CatalogPost = ({post}) => {
|
||||
)}
|
||||
</div>
|
||||
<BoardForm selectedStyle={selectedStyle}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
handleMouseOnLeaveThread();
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}
|
||||
style={{ all: "unset"}}>
|
||||
<div key={`meta-`} className="meta" title="(R)eplies / (L)ink Replies" >
|
||||
R: <b key={`b-`}>{thread.replyCount}</b>
|
||||
@@ -432,7 +488,7 @@ const CatalogPost = ({post}) => {
|
||||
</>
|
||||
) : null}
|
||||
<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',
|
||||
zIndex: '999'}}
|
||||
key={`pmb-`}
|
||||
@@ -572,13 +628,22 @@ const CatalogPost = ({post}) => {
|
||||
</BoardForm>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link2-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
<div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}}
|
||||
ref={(el) => (threadRefs.current[thread.cid] = el)}>
|
||||
<div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}}>
|
||||
<span key={`teaser-width${thread.cid}`} ref={textRef}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread(thread.cid);
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
const rect = threadRefs.current[thread.cid].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
<b key={`b2-`}>{thread.title ? `${thread.title}` : null}</b>
|
||||
{thread.content ? `: ${thread.content}` : null}
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1414,7 +1414,7 @@ const Board = () => {
|
||||
commentMediaInfo?.url.slice(0, 30) + "(...)" :
|
||||
commentMediaInfo?.url
|
||||
}</a> ({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
|
||||
{isThreadThumbnailClicked[index] ? (
|
||||
{isThreadThumbnailClicked[index] && commentMediaInfo.type !== "image" ? (
|
||||
<span>
|
||||
-[
|
||||
<span className='reply-link'
|
||||
@@ -2123,8 +2123,8 @@ const Board = () => {
|
||||
replyMediaInfo?.url.slice(0, 30) + "(...)" :
|
||||
replyMediaInfo?.url
|
||||
}</a> ({replyMediaInfo?.type})
|
||||
{replyMediaInfo?.type === "video" || "iframe" ? (
|
||||
isReplyThumbnailClicked[index] ? (
|
||||
{replyMediaInfo?.type === "video" || replyMediaInfo?.type === "iframe" ? (
|
||||
isReplyThumbnailClicked[index] && commentMediaInfo.type !== "image" ? (
|
||||
<span>
|
||||
-[
|
||||
<span className='reply-link'
|
||||
@@ -2530,7 +2530,7 @@ const Board = () => {
|
||||
style={{cursor: "pointer"}}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -2587,7 +2587,7 @@ const Board = () => {
|
||||
onError={(e) => e.target.src = fallbackImgUrl}
|
||||
/>
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -2787,7 +2787,7 @@ const Board = () => {
|
||||
onError={(e) => e.target.src = fallbackImgUrl}
|
||||
/>
|
||||
)}
|
||||
{replyMediaInfo?.type === "video" || "iframe" ? (
|
||||
{replyMediaInfo?.type === "video" || replyMediaInfo?.type === "iframe" ? (
|
||||
isMobileReplyThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
|
||||
+214
-127
@@ -8,7 +8,7 @@ import { Virtuoso } from 'react-virtuoso';
|
||||
import { useAccount, useFeed, usePublishComment, usePublishCommentEdit, useSubplebbit, useSubscribe } from '@plebbit/plebbit-react-hooks';
|
||||
import { debounce } from 'lodash';
|
||||
import { Container, NavBar, Header, Break, PostForm, PostFormLink, PostFormTable, PostMenu, BoardForm } from '../styled/views/Board.styled';
|
||||
import { Threads, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { Threads, PostPreview, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { TopBar, Footer } from '../styled/views/Thread.styled';
|
||||
import { AlertModal } from '../styled/modals/AlertModal.styled';
|
||||
import EditModal from '../modals/EditModal';
|
||||
@@ -67,6 +67,7 @@ const CatalogPost = ({post}) => {
|
||||
const fallbackImgUrl = "assets/filedeleted-res.gif";
|
||||
const [isHoveringOnThread, setIsHoveringOnThread] = useState(false);
|
||||
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
|
||||
const [popupPosition, setPopupPosition] = useState({top: 0, left: 0});
|
||||
const [openMenuCid, setOpenMenuCid] = useState(null);
|
||||
const [triggerPublishCommentEdit, setTriggerPublishCommentEdit] = useState(false);
|
||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||
@@ -74,8 +75,12 @@ const CatalogPost = ({post}) => {
|
||||
const [commentCid, setCommentCid] = useState(null);
|
||||
|
||||
const threadMenuRefs = useRef({});
|
||||
const threadRefs = useRef({});
|
||||
const postMenuRef = useRef(null);
|
||||
const popupRef = useRef(null);
|
||||
const imageRef = useRef(null);
|
||||
const postMenuCatalogRef = useRef(null);
|
||||
const textRef = useRef(null);
|
||||
const { subplebbitAddress } = useParams();
|
||||
|
||||
const [, setNewErrorMessage] = useError();
|
||||
@@ -84,54 +89,75 @@ const CatalogPost = ({post}) => {
|
||||
const subplebbit = useSubplebbit({subplebbitAddress: selectedAddress});
|
||||
|
||||
const account = useAccount();
|
||||
const popupRef = useRef(null);
|
||||
const threadRefs = useRef([]);
|
||||
const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null);
|
||||
const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null);
|
||||
const [spaceOnRight, setSpaceOnRight] = useState(null);
|
||||
const [isCalculationDone,setIsCalculationDone] = useState(false);
|
||||
const [hoverTimeoutId, setHoverTimeoutId] = useState(null);
|
||||
const [isHoveringForMenu, setIsHoveringForMenu] = useState(false);
|
||||
const textRect = textRef.current?.getBoundingClientRect();
|
||||
const imageRect = imageRef.current?.getBoundingClientRect();
|
||||
const popupRect = popupRef.current?.getBoundingClientRect();
|
||||
const isMediaShowed = (thread.link && commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail) ||
|
||||
(commentMediaInfo.type === 'iframe' &&
|
||||
commentMediaInfo.thumbnail))) ? true : false;
|
||||
|
||||
const { left: textLeft, right: textRight, width: textWidth } = textRef.current?.getBoundingClientRect() || {};
|
||||
const { left: imageLeft, right: imageRight, width: imageWidth } = imageRef.current?.getBoundingClientRect() || {};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const executeLayoutEffectLogic = () => {
|
||||
let ref;
|
||||
if (isHoveringOnThread === 'rules' || isHoveringOnThread === 'description') {
|
||||
ref = popupRef.current;
|
||||
|
||||
if (isMediaShowed) {
|
||||
ref = imageRef.current;
|
||||
} else {
|
||||
ref = threadRefs.current[isHoveringOnThread];
|
||||
ref = textRef.current;
|
||||
}
|
||||
|
||||
if (ref && popupRef.current) {
|
||||
const threadRect = ref.getBoundingClientRect();
|
||||
const popupRect = popupRef.current.getBoundingClientRect();
|
||||
const rect = ref.getBoundingClientRect();
|
||||
const viewportWidth = document.documentElement.clientWidth;
|
||||
const spaceOnRight = viewportWidth - (threadRect.left + threadRect.width);
|
||||
const spaceOnLeft = threadRect.left;
|
||||
const popupWidth = popupRect.width;
|
||||
setIsEnoughSpaceOnLeft(spaceOnLeft >= popupWidth + 10);
|
||||
setIsEnoughSpaceOnRight(spaceOnRight >= popupWidth + 10);
|
||||
const spaceRight = viewportWidth - (rect.left + rect.width);
|
||||
const spaceLeft = rect.left;
|
||||
|
||||
if (spaceRight < 200 && spaceLeft > spaceRight && spaceLeft < 500) {
|
||||
popupRef.current.style.maxWidth = `calc(
|
||||
100vw -
|
||||
${isMediaShowed ? imageWidth : textWidth}px
|
||||
- ${spaceRight + 40}px
|
||||
)`;
|
||||
} else if (spaceRight < 200 && spaceLeft < spaceRight) {
|
||||
popupRef.current.style.maxWidth = `calc(100vw - ${isMediaShowed ? imageWidth : textWidth}px)`;
|
||||
} else {
|
||||
popupRef.current.style.maxWidth = `500px`;
|
||||
}
|
||||
|
||||
setSpaceOnRight(spaceRight);
|
||||
setIsCalculationDone(true);
|
||||
}
|
||||
};
|
||||
|
||||
if (isHoveringOnThread) {
|
||||
const timeoutId = setTimeout(executeLayoutEffectLogic, 500);
|
||||
return () => clearTimeout(timeoutId);
|
||||
const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
setIsCalculationDone(false);
|
||||
};
|
||||
}
|
||||
|
||||
}, [isHoveringOnThread]);
|
||||
}, [isHoveringOnThread, isMediaShowed, textLeft, textRight, imageLeft, imageRight, textWidth, imageWidth]);
|
||||
|
||||
|
||||
const handleMouseOnLeaveThread = () => {
|
||||
setIsHoveringForMenu(false);
|
||||
if (hoverTimeoutId) {
|
||||
clearTimeout(hoverTimeoutId);
|
||||
setHoverTimeoutId(null);
|
||||
setIsHoveringOnThread("")
|
||||
} else if (isHoveringOnThread !== "") {
|
||||
setIsHoveringOnThread("");
|
||||
setIsEnoughSpaceOnRight(null);
|
||||
setIsCalculationDone(false);
|
||||
}
|
||||
};
|
||||
@@ -325,28 +351,43 @@ const CatalogPost = ({post}) => {
|
||||
|
||||
if (post.type === 'rules') {
|
||||
return (
|
||||
<div className='thread'
|
||||
onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
|
||||
<>
|
||||
{isHoveringOnThread === 'rules' ?
|
||||
<div style={{left:"100%"}}
|
||||
onMouseOver={() => setIsHoveringOnThread("")}
|
||||
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>
|
||||
{getFormattedTime(subplebbit.createdAt)}</p>
|
||||
</div> : null }
|
||||
createPortal(
|
||||
<PostPreview selectedStyle={selectedStyle}>
|
||||
<div ref={popupRef}
|
||||
className="post-preview"
|
||||
onMouseOver={() => handleMouseOnLeaveThread()}
|
||||
style={{
|
||||
visibility: isCalculationDone ? 'visible' : 'hidden',
|
||||
left:
|
||||
isCalculationDone && spaceOnRight > 250 ? textRect.right + 5 :
|
||||
isCalculationDone && spaceOnRight < 250 ? textRect.left - popupRect.width - 5
|
||||
: 'auto',
|
||||
top: popupPosition.top + 5,
|
||||
}}>
|
||||
<span className="post-subject" >
|
||||
Rules
|
||||
</span> by
|
||||
<span className="post-author-admin"> ## Board Admins </span>
|
||||
<span className='post-ago'>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}
|
||||
</span>
|
||||
</div>
|
||||
</PostPreview>, document.body
|
||||
)
|
||||
: null }
|
||||
<div className='thread'
|
||||
ref={el => {
|
||||
threadRefs.current['rules'] = el;
|
||||
}}
|
||||
onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
|
||||
<BoardForm selectedStyle={selectedStyle} style={{all: 'unset'}}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringForMenu('rules');
|
||||
if (!hoverTimeoutId) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
setIsHoveringOnThread("rules");
|
||||
}, 500);
|
||||
setHoverTimeoutId(timeoutId);
|
||||
}
|
||||
}}>
|
||||
handleMouseOnLeaveThread();
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
<div className='meta' title="(R)eplies / (L)ink Replies">
|
||||
R: <b>0</b> / L: <b>0</b>
|
||||
<div className='thread-icons'
|
||||
@@ -405,50 +446,71 @@ const CatalogPost = ({post}) => {
|
||||
</PostMenuCatalog>, document.body
|
||||
)}
|
||||
</BoardForm>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} to={`/p/${selectedAddress}/rules`}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringForMenu('rules');
|
||||
if (!hoverTimeoutId) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
setIsHoveringOnThread("rules");
|
||||
}, 500);
|
||||
setHoverTimeoutId(timeoutId);
|
||||
}
|
||||
}}>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} to={`/p/${selectedAddress}/rules`}>
|
||||
<div className="teaser" style={{maxHeight: '312px'}}>
|
||||
<div style={{cursor: 'text'}}>
|
||||
<span ref={textRef}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread('rules');
|
||||
setIsHoveringForMenu('rules');
|
||||
const rect = threadRefs.current['rules'].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
<b>Rules</b>
|
||||
{": " + subplebbit.rules?.map((rule, index) => `${index + 1}. ${rule}`).join(' ')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
} else if (post.type === 'description') {
|
||||
return (
|
||||
<>
|
||||
<div className='thread'
|
||||
onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
|
||||
{isHoveringOnThread === 'description' ?
|
||||
<div style={{left:"100%"}}
|
||||
onMouseOver={() => setIsHoveringOnThread("")}
|
||||
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>
|
||||
{getFormattedTime(subplebbit.createdAt)}</p>
|
||||
</div> : null }
|
||||
createPortal(
|
||||
<PostPreview selectedStyle={selectedStyle}>
|
||||
<div ref={popupRef}
|
||||
className="post-preview"
|
||||
onMouseOver={() => handleMouseOnLeaveThread()}
|
||||
style={{
|
||||
visibility: isCalculationDone ? 'visible' : 'hidden',
|
||||
left:
|
||||
isCalculationDone && spaceOnRight > 250
|
||||
? subplebbit.suggestedAvatarUrl ? imageRect.right + 5 : textRect.right + 5 :
|
||||
isCalculationDone && spaceOnRight < 250
|
||||
? subplebbit.suggestedAvatarUrl ? imageRect.left - popupRect.width - 5 : textRect.left - popupRect.width - 5
|
||||
: 'auto',
|
||||
top: popupPosition.top + 5,
|
||||
}}>
|
||||
<span className="post-subject" >
|
||||
Welcome to {subplebbit.title || subplebbit.address}
|
||||
</span> by
|
||||
<span className="post-author-admin"> ## Board Admins </span>
|
||||
<span className='post-ago'>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}
|
||||
</span>
|
||||
</div>
|
||||
</PostPreview>, document.body
|
||||
)
|
||||
: null }
|
||||
<div className='thread'
|
||||
ref={el => {
|
||||
threadRefs.current['description'] = el;
|
||||
}}
|
||||
onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
|
||||
<Link style={{all: 'unset', cursor: 'pointer'}} to={`/p/${selectedAddress}/description`}>
|
||||
{subplebbit.suggested?.avatarUrl ? (
|
||||
<img className='card'
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread('description');
|
||||
setIsHoveringForMenu('description');
|
||||
if (!hoverTimeoutId) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
setIsHoveringOnThread("description");
|
||||
}, 500);
|
||||
setHoverTimeoutId(timeoutId);
|
||||
}
|
||||
const rect = threadRefs.current['description'].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}
|
||||
src={subplebbit.suggested.avatarUrl} alt="board avatar" />
|
||||
) : null}
|
||||
</Link>
|
||||
@@ -465,13 +527,9 @@ const CatalogPost = ({post}) => {
|
||||
<BoardForm selectedStyle={selectedStyle} style={{all: 'unset'}}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringForMenu('description');
|
||||
if (!hoverTimeoutId) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
setIsHoveringOnThread("description");
|
||||
}, 500);
|
||||
setHoverTimeoutId(timeoutId);
|
||||
}
|
||||
}}>
|
||||
handleMouseOnLeaveThread();
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
<div className='meta' title="(R)eplies / (L)ink Replies">
|
||||
R: <b>0</b> / L: <b>0</b>
|
||||
{subplebbit.suggested?.avatarUrl ? null : (
|
||||
@@ -561,18 +619,21 @@ const CatalogPost = ({post}) => {
|
||||
)}
|
||||
</BoardForm>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} to={`/p/${selectedAddress}/description`}
|
||||
onClick={() => setSelectedThread("description")} onMouseOver={() => {
|
||||
setIsHoveringForMenu('description');
|
||||
if (!hoverTimeoutId) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
setIsHoveringOnThread("description");
|
||||
}, 500);
|
||||
setHoverTimeoutId(timeoutId);
|
||||
}
|
||||
}}>
|
||||
onClick={() => setSelectedThread("description")}>
|
||||
<div className="teaser" style={{maxHeight: '170px'}}>
|
||||
<div style={{cursor: 'text'}}>
|
||||
<span ref={textRef}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread('description');
|
||||
setIsHoveringForMenu('description');
|
||||
const rect = threadRefs.current['description'].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
<b>Welcome to {subplebbit.title || subplebbit.address}!</b>
|
||||
{": " + subplebbit.description}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
@@ -580,47 +641,63 @@ const CatalogPost = ({post}) => {
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div key={`thread-`} className="thread"
|
||||
onMouseLeave={()=>{handleMouseOnLeaveThread()}} onMouseOver={() => setIsHoveringOnThread(thread.cid)}>
|
||||
<>
|
||||
{isHoveringOnThread === thread.cid ?
|
||||
createPortal(
|
||||
<PostPreview selectedStyle={selectedStyle}>
|
||||
<div ref={popupRef}
|
||||
className="post-preview"
|
||||
onMouseOver={() => handleMouseOnLeaveThread()}
|
||||
style={{
|
||||
opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0,
|
||||
visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden',
|
||||
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" >
|
||||
visibility: isCalculationDone ? 'visible' : 'hidden',
|
||||
left:
|
||||
isCalculationDone && spaceOnRight > 250
|
||||
? isMediaShowed ? imageRect.right + 5 : textRect.right + 5 :
|
||||
isCalculationDone && spaceOnRight < 250
|
||||
? isMediaShowed ? imageRect.left - popupRect.width - 5 : textRect.left - popupRect.width - 5
|
||||
: 'auto',
|
||||
top: popupPosition.top + 5,
|
||||
}}>
|
||||
<span className="post-subject" >
|
||||
{thread.title ? `${thread.title} ` : "Posted "}
|
||||
</span>
|
||||
by
|
||||
<span className="thread_popup_author">
|
||||
<span className="post-author">
|
||||
{thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
|
||||
</span>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}</p>
|
||||
<div>
|
||||
<span className='post-ago'>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}
|
||||
</span>
|
||||
{thread.replyCount > 0 ?
|
||||
<p className="thread_popup_lastReply">
|
||||
Last reply by <span className="thread_popup_author"> Anonymous </span>
|
||||
{getFormattedTime(thread.lastReplyTimestamp)}</p>
|
||||
: null}</div>
|
||||
</div> : null }
|
||||
<div className='post-last'>
|
||||
Last reply by
|
||||
<span className="post-author"> Anonymous </span>
|
||||
<span className='post-ago'>{getFormattedTime(thread.lastReplyTimestamp)}</span>
|
||||
</div>
|
||||
: null}
|
||||
</div>
|
||||
</PostPreview>, document.body
|
||||
)
|
||||
: null }
|
||||
<div key={`thread-`} className="thread"
|
||||
ref={el => {
|
||||
threadRefs.current[thread.cid] = el;
|
||||
}}
|
||||
onMouseLeave={()=>{handleMouseOnLeaveThread()}}>
|
||||
{commentMediaInfo?.url ? (
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${selectedAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
onClick={() => setSelectedThread(thread.cid)}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread(thread.cid);
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
const rect = threadRefs.current[thread.cid].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
{commentMediaInfo?.type === "webpage" ? (
|
||||
thread.thumbnailUrl ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" key={`img-`}
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
@@ -629,9 +706,16 @@ const CatalogPost = ({post}) => {
|
||||
</span>
|
||||
) : null
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "iframe" && (thread.thumbnailUrl || commentMediaInfo.thumbnail) ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => { e.target.src = fallbackImgUrl }} />
|
||||
</span>
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "image" ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" key={`img-`}
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.url} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
@@ -640,14 +724,14 @@ const CatalogPost = ({post}) => {
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "video" ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<video className="card" key={`fti-`}
|
||||
<video className="card" ref={imageRef} key={`fti-`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
</span>
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "audio" ? (
|
||||
<audio className="card" controls
|
||||
<audio className="card" ref={imageRef} controls
|
||||
key={`fti-`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
@@ -655,11 +739,7 @@ const CatalogPost = ({post}) => {
|
||||
) : null}
|
||||
</Link>
|
||||
) : null}
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? (
|
||||
{isMediaShowed ? (
|
||||
<div key={`ti-`} className="thread-icons" >
|
||||
{thread.pinned ? (
|
||||
<span key={`si-`} className="thread-icon sticky-icon" title="Sticky"
|
||||
@@ -674,6 +754,11 @@ const CatalogPost = ({post}) => {
|
||||
</div>
|
||||
) : null}
|
||||
<BoardForm selectedStyle={selectedStyle}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
handleMouseOnLeaveThread();
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}
|
||||
style={{ all: "unset"}}>
|
||||
<div key={`meta-`} className="meta" title="(R)eplies / (L)ink Replies" >
|
||||
R: <b key={`b-`}>{thread.replyCount}</b>
|
||||
@@ -683,11 +768,7 @@ const CatalogPost = ({post}) => {
|
||||
L: <b key={`i-`}>{linkCount}</b>
|
||||
</>
|
||||
) : null}
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? null : (
|
||||
{isMediaShowed ? null : (
|
||||
<div className='thread-icons'
|
||||
style={{position: 'absolute', top: '-2px', right: '15px'}}>
|
||||
{thread.pinned ? (
|
||||
@@ -703,7 +784,7 @@ const CatalogPost = ({post}) => {
|
||||
</div>
|
||||
)}
|
||||
<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',
|
||||
zIndex: '999'}}
|
||||
key={`pmb-`}
|
||||
@@ -776,10 +857,7 @@ const CatalogPost = ({post}) => {
|
||||
) : null}
|
||||
</>
|
||||
)}</VerifiedAuthor>
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? (
|
||||
{isMediaShowed ? (
|
||||
<li
|
||||
onMouseOver={() => {setIsImageSearchOpen(true)}}
|
||||
onMouseLeave={() => {setIsImageSearchOpen(false)}}>
|
||||
@@ -842,14 +920,23 @@ const CatalogPost = ({post}) => {
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link2-`} to={`/p/${selectedAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
<div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}}>
|
||||
<div style={{cursor:"text"}}
|
||||
ref={(el) => (threadRefs.current[thread.cid] = el)}>
|
||||
<div style={{cursor:"text"}}>
|
||||
<span key={`teaser-width${thread.cid}`} ref={textRef}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread(thread.cid);
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
const rect = threadRefs.current[thread.cid].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
<b key={`b2-`}>{thread.title ? `${thread.title}` : null}</b>
|
||||
{thread.content ? `: ${thread.content}` : null}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -496,7 +496,7 @@ const Pending = () => {
|
||||
style={{cursor: "pointer"}}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -553,7 +553,7 @@ const Pending = () => {
|
||||
onError={(e) => e.target.src = fallbackImgUrl}
|
||||
/>
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
|
||||
@@ -729,7 +729,7 @@ const Subscriptions = () => {
|
||||
commentMediaInfo?.url.slice(0, 30) + "(...)" :
|
||||
commentMediaInfo?.url
|
||||
}</a> ({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
|
||||
{isThreadThumbnailClicked[index] ? (
|
||||
{isThreadThumbnailClicked[index] && commentMediaInfo.type !== "image" ? (
|
||||
<span>
|
||||
-[
|
||||
<span className='reply-link'
|
||||
@@ -938,7 +938,7 @@ const Subscriptions = () => {
|
||||
<ul className="post-menu-catalog">
|
||||
<li onClick={() => {
|
||||
handleOptionClick(thread.cid);
|
||||
handleShareClick(selectedAddress, thread.cid);
|
||||
handleShareClick(thread.subplebbitAddress, thread.cid);
|
||||
}}>Share thread</li>
|
||||
<VerifiedAuthor commentCid={thread.cid}>{({ authorAddress }) => (
|
||||
<>
|
||||
@@ -1018,19 +1018,19 @@ const Subscriptions = () => {
|
||||
style={{display: isClientRedirectMenuOpen ? 'block': 'none'}}>
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://plebbitapp.eth.limo/#/p/${selectedAddress}/c/${thread.cid}`}
|
||||
href={`https://plebbitapp.eth.limo/#/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebbit</a>
|
||||
</li>
|
||||
{/* <li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://seedit.eth.limo/#/p/${selectedAddress}/c/${thread.cid}`}
|
||||
href={`https://seedit.eth.limo/#/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Seedit</a>
|
||||
</li> */}
|
||||
<li onClick={() => handleOptionClick(thread.cid)}>
|
||||
<a
|
||||
href={`https://plebones.netlify.app/#/p/${selectedAddress}/c/${thread.cid}`}
|
||||
href={`https://plebones.netlify.app/#/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebones</a>
|
||||
</li>
|
||||
@@ -1110,7 +1110,7 @@ const Subscriptions = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`ttl-s-br2${index}`} />
|
||||
Post too long.
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view.
|
||||
</span>
|
||||
</blockquote>
|
||||
@@ -1273,7 +1273,7 @@ const Subscriptions = () => {
|
||||
<ul className="post-menu-catalog">
|
||||
<li onClick={() => {
|
||||
handleOptionClick(reply.cid);
|
||||
handleShareClick(selectedAddress, thread.cid);
|
||||
handleShareClick(thread.subplebbitAddress, thread.cid);
|
||||
}}>Share thread</li>
|
||||
<VerifiedAuthor commentCid={reply.cid}>{({ authorAddress }) => (
|
||||
<>
|
||||
@@ -1353,19 +1353,19 @@ const Subscriptions = () => {
|
||||
style={{display: isClientRedirectMenuOpen ? 'block': 'none'}}>
|
||||
<li onClick={() => handleOptionClick(reply.cid)}>
|
||||
<a
|
||||
href={`https://plebbitapp.eth.limo/#/p/${selectedAddress}/c/${reply.cid}`}
|
||||
href={`https://plebbitapp.eth.limo/#/p/${thread.subplebbitAddress}/c/${reply.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebbit</a>
|
||||
</li>
|
||||
{/* <li onClick={() => handleOptionClick(reply.cid)}>
|
||||
<a
|
||||
href={`https://seedit.eth.limo/#/p/${selectedAddress}/c/${reply.cid}`}
|
||||
href={`https://seedit.eth.limo/#/p/${thread.subplebbitAddress}/c/${reply.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Seedit</a>
|
||||
</li> */}
|
||||
<li onClick={() => handleOptionClick(reply.cid)}>
|
||||
<a
|
||||
href={`https://plebones.netlify.app/#/p/${selectedAddress}/c/${reply.cid}`}
|
||||
href={`https://plebones.netlify.app/#/p/${thread.subplebbitAddress}/c/${reply.cid}`}
|
||||
target="_blank" rel="noreferrer"
|
||||
>Plebones</a>
|
||||
</li>
|
||||
@@ -1441,7 +1441,7 @@ const Subscriptions = () => {
|
||||
replyMediaInfo?.url.slice(0, 30) + "(...)" :
|
||||
replyMediaInfo?.url
|
||||
}</a> ({replyMediaInfo?.type})
|
||||
{replyMediaInfo?.type === "video" || "iframe" ? (
|
||||
{replyMediaInfo?.type === "video" || replyMediaInfo?.type === "iframe" ? (
|
||||
isReplyThumbnailClicked[index] ? (
|
||||
<span>
|
||||
-[
|
||||
@@ -1619,7 +1619,7 @@ const Subscriptions = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`ttl-s-br2${reply.cid}`} />
|
||||
Comment too long.
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view. </span>
|
||||
</blockquote>
|
||||
</Fragment>
|
||||
@@ -1853,7 +1853,7 @@ const Subscriptions = () => {
|
||||
style={{cursor: "pointer"}}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -1910,7 +1910,7 @@ const Subscriptions = () => {
|
||||
onError={(e) => e.target.src = fallbackImgUrl}
|
||||
/>
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -1947,7 +1947,7 @@ const Subscriptions = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`mob-ttl-s-br2${thread.cid}`} />
|
||||
Post too long.
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view. </span>
|
||||
</blockquote>
|
||||
</Fragment>
|
||||
@@ -2226,7 +2226,7 @@ const Subscriptions = () => {
|
||||
className="ttl ellipsis"/>
|
||||
<br key={`mob-ttl-s-br2${reply.cid}`} />
|
||||
Comment too long.
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
<Link key={`mob-ttl-l-${index}`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="ttl-link">Click here</Link>
|
||||
to view. </span>
|
||||
</blockquote>
|
||||
</Fragment>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Virtuoso } from 'react-virtuoso';
|
||||
import { useAccount, useFeed, usePublishCommentEdit, useSubplebbit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import { debounce } from 'lodash';
|
||||
import { Container, NavBar, Header, Break, PostMenu, BoardForm } from '../styled/views/Board.styled';
|
||||
import { Threads, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { Threads, PostPreview, PostMenuCatalog } from '../styled/views/Catalog.styled';
|
||||
import { TopBar, Footer } from '../styled/views/Thread.styled';
|
||||
import { AlertModal } from '../styled/modals/AlertModal.styled';
|
||||
import CatalogLoader from '../CatalogLoader';
|
||||
@@ -61,6 +61,7 @@ const CatalogPost = ({post}) => {
|
||||
const fallbackImgUrl = "assets/filedeleted-res.gif";
|
||||
const [isHoveringOnThread, setIsHoveringOnThread] = useState(false);
|
||||
const [menuPosition, setMenuPosition] = useState({top: 0, left: 0});
|
||||
const [popupPosition, setPopupPosition] = useState({top: 0, left: 0});
|
||||
const [openMenuCid, setOpenMenuCid] = useState(null);
|
||||
const [triggerPublishCommentEdit, setTriggerPublishCommentEdit] = useState(false);
|
||||
const [isImageSearchOpen, setIsImageSearchOpen] = useState(false);
|
||||
@@ -74,40 +75,73 @@ const CatalogPost = ({post}) => {
|
||||
const account = useAccount();
|
||||
const subplebbit = useSubplebbit({subplebbitAddress: thread.subplebbitAddress});
|
||||
const threadMenuRefs = useRef({});
|
||||
const threadRefs = useRef({});
|
||||
const postMenuRef = useRef(null);
|
||||
const postMenuCatalogRef = useRef(null);
|
||||
const popupRef = useRef(null);
|
||||
const threadRefs = useRef([]);
|
||||
const [isEnoughSpaceOnRight, setIsEnoughSpaceOnRight] = useState(null);
|
||||
const [isEnoughSpaceOnLeft,setIsEnoughSpaceOnLeft] = useState(null);
|
||||
const textRef = useRef(null);
|
||||
const imageRef = useRef(null);
|
||||
const [spaceOnRight, setSpaceOnRight] = useState(null);
|
||||
const [isCalculationDone,setIsCalculationDone] = useState(false);
|
||||
const [hoverTimeoutId, setHoverTimeoutId] = useState(null);
|
||||
const [isHoveringForMenu, setIsHoveringForMenu] = useState(false);
|
||||
const textRect = textRef.current?.getBoundingClientRect();
|
||||
const imageRect = imageRef.current?.getBoundingClientRect();
|
||||
const popupRect = popupRef.current?.getBoundingClientRect();
|
||||
const isMediaShowed = (thread.link && commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail) ||
|
||||
(commentMediaInfo.type === 'iframe' &&
|
||||
commentMediaInfo.thumbnail))) ? true : false;
|
||||
|
||||
|
||||
const { left: textLeft, right: textRight, width: textWidth } = textRef.current?.getBoundingClientRect() || {};
|
||||
const { left: imageLeft, right: imageRight, width: imageWidth } = imageRef.current?.getBoundingClientRect() || {};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const executeLayoutEffectLogic = () => {
|
||||
let ref;
|
||||
ref = threadRefs.current[isHoveringOnThread];
|
||||
|
||||
if (isMediaShowed) {
|
||||
ref = imageRef.current;
|
||||
} else {
|
||||
ref = textRef.current;
|
||||
}
|
||||
|
||||
if (ref && popupRef.current) {
|
||||
const threadRect = ref.getBoundingClientRect();
|
||||
const popupRect = popupRef.current.getBoundingClientRect();
|
||||
const rect = ref.getBoundingClientRect();
|
||||
const viewportWidth = document.documentElement.clientWidth;
|
||||
const spaceOnRight = viewportWidth - (threadRect.left + threadRect.width);
|
||||
const spaceOnLeft = threadRect.left;
|
||||
const popupWidth = popupRect.width;
|
||||
setIsEnoughSpaceOnLeft(spaceOnLeft >= popupWidth + 10);
|
||||
setIsEnoughSpaceOnRight(spaceOnRight >= popupWidth + 10);
|
||||
const spaceRight = viewportWidth - (rect.left + rect.width);
|
||||
const spaceLeft = rect.left;
|
||||
|
||||
if (spaceRight < 200 && spaceLeft > spaceRight && spaceLeft < 500) {
|
||||
popupRef.current.style.maxWidth = `calc(
|
||||
100vw -
|
||||
${isMediaShowed ? imageWidth : textWidth}px
|
||||
- ${spaceRight + 40}px
|
||||
)`;
|
||||
} else if (spaceRight < 200 && spaceLeft < spaceRight) {
|
||||
popupRef.current.style.maxWidth = `calc(100vw - ${isMediaShowed ? imageWidth : textWidth}px)`;
|
||||
} else {
|
||||
popupRef.current.style.maxWidth = `500px`;
|
||||
}
|
||||
|
||||
setSpaceOnRight(spaceRight);
|
||||
setIsCalculationDone(true);
|
||||
}
|
||||
};
|
||||
|
||||
if (isHoveringOnThread) {
|
||||
const timeoutId = setTimeout(executeLayoutEffectLogic, 500);
|
||||
return () => clearTimeout(timeoutId);
|
||||
const timeoutId = setTimeout(executeLayoutEffectLogic, 250);
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
setIsCalculationDone(false);
|
||||
};
|
||||
}
|
||||
|
||||
}, [isHoveringOnThread]);
|
||||
}, [isHoveringOnThread, isMediaShowed, textLeft, textRight, imageLeft, imageRight, textWidth, imageWidth]);
|
||||
|
||||
|
||||
const handleMouseOnLeaveThread = () => {
|
||||
@@ -117,7 +151,6 @@ const CatalogPost = ({post}) => {
|
||||
setIsHoveringOnThread("")
|
||||
} else if (isHoveringOnThread !== "") {
|
||||
setIsHoveringOnThread("");
|
||||
setIsEnoughSpaceOnRight(null);
|
||||
setIsCalculationDone(false);
|
||||
}
|
||||
};
|
||||
@@ -328,48 +361,63 @@ const CatalogPost = ({post}) => {
|
||||
|
||||
|
||||
return (
|
||||
<div key={`thread-`} className="thread"
|
||||
onMouseOver={() => {setIsHoveringOnThread(thread.cid)}}
|
||||
onMouseLeave={() => {handleMouseOnLeaveThread()}}>
|
||||
<>
|
||||
{isHoveringOnThread === thread.cid ?
|
||||
createPortal(
|
||||
<PostPreview selectedStyle={selectedStyle}>
|
||||
<div ref={popupRef}
|
||||
className="post-preview"
|
||||
onMouseOver={() => handleMouseOnLeaveThread()}
|
||||
style={{
|
||||
opacity: isCalculationDone && isEnoughSpaceOnRight !== null ? 1 : 0,
|
||||
visibility: isCalculationDone && isEnoughSpaceOnRight !== null ? 'visible' : 'hidden',
|
||||
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" >
|
||||
visibility: isCalculationDone ? 'visible' : 'hidden',
|
||||
left:
|
||||
isCalculationDone && spaceOnRight > 250
|
||||
? isMediaShowed ? imageRect.right + 5 : textRect.right + 5 :
|
||||
isCalculationDone && spaceOnRight < 250
|
||||
? isMediaShowed ? imageRect.left - popupRect.width - 5 : textRect.left - popupRect.width - 5
|
||||
: 'auto',
|
||||
top: popupPosition.top + 5,
|
||||
}}>
|
||||
<span className="post-subject" >
|
||||
{thread.title ? `${thread.title} ` : "Posted "}
|
||||
</span>
|
||||
by
|
||||
<span className="thread_popup_author">
|
||||
<span className="post-author">
|
||||
{thread.author.displayName ?` ${thread.author.displayName} ` : " Anonymous "}
|
||||
</span>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}</p>
|
||||
<div>
|
||||
<span className='post-ago'>
|
||||
{thread.timestamp ? getFormattedTime(thread.timestamp) : null}
|
||||
</span>
|
||||
{thread.replyCount > 0 ?
|
||||
<p className="thread_popup_lastReply">
|
||||
Last reply by <span className="thread_popup_author"> Anonymous </span>
|
||||
{getFormattedTime(thread.lastReplyTimestamp)}</p>
|
||||
: null}</div>
|
||||
</div> : null }
|
||||
<div className='post-last'>
|
||||
Last reply by
|
||||
<span className="post-author"> Anonymous </span>
|
||||
<span className='post-ago'>{getFormattedTime(thread.lastReplyTimestamp)}</span>
|
||||
</div>
|
||||
: null}
|
||||
</div>
|
||||
</PostPreview>, document.body
|
||||
)
|
||||
: null }
|
||||
<div key={`thread-`} className="thread"
|
||||
ref={el => {
|
||||
threadRefs.current[thread.cid] = el;
|
||||
}}
|
||||
onMouseLeave={() => {handleMouseOnLeaveThread()}}>
|
||||
{commentMediaInfo?.url ? (
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
onClick={() => setSelectedThread(thread.cid)}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread(thread.cid);
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
const rect = threadRefs.current[thread.cid].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
{commentMediaInfo?.type === "webpage" ? (
|
||||
thread.thumbnailUrl ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" key={`img-`}
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
@@ -378,9 +426,16 @@ const CatalogPost = ({post}) => {
|
||||
</span>
|
||||
) : null
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "iframe" && (thread.thumbnailUrl || commentMediaInfo.thumbnail) ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
|
||||
onError={(e) => { e.target.src = fallbackImgUrl }} />
|
||||
</span>
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "image" ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<img className="card" key={`img-`}
|
||||
<img className="card" ref={imageRef} key={`img-`}
|
||||
src={commentMediaInfo.url} alt={commentMediaInfo.type}
|
||||
onError={(e) => {
|
||||
e.target.src = fallbackImgUrl
|
||||
@@ -389,14 +444,14 @@ const CatalogPost = ({post}) => {
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "video" ? (
|
||||
<span className="file-thumb" style={{width: displayWidth, height: displayHeight}}>
|
||||
<video className="card" key={`fti-`}
|
||||
<video className="card" ref={imageRef} key={`fti-`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
</span>
|
||||
) : null}
|
||||
{commentMediaInfo?.type === "audio" ? (
|
||||
<audio className="card" controls
|
||||
<audio className="card" ref={imageRef} controls
|
||||
key={`fti-`}
|
||||
src={commentMediaInfo.url}
|
||||
alt={commentMediaInfo.type}
|
||||
@@ -405,11 +460,7 @@ const CatalogPost = ({post}) => {
|
||||
</Link>
|
||||
) : null}
|
||||
<div key={`ti-`} className="thread-icons" >
|
||||
{(commentMediaInfo && (
|
||||
commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' &&
|
||||
commentMediaInfo.thumbnail))) ? (
|
||||
{isMediaShowed ? (
|
||||
<OfflineIndicator
|
||||
address={thread.subplebbitAddress}
|
||||
className="thread-icon offline-icon"
|
||||
@@ -422,6 +473,11 @@ const CatalogPost = ({post}) => {
|
||||
)}
|
||||
</div>
|
||||
<BoardForm selectedStyle={selectedStyle}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
handleMouseOnLeaveThread();
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}
|
||||
style={{ all: "unset"}}>
|
||||
<div key={`meta-`} className="meta" title="(R)eplies / (L)ink Replies" >
|
||||
R: <b key={`b-`}>{thread.replyCount}</b>
|
||||
@@ -432,7 +488,7 @@ const CatalogPost = ({post}) => {
|
||||
</>
|
||||
) : null}
|
||||
<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',
|
||||
zIndex: '999'}}
|
||||
key={`pmb-`}
|
||||
@@ -572,13 +628,22 @@ const CatalogPost = ({post}) => {
|
||||
</BoardForm>
|
||||
<Link style={{all: "unset", cursor: "pointer"}} key={`link2-`} to={`/p/${thread.subplebbitAddress}/c/${thread.cid}`}
|
||||
onClick={() => setSelectedThread(thread.cid)}>
|
||||
<div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}}
|
||||
ref={(el) => (threadRefs.current[thread.cid] = el)}>
|
||||
<div key={`t-`} className="teaser" style={{maxHeight: `calc(320px - ${displayHeight})`}}>
|
||||
<span key={`teaser-width${thread.cid}`} ref={textRef}
|
||||
onMouseOver={() => {
|
||||
setIsHoveringOnThread(thread.cid);
|
||||
setIsHoveringForMenu(thread.cid);
|
||||
const rect = threadRefs.current[thread.cid].getBoundingClientRect();
|
||||
setPopupPosition({top: rect.top + window.scrollY, left: rect.left});
|
||||
}}
|
||||
onMouseLeave={() => setIsHoveringForMenu(false)}>
|
||||
<b key={`b2-`}>{thread.title ? `${thread.title}` : null}</b>
|
||||
{thread.content ? `: ${thread.content}` : null}
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1531,7 +1531,7 @@ const Thread = () => {
|
||||
replyMediaInfo?.url.slice(0, 30) + "(...)" :
|
||||
replyMediaInfo?.url
|
||||
}</a> ({replyMediaInfo?.type})
|
||||
{replyMediaInfo?.type === "video" || "iframe" ? (
|
||||
{replyMediaInfo?.type === "video" || replyMediaInfo?.type === "iframe" ? (
|
||||
isReplyThumbnailClicked[index] ? (
|
||||
<span>
|
||||
-[
|
||||
@@ -1816,7 +1816,7 @@ const Thread = () => {
|
||||
style={{cursor: "pointer"}}
|
||||
onError={(e) => e.target.src = fallbackImgUrl} />
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
@@ -1873,7 +1873,7 @@ const Thread = () => {
|
||||
onError={(e) => e.target.src = fallbackImgUrl}
|
||||
/>
|
||||
)}
|
||||
{commentMediaInfo?.type === "video" || "iframe" ? (
|
||||
{commentMediaInfo?.type === "video" || commentMediaInfo?.type === "iframe" ? (
|
||||
isMobileThreadThumbnailClicked[index] ? (
|
||||
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
|
||||
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
|
||||
|
||||
@@ -14,6 +14,13 @@ const getCommentMediaInfo = (comment) => {
|
||||
if (['youtube.com', 'www.youtube.com', 'youtu.be'].includes(host)) {
|
||||
const videoId = host === 'youtu.be' ? url.pathname.slice(1) : url.searchParams.get('v');
|
||||
embedUrl = `https://www.youtube-nocookie.com/embed/${videoId}`;
|
||||
const thumbnailUrl = `https://img.youtube.com/vi/${videoId}/sddefault.jpg`;
|
||||
return {
|
||||
url: comment.link,
|
||||
embedUrl,
|
||||
type: 'iframe',
|
||||
thumbnail: comment.thumbnailUrl || thumbnailUrl,
|
||||
};
|
||||
} else if (host.includes('odysee.com')) {
|
||||
const pathComponents = url.pathname.split('/');
|
||||
const channelAndId = pathComponents[1];
|
||||
|
||||
@@ -2709,6 +2709,54 @@
|
||||
uuid "9.0.0"
|
||||
viem "1.5.2"
|
||||
|
||||
"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#d45a63f7a23e44cd940419124ccb53754db2f14b":
|
||||
version "0.0.3"
|
||||
resolved "https://github.com/plebbit/plebbit-js.git#d45a63f7a23e44cd940419124ccb53754db2f14b"
|
||||
dependencies:
|
||||
"@ensdomains/eth-ens-namehash" "2.0.15"
|
||||
"@keyv/sqlite" "3.6.2"
|
||||
"@plebbit/plebbit-logger" "github:plebbit/plebbit-logger#9525ca9539479918931c3b334e8d490d1c87e507"
|
||||
"@plebbit/proper-lockfile" "github:plebbit/node-proper-lockfile#7fd6332117340c1d3d98dd0afee2d31cc06f72b8"
|
||||
"@types/node-fetch" "2.6.2"
|
||||
"@types/proper-lockfile" "4.1.2"
|
||||
"@types/uuid" "8.3.4"
|
||||
assert "2.0.0"
|
||||
async-wait-until "2.0.12"
|
||||
buffer "6.0.3"
|
||||
captcha-canvas "3.2.1"
|
||||
err-code "3.0.1"
|
||||
ethers "6.7.0"
|
||||
file-type "16.5.4"
|
||||
form-data "4.0.0"
|
||||
hpagent "1.2.0"
|
||||
ipfs-http-client "56.0.3"
|
||||
ipfs-only-hash "4.0.0"
|
||||
is-ipfs "6.0.2"
|
||||
jose "4.11.0"
|
||||
js-sha256 "0.9.0"
|
||||
keyv "4.5.2"
|
||||
knex "2.4.2"
|
||||
libp2p-crypto "0.21.2"
|
||||
limiter "2.1.0"
|
||||
localforage "1.10.0"
|
||||
lodash-es "4.17.21"
|
||||
lru-cache "7.18.3"
|
||||
open-graph-scraper "4.11.1"
|
||||
p-limit "3.1.0"
|
||||
peer-id "0.16.0"
|
||||
probe-image-size "^7.2.3"
|
||||
retry "0.13.1"
|
||||
rpc-websockets "7.5.1"
|
||||
safe-stable-stringify "2.4.1"
|
||||
sha1-uint8array "0.10.3"
|
||||
skia-canvas "1.0.0"
|
||||
sqlite3 "5.1.6"
|
||||
tiny-typed-emitter "2.1.0"
|
||||
tinycache "1.1.2"
|
||||
ts-custom-error "3.3.1"
|
||||
uuid "9.0.0"
|
||||
viem "1.5.2"
|
||||
|
||||
"@plebbit/plebbit-logger@github:plebbit/plebbit-logger#9525ca9539479918931c3b334e8d490d1c87e507":
|
||||
version "0.0.1"
|
||||
uid "9525ca9539479918931c3b334e8d490d1c87e507"
|
||||
@@ -2722,6 +2770,21 @@
|
||||
dependencies:
|
||||
debug "4.3.3"
|
||||
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#55b6e1dc3f11f19fb0b71f5770909d7904cb29c0":
|
||||
version "0.0.1"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#55b6e1dc3f11f19fb0b71f5770909d7904cb29c0"
|
||||
dependencies:
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#d45a63f7a23e44cd940419124ccb53754db2f14b"
|
||||
"@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git"
|
||||
assert "2.0.0"
|
||||
ethers "5.6.9"
|
||||
localforage "1.10.0"
|
||||
lodash.isequal "4.5.0"
|
||||
memoizee "0.4.15"
|
||||
quick-lru "5.1.1"
|
||||
uuid "8.3.2"
|
||||
zustand "4.0.0"
|
||||
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#e741b0dad5bba65cf1f0896053f25cd91ed55cf1":
|
||||
version "0.0.1"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#e741b0dad5bba65cf1f0896053f25cd91ed55cf1"
|
||||
@@ -2737,6 +2800,14 @@
|
||||
uuid "8.3.2"
|
||||
zustand "4.0.0"
|
||||
|
||||
"@plebbit/proper-lockfile@github:plebbit/node-proper-lockfile#7fd6332117340c1d3d98dd0afee2d31cc06f72b8":
|
||||
version "4.1.2"
|
||||
resolved "https://codeload.github.com/plebbit/node-proper-lockfile/tar.gz/7fd6332117340c1d3d98dd0afee2d31cc06f72b8"
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
retry "^0.12.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
"@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
|
||||
version "0.5.11"
|
||||
resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz#7c2268cedaa0644d677e8c4f377bc8fb304f714a"
|
||||
@@ -2906,6 +2977,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
|
||||
|
||||
"@sindresorhus/is@^4.0.0":
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
|
||||
integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
|
||||
|
||||
"@sindresorhus/is@^5.2.0":
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668"
|
||||
@@ -3045,6 +3121,13 @@
|
||||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@szmarczak/http-timer@^4.0.5":
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
|
||||
integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
|
||||
dependencies:
|
||||
defer-to-connect "^2.0.0"
|
||||
|
||||
"@szmarczak/http-timer@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a"
|
||||
@@ -3182,6 +3265,16 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/cacheable-request@^6.0.1":
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183"
|
||||
integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==
|
||||
dependencies:
|
||||
"@types/http-cache-semantics" "*"
|
||||
"@types/keyv" "^3.1.4"
|
||||
"@types/node" "*"
|
||||
"@types/responselike" "^1.0.0"
|
||||
|
||||
"@types/connect-history-api-fallback@^1.3.5":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41"
|
||||
@@ -3291,7 +3384,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
|
||||
integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==
|
||||
|
||||
"@types/http-cache-semantics@^4.0.1":
|
||||
"@types/http-cache-semantics@*", "@types/http-cache-semantics@^4.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
|
||||
integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
|
||||
@@ -3345,6 +3438,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/keyv@^3.1.4":
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6"
|
||||
integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/long@^4.0.1":
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
|
||||
@@ -3497,6 +3597,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/responselike@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
|
||||
integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/retry@*":
|
||||
version "0.12.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a"
|
||||
@@ -4883,6 +4990,11 @@ cacache@^15.2.0:
|
||||
tar "^6.0.2"
|
||||
unique-filename "^1.1.1"
|
||||
|
||||
cacheable-lookup@^5.0.3:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
|
||||
integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==
|
||||
|
||||
cacheable-lookup@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27"
|
||||
@@ -4914,6 +5026,19 @@ cacheable-request@^6.0.0:
|
||||
normalize-url "^4.1.0"
|
||||
responselike "^1.0.2"
|
||||
|
||||
cacheable-request@^7.0.2:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817"
|
||||
integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==
|
||||
dependencies:
|
||||
clone-response "^1.0.2"
|
||||
get-stream "^5.1.0"
|
||||
http-cache-semantics "^4.0.0"
|
||||
keyv "^4.0.0"
|
||||
lowercase-keys "^2.0.0"
|
||||
normalize-url "^6.0.1"
|
||||
responselike "^2.0.0"
|
||||
|
||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
@@ -5041,7 +5166,7 @@ character-entities@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22"
|
||||
integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==
|
||||
|
||||
chardet@^1.5.1:
|
||||
chardet@^1.4.0, chardet@^1.5.1:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-1.6.0.tgz#d04ea6e254916770c0e15ab678cbc7864c967fd1"
|
||||
integrity sha512-+QOTw3otC4+FxdjK9RopGpNOglADbr4WPFi0SonkO99JbpkTPbMxmdm4NenhF5Zs+4gPXLI1+y2uazws5TMe8w==
|
||||
@@ -5063,7 +5188,7 @@ cheerio-select@^2.1.0:
|
||||
domhandler "^5.0.3"
|
||||
domutils "^3.0.1"
|
||||
|
||||
cheerio@^1.0.0-rc.12:
|
||||
cheerio@^1.0.0-rc.11, cheerio@^1.0.0-rc.12:
|
||||
version "1.0.0-rc.12"
|
||||
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683"
|
||||
integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==
|
||||
@@ -5826,7 +5951,7 @@ date-fns@^2.29.3:
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.21.0"
|
||||
|
||||
debug@2.6.9, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9:
|
||||
debug@2, debug@2.6.9, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
@@ -5847,7 +5972,7 @@ debug@4.3.3:
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^3.2.7:
|
||||
debug@^3.2.6, debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
@@ -6007,7 +6132,7 @@ defer-to-connect@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
||||
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
|
||||
|
||||
defer-to-connect@^2.0.1:
|
||||
defer-to-connect@^2.0.0, defer-to-connect@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
|
||||
integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
|
||||
@@ -7816,6 +7941,23 @@ gopd@^1.0.1:
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
got@^11.8.5:
|
||||
version "11.8.6"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a"
|
||||
integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==
|
||||
dependencies:
|
||||
"@sindresorhus/is" "^4.0.0"
|
||||
"@szmarczak/http-timer" "^4.0.5"
|
||||
"@types/cacheable-request" "^6.0.1"
|
||||
"@types/responselike" "^1.0.0"
|
||||
cacheable-lookup "^5.0.3"
|
||||
cacheable-request "^7.0.2"
|
||||
decompress-response "^6.0.0"
|
||||
http2-wrapper "^1.0.0-beta.5.2"
|
||||
lowercase-keys "^2.0.0"
|
||||
p-cancelable "^2.0.0"
|
||||
responselike "^2.0.0"
|
||||
|
||||
got@^12.6.0:
|
||||
version "12.6.1"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549"
|
||||
@@ -8164,6 +8306,14 @@ http-proxy@^1.18.1:
|
||||
follow-redirects "^1.0.0"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
http2-wrapper@^1.0.0-beta.5.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d"
|
||||
integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==
|
||||
dependencies:
|
||||
quick-lru "^5.1.1"
|
||||
resolve-alpn "^1.0.0"
|
||||
|
||||
http2-wrapper@^2.1.10:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.0.tgz#b80ad199d216b7d3680195077bd7b9060fa9d7f3"
|
||||
@@ -8200,7 +8350,7 @@ iconv-corefoundation@^1.1.7:
|
||||
cli-truncate "^2.1.0"
|
||||
node-addon-api "^1.6.3"
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.4:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
@@ -9798,7 +9948,7 @@ keyv@^3.0.0:
|
||||
dependencies:
|
||||
json-buffer "3.0.0"
|
||||
|
||||
keyv@^4.5.3:
|
||||
keyv@^4.0.0, keyv@^4.5.3:
|
||||
version "4.5.3"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25"
|
||||
integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==
|
||||
@@ -10825,6 +10975,15 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
needle@^2.5.2:
|
||||
version "2.9.1"
|
||||
resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684"
|
||||
integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==
|
||||
dependencies:
|
||||
debug "^3.2.6"
|
||||
iconv-lite "^0.4.4"
|
||||
sax "^1.2.4"
|
||||
|
||||
negotiator@0.6.3, negotiator@^0.6.2:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
@@ -11146,6 +11305,17 @@ onetime@^5.1.2:
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
open-graph-scraper@4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/open-graph-scraper/-/open-graph-scraper-4.11.1.tgz#cf52bb8f5703840a6723e8a8911ddbf1628752b2"
|
||||
integrity sha512-cGffZ6MtlEj6e46MqEnRU0qf+OmQDG3YTZOaEI15lhZMGAoUbu0bUsDFaq4QOz3lc9DHC7JprQeyJkTNqs7HjA==
|
||||
dependencies:
|
||||
chardet "^1.4.0"
|
||||
cheerio "^1.0.0-rc.11"
|
||||
got "^11.8.5"
|
||||
iconv-lite "^0.6.3"
|
||||
validator "^13.7.0"
|
||||
|
||||
open-graph-scraper@5.2.3:
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/open-graph-scraper/-/open-graph-scraper-5.2.3.tgz#8a84b4f48d42e18d9ec44453377499acf57cfe66"
|
||||
@@ -11191,6 +11361,11 @@ p-cancelable@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
||||
integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
|
||||
|
||||
p-cancelable@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
|
||||
integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==
|
||||
|
||||
p-cancelable@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050"
|
||||
@@ -12113,6 +12288,15 @@ pretty-format@^29.0.0, pretty-format@^29.6.3:
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^18.0.0"
|
||||
|
||||
probe-image-size@^7.2.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-7.2.3.tgz#d49c64be540ec8edea538f6f585f65a9b3ab4309"
|
||||
integrity sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==
|
||||
dependencies:
|
||||
lodash.merge "^4.6.2"
|
||||
needle "^2.5.2"
|
||||
stream-parser "~0.3.1"
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
@@ -12832,7 +13016,7 @@ requires-port@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
|
||||
|
||||
resolve-alpn@^1.2.0:
|
||||
resolve-alpn@^1.0.0, resolve-alpn@^1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
|
||||
integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==
|
||||
@@ -12895,6 +13079,13 @@ responselike@^1.0.2:
|
||||
dependencies:
|
||||
lowercase-keys "^1.0.0"
|
||||
|
||||
responselike@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc"
|
||||
integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==
|
||||
dependencies:
|
||||
lowercase-keys "^2.0.0"
|
||||
|
||||
responselike@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626"
|
||||
@@ -13639,6 +13830,13 @@ stop-iteration-iterator@^1.0.0:
|
||||
dependencies:
|
||||
internal-slot "^1.0.4"
|
||||
|
||||
stream-parser@~0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773"
|
||||
integrity sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==
|
||||
dependencies:
|
||||
debug "2"
|
||||
|
||||
stream-to-it@^0.2.2:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/stream-to-it/-/stream-to-it-0.2.4.tgz#d2fd7bfbd4a899b4c0d6a7e6a533723af5749bd0"
|
||||
@@ -14797,7 +14995,7 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
validator@^13.9.0:
|
||||
validator@^13.7.0, validator@^13.9.0:
|
||||
version "13.11.0"
|
||||
resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b"
|
||||
integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==
|
||||
|
||||
Reference in New Issue
Block a user