From 308b2e05f1279b0692d0a58466ae1deb4434cece Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 26 May 2026 19:55:22 +0300 Subject: [PATCH] [Chat] Moderation stuff (#10610) --- src/components/AvatarBubbles.tsx | 20 ++++++++++++++- .../PostControls/ShareMenu/RecentChats.tsx | 6 ++++- .../dialogs/SearchablePeopleList.tsx | 6 ++++- .../dms/MessagesListBlockedFooter.tsx | 14 ++++++----- src/components/dms/MessagesListHeader.tsx | 10 ++++++-- src/screens/Messages/Conversation.tsx | 10 +++++++- .../Messages/ConversationSettings/index.tsx | 5 +++- .../Messages/components/ChatListItem.tsx | 1 + .../components/MessagesListGroupInfoPanel.tsx | 6 ++++- src/state/cache/profile-shadow.ts | 2 ++ src/state/queries/messages/conversation.ts | 25 ++++++++++++++++++- 11 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/components/AvatarBubbles.tsx b/src/components/AvatarBubbles.tsx index 515606994c..880a5284f0 100644 --- a/src/components/AvatarBubbles.tsx +++ b/src/components/AvatarBubbles.tsx @@ -1,4 +1,4 @@ -import {useEffect} from 'react' +import {useEffect, useMemo} from 'react' import {View} from 'react-native' import Animated, { Easing, @@ -8,6 +8,11 @@ import Animated, { withDelay, withTiming, } from 'react-native-reanimated' +import { + moderateProfile, + type ModerationOpts, + type ModerationUI, +} from '@atproto/api' import {useSession} from '#/state/session' import {UserAvatar} from '#/view/com/util/UserAvatar' @@ -27,18 +32,27 @@ type Props = { animate?: boolean profiles: bsky.profile.AnyProfileView[] size?: number + moderationOpts?: ModerationOpts } export function AvatarBubbles({ animate = false, profiles: allProfiles, size = 120, + moderationOpts, }: Props) { const {currentAccount} = useSession() const profiles = allProfiles.length > 2 ? allProfiles.filter(p => p.did !== currentAccount?.did) : allProfiles + const moderations = useMemo(() => { + if (!moderationOpts) return [] + return profiles.map(p => { + return moderateProfile(p, moderationOpts) + }) + }, [profiles, moderationOpts]) + const scale = size / 120 const marginOffset = size < 120 ? -2 : 0 @@ -90,6 +104,7 @@ export function AvatarBubbles({ y={layout.y} zIndex={layout.zIndex} includeProfileBorder={layout.border} + moderation={moderations[i]?.ui('avatar')} /> ))} @@ -105,6 +120,7 @@ function AvatarBubble({ y, zIndex, includeProfileBorder, + moderation, }: { profile?: bsky.profile.AnyProfileView scale: SharedValue @@ -113,6 +129,7 @@ function AvatarBubble({ y: number zIndex?: number includeProfileBorder?: boolean + moderation?: ModerationUI }) { const t = useTheme() @@ -140,6 +157,7 @@ function AvatarBubble({ type="user" hideLiveBadge noBorder + moderation={moderation} /> ) : ( diff --git a/src/components/PostControls/ShareMenu/RecentChats.tsx b/src/components/PostControls/ShareMenu/RecentChats.tsx index bab3cbfded..6107fa5755 100644 --- a/src/components/PostControls/ShareMenu/RecentChats.tsx +++ b/src/components/PostControls/ShareMenu/RecentChats.tsx @@ -152,7 +152,11 @@ function RecentChatItem({ a.align_center, ]}> {convo.kind === 'group' ? ( - + ) : ( {convo.kind === 'group' ? ( - + ) : ( - {isBlocking - ? l`You are blocking this person` - : l`This person is blocking you`} + {isGroup + ? l`You are blocking the chat owner` + : isBlocking + ? l`You are blocking this person` + : l`This person is blocking you`} ) : ( - + ) ) : ( <> @@ -152,8 +152,10 @@ function ProfileHeaderReady({ function GroupHeaderReady({ convo, + moderationOpts, }: { convo: Extract + moderationOpts: ModerationOpts }) { const {t: l} = useLingui() @@ -176,7 +178,11 @@ function GroupHeaderReady({ }, } }> - + - } else if (convo && primaryMember && primaryMemberModeration?.blocked) { + } else if ( + convo && + primaryMember && + primaryMemberModeration && + (convo.kind === 'group' + ? primaryMemberModeration?.blockCause?.type === 'blocking' + : primaryMemberModeration?.blocked) + ) { footer = ( ) diff --git a/src/screens/Messages/ConversationSettings/index.tsx b/src/screens/Messages/ConversationSettings/index.tsx index 2696bac2d7..c23a36552f 100644 --- a/src/screens/Messages/ConversationSettings/index.tsx +++ b/src/screens/Messages/ConversationSettings/index.tsx @@ -435,7 +435,10 @@ function SettingsHeader({ - + } title={chatName} diff --git a/src/screens/Messages/components/MessagesListGroupInfoPanel.tsx b/src/screens/Messages/components/MessagesListGroupInfoPanel.tsx index 78c61ac313..79a016cf69 100644 --- a/src/screens/Messages/components/MessagesListGroupInfoPanel.tsx +++ b/src/screens/Messages/components/MessagesListGroupInfoPanel.tsx @@ -88,7 +88,11 @@ export function MessagesListGroupInfoPanel({ return ( <> - + {convo.details.name ? ( diff --git a/src/state/cache/profile-shadow.ts b/src/state/cache/profile-shadow.ts index 85e5b73396..8b61b4416e 100644 --- a/src/state/cache/profile-shadow.ts +++ b/src/state/cache/profile-shadow.ts @@ -10,6 +10,7 @@ import {findAllProfilesInQueryData as findAllProfilesInExploreFeedPreviewsQueryD import {findAllProfilesInQueryData as findAllProfilesInContactMatchesQueryData} from '#/state/queries/find-contacts' import {findAllProfilesInQueryData as findAllProfilesInKnownFollowersQueryData} from '#/state/queries/known-followers' import {findAllProfilesInQueryData as findAllProfilesInListMembersQueryData} from '#/state/queries/list-members' +import {findAllProfilesInQueryData as findAllProfilesInGetConvoQueryData} from '#/state/queries/messages/conversation' import {findAllProfilesInQueryData as findAllProfilesInListConvosQueryData} from '#/state/queries/messages/list-conversations' import {findAllProfilesInQueryData as findAllProfilesInMessagesQueryData} from '#/state/queries/messages/list-convo-members' import {findAllProfilesInQueryData as findAllProfilesInMyBlockedAccountsQueryData} from '#/state/queries/my-blocked-accounts' @@ -266,4 +267,5 @@ function* findProfilesInCache( yield* findAllProfilesInNotifsQueryData(queryClient, did) yield* findAllProfilesInContactMatchesQueryData(queryClient, did) yield* findAllProfilesInMessagesQueryData(queryClient, did) + yield* findAllProfilesInGetConvoQueryData(queryClient, did) } diff --git a/src/state/queries/messages/conversation.ts b/src/state/queries/messages/conversation.ts index 76557991d1..2ce6c06e51 100644 --- a/src/state/queries/messages/conversation.ts +++ b/src/state/queries/messages/conversation.ts @@ -1,4 +1,8 @@ -import {type ChatBskyConvoDefs} from '@atproto/api' +import { + type ChatBskyActorDefs, + type ChatBskyConvoDefs, + type ChatBskyConvoGetConvo, +} from '@atproto/api' import { type QueryClient, useMutation, @@ -109,3 +113,22 @@ export function useMarkAsReadMutation() { }, }) } + +export function* findAllProfilesInQueryData( + queryClient: QueryClient, + did: string, +): Generator { + const queryDatas = queryClient.getQueriesData< + ChatBskyConvoGetConvo.OutputSchema['convo'] + >({ + queryKey: [RQKEY_ROOT], + }) + for (const [_queryKey, queryData] of queryDatas) { + if (!queryData) continue + for (const member of queryData.members) { + if (member.did === did) { + yield member + } + } + } +}