restore placeholder bubbles for undefined profiles

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-06-10 16:03:21 +03:00
parent fdb5cdcf46
commit df6cb73284
+39 -51
View File
@@ -10,7 +10,7 @@ import Animated, {
} from 'react-native-reanimated' } from 'react-native-reanimated'
import {moderateProfile} from '@atproto/api' import {moderateProfile} from '@atproto/api'
import {useProfileShadow} from '#/state/cache/profile-shadow' import {useMaybeProfileShadow} from '#/state/cache/profile-shadow'
import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
@@ -90,22 +90,18 @@ export function AvatarBubbles({
transform: [{scale}], transform: [{scale}],
transformOrigin: 'top left', transformOrigin: 'top left',
}}> }}>
{layouts.map((layout, i) => { {layouts.map((layout, i) => (
const profile = profiles[i] <AvatarBubble
if (!profile) return null key={i}
return ( profile={profiles[i]}
<AvatarBubble scale={scales[i]}
key={i} size={layout.size}
profile={profile} x={layout.x}
scale={scales[i]} y={layout.y}
size={layout.size} zIndex={layout.zIndex}
x={layout.x} includeProfileBorder={layout.border}
y={layout.y} />
zIndex={layout.zIndex} ))}
includeProfileBorder={layout.border}
/>
)
})}
</View> </View>
</Animated.View> </Animated.View>
) )
@@ -120,7 +116,7 @@ function AvatarBubble({
zIndex, zIndex,
includeProfileBorder, includeProfileBorder,
}: { }: {
profile: bsky.profile.AnyProfileView profile?: bsky.profile.AnyProfileView
scale: SharedValue<number> scale: SharedValue<number>
size: number size: number
x: number x: number
@@ -133,42 +129,34 @@ function AvatarBubble({
transform: [{translateX: x}, {translateY: y}, {scale: scale.get()}], transform: [{translateX: x}, {translateY: y}, {scale: scale.get()}],
})) }))
const style = [ const profile = useMaybeProfileShadow(profileUnshadowed)
a.absolute,
a.rounded_full,
a.flex_grow_0,
includeProfileBorder && {
borderColor: t.atoms.text_inverted.color,
borderWidth: 2,
},
zIndex != null && {zIndex},
animatedStyle,
]
const profile = useProfileShadow(profileUnshadowed)
const moderationOpts = useModerationOpts() const moderationOpts = useModerationOpts()
if (!moderationOpts) {
return (
<Animated.View style={style}>
<AvatarPlaceholder size={size} />
</Animated.View>
)
}
const moderation = moderateProfile(profile, moderationOpts)
const avatarModeration = moderation.ui('avatar')
return ( return (
<Animated.View style={style}> <Animated.View
<UserAvatar style={[
avatar={profile.avatar} a.absolute,
size={size} a.rounded_full,
type="user" a.flex_grow_0,
hideLiveBadge includeProfileBorder && {
noBorder borderColor: t.atoms.text_inverted.color,
moderation={avatarModeration} borderWidth: 2,
/> },
zIndex != null && {zIndex},
animatedStyle,
]}>
{profile && moderationOpts ? (
<UserAvatar
avatar={profile.avatar}
size={size}
type="user"
hideLiveBadge
noBorder
moderation={moderateProfile(profile, moderationOpts).ui('avatar')}
/>
) : (
<AvatarPlaceholder size={size} />
)}
</Animated.View> </Animated.View>
) )
} }