diff --git a/src/lib/microcosm/thread.ts b/src/lib/microcosm/thread.ts index ff3de96..7ebbb23 100644 --- a/src/lib/microcosm/thread.ts +++ b/src/lib/microcosm/thread.ts @@ -181,7 +181,7 @@ async function expandBelow( signal?: AbortSignal, ): Promise { if (parentDepth >= below) return - const {replies, total} = await fetchReplies( + const {replies} = await fetchReplies( parentUri, branchingFactor, sort, @@ -191,24 +191,47 @@ async function expandBelow( if (replies.length === 0) return const depth = parentDepth + 1 + const willExpandChildren = depth < below for (const reply of replies) { const opThread = !!rootAuthorDid && reply.author.did === rootAuthorDid - // moreReplies is best-effort: how many direct replies we didn't render. - const moreReplies = Math.max(0, total - replies.length) - out.push( - makeThreadItem(reply.uri, depth, reply, {opThread, moreReplies}), - ) - await expandBelow( - reply.uri, - depth, - below, - branchingFactor, - sort, - rootAuthorDid, - viewerDid, - out, - signal, - ) + + // `moreReplies` is about THIS reply's own unshown children, not its + // siblings. If we won't recurse into it (depth limit), it's the reply's full + // reply count; otherwise we recurse and the count is filled by that call, so + // 0 here. (replyCount comes from the full hydration of the reply.) + const ownReplyCount = reply.replyCount ?? 0 + const moreReplies = willExpandChildren ? 0 : ownReplyCount + + const before = out.length + out.push(makeThreadItem(reply.uri, depth, reply, {opThread, moreReplies})) + + if (willExpandChildren) { + await expandBelow( + reply.uri, + depth, + below, + branchingFactor, + sort, + rootAuthorDid, + viewerDid, + out, + signal, + ) + // If recursion rendered fewer children than this reply actually has + // (capped by branchingFactor, or some failed to hydrate), report the + // remainder so the UI can offer to load them. + const rendered = out.length - before - 1 + if (rendered < ownReplyCount) { + const item = out[before] + if ( + item.value.$type === 'app.bsky.unspecced.defs#threadItemPost' + ) { + ;( + item.value as AppBskyUnspeccedDefs.ThreadItemPost + ).moreReplies = ownReplyCount - rendered + } + } + } } }