diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx
index e5f821bc..f3bc86f3 100644
--- a/src/components/post-desktop/post-desktop.tsx
+++ b/src/components/post-desktop/post-desktop.tsx
@@ -73,6 +73,7 @@ const PostInfo = ({
isPublishing,
onApprove,
onReject,
+ quotedByMap,
}: PostProps) => {
const { t } = useTranslation();
const { author, cid, deleted, locked, pinned, parentCid, postCid, reason, removed, state, subplebbitAddress, timestamp } = post || {};
@@ -425,6 +426,16 @@ const PostInfo = ({
reply?.cid &&
!(reply?.deleted || reply?.removed) && ,
)}
+ {cid &&
+ parentCid &&
+ quotedByMap
+ ?.get(cid)
+ ?.map(
+ (reply: Comment, index: number) =>
+ reply?.parentCid !== cid &&
+ reply?.cid &&
+ !(reply?.deleted || reply?.removed) && ,
+ )}
);
@@ -527,7 +538,7 @@ const PostMedia = ({
);
};
-const Reply = ({ postReplyCount, reply, roles, threadNumber }: PostProps) => {
+const Reply = ({ postReplyCount, reply, roles, threadNumber, quotedByMap }: PostProps) => {
let post = reply;
// handle pending mod or author edit
const { editedComment } = useEditedComment({ comment: reply });
@@ -555,7 +566,7 @@ const Reply = ({ postReplyCount, reply, roles, threadNumber }: PostProps) => {
{'>>'}
-
+
{link && !hidden && !(deleted || removed) && isValidURL(link) && (
(replies || []).filter((reply) => !(reply.deleted && (reply.replyCount === 0 || !reply.replyCount))), [replies]);
+ // Compute quotedByMap: map each quoted CID to array of replies that quote it
+ const quotedByMap = useMemo(() => {
+ const map = new Map();
+ for (const reply of filteredReplies) {
+ const quotedCids = reply.quotedCids;
+ if (quotedCids?.length) {
+ for (const quotedCid of quotedCids) {
+ const arr = map.get(quotedCid);
+ if (arr) arr.push(reply);
+ else map.set(quotedCid, [reply]);
+ }
+ }
+ }
+ return map;
+ }, [filteredReplies]);
+
// Virtuoso scroll position management for infinite replies
const virtuosoRef = useRef(null);
const virtuosoStateKey = `replies-desktop-${cid}`;
@@ -747,7 +774,7 @@ const PostDesktop = ({
data={filteredReplies}
itemContent={(index, reply) => (
-
+
)}
useWindowScroll={true}
@@ -766,7 +793,7 @@ const PostDesktop = ({
!hasMore &&
filteredReplies.map((reply, index) => (
-
+
))}
{/* Non-virtualized rendering for board view (last 5 replies or show omitted) */}
@@ -778,7 +805,7 @@ const PostDesktop = ({
showReplies &&
(showOmittedReplies[cid] ? filteredReplies : filteredReplies.slice(-5)).map((reply, index) => (
-
+
))}
diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx
index 9a0fc77c..4a8d5dee 100644
--- a/src/components/post-mobile/post-mobile.tsx
+++ b/src/components/post-mobile/post-mobile.tsx
@@ -377,14 +377,14 @@ const PostMediaContent = ({ post, link }: { post: any; link: string }) => {
);
};
-const ReplyBacklinks = ({ post }: PostProps) => {
+const ReplyBacklinks = ({ post, quotedByMap }: PostProps) => {
const { cid, parentCid } = post || {};
const { replies } = useReplies({ comment: post, flat: true, accountComments: { newerThan: Infinity } });
return (
cid &&
parentCid &&
- replies.length > 0 && (
+ (replies.length > 0 || quotedByMap?.get(cid)?.length) && (
{replies.map(
(reply: Comment, index: number) =>
@@ -392,12 +392,20 @@ const ReplyBacklinks = ({ post }: PostProps) => {
reply?.cid &&
!(reply?.deleted || reply?.removed) && ,
)}
+ {quotedByMap
+ ?.get(cid)
+ ?.map(
+ (reply: Comment, index: number) =>
+ reply?.parentCid !== cid &&
+ reply?.cid &&
+ !(reply?.deleted || reply?.removed) && ,
+ )}
)
);
};
-const Reply = ({ postReplyCount, reply, roles, threadNumber }: PostProps) => {
+const Reply = ({ postReplyCount, reply, roles, threadNumber, quotedByMap }: PostProps) => {
let post = reply;
// handle pending mod or author edit
const { editedComment } = useEditedComment({ comment: reply });
@@ -423,7 +431,7 @@ const Reply = ({ postReplyCount, reply, roles, threadNumber }: PostProps) => {
>
{!hidden && (!(removed || deleted) || ((removed || deleted) && reason)) &&
}
-
+
@@ -463,6 +471,22 @@ const PostMobile = ({
// Filter out deleted replies with no children for both virtuoso and non-virtuoso rendering
const filteredReplies = useMemo(() => (replies || []).filter((reply) => !(reply.deleted && (reply.replyCount === 0 || !reply.replyCount))), [replies]);
+ // Compute quotedByMap: map each quoted CID to array of replies that quote it
+ const quotedByMap = useMemo(() => {
+ const map = new Map();
+ for (const reply of filteredReplies) {
+ const quotedCids = reply.quotedCids;
+ if (quotedCids?.length) {
+ for (const quotedCid of quotedCids) {
+ const arr = map.get(quotedCid);
+ if (arr) arr.push(reply);
+ else map.set(quotedCid, [reply]);
+ }
+ }
+ }
+ return map;
+ }, [filteredReplies]);
+
// Virtuoso scroll position management for infinite replies
const virtuosoRef = useRef(null);
const virtuosoStateKey = `replies-mobile-${cid}`;
@@ -578,7 +602,7 @@ const PostMobile = ({
data={filteredReplies}
itemContent={(index, reply) => (
-
+
)}
useWindowScroll={true}
@@ -597,7 +621,7 @@ const PostMobile = ({
!hasMore &&
filteredReplies.map((reply, index) => (
-
+
))}
{/* Non-virtualized rendering for board view (last 5 replies) */}
@@ -608,7 +632,7 @@ const PostMobile = ({
showReplies &&
filteredReplies.slice(-5).map((reply, index) => (
-
+
))}
diff --git a/src/views/post/post.tsx b/src/views/post/post.tsx
index e1416051..cebcea9b 100644
--- a/src/views/post/post.tsx
+++ b/src/views/post/post.tsx
@@ -31,6 +31,7 @@ export interface PostProps {
isPublishing?: boolean;
onApprove?: () => void;
onReject?: () => void;
+ quotedByMap?: Map;
}
export const Post = ({