···77777878 function mutator<T>(thread: ApiThreadItem[]): T[] {
7979 for (let i = 0; i < thread.length; i++) {
8080- const existingParent = thread[i]
8181- if (!AppBskyUnspeccedDefs.isThreadItemPost(existingParent.value))
8282- continue
8383- if (existingParent.uri !== parentUri) continue
8080+ const parent = thread[i]
8181+8282+ if (!AppBskyUnspeccedDefs.isThreadItemPost(parent.value)) continue
8383+ if (parent.uri !== parentUri) continue
84848585 /*
8686 * Update parent data
8787 */
8888- existingParent.value.post = {
8989- ...existingParent.value.post,
9090- replyCount: (existingParent.value.post.replyCount || 0) + 1,
8888+ parent.value.post = {
8989+ ...parent.value.post,
9090+ replyCount: (parent.value.post.replyCount || 0) + 1,
9191 }
92929393- const opDid = getRootPostAtUri(existingParent.value.post)?.host
9494- const nextItem = thread.at(i + 1)
9595- const isReplyToRoot = existingParent.depth === 0
9393+ const opDid = getRootPostAtUri(parent.value.post)?.host
9494+ const nextPreexistingItem = thread.at(i + 1)
9695 const isEndOfReplyChain =
9797- !nextItem || nextItem.depth <= existingParent.depth
9898- const firstReply = replies.at(0)
9696+ !nextPreexistingItem || nextPreexistingItem.depth <= parent.depth
9797+ const isParentRoot = parent.depth === 0
9898+ const isParentBelowRoot = parent.depth > 0
9999+ const optimisticReply = replies.at(0)
99100 const opIsReplier = AppBskyUnspeccedDefs.isThreadItemPost(
100100- firstReply?.value,
101101+ optimisticReply?.value,
101102 )
102102- ? opDid === firstReply.value.post.author.did
103103+ ? opDid === optimisticReply.value.post.author.did
103104 : false
104105105106 /*
106106- * Always insert replies if the following conditions are met.
107107+ * Always insert replies if the following conditions are met. Max
108108+ * depth checks are handled below.
107109 */
108108- const shouldAlwaysInsertReplies =
109109- isReplyToRoot ||
110110- params.view === 'tree' ||
110110+ const canAlwaysInsertReplies =
111111+ isParentRoot ||
112112+ (params.view === 'tree' && isParentBelowRoot) ||
111113 (params.view === 'linear' && isEndOfReplyChain)
112114 /*
113113- * Maybe insert replies if the replier is the OP and certain conditions are met
115115+ * Maybe insert replies if we're in linear view, the replier is the
116116+ * OP, and certain conditions are met
114117 */
115118 const shouldReplaceWithOPReplies =
116116- !isReplyToRoot && params.view === 'linear' && opIsReplier
119119+ params.view === 'linear' && opIsReplier && isParentBelowRoot
117120118118- if (shouldAlwaysInsertReplies || shouldReplaceWithOPReplies) {
119119- const branch = getBranch(thread, i, existingParent.depth)
121121+ if (canAlwaysInsertReplies || shouldReplaceWithOPReplies) {
122122+ const branch = getBranch(thread, i, parent.depth)
120123 /*
121124 * OP insertions replace other replies _in linear view_.
122125 */
123126 const itemsToRemove = shouldReplaceWithOPReplies ? branch.length : 0
124127 const itemsToInsert = replies
125128 .map((r, ri) => {
126126- r.depth = existingParent.depth + 1 + ri
129129+ r.depth = parent.depth + 1 + ri
127130 return r
128131 })
129132 .filter(r => {
+6
src/state/queries/usePostThread/utils.ts
···3333 AppBskyFeedPost.isRecord,
3434 )
3535 ) {
3636+ /**
3737+ * If the record has no `reply` field, it is a root post.
3838+ */
3939+ if (!post.record.reply) {
4040+ return new AtUri(post.uri)
4141+ }
3642 if (post.record.reply?.root?.uri) {
3743 return new AtUri(post.record.reply.root.uri)
3844 }