pad avatar bubbles to reflect true member count

Invite/request previews only carry the group owner's profile (convo.members
is only present for actual members), so AvatarBubbles only ever rendered the
owner plus a single placeholder. Add a `count` prop so the bubble pile reflects
the real member count, and use it for the invite card and the join/outgoing
request previews that were padding the profiles array by hand.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-06-12 15:55:56 +03:00
parent ec695a42c5
commit c65698d5f1
4 changed files with 21 additions and 14 deletions
+11 -1
View File
@@ -31,6 +31,7 @@ export function AvatarBubbles({
profiles: allProfiles,
self = false,
size = 120,
count,
}: {
animate?: boolean
profiles: (bsky.profile.AnyProfileView | undefined)[]
@@ -42,6 +43,13 @@ export function AvatarBubbles({
*/
self?: boolean
size?: number
/**
* The true number of members, used to decide how many bubbles to render when
* it exceeds the number of `profiles` we have on hand (e.g. an invite preview
* that only carries a few member profiles for a much larger group). Slots
* without a profile render as placeholders. Defaults to `profiles.length`.
*/
count?: number
}) {
const {currentAccount} = useSession()
const profiles =
@@ -49,6 +57,8 @@ export function AvatarBubbles({
? allProfiles.filter(p => !p || p.did !== currentAccount?.did)
: allProfiles
const bubbleCount = Math.max(profiles.length, count ?? 0)
const scale = size / 120
const marginOffset = size < 120 ? -2 : 0
@@ -79,7 +89,7 @@ export function AvatarBubbles({
}, [animate, p0, p1, p2, p3])
const scales = [p0, p1, p2, p3]
const layouts = getLayouts(profiles.length)
const layouts = getLayouts(bubbleCount)
return (
<Animated.View style={[a.p_2xs, {height: size, width: size}]}>
+6 -1
View File
@@ -29,7 +29,12 @@ export function Card({size}: {size: 'large' | 'small'}) {
return (
<View style={[a.flex_row, a.gap_md, a.align_center]}>
<AvatarBubbles size={56} self profiles={avatarProfiles} />
<AvatarBubbles
size={56}
self
profiles={avatarProfiles}
count={preview.memberCount}
/>
<View style={[a.flex_1, size === 'large' ? a.gap_2xs : a.gap_xs]}>
<Text
emoji
+2 -6
View File
@@ -103,12 +103,8 @@ export function JoinRequest({setScreenState}: Props) {
ChatBskyGroupDefs.isJoinLinkPreviewView(joinLinkPreview) ? (
<Wrapper>
<AvatarBubbles
profiles={[
joinLinkPreview.owner,
...Array(
Math.min(3, Math.max(0, joinLinkPreview.memberCount - 1)),
).fill(undefined),
]}
profiles={[joinLinkPreview.owner]}
count={joinLinkPreview.memberCount}
size={135}
/>
<View style={[a.gap_2xs]}>
@@ -63,12 +63,8 @@ export function OutgoingRequestListItem({
(hovered || pressed || focused) && t.atoms.bg_contrast_25,
]}>
<AvatarBubbles
profiles={[
convoView?.owner ?? undefined,
...Array(
Math.min(3, Math.max(0, convoView.memberCount - 1)),
).fill(undefined),
]}
profiles={[convoView?.owner ?? undefined]}
count={convoView.memberCount}
size={48}
/>
<View style={[a.flex_1]}>