diff options
author | Eric Bailey <git@esb.lol> | 2024-08-21 21:20:45 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-21 19:20:45 -0700 |
commit | 6616a6467ec53aa71e5f823c2d8c46dc01442703 (patch) | |
tree | 5e49d6916bc9b9fc71a475cf0d02f169c744bf59 /src/view/com/posts/FeedItem.tsx | |
parent | 56ab5e177fa2b24d0e5d9d969aa37532b96128da (diff) | |
download | voidsky-6616a6467ec53aa71e5f823c2d8c46dc01442703.tar.zst |
Detached QPs and hidden replies (#4878)
Co-authored-by: Hailey <me@haileyok.com>
Diffstat (limited to 'src/view/com/posts/FeedItem.tsx')
-rw-r--r-- | src/view/com/posts/FeedItem.tsx | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index 0fef4c5a8..e90e8b885 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -4,6 +4,7 @@ import { AppBskyActorDefs, AppBskyFeedDefs, AppBskyFeedPost, + AppBskyFeedThreadgate, AtUri, ModerationDecision, RichText as RichTextAPI, @@ -21,6 +22,7 @@ import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow' import {useFeedFeedbackContext} from '#/state/feed-feedback' import {useSession} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' +import {useThreadgateHiddenReplyUris} from '#/state/threadgate-hidden-replies' import {isReasonFeedSource, ReasonFeedSource} from 'lib/api/feed/types' import {MAX_POST_LINES} from 'lib/constants' import {usePalette} from 'lib/hooks/usePalette' @@ -33,6 +35,7 @@ import {precacheProfile} from 'state/queries/profile' import {atoms as a} from '#/alf' import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost' import {ContentHider} from '#/components/moderation/ContentHider' +import {AppModerationCause} from '#/components/Pills' import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {RichText} from '#/components/RichText' import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe' @@ -80,7 +83,11 @@ export function FeedItem({ hideTopBorder, isParentBlocked, isParentNotFound, -}: FeedItemProps & {post: AppBskyFeedDefs.PostView}): React.ReactNode { + rootPost, +}: FeedItemProps & { + post: AppBskyFeedDefs.PostView + rootPost: AppBskyFeedDefs.PostView +}): React.ReactNode { const postShadowed = usePostShadow(post) const richText = useMemo( () => @@ -112,6 +119,7 @@ export function FeedItem({ hideTopBorder={hideTopBorder} isParentBlocked={isParentBlocked} isParentNotFound={isParentNotFound} + rootPost={rootPost} /> ) } @@ -133,9 +141,11 @@ let FeedItemInner = ({ hideTopBorder, isParentBlocked, isParentNotFound, + rootPost, }: FeedItemProps & { richText: RichTextAPI post: Shadow<AppBskyFeedDefs.PostView> + rootPost: AppBskyFeedDefs.PostView }): React.ReactNode => { const queryClient = useQueryClient() const {openComposer} = useComposerControls() @@ -217,6 +227,12 @@ let FeedItemInner = ({ AppBskyFeedDefs.isReasonRepost(reason) && reason.by.did === currentAccount?.did + const threadgateRecord = AppBskyFeedThreadgate.isRecord( + rootPost.threadgate?.record, + ) + ? rootPost.threadgate.record + : undefined + return ( <Link testID={`feedItem-by-${post.author.handle}`} @@ -363,6 +379,8 @@ let FeedItemInner = ({ postEmbed={post.embed} postAuthor={post.author} onOpenEmbed={onOpenEmbed} + post={post} + threadgateRecord={threadgateRecord} /> <VideoDebug /> <PostCtrls @@ -372,6 +390,7 @@ let FeedItemInner = ({ onPressReply={onPressReply} logContext="FeedItem" feedContext={feedContext} + threadgateRecord={threadgateRecord} /> </View> </View> @@ -381,23 +400,63 @@ let FeedItemInner = ({ FeedItemInner = memo(FeedItemInner) let PostContent = ({ + post, moderation, richText, postEmbed, postAuthor, onOpenEmbed, + threadgateRecord, }: { moderation: ModerationDecision richText: RichTextAPI postEmbed: AppBskyFeedDefs.PostView['embed'] postAuthor: AppBskyFeedDefs.PostView['author'] onOpenEmbed: () => void + post: AppBskyFeedDefs.PostView + threadgateRecord?: AppBskyFeedThreadgate.Record }): React.ReactNode => { const pal = usePalette('default') const {_} = useLingui() + const {currentAccount} = useSession() const [limitLines, setLimitLines] = useState( () => countLines(richText.text) >= MAX_POST_LINES, ) + const {uris: hiddenReplyUris, recentlyUnhiddenUris} = + useThreadgateHiddenReplyUris() + const additionalPostAlerts: AppModerationCause[] = React.useMemo(() => { + const isPostHiddenByHiddenReplyCache = hiddenReplyUris.has(post.uri) + const isPostHiddenByThreadgate = + !recentlyUnhiddenUris.has(post.uri) && + !!threadgateRecord?.hiddenReplies?.includes(post.uri) + const isHidden = isPostHiddenByHiddenReplyCache || isPostHiddenByThreadgate + const isControlledByViewer = + isPostHiddenByHiddenReplyCache || + (threadgateRecord && + new AtUri(threadgateRecord.post).host === currentAccount?.did) + if (!isControlledByViewer) return [] + const alertSource = + threadgateRecord && isPostHiddenByThreadgate + ? new AtUri(threadgateRecord.post).host + : isPostHiddenByHiddenReplyCache + ? currentAccount?.did + : undefined + return isHidden && alertSource + ? [ + { + type: 'reply-hidden', + source: {type: 'user', did: alertSource}, + priority: 6, + }, + ] + : [] + }, [ + post, + hiddenReplyUris, + recentlyUnhiddenUris, + threadgateRecord, + currentAccount?.did, + ]) const onPressShowMore = React.useCallback(() => { setLimitLines(false) @@ -409,7 +468,11 @@ let PostContent = ({ modui={moderation.ui('contentList')} ignoreMute childContainerStyle={styles.contentHiderChild}> - <PostAlerts modui={moderation.ui('contentList')} style={[a.py_2xs]} /> + <PostAlerts + modui={moderation.ui('contentList')} + style={[a.py_2xs]} + additionalCauses={additionalPostAlerts} + /> {richText.text ? ( <View style={styles.postTextContainer}> <RichText @@ -460,7 +523,7 @@ function ReplyToLabel({ if (blocked) { label = <Trans context="description">Reply to a blocked post</Trans> } else if (notFound) { - label = <Trans context="description">Reply to an unknown post</Trans> + label = <Trans context="description">Reply to a post</Trans> } else if (profile != null) { const isMe = profile.did === currentAccount?.did if (isMe) { |