From a4a0fdb060bbc055dbb0cbb8f4e65489d98d99ac Mon Sep 17 00:00:00 2001
From: soxa <6390896+Soxasora@users.noreply.github.com>
Date: Sun, 27 Jul 2025 01:06:22 +0200
Subject: [PATCH] Fix live comments behavior on paginated comments and threads
(#2334)
* livecomments: patches for paginated comments; broader ViewMoreReplies component
live comments:
- don't show the thread button for thread comments that are shown as full items (top level)
- don't try to count/inject on paginated comments, just show the live comments dot
- dedupe new comments being fetched with already existing comments, useful for just showing the dot, but not the button
comments:
- live comments dot now appears on both paginated and bottomed out comments
-- merge ViewAllReplies with ReplyToAnotherPage
* fix thread comment recognition, now based on depth
---
components/comment.js | 40 ++++++++++++++-------------------
components/show-new-comments.js | 8 +++++--
components/use-live-comments.js | 7 +++---
3 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/components/comment.js b/components/comment.js
index 6dab627e..4002d330 100644
--- a/components/comment.js
+++ b/components/comment.js
@@ -261,7 +261,7 @@ export default function Comment ({
{collapse !== 'yep' && (
bottomedOut
- ?
+ )}
>
)
: null}
@@ -294,31 +298,24 @@ export default function Comment ({
)
}
-export function ViewAllReplies ({ id, nshown, nhas }) {
- const text = `view all ${nhas} replies`
-
- return (
-
-
- {text}
-
-
- )
-}
-
-function ReplyOnAnotherPage ({ item }) {
+export function ViewMoreReplies ({ item, navigateRoot = false }) {
const root = useRoot()
- const rootId = commentSubTreeRootId(item, root)
const { cache } = useApolloClient()
+ const id = navigateRoot ? commentSubTreeRootId(item, root) : item.id
- let text = 'reply on another page'
- if (item.ncomments > 0) {
- text = `view all ${item.ncomments} replies`
- }
+ const href = `/items/${id}` + (navigateRoot ? '' : `?commentId=${item.id}`)
+
+ const text = navigateRoot && item.ncomments === 0
+ ? 'reply on another page'
+ : `view all ${item.ncomments} replies`
return (
{
+ if (!item.newComments?.length) return
// clear new comments going to another page
cache.writeFragment({
id: `Item:${item.id}`,
@@ -331,9 +328,6 @@ function ReplyOnAnotherPage ({ item }) {
}
})
}}
- href={`/items/${rootId}?commentId=${item.id}`}
- as={`/items/${rootId}`}
- className='pb-2 fw-bold d-flex align-items-center gap-2 text-muted'
>
{text}
{item.newComments?.length > 0 && }
diff --git a/components/show-new-comments.js b/components/show-new-comments.js
index 914fec2a..cc28686e 100644
--- a/components/show-new-comments.js
+++ b/components/show-new-comments.js
@@ -74,6 +74,10 @@ function traverseNewComments (client, item, onLevel, currentDepth, inSubtree) {
// if we're at the depth limit, stop traversing, we've reached the bottom of the visible thread
if (currentDepth >= COMMENT_DEPTH_LIMIT) return
+ // if the current item shows less comments than its nDirectComments, it's paginated
+ // we don't want to count/inject new comments in paginated items, as they shouldn't be visible
+ if (item.comments?.comments?.length < item.nDirectComments) return
+
if (item.newComments && item.newComments.length > 0) {
const dedupedNewComments = dedupeNewComments(item.newComments, item.comments?.comments)
@@ -161,8 +165,8 @@ export function ShowNewComments ({ topLevel, item, sort, depth = 0 }) {
const client = useApolloClient()
const ref = useRef(null)
- // a thread is a top-level comment
- const thread = item.path?.split('.').length === 2
+ // a thread comment is a comment at depth 1 (parent)
+ const thread = depth === 1
// recurse through all new comments and their children
// if the item is a thread, we also consider all of their existing children
diff --git a/components/use-live-comments.js b/components/use-live-comments.js
index 60d93dc7..d85f3fc2 100644
--- a/components/use-live-comments.js
+++ b/components/use-live-comments.js
@@ -7,12 +7,13 @@ import { itemUpdateQuery, commentUpdateFragment, getLatestCommentCreatedAt } fro
const POLL_INTERVAL = 1000 * 10 // 10 seconds
// merge new comment into item's newComments
-// and prevent duplicates by checking if the comment is already in item's newComments
+// and prevent duplicates by checking if the comment is already in item's newComments or existing comments
function mergeNewComment (item, newComment) {
const existingNewComments = item.newComments || []
+ const existingComments = item.comments?.comments || []
- // is the incoming new comment already in item's new comments?
- if (existingNewComments.includes(newComment.id)) {
+ // is the incoming new comment already in item's new comments or existing comments?
+ if (existingNewComments.includes(newComment.id) || existingComments.some(comment => comment.id === newComment.id)) {
return item
}