diff --git a/src/screens/PostThread/index.tsx b/src/screens/PostThread/index.tsx index 5a9b5f06a9..b78e5e7387 100644 --- a/src/screens/PostThread/index.tsx +++ b/src/screens/PostThread/index.tsx @@ -237,7 +237,7 @@ export function Inner({uri}: {uri: string | undefined}) { threadgateRecord={data?.threadgate?.record ?? undefined} overrides={{ moderation: - shownHiddenReplyKinds.has(HiddenReplyKind.Muted) && + shownHiddenReplyKinds.has(HiddenReplyKind.Hidden) && item.depth > 0, }} onPostSuccess={optimisticOnPostReply} diff --git a/src/state/queries/usePostThread/traversal.ts b/src/state/queries/usePostThread/traversal.ts index feceb9dc67..d407e0f93d 100644 --- a/src/state/queries/usePostThread/traversal.ts +++ b/src/state/queries/usePostThread/traversal.ts @@ -145,8 +145,9 @@ export function traverse( /* * Set this value before incrementing the parent's repliesSeenCount */ - metadata!.repliesIndex = parentMetadata.repliesSeenCount - parentMetadata.repliesSeenCount += 1 + metadata!.repliesIndex = parentMetadata.repliesIndexCount + // Increment the parent's repliesIndexCount + parentMetadata.repliesIndexCount += 1 } const post = views.threadPost({ @@ -165,6 +166,13 @@ export function traverse( * Not moderated, probably need to insert it */ items.push(post) + + /* + * Update seen reply count of parent + */ + if (parentMetadata) { + parentMetadata.repliesSeenCount += 1 + } } else { /* * Moderated in some way, we're going to walk children @@ -201,11 +209,11 @@ export function traverse( storeTraversalMetadata(metadatas, childMetadata) if (childParentMetadata) { /* - * Set this value before incrementing the parent's repliesSeenCount + * Set this value before incrementing the parent's repliesIndexCount */ childMetadata!.repliesIndex = - childParentMetadata.repliesSeenCount - childParentMetadata.repliesSeenCount += 1 + childParentMetadata.repliesIndexCount + childParentMetadata.repliesIndexCount += 1 } const childPost = views.threadPost({ @@ -251,8 +259,44 @@ export function traverse( } } + if (hidden.length) { + if (showHidden) { + items.push(...hidden) + + if (muted.length) { + if (showMuted) { + items.push(...muted) + } else { + items.push({ + type: 'showHiddenReplies', + key: 'showMutedReplies', + kind: HiddenReplyKind.Muted, + }) + } + } + } else { + items.push({ + type: 'showHiddenReplies', + key: 'showHiddenReplies', + kind: HiddenReplyKind.Hidden, + }) + } + } else if (muted.length) { + if (showMuted) { + items.push(...muted) + } else { + items.push({ + type: 'showHiddenReplies', + key: 'showMutedReplies', + kind: HiddenReplyKind.Muted, + }) + } + } + for (let i = 0; i < items.length; i++) { const item = items[i] + const prevItem = items.at(i - 1) + const nextItem = items.at(i + 1) if (item.type === 'threadPost') { if ( @@ -272,19 +316,23 @@ export function traverse( if (metadata) { if (metadata.parentMetadata) { /* - * Copy in the parent's skipped indents + * Track what's before/after now that we've applied moderation */ - metadata.skippedIndentIndices = new Set([ - ...metadata.parentMetadata.skippedIndentIndices, - ]) + if (prevItem?.type === 'threadPost') + metadata.prevItemDepth = prevItem?.depth + if (nextItem?.type === 'threadPost') + metadata.nextItemDepth = nextItem?.depth /* - * We can now officially calculate `isLastSibling` based on the actual data that - * we've seen. + * We can now officially calculate `isLastSibling` and `isLastChild` + * based on the actual data that we've seen. */ metadata.isLastSibling = metadata.repliesIndex === metadata.parentMetadata.repliesSeenCount - 1 + metadata.isLastChild = + metadata.nextItemDepth === undefined || + metadata.nextItemDepth <= metadata.depth /* * If this is the last sibling, it's implicitly part of the last @@ -322,6 +370,13 @@ export function traverse( metadata.parentMetadata.upcomingParentReadMore } + /* + * Copy in the parent's skipped indents + */ + metadata.skippedIndentIndices = new Set([ + ...metadata.parentMetadata.skippedIndentIndices, + ]) + /** * If this is the last sibling, and the parent has no unhydrated * replies, then we know we can skip an indent line. @@ -379,40 +434,6 @@ export function traverse( } } - if (hidden.length) { - if (showHidden) { - items.push(...hidden) - - if (muted.length) { - if (showMuted) { - items.push(...muted) - } else { - items.push({ - type: 'showHiddenReplies', - key: 'showMutedReplies', - kind: HiddenReplyKind.Muted, - }) - } - } - } else { - items.push({ - type: 'showHiddenReplies', - key: 'showHiddenReplies', - kind: HiddenReplyKind.Hidden, - }) - } - } else if (muted.length) { - if (showMuted) { - items.push(...muted) - } else { - items.push({ - type: 'showHiddenReplies', - key: 'showMutedReplies', - kind: HiddenReplyKind.Muted, - }) - } - } - return items } @@ -463,5 +484,6 @@ export function getModerationState(moderation: ModerationDecision) { return { blurred, muted, + modui, } } diff --git a/src/state/queries/usePostThread/types.ts b/src/state/queries/usePostThread/types.ts index 978f2287c0..0809f10516 100644 --- a/src/state/queries/usePostThread/types.ts +++ b/src/state/queries/usePostThread/types.ts @@ -150,11 +150,21 @@ export type TraversalMetadata = { */ repliesUnhydrated: number /** - * The number of replies that have been seen so far in the traversal. After - * traverssal, we can use this to calculate if we actually got all the + * The number of replies that have been seen so far in the traversal. + * Excludes replies that are moderated in some way, since those are not + * "seen" on first load. Use `repliesIndexCount` for the total number of + * replies that were hydrated in the response. + * + * After traverssal, we can use this to calculate if we actually got all the * replies we expected, or if some were blocked, etc. */ repliesSeenCount: number + /** + * The total number of replies to this post hydrated in this response. Used + * for populating the `repliesIndex` of the post by referencing this value on + * the parent. + */ + repliesIndexCount: number /** * The index-0-based index of this reply in the parent post's replies. */ diff --git a/src/state/queries/usePostThread/utils.ts b/src/state/queries/usePostThread/utils.ts index 3db8121c2f..704aefbf67 100644 --- a/src/state/queries/usePostThread/utils.ts +++ b/src/state/queries/usePostThread/utils.ts @@ -59,12 +59,9 @@ export function getTraversalMetadata({ const metadata = { depth: item.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 - * is not necessarily the last leaf in the parent branch, since it could - * have another sibling. + * Unknown until after traversal */ - isLastChild: nextItem?.depth === undefined || nextItem?.depth <= item.depth, + isLastChild: false, /* * Unknown until after traversal */ @@ -89,6 +86,7 @@ export function getTraversalMetadata({ repliesCount, repliesUnhydrated, repliesSeenCount: 0, + repliesIndexCount: 0, repliesIndex: 0, skippedIndentIndices: new Set(), } @@ -138,10 +136,12 @@ export function getThreadPostUI({ showChildReplyLine: depth < 0 || isReplyAndHasReplies, indent: depth, /* - * If there are no slices below this one, or the next slice is less - * indented than the computed indent for this post. + * 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 + * is not necessarily the last leaf in the parent branch, since it could + * have another sibling. */ - isLastChild, //nextItemDepth === undefined || nextItemDepth < depth, + isLastChild, skippedIndentIndices, precedesChildReadMore: precedesChildReadMore ?? false, }