diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index 8a681139..7ef07f5a 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -990,7 +990,8 @@ const PostDesktop = ({ const commentMediaInfo = useCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight); const hasThumbnail = getHasThumbnail(commentMediaInfo, link); - // Author-deleted replies are hidden from thread replies; moderator removals still render their placeholder. + // Author-deleted replies and no-reason moderator removals are hidden from thread replies. + // Moderator removals with a reason still render their placeholder and reason. const filteredReplies = useMemo(() => filterRepliesForDisplay(freshRepliesForRender), [freshRepliesForRender]); const postsByAuthorInThread = useMemo(() => getThreadPostCountsByAuthor(resolvedPost, filteredReplies), [resolvedPost, filteredReplies]); const directRepliesByParentCid = useMemo(() => { diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 58e13988..33279880 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -717,7 +717,8 @@ const PostMobile = ({ const [failedMediaUrl, setFailedMediaUrl] = useState(); const mediaLoadFailureInfo = failedMediaUrl && failedMediaUrl === resolvedPost?.link ? : undefined; - // Author-deleted replies are hidden from thread replies; moderator removals still render their placeholder. + // Author-deleted replies and no-reason moderator removals are hidden from thread replies. + // Moderator removals with a reason still render their placeholder and reason. const filteredReplies = useMemo(() => filterRepliesForDisplay(freshRepliesForRender), [freshRepliesForRender]); const postsByAuthorInThread = useMemo(() => getThreadPostCountsByAuthor(resolvedPost, filteredReplies), [resolvedPost, filteredReplies]); const previewDisplayReplies = useMemo(() => getPreviewDisplayReplies(filteredReplies, BOARD_REPLIES_PREVIEW_VISIBLE_COUNT), [filteredReplies]); diff --git a/src/lib/utils/__tests__/misc-utils.test.ts b/src/lib/utils/__tests__/misc-utils.test.ts index b62466e7..36124d59 100644 --- a/src/lib/utils/__tests__/misc-utils.test.ts +++ b/src/lib/utils/__tests__/misc-utils.test.ts @@ -171,10 +171,15 @@ describe('misc utils', () => { }); it('builds reply previews, omitted counts, and fallback reply totals', () => { - expect(filterRepliesForDisplay([{ cid: 'visible' }, { cid: 'deleted', deleted: true }, { cid: 'removed', deleted: false }])).toEqual([ - { cid: 'visible' }, - { cid: 'removed', deleted: false }, - ]); + expect( + filterRepliesForDisplay([ + { cid: 'visible' }, + { cid: 'deleted', deleted: true }, + { cid: 'removed', removed: true }, + { cid: 'blank-reason', reason: ' ', removed: true }, + { cid: 'removed-with-reason', reason: 'off-topic', removed: true }, + ]), + ).toEqual([{ cid: 'visible' }, { cid: 'removed-with-reason', reason: 'off-topic', removed: true }]); expect( getPreviewDisplayReplies( diff --git a/src/lib/utils/replies-preview-utils.ts b/src/lib/utils/replies-preview-utils.ts index 31317f2b..7b03fdc7 100644 --- a/src/lib/utils/replies-preview-utils.ts +++ b/src/lib/utils/replies-preview-utils.ts @@ -6,6 +6,8 @@ interface CommentLike { index?: number; number?: number; pendingApproval?: boolean; + reason?: string | null; + removed?: boolean; state?: string; timestamp?: number; } @@ -44,7 +46,7 @@ export function sortRepliesForDisplay(replies: T[]): T[] } export function filterRepliesForDisplay(replies: T[]): T[] { - return replies.filter((reply) => !reply.deleted); + return replies.filter((reply) => !reply.deleted && (!reply.removed || Boolean(reply.reason?.trim()))); } /**