diff --git a/src/screens/PostThread/components/ThreadItemReadMore.tsx b/src/screens/PostThread/components/ThreadItemReadMore.tsx index ba1230f263..47290b19fb 100644 --- a/src/screens/PostThread/components/ThreadItemReadMore.tsx +++ b/src/screens/PostThread/components/ThreadItemReadMore.tsx @@ -29,7 +29,6 @@ export const ThreadItemReadMore = memo(function ThreadItemReadMore({ const {_} = useLingui() const isTreeView = view === 'tree' const indent = Math.max(0, item.ui.indent - 1) - console.log({indent, id: item.ui.indent}) const spacers = isTreeView ? Array.from(Array(indent)).map((_, n: number) => { diff --git a/src/state/queries/usePostThread/traversal.ts b/src/state/queries/usePostThread/traversal.ts index 59e98589f5..2a174ab11a 100644 --- a/src/state/queries/usePostThread/traversal.ts +++ b/src/state/queries/usePostThread/traversal.ts @@ -154,6 +154,7 @@ export function sortAndAnnotateThreadItems( if (!post.isBlurred || skipModerationHandling) { const skip = parentMetadata?.isPartOfOPThreadFromRoot && + !parentMetadata.isEndOfOPThreadFromRoot && !metadata?.isPartOfOPThreadFromRoot if (skip) { @@ -364,19 +365,25 @@ export function sortAndAnnotateThreadItems( ]) /** - * If this is the last sibling, and the parent has no unhydrated - * replies, then we know we can skip an indent line. + * If the parent has no unhydrated replies that may require a + * `readMore`, we may be able to skip some of the indent lines. */ - if ( - metadata.parentMetadata.repliesUnhydrated <= 0 && - metadata.isLastSibling - ) { - /** - * Depth is 2 more than the 0-index of the indent calculation - * bc of how we render these. So instead of handling that in the - * component, we just adjust that back to 0-index here. - */ - metadata.skippedIndentIndices.add(item.depth - 2) + if (metadata.parentMetadata.repliesUnhydrated <= 0) { + if (metadata.isLastSibling) { + /** + * We should definitely have a "last sibling" at this point. + * + * Note: depth is 2 more than the 0-index of the indent + * calculation bc of how we render these. So instead of + * handling that in the component, we just adjust that back to + * 0-index here. + */ + metadata.skippedIndentIndices.add(item.depth - 2) + } else if (metadata.parentMetadata?.isEndOfOPThreadFromRoot) { + metadata.skippedIndentIndices.delete( + metadata.parentMetadata.indent - 1, + ) + } } } diff --git a/src/state/queries/usePostThread/types.ts b/src/state/queries/usePostThread/types.ts index 6c88317c59..588c23ebf4 100644 --- a/src/state/queries/usePostThread/types.ts +++ b/src/state/queries/usePostThread/types.ts @@ -170,10 +170,12 @@ export type TraversalMetadata = { * of the tree are not considered part of the OP thread. */ isPartOfOPThreadFromRoot: boolean + isEndOfOPThreadFromRoot: boolean /** * Indicates if this item is the root post of the thread. */ - isRoot: boolean + isRootPost: boolean + endOfOPThreadDepthOffset: number /** * 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 7bd6ac63ee..9ef0a4e11c 100644 --- a/src/state/queries/usePostThread/utils.ts +++ b/src/state/queries/usePostThread/utils.ts @@ -63,18 +63,40 @@ 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 === rootUri?.toString() - const isPartOfOPThreadFromRoot = Boolean( - item.value.post.author.did === rootAuthorDid && - (parentMetadata?.isRoot || parentMetadata?.isPartOfOPThreadFromRoot), + const rootPostUri = getRootPostAtUri(item.value.post) + const isRootPost = item.uri === rootPostUri?.toString() + const rootPostAuthorDid = rootPostUri?.host + const currentPostAuthorDid = item.value.post.author.did + const currentPostIsByRootAuthor = currentPostAuthorDid === rootPostAuthorDid + const nextPostAuthorDid = + nextItem && AppBskyUnspeccedDefs.isThreadItemPost(nextItem.value) + ? nextItem.value.post.author.did + : undefined + + const parentIsPartOfOPThreadFromRoot = Boolean( + parentMetadata?.isRootPost || parentMetadata?.isPartOfOPThreadFromRoot, ) + const isPartOfOPThreadFromRoot = + currentPostIsByRootAuthor && parentIsPartOfOPThreadFromRoot + const isEndOfOPThreadFromRoot = + isPartOfOPThreadFromRoot && currentPostAuthorDid !== nextPostAuthorDid + + let indent = item.depth + if (isPartOfOPThreadFromRoot) { + indent = item.depth > 1 ? 1 : 0 + } else if (parentMetadata?.endOfOPThreadDepthOffset) { + indent = item.depth - parentMetadata?.endOfOPThreadDepthOffset + } + + // minus 1 so that the next reply under the end of the OP thread is indented by 1 + const endOfOPThreadDepthOffset = isEndOfOPThreadFromRoot ? item.depth - 1 : 0 + const repliesCount = item.value.post.replyCount || 0 const repliesUnhydrated = item.value.moreReplies || 0 + const metadata = { depth: item.depth, - indent: isPartOfOPThreadFromRoot ? (item.depth < 1 ? 0 : 1) : item.depth, + indent, /* * Unknown until after traversal */ @@ -90,7 +112,10 @@ export function getTraversalMetadata({ */ isPartOfLastBranchFromDepth: item.depth === 1 ? 1 : undefined, isPartOfOPThreadFromRoot, - isRoot, + isEndOfOPThreadFromRoot, + isRootPost, + endOfOPThreadDepthOffset: + parentMetadata?.endOfOPThreadDepthOffset || endOfOPThreadDepthOffset, nextItemDepth: nextItem?.depth, parentMetadata, prevItemDepth: prevItem?.depth,