Improve moderation behaviors: show alert/inform sources and improve UX around threads (#3677)
* Dont show account or profile alerts and informs on posts * Sort threads to put blurred items at bottom * Group blurred replies under a single 'show hidden replies' control * Distinguish between muted and hidden replies in the thread view * Fix types * Modify the label alerts with some minor aesthetic updates and to show the source of a label * Tune when an account-level alert is shown on a post * Revert: show account-level alerts on posts again * Rm unused import * Fix to showing hidden replies when viewing a blurred item * Go ahead and uncover replies when 'show hidden posts' is clicked --------- Co-authored-by: dan <dan.abramov@gmail.com>
This commit is contained in:
parent
d2c42cf169
commit
f7ee532a85
9 changed files with 311 additions and 67 deletions
|
@ -3,9 +3,12 @@ import {
|
|||
AppBskyFeedDefs,
|
||||
AppBskyFeedGetPostThread,
|
||||
AppBskyFeedPost,
|
||||
ModerationDecision,
|
||||
ModerationOpts,
|
||||
} from '@atproto/api'
|
||||
import {QueryClient, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
|
||||
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from 'state/queries/search-posts'
|
||||
|
@ -21,8 +24,6 @@ export interface ThreadCtx {
|
|||
depth: number
|
||||
isHighlightedPost?: boolean
|
||||
hasMore?: boolean
|
||||
showChildReplyLine?: boolean
|
||||
showParentReplyLine?: boolean
|
||||
isParentLoading?: boolean
|
||||
isChildLoading?: boolean
|
||||
}
|
||||
|
@ -63,6 +64,8 @@ export type ThreadNode =
|
|||
| ThreadBlocked
|
||||
| ThreadUnknown
|
||||
|
||||
export type ThreadModerationCache = WeakMap<ThreadNode, ModerationDecision>
|
||||
|
||||
export function usePostThreadQuery(uri: string | undefined) {
|
||||
const queryClient = useQueryClient()
|
||||
const {getAgent} = useAgent()
|
||||
|
@ -92,9 +95,28 @@ export function usePostThreadQuery(uri: string | undefined) {
|
|||
})
|
||||
}
|
||||
|
||||
export function fillThreadModerationCache(
|
||||
cache: ThreadModerationCache,
|
||||
node: ThreadNode,
|
||||
moderationOpts: ModerationOpts,
|
||||
) {
|
||||
if (node.type === 'post') {
|
||||
cache.set(node, moderatePost(node.post, moderationOpts))
|
||||
if (node.parent) {
|
||||
fillThreadModerationCache(cache, node.parent, moderationOpts)
|
||||
}
|
||||
if (node.replies) {
|
||||
for (const reply of node.replies) {
|
||||
fillThreadModerationCache(cache, reply, moderationOpts)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function sortThread(
|
||||
node: ThreadNode,
|
||||
opts: UsePreferencesQueryResponse['threadViewPrefs'],
|
||||
modCache: ThreadModerationCache,
|
||||
): ThreadNode {
|
||||
if (node.type !== 'post') {
|
||||
return node
|
||||
|
@ -117,6 +139,18 @@ export function sortThread(
|
|||
} else if (bIsByOp) {
|
||||
return 1 // op's own reply
|
||||
}
|
||||
|
||||
const aBlur = Boolean(modCache.get(a)?.ui('contentList').blur)
|
||||
const bBlur = Boolean(modCache.get(b)?.ui('contentList').blur)
|
||||
if (aBlur !== bBlur) {
|
||||
if (aBlur) {
|
||||
return 1
|
||||
}
|
||||
if (bBlur) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.prioritizeFollowedUsers) {
|
||||
const af = a.post.author.viewer?.following
|
||||
const bf = b.post.author.viewer?.following
|
||||
|
@ -126,6 +160,7 @@ export function sortThread(
|
|||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.sort === 'oldest') {
|
||||
return a.post.indexedAt.localeCompare(b.post.indexedAt)
|
||||
} else if (opts.sort === 'newest') {
|
||||
|
@ -141,7 +176,7 @@ export function sortThread(
|
|||
}
|
||||
return b.post.indexedAt.localeCompare(a.post.indexedAt)
|
||||
})
|
||||
node.replies.forEach(reply => sortThread(reply, opts))
|
||||
node.replies.forEach(reply => sortThread(reply, opts, modCache))
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
@ -188,12 +223,6 @@ function responseToThreadNodes(
|
|||
isHighlightedPost: depth === 0,
|
||||
hasMore:
|
||||
direction === 'down' && !node.replies?.length && !!node.replyCount,
|
||||
showChildReplyLine:
|
||||
direction === 'up' ||
|
||||
(direction === 'down' && !!node.replies?.length),
|
||||
showParentReplyLine:
|
||||
(direction === 'up' && !!node.parent) ||
|
||||
(direction === 'down' && depth !== 1),
|
||||
},
|
||||
}
|
||||
} else if (AppBskyFeedDefs.isBlockedPost(node)) {
|
||||
|
@ -296,8 +325,6 @@ function threadNodeToPlaceholderThread(
|
|||
depth: 0,
|
||||
isHighlightedPost: true,
|
||||
hasMore: false,
|
||||
showChildReplyLine: false,
|
||||
showParentReplyLine: false,
|
||||
isParentLoading: !!node.record.reply,
|
||||
isChildLoading: !!node.post.replyCount,
|
||||
},
|
||||
|
@ -319,8 +346,6 @@ function postViewToPlaceholderThread(
|
|||
depth: 0,
|
||||
isHighlightedPost: true,
|
||||
hasMore: false,
|
||||
showChildReplyLine: false,
|
||||
showParentReplyLine: false,
|
||||
isParentLoading: !!(post.record as AppBskyFeedPost.Record).reply,
|
||||
isChildLoading: true, // assume yes (show the spinner) just in case
|
||||
},
|
||||
|
@ -342,8 +367,6 @@ function embedViewRecordToPlaceholderThread(
|
|||
depth: 0,
|
||||
isHighlightedPost: true,
|
||||
hasMore: false,
|
||||
showChildReplyLine: false,
|
||||
showParentReplyLine: false,
|
||||
isParentLoading: !!(record.value as AppBskyFeedPost.Record).reply,
|
||||
isChildLoading: true, // not available, so assume yes (to show the spinner)
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue