[Chat] Moderation stuff (#10610)

This commit is contained in:
Samuel Newman
2026-05-26 19:55:22 +03:00
committed by GitHub
parent 3f4cd1c683
commit 308b2e05f1
11 changed files with 90 additions and 15 deletions
+19 -1
View File
@@ -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')}
/>
))}
</View>
@@ -105,6 +120,7 @@ function AvatarBubble({
y,
zIndex,
includeProfileBorder,
moderation,
}: {
profile?: bsky.profile.AnyProfileView
scale: SharedValue<number>
@@ -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}
/>
) : (
<AvatarPlaceholder size={size} />
@@ -152,7 +152,11 @@ function RecentChatItem({
a.align_center,
]}>
{convo.kind === 'group' ? (
<AvatarBubbles profiles={convo.members} size={WIDTH - 8} />
<AvatarBubbles
profiles={convo.members}
size={WIDTH - 8}
moderationOpts={moderationOpts}
/>
) : (
<UserAvatar
avatar={primaryProfile.avatar}
@@ -514,7 +514,11 @@ function ExistingChatCard({
]}>
<ProfileCard.Header>
{convo.kind === 'group' ? (
<AvatarBubbles profiles={convo.members} size={40} />
<AvatarBubbles
profiles={convo.members}
size={40}
moderationOpts={moderationOpts}
/>
) : (
<ProfileCard.Avatar
profile={convo.primaryMember}
@@ -22,10 +22,12 @@ export function MessagesListBlockedFooter({
recipient: initialRecipient,
convoId,
moderation,
isGroup,
}: {
recipient: bsky.profile.AnyProfileView
convoId: string
moderation: ModerationDecision
isGroup: boolean
}) {
const t = useTheme()
const {t: l} = useLingui()
@@ -64,9 +66,7 @@ export function MessagesListBlockedFooter({
a.justify_center,
a.p_lg,
t.atoms.bg_contrast_50,
{
borderRadius: 40,
},
{borderRadius: 40},
]}>
<PersonXIcon fill={t.atoms.text.color} size="lg" style={[a.mb_xs]} />
<Text
@@ -77,9 +77,11 @@ export function MessagesListBlockedFooter({
a.font_semi_bold,
t.atoms.text,
]}>
{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`}
</Text>
<Text
style={[
+8 -2
View File
@@ -46,7 +46,7 @@ export function MessagesListHeader({convo}: {convo?: ConvoWithDetails | null}) {
convo.kind === 'direct' ? (
<ProfileHeaderReady convo={convo} moderationOpts={moderationOpts} />
) : (
<GroupHeaderReady convo={convo} />
<GroupHeaderReady convo={convo} moderationOpts={moderationOpts} />
)
) : (
<>
@@ -152,8 +152,10 @@ function ProfileHeaderReady({
function GroupHeaderReady({
convo,
moderationOpts,
}: {
convo: Extract<ConvoWithDetails, {kind: 'group'}>
moderationOpts: ModerationOpts
}) {
const {t: l} = useLingui()
@@ -176,7 +178,11 @@ function GroupHeaderReady({
},
}
}>
<AvatarBubbles size={40} profiles={convo.members} />
<AvatarBubbles
size={40}
profiles={convo.members}
moderationOpts={moderationOpts}
/>
<View style={[a.flex_row, a.flex_1, a.align_center]}>
<Text
style={[a.text_md, a.font_semi_bold, a.flex_shrink]}