diff --git a/src/state/queries/usePostThread/traversal.ts b/src/state/queries/usePostThread/traversal.ts index 3680173384..5a854e11d9 100644 --- a/src/state/queries/usePostThread/traversal.ts +++ b/src/state/queries/usePostThread/traversal.ts @@ -151,6 +151,17 @@ export function sortAndAnnotateThreadItems( }) if (!post.isBlurred || skipModerationHandling) { + const skip = + parentMetadata?.isPartOfOPThreadFromRoot && + !metadata?.isPartOfOPThreadFromRoot + + if (skip) { + const branch = getBranch(thread, i, item.depth) + // could insert tombstone + i = branch.end + continue traversal + } + /* * Not moderated, need to insert it */ diff --git a/src/state/queries/usePostThread/types.ts b/src/state/queries/usePostThread/types.ts index 3e84dbfc71..1c1eab87e0 100644 --- a/src/state/queries/usePostThread/types.ts +++ b/src/state/queries/usePostThread/types.ts @@ -155,6 +155,16 @@ export type TraversalMetadata = { * tree. Value corresponds to the depth at which this branch started. */ isPartOfLastBranchFromDepth?: number + /** + * Indicates if the post is part of the thread started by the original + * poster, starting from the root post. OP threads within other branches + * of the tree are not considered part of the OP thread. + */ + isPartOfOPThreadFromRoot: boolean + /** + * Indicates if this item is the root post of the thread. + */ + isRoot: boolean /** * The depth of the slice immediately following this one, if it exists. */ diff --git a/src/state/queries/usePostThread/utils.ts b/src/state/queries/usePostThread/utils.ts index be3be36b85..200e0f34c7 100644 --- a/src/state/queries/usePostThread/utils.ts +++ b/src/state/queries/usePostThread/utils.ts @@ -63,6 +63,13 @@ export function getTraversalMetadata({ if (!AppBskyUnspeccedDefs.isThreadItemPost(item.value)) { throw new Error(`Expected thread item to be a post`) } + const rootUri = getRootPostAtUri(item.value.post) + const rootAuthorDid = rootUri?.host + const isRoot = item.uri === item.value.post.uri + const isPartOfOPThreadFromRoot = Boolean( + item.value.post.author.did === rootAuthorDid && + (parentMetadata?.isRoot || parentMetadata?.isPartOfOPThreadFromRoot), + ) const repliesCount = item.value.post.replyCount || 0 const repliesUnhydrated = item.value.moreReplies || 0 const metadata = { @@ -81,6 +88,8 @@ export function getTraversalMetadata({ * replies, we'll override this after traversal. */ isPartOfLastBranchFromDepth: item.depth === 1 ? 1 : undefined, + isPartOfOPThreadFromRoot, + isRoot, nextItemDepth: nextItem?.depth, parentMetadata, prevItemDepth: prevItem?.depth, @@ -130,6 +139,7 @@ export function getThreadPostUI({ repliesCount, prevItemDepth, isLastChild, + isPartOfOPThreadFromRoot, skippedIndentIndices, repliesSeenCounter, repliesUnhydrated, @@ -147,7 +157,7 @@ export function getThreadPostUI({ followsReadMoreUp || (!!prevItemDepth && prevItemDepth !== 0 && prevItemDepth < depth), showChildReplyLine: depth < 0 || isReplyAndHasReplies, - indent: depth, + indent: isPartOfOPThreadFromRoot ? (depth < 1 ? 0 : 1) : depth, /* * If there are no slices below this one, or the next slice has a depth <= * than the depth of this post, it's the last child of the reply tree. It