Fix bug where replying to grandparents re-orders thread (#8662)
* Fix bug where optimistic replies were inserted above the root post * Rename variables for clarity
This commit is contained in:
@@ -77,53 +77,56 @@ export function createCacheMutator({
|
|||||||
|
|
||||||
function mutator<T>(thread: ApiThreadItem[]): T[] {
|
function mutator<T>(thread: ApiThreadItem[]): T[] {
|
||||||
for (let i = 0; i < thread.length; i++) {
|
for (let i = 0; i < thread.length; i++) {
|
||||||
const existingParent = thread[i]
|
const parent = thread[i]
|
||||||
if (!AppBskyUnspeccedDefs.isThreadItemPost(existingParent.value))
|
|
||||||
continue
|
if (!AppBskyUnspeccedDefs.isThreadItemPost(parent.value)) continue
|
||||||
if (existingParent.uri !== parentUri) continue
|
if (parent.uri !== parentUri) continue
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update parent data
|
* Update parent data
|
||||||
*/
|
*/
|
||||||
existingParent.value.post = {
|
parent.value.post = {
|
||||||
...existingParent.value.post,
|
...parent.value.post,
|
||||||
replyCount: (existingParent.value.post.replyCount || 0) + 1,
|
replyCount: (parent.value.post.replyCount || 0) + 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
const opDid = getRootPostAtUri(existingParent.value.post)?.host
|
const opDid = getRootPostAtUri(parent.value.post)?.host
|
||||||
const nextItem = thread.at(i + 1)
|
const nextPreexistingItem = thread.at(i + 1)
|
||||||
const isReplyToRoot = existingParent.depth === 0
|
|
||||||
const isEndOfReplyChain =
|
const isEndOfReplyChain =
|
||||||
!nextItem || nextItem.depth <= existingParent.depth
|
!nextPreexistingItem || nextPreexistingItem.depth <= parent.depth
|
||||||
const firstReply = replies.at(0)
|
const isParentRoot = parent.depth === 0
|
||||||
|
const isParentBelowRoot = parent.depth > 0
|
||||||
|
const optimisticReply = replies.at(0)
|
||||||
const opIsReplier = AppBskyUnspeccedDefs.isThreadItemPost(
|
const opIsReplier = AppBskyUnspeccedDefs.isThreadItemPost(
|
||||||
firstReply?.value,
|
optimisticReply?.value,
|
||||||
)
|
)
|
||||||
? opDid === firstReply.value.post.author.did
|
? opDid === optimisticReply.value.post.author.did
|
||||||
: false
|
: false
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Always insert replies if the following conditions are met.
|
* Always insert replies if the following conditions are met. Max
|
||||||
|
* depth checks are handled below.
|
||||||
*/
|
*/
|
||||||
const shouldAlwaysInsertReplies =
|
const canAlwaysInsertReplies =
|
||||||
isReplyToRoot ||
|
isParentRoot ||
|
||||||
params.view === 'tree' ||
|
(params.view === 'tree' && isParentBelowRoot) ||
|
||||||
(params.view === 'linear' && isEndOfReplyChain)
|
(params.view === 'linear' && isEndOfReplyChain)
|
||||||
/*
|
/*
|
||||||
* Maybe insert replies if the replier is the OP and certain conditions are met
|
* Maybe insert replies if we're in linear view, the replier is the
|
||||||
|
* OP, and certain conditions are met
|
||||||
*/
|
*/
|
||||||
const shouldReplaceWithOPReplies =
|
const shouldReplaceWithOPReplies =
|
||||||
!isReplyToRoot && params.view === 'linear' && opIsReplier
|
params.view === 'linear' && opIsReplier && isParentBelowRoot
|
||||||
|
|
||||||
if (shouldAlwaysInsertReplies || shouldReplaceWithOPReplies) {
|
if (canAlwaysInsertReplies || shouldReplaceWithOPReplies) {
|
||||||
const branch = getBranch(thread, i, existingParent.depth)
|
const branch = getBranch(thread, i, parent.depth)
|
||||||
/*
|
/*
|
||||||
* OP insertions replace other replies _in linear view_.
|
* OP insertions replace other replies _in linear view_.
|
||||||
*/
|
*/
|
||||||
const itemsToRemove = shouldReplaceWithOPReplies ? branch.length : 0
|
const itemsToRemove = shouldReplaceWithOPReplies ? branch.length : 0
|
||||||
const itemsToInsert = replies
|
const itemsToInsert = replies
|
||||||
.map((r, ri) => {
|
.map((r, ri) => {
|
||||||
r.depth = existingParent.depth + 1 + ri
|
r.depth = parent.depth + 1 + ri
|
||||||
return r
|
return r
|
||||||
})
|
})
|
||||||
.filter(r => {
|
.filter(r => {
|
||||||
|
|||||||
@@ -33,6 +33,12 @@ export function getRootPostAtUri(post: AppBskyFeedDefs.PostView) {
|
|||||||
AppBskyFeedPost.isRecord,
|
AppBskyFeedPost.isRecord,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
/**
|
||||||
|
* If the record has no `reply` field, it is a root post.
|
||||||
|
*/
|
||||||
|
if (!post.record.reply) {
|
||||||
|
return new AtUri(post.uri)
|
||||||
|
}
|
||||||
if (post.record.reply?.root?.uri) {
|
if (post.record.reply?.root?.uri) {
|
||||||
return new AtUri(post.record.reply.root.uri)
|
return new AtUri(post.record.reply.root.uri)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user