Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions components/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export default function Comment ({
? 'yep'
: 'nope')
const ref = useRef(null)
// if comment is registered with the new comments navigator
const didTrackRef = useRef(false)
const { ref: readerRef, onRef: onReaderRef } = useCallbackRef()
const router = useRouter()
const root = useRoot()
Expand Down Expand Up @@ -165,6 +167,8 @@ export default function Comment ({
useEffect(() => {
// checking navigator because outlining should happen only on item pages
if (!navigator || me?.id === item.user?.id) return
// bail if we already registered this comment
if (didTrackRef.current) return

const itemCreatedAt = new Date(item.createdAt).getTime()

Expand Down Expand Up @@ -192,12 +196,18 @@ export default function Comment ({
ref.current.classList.add('outline-new-comment')
}

navigator.trackNewComment(ref, itemCreatedAt)
// track the new comment instantly so that a subsequent unsetOutline can remove it immediately
didTrackRef.current = navigator.trackNewComment(ref, itemCreatedAt)
}, [item.id, root.lastCommentAt, root.meCommentsViewedAt])

// untrack comment from the new comments navigator on unmount
useEffect(() => {
return () => {
navigator.untrackNewComment(ref, { includeDescendants: true })
if (!didTrackRef.current) return
navigator?.untrackNewComment(ref, { includeDescendants: true })
didTrackRef.current = false
}
}, [item.id, root.lastCommentAt, root.meCommentsViewedAt])
}, [])

const bottomedOut = depth === COMMENT_DEPTH_LIMIT || (item.comments?.comments.length === 0 && item.nDirectComments > 0)
// Don't show OP badge when anon user comments on anon user posts
Expand Down
50 changes: 23 additions & 27 deletions components/use-comments-navigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,35 +59,31 @@ export function useCommentsNavigator () {
setHasNewComments(false)
}, [])

// track a new comment
// track a new comment, returns true if the ref was actually inserted
const trackNewComment = useCallback((commentRef, createdAt) => {
setHasNewComments(true)
try {
window.requestAnimationFrame(() => {
if (!commentRef?.current || !commentRef.current.isConnected) return

// dedupe
const existing = commentRefs.current.some(item => item.ref.current === commentRef.current)
if (existing) return

// find the correct insertion position to maintain sort order
const insertIndex = commentRefs.current.findIndex(item => item.createdAt > createdAt)
const newItem = { ref: commentRef, createdAt }

if (insertIndex === -1) {
// append if no newer comments found
commentRefs.current.push(newItem)
} else {
// insert at the correct position to maintain sort order
commentRefs.current.splice(insertIndex, 0, newItem)
}

throttleCountUpdate()
})
} catch {
// in the rare case of a ref being disconnected during RAF, ignore to avoid blocking UI
const node = commentRef?.current
if (!node || !node.isConnected) return false

// dedupe
const existing = commentRefs.current.some(item => item.ref.current === node)
if (existing) return false

// find the correct insertion position to maintain sort order
const insertIndex = commentRefs.current.findIndex(item => item.createdAt > createdAt)
const newItem = { ref: commentRef, createdAt }

if (insertIndex === -1) {
// append if no newer comments found
commentRefs.current.push(newItem)
} else {
// insert at the correct position to maintain sort order
commentRefs.current.splice(insertIndex, 0, newItem)
}
}, [throttleCountUpdate])

setHasNewComments(true)
throttleCountUpdate()
return true
}, [throttleCountUpdate, setHasNewComments])

// remove a comment ref from the list
const untrackNewComment = useCallback((commentRef, options = {}) => {
Expand Down
Loading