mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix pending reply logic, add it to board
This commit is contained in:
+122
-34
@@ -1,9 +1,10 @@
|
|||||||
import React, { useState, useEffect, useRef, Fragment } from 'react';
|
import React, { Fragment, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { Helmet } from 'react-helmet-async';
|
import { Helmet } from 'react-helmet-async';
|
||||||
import InfiniteScroll from 'react-infinite-scroller';
|
import InfiniteScroll from 'react-infinite-scroller';
|
||||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Tooltip } from 'react-tooltip';
|
import { Tooltip } from 'react-tooltip';
|
||||||
import { useFeed, usePublishComment } from '@plebbit/plebbit-react-hooks';
|
import { useAccount, useAccountComments, useFeed, usePublishComment } from '@plebbit/plebbit-react-hooks';
|
||||||
|
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||||
import { Container, NavBar, Header, Break, PostFormLink, PostFormTable, PostForm, TopBar, BoardForm } from '../styled/Board.styled';
|
import { Container, NavBar, Header, Break, PostFormLink, PostFormTable, PostForm, TopBar, BoardForm } from '../styled/Board.styled';
|
||||||
@@ -19,7 +20,6 @@ import getDate from '../../utils/getDate';
|
|||||||
import handleAddressClick from '../../utils/handleAddressClick';
|
import handleAddressClick from '../../utils/handleAddressClick';
|
||||||
import handleQuoteClick from '../../utils/handleQuoteClick';
|
import handleQuoteClick from '../../utils/handleQuoteClick';
|
||||||
import handleStyleChange from '../../utils/handleStyleChange';
|
import handleStyleChange from '../../utils/handleStyleChange';
|
||||||
import renderComments from '../../utils/renderComments';
|
|
||||||
import useClickForm from '../../hooks/useClickForm';
|
import useClickForm from '../../hooks/useClickForm';
|
||||||
import useError from '../../hooks/useError';
|
import useError from '../../hooks/useError';
|
||||||
import packageJson from '../../../package.json'
|
import packageJson from '../../../package.json'
|
||||||
@@ -62,6 +62,62 @@ const Board = () => {
|
|||||||
const [errorMessage, setErrorMessage] = useState(null);
|
const [errorMessage, setErrorMessage] = useState(null);
|
||||||
useError(errorMessage, [errorMessage]);
|
useError(errorMessage, [errorMessage]);
|
||||||
|
|
||||||
|
const account = useAccount();
|
||||||
|
|
||||||
|
|
||||||
|
const flattenedRepliesByThread = useMemo(() => {
|
||||||
|
return selectedFeed.reduce((acc, thread) => {
|
||||||
|
const replies = flattenCommentsPages(thread.replies);
|
||||||
|
acc[thread.cid] = replies;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}, [selectedFeed]);
|
||||||
|
|
||||||
|
|
||||||
|
const allParentCids = useMemo(() => {
|
||||||
|
const allRepliesCids = Object.values(flattenedRepliesByThread).flatMap(replies => replies.map(reply => reply.cid));
|
||||||
|
const allThreadCids = selectedFeed.map(thread => thread.cid);
|
||||||
|
return [...allThreadCids, ...allRepliesCids];
|
||||||
|
}, [flattenedRepliesByThread, selectedFeed]);
|
||||||
|
|
||||||
|
|
||||||
|
const filter = useMemo(() => ({
|
||||||
|
parentCids: allParentCids
|
||||||
|
}), [allParentCids]);
|
||||||
|
|
||||||
|
|
||||||
|
const { accountComments } = useAccountComments({ filter });
|
||||||
|
|
||||||
|
|
||||||
|
const filteredRepliesByThread = useMemo(() => {
|
||||||
|
const maxRepliesPerThread = 5;
|
||||||
|
|
||||||
|
const accountRepliesNotYetInCommentReplies = selectedFeed.reduce((acc, thread) => {
|
||||||
|
const replyCids = new Set(flattenedRepliesByThread[thread.cid].map(reply => reply.cid));
|
||||||
|
acc[thread.cid] = accountComments.filter(accountReply => !replyCids.has(accountReply.cid) && accountReply.parentCid === thread.cid);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return selectedFeed.reduce((acc, thread) => {
|
||||||
|
const combinedReplies = [...flattenedRepliesByThread[thread.cid], ...accountRepliesNotYetInCommentReplies[thread.cid]].sort((a, b) => a.timestamp - b.timestamp);
|
||||||
|
acc[thread.cid] = {
|
||||||
|
displayedReplies: combinedReplies.slice(0, maxRepliesPerThread),
|
||||||
|
omittedCount: Math.max(combinedReplies.length - maxRepliesPerThread, 0),
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}, [flattenedRepliesByThread, accountComments, selectedFeed]);
|
||||||
|
|
||||||
|
|
||||||
|
const pendingReplyCounts = useMemo(() => {
|
||||||
|
return selectedFeed.reduce((acc, thread) => {
|
||||||
|
const replyCids = new Set(flattenedRepliesByThread[thread.cid].map(reply => reply.cid));
|
||||||
|
acc[thread.cid] = accountComments.filter(accountReply => !replyCids.has(accountReply.cid) && accountReply.parentCid === thread.cid).length;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}, [flattenedRepliesByThread, accountComments, selectedFeed]);
|
||||||
|
|
||||||
|
|
||||||
// temporary title from JSON, gets subplebbitAddress from URL
|
// temporary title from JSON, gets subplebbitAddress from URL
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedAddress(subplebbitAddress);
|
setSelectedAddress(subplebbitAddress);
|
||||||
@@ -396,8 +452,8 @@ const Board = () => {
|
|||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
>
|
>
|
||||||
{selectedFeed.map((thread) => {
|
{selectedFeed.map((thread) => {
|
||||||
const { replies: { pages: { topAll: { comments } = {} } = {} } = {} } = thread;
|
const { replies: { pages: { topAll: {} = {} } = {} } = {} } = thread;
|
||||||
const { renderedComments, omittedCount } = renderComments(comments);
|
const { displayedReplies, omittedCount } = filteredRepliesByThread[thread.cid] || {};
|
||||||
const commentMediaInfo = getCommentMediaInfo(thread);
|
const commentMediaInfo = getCommentMediaInfo(thread);
|
||||||
const fallbackImgUrl = "/assets/filedeleted-res.gif";
|
const fallbackImgUrl = "/assets/filedeleted-res.gif";
|
||||||
return (
|
return (
|
||||||
@@ -542,7 +598,7 @@ const Board = () => {
|
|||||||
</span>
|
</span>
|
||||||
</span>) : null}
|
</span>) : null}
|
||||||
</span>
|
</span>
|
||||||
{renderedComments?.map((reply) => {
|
{displayedReplies?.map((reply) => {
|
||||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||||
const fallbackImgUrl = "/assets/filedeleted-res.gif";
|
const fallbackImgUrl = "/assets/filedeleted-res.gif";
|
||||||
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
|
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
|
||||||
@@ -572,9 +628,21 @@ const Board = () => {
|
|||||||
onClick={() => handleAddressClick(reply.author.shortAddress)}
|
onClick={() => handleAddressClick(reply.author.shortAddress)}
|
||||||
>
|
>
|
||||||
(u/
|
(u/
|
||||||
<span key={`mob-ha-${reply.cid}`}>
|
{reply.author?.shortAddress ?
|
||||||
{reply.author.shortAddress}
|
(
|
||||||
</span>
|
<span key={`mob-ha-${reply.cid}`}>
|
||||||
|
{reply.author?.shortAddress}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span key={`mob-ha-${reply.cid}`}
|
||||||
|
data-tooltip-id="tooltip"
|
||||||
|
data-tooltip-content={account?.author?.address}
|
||||||
|
data-tooltip-place="top"
|
||||||
|
>
|
||||||
|
{account?.author?.address.slice(0, 10) + "(...)"}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -583,14 +651,18 @@ const Board = () => {
|
|||||||
|
|
||||||
<span key={`pn-${reply.cid}`} className="post-number post-number-desktop">
|
<span key={`pn-${reply.cid}`} className="post-number post-number-desktop">
|
||||||
<Link to={() => {}} key={`pl1-${reply.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
|
<Link to={() => {}} key={`pl1-${reply.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
|
||||||
<Link to={`/p/${selectedAddress}/c/${thread.cid}`} id="reply-button" key={`pl2-${reply.cid}`}
|
{reply.shortCid ? (
|
||||||
onClick={(e) => {
|
<Link to={`/p/${selectedAddress}/c/${thread.cid}`} id="reply-button" key={`pl2-${reply.cid}`}
|
||||||
if (e.button === 2) return;
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
if (e.button === 2) return;
|
||||||
setIsReplyOpen(true);
|
e.preventDefault();
|
||||||
setSelectedShortCid(reply.shortCid);
|
setIsReplyOpen(true);
|
||||||
setSelectedParentCid(reply.cid);
|
setSelectedShortCid(reply.shortCid);
|
||||||
}} title="Reply to this post">{reply.shortCid}</Link>
|
setSelectedParentCid(reply.cid);
|
||||||
|
}} title="Reply to this post">{reply.shortCid}</Link>
|
||||||
|
) : (
|
||||||
|
<span key="pending" style={{color: 'red', fontWeight: '700'}}>Pending</span>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
<button key={`pmb-${reply.cid}`} className="post-menu-button" onClick={() => {}} title="Post menu" style={{ all: 'unset', cursor: 'pointer' }} data-cmd="post-menu">▶</button>
|
<button key={`pmb-${reply.cid}`} className="post-menu-button" onClick={() => {}} title="Post menu" style={{ all: 'unset', cursor: 'pointer' }} data-cmd="post-menu">▶</button>
|
||||||
<div id="backlink-id" className="backlink">
|
<div id="backlink-id" className="backlink">
|
||||||
@@ -797,18 +869,18 @@ const Board = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div key={`mob-pl-${thread.cid}`} className="post-link-mobile">
|
<div key={`mob-pl-${thread.cid}`} className="post-link-mobile">
|
||||||
<span key={`mob-info-${thread.cid}`} className="info-mobile">{
|
<span key={`mob-info-${thread.cid}`} className="info-mobile">{
|
||||||
thread.replyCount === 0 ?
|
(thread.replyCount + pendingReplyCounts[thread.cid]) === 0 ?
|
||||||
("No replies")
|
("No replies")
|
||||||
: thread.replyCount === 1 ?
|
: (thread.replyCount + pendingReplyCounts[thread.cid]) === 1 ?
|
||||||
("1 reply")
|
("1 reply")
|
||||||
: thread.replyCount > 1 ?
|
: (thread.replyCount + pendingReplyCounts[thread.cid]) > 1 ?
|
||||||
(thread.replyCount + " replies")
|
((thread.replyCount + pendingReplyCounts[thread.cid]) + " replies")
|
||||||
: null
|
: null
|
||||||
}</span>
|
}</span>
|
||||||
<Link key={`rl2-${thread.cid}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="button-mobile" >View Thread</Link>
|
<Link key={`rl2-${thread.cid}`} to={`/p/${selectedAddress}/c/${thread.cid}`} onClick={() => setSelectedThread(thread.cid)} className="button-mobile" >View Thread</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{renderedComments?.map((reply) => {
|
{displayedReplies?.map((reply) => {
|
||||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||||
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
|
const shortParentCid = findShortParentCid(reply.parentCid, selectedFeed);
|
||||||
return (
|
return (
|
||||||
@@ -837,9 +909,21 @@ const Board = () => {
|
|||||||
onClick={() => handleAddressClick(reply.author.shortAddress)}
|
onClick={() => handleAddressClick(reply.author.shortAddress)}
|
||||||
>
|
>
|
||||||
(u/
|
(u/
|
||||||
<span key={`mob-ha-${reply.cid}`} className="highlight-address-mobile">
|
{reply.author?.shortAddress ?
|
||||||
{reply.author.shortAddress}
|
(
|
||||||
</span>
|
<span key={`mob-ha-${reply.cid}`} className="highlight-address-mobile">
|
||||||
|
{reply.author?.shortAddress}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span key={`mob-ha-${reply.cid}`}
|
||||||
|
data-tooltip-id="tooltip"
|
||||||
|
data-tooltip-content={account?.author?.address}
|
||||||
|
data-tooltip-place="top"
|
||||||
|
>
|
||||||
|
{account?.author?.address.slice(0, 8) + "(...)"}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
</span>
|
</span>
|
||||||
<br key={`mob-br-${reply.cid}`} />
|
<br key={`mob-br-${reply.cid}`} />
|
||||||
@@ -847,15 +931,19 @@ const Board = () => {
|
|||||||
<span key={`mob-dt-${reply.cid}`} className="date-time-mobile post-number-mobile">
|
<span key={`mob-dt-${reply.cid}`} className="date-time-mobile post-number-mobile">
|
||||||
{getDate(reply.timestamp)}
|
{getDate(reply.timestamp)}
|
||||||
<Link to={() => {}} key={`mob-pl1-${reply.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
|
<Link to={() => {}} key={`mob-pl1-${reply.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
|
||||||
<Link to={`/p/${selectedAddress}/c/${thread.cid}`} id="reply-button" key={`mob-pl2-${reply.cid}`}
|
{reply.shortCid ? (
|
||||||
onClick={(e) => {
|
<Link to={`/p/${selectedAddress}/c/${thread.cid}`} id="reply-button" key={`mob-pl2-${reply.cid}`}
|
||||||
if (e.button === 2) return;
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
if (e.button === 2) return;
|
||||||
setIsReplyOpen(true);
|
e.preventDefault();
|
||||||
setSelectedShortCid(reply.shortCid);
|
setIsReplyOpen(true);
|
||||||
setSelectedParentCid(reply.cid);
|
setSelectedShortCid(reply.shortCid);
|
||||||
}} title="Reply to this post">{reply.shortCid}
|
setSelectedParentCid(reply.cid);
|
||||||
</Link>
|
}} title="Reply to this post">{reply.shortCid}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span key="pending" style={{color: 'red', fontWeight: '700'}}>Pending</span>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{reply.link ? (
|
{reply.link ? (
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { Helmet } from 'react-helmet-async';
|
import { Helmet } from 'react-helmet-async';
|
||||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Tooltip } from 'react-tooltip';
|
import { Tooltip } from 'react-tooltip';
|
||||||
import { useAccount, useAccountComment, useComment, usePublishComment } from '@plebbit/plebbit-react-hooks';
|
import { useAccount, useAccountComments, useComment, usePublishComment } from '@plebbit/plebbit-react-hooks';
|
||||||
|
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils'
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
import useGeneralStore from '../../hooks/stores/useGeneralStore';
|
||||||
import { Container, NavBar, Header, Break, PostForm, PostFormTable } from '../styled/Board.styled';
|
import { Container, NavBar, Header, Break, PostForm, PostFormTable } from '../styled/Board.styled';
|
||||||
@@ -19,7 +20,6 @@ import getDate from '../../utils/getDate';
|
|||||||
import handleAddressClick from '../../utils/handleAddressClick';
|
import handleAddressClick from '../../utils/handleAddressClick';
|
||||||
import handleQuoteClick from '../../utils/handleQuoteClick';
|
import handleQuoteClick from '../../utils/handleQuoteClick';
|
||||||
import handleStyleChange from '../../utils/handleStyleChange';
|
import handleStyleChange from '../../utils/handleStyleChange';
|
||||||
import renderThreadComments from '../../utils/renderThreadComments';
|
|
||||||
import useClickForm from '../../hooks/useClickForm';
|
import useClickForm from '../../hooks/useClickForm';
|
||||||
import useError from '../../hooks/useError';
|
import useError from '../../hooks/useError';
|
||||||
import packageJson from '../../../package.json'
|
import packageJson from '../../../package.json'
|
||||||
@@ -35,7 +35,7 @@ const Thread = () => {
|
|||||||
isSettingsOpen, setIsSettingsOpen,
|
isSettingsOpen, setIsSettingsOpen,
|
||||||
setResolveCaptchaPromise,
|
setResolveCaptchaPromise,
|
||||||
setPendingComment,
|
setPendingComment,
|
||||||
pendingCommentIndex, setPendingCommentIndex,
|
setPendingCommentIndex,
|
||||||
selectedAddress, setSelectedAddress,
|
selectedAddress, setSelectedAddress,
|
||||||
setSelectedParentCid,
|
setSelectedParentCid,
|
||||||
setSelectedShortCid,
|
setSelectedShortCid,
|
||||||
@@ -65,9 +65,32 @@ const Thread = () => {
|
|||||||
const [errorMessage, setErrorMessage] = useState(null);
|
const [errorMessage, setErrorMessage] = useState(null);
|
||||||
useError(errorMessage, [errorMessage]);
|
useError(errorMessage, [errorMessage]);
|
||||||
|
|
||||||
const pendingComment = useAccountComment({commentIndex: pendingCommentIndex});
|
|
||||||
|
|
||||||
const renderedComments = renderThreadComments(comment, pendingComment);
|
const flattenedReplies = useMemo(() =>
|
||||||
|
flattenCommentsPages(comment.replies), [comment.replies]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const filter = useMemo(() => ({
|
||||||
|
parentCids: [
|
||||||
|
selectedThread || 'n/a', ...flattenedReplies.map(reply => reply.cid)
|
||||||
|
]
|
||||||
|
}), [flattenedReplies]);
|
||||||
|
|
||||||
|
|
||||||
|
const { accountComments } = useAccountComments({filter});
|
||||||
|
|
||||||
|
|
||||||
|
const accountRepliesNotYetInCommentReplies = useMemo(() => {
|
||||||
|
const commentReplyCids = new Set(flattenedReplies.map(reply => reply.cid))
|
||||||
|
return accountComments.filter(accountReply => !commentReplyCids.has(accountReply.cid))
|
||||||
|
}, [flattenedReplies, accountComments]);
|
||||||
|
|
||||||
|
|
||||||
|
const sortedReplies = useMemo(() => [
|
||||||
|
...accountRepliesNotYetInCommentReplies, ...flattenedReplies
|
||||||
|
].sort((a, b) => a.timestamp - b.timestamp
|
||||||
|
), [accountRepliesNotYetInCommentReplies, flattenedReplies]);
|
||||||
|
|
||||||
// temporary title from JSON, gets subplebbitAddress and threadCid from URL
|
// temporary title from JSON, gets subplebbitAddress and threadCid from URL
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -522,7 +545,7 @@ const Thread = () => {
|
|||||||
{comment.state === "fetching-ipns" ?
|
{comment.state === "fetching-ipns" ?
|
||||||
(null) :
|
(null) :
|
||||||
(comment.replyCount === undefined ? (<PostLoader />) : (null))}
|
(comment.replyCount === undefined ? (<PostLoader />) : (null))}
|
||||||
{renderedComments.map((reply, index) => {
|
{sortedReplies.map((reply, index) => {
|
||||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||||
const fallbackImgUrl = "/assets/filedeleted-res.gif";
|
const fallbackImgUrl = "/assets/filedeleted-res.gif";
|
||||||
const shortParentCid = findShortParentCid(reply.parentCid, comment);
|
const shortParentCid = findShortParentCid(reply.parentCid, comment);
|
||||||
@@ -758,7 +781,7 @@ const Thread = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{comment.replyCount === undefined ? <PostLoader /> : null}
|
{comment.replyCount === undefined ? <PostLoader /> : null}
|
||||||
{renderedComments.map((reply, index) => {
|
{sortedReplies.map((reply, index) => {
|
||||||
const replyMediaInfo = getCommentMediaInfo(reply);
|
const replyMediaInfo = getCommentMediaInfo(reply);
|
||||||
const shortParentCid = findShortParentCid(reply.parentCid, comment);
|
const shortParentCid = findShortParentCid(reply.parentCid, comment);
|
||||||
return (
|
return (
|
||||||
@@ -798,7 +821,7 @@ const Thread = () => {
|
|||||||
data-tooltip-content={account?.author?.address}
|
data-tooltip-content={account?.author?.address}
|
||||||
data-tooltip-place="top"
|
data-tooltip-place="top"
|
||||||
>
|
>
|
||||||
{account?.author?.address.slice(0, 6) + "(...)"}
|
{account?.author?.address.slice(0, 8) + "(...)"}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
function renderComments(comments) {
|
|
||||||
let displayedCount = 0;
|
|
||||||
let omittedCount = 0;
|
|
||||||
|
|
||||||
const renderComment = (comment) => {
|
|
||||||
const { replyCount, replies: { pages: { topAll: { comments: nestedComments = [] } = {} } = {} } = {} } = comment;
|
|
||||||
let renderedNestedComments = [];
|
|
||||||
|
|
||||||
if (replyCount > 0 && nestedComments.length > 0) {
|
|
||||||
const result = renderComments(nestedComments);
|
|
||||||
renderedNestedComments = result.renderedComments;
|
|
||||||
omittedCount += result.omittedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
const allComments = [comment, ...renderedNestedComments];
|
|
||||||
const displayedComments = allComments.slice(0, 5 - displayedCount);
|
|
||||||
|
|
||||||
displayedCount += displayedComments.length;
|
|
||||||
omittedCount += allComments.length - displayedComments.length;
|
|
||||||
|
|
||||||
return displayedComments;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderedComments = comments?.flatMap(renderComment);
|
|
||||||
renderedComments?.sort((a, b) => a.timestamp - b.timestamp);
|
|
||||||
|
|
||||||
return { renderedComments, omittedCount };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default renderComments;
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
function renderThreadComments(comment, pendingComment = null) {
|
|
||||||
const nestedComments = comment?.replies?.pages?.topAll?.comments || {};
|
|
||||||
const commentKeys = Object.keys(nestedComments);
|
|
||||||
|
|
||||||
const renderedComments = commentKeys.map(key => {
|
|
||||||
const comment = nestedComments[key];
|
|
||||||
const { replies: { pages: { topAll: { comments: childNestedComments = [] } = {} } = {} } = {} } = comment;
|
|
||||||
if (comment.replyCount > 0 && childNestedComments) {
|
|
||||||
const renderedNestedComments = renderThreadComments(comment);
|
|
||||||
return [comment, ...renderedNestedComments];
|
|
||||||
}
|
|
||||||
return [comment];
|
|
||||||
}).flat();
|
|
||||||
|
|
||||||
const sortedComments = renderedComments.sort((a, b) => a.timestamp - b.timestamp);
|
|
||||||
|
|
||||||
if (pendingComment?.parentCid === comment?.cid) {
|
|
||||||
sortedComments.push(pendingComment);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sortedComments;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default renderThreadComments;
|
|
||||||
Reference in New Issue
Block a user