From 71454ba27cfa2135cf20e403fd87def27ebca408 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 14 Aug 2023 17:11:03 -0700 Subject: [PATCH] Limit number of participants shown in channel face piles Co-authored-by: Mikayla --- crates/collab_ui/src/collab_panel.rs | 45 +++++++++++++++++++-------- crates/collab_ui/src/face_pile.rs | 1 + crates/theme/src/theme.rs | 1 + styles/src/style_tree/collab_panel.ts | 9 ++++++ 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 563cc942da1ad924a67c8eb304a8a681ff34d3df..e4838df93927370a03ccd55fd4384aa246ef0baa 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -1514,6 +1514,8 @@ impl CollabPanel { ) -> AnyElement { let channel_id = channel.id; + const FACEPILE_LIMIT: usize = 4; + MouseEventHandler::::new(channel.id as usize, cx, |state, cx| { Flex::row() .with_child( @@ -1532,20 +1534,37 @@ impl CollabPanel { .left() .flex(1., true), ) - .with_child( - FacePile::new(theme.face_overlap).with_children( - self.channel_store - .read(cx) - .channel_participants(channel_id) - .iter() - .filter_map(|user| { - Some( - Image::from_data(user.avatar.clone()?) - .with_style(theme.contact_avatar), + .with_children({ + let participants = self.channel_store.read(cx).channel_participants(channel_id); + if !participants.is_empty() { + let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT); + + Some( + FacePile::new(theme.face_overlap) + .with_children( + participants + .iter() + .filter_map(|user| { + Some( + Image::from_data(user.avatar.clone()?) + .with_style(theme.contact_avatar), + ) + }) + .take(FACEPILE_LIMIT), ) - }), - ), - ) + .with_children((extra_count > 0).then(|| { + Label::new( + format!("+{}", extra_count), + theme.extra_participant_label.text.clone(), + ) + .contained() + .with_style(theme.extra_participant_label.container) + })), + ) + } else { + None + } + }) .align_children_center() .constrained() .with_height(theme.row_height) diff --git a/crates/collab_ui/src/face_pile.rs b/crates/collab_ui/src/face_pile.rs index ba9b61c98b80f111e8385d9ee3e57d76e41ea1de..a86b2576869b5d2e3b695ae41d073bf6fa631812 100644 --- a/crates/collab_ui/src/face_pile.rs +++ b/crates/collab_ui/src/face_pile.rs @@ -68,6 +68,7 @@ impl Element for FacePile { for face in self.faces.iter_mut().rev() { let size = face.size(); origin_x -= size.x(); + let origin_y = origin_y + (bounds.height() - size.y()) / 2.0; scene.paint_layer(None, |scene| { face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx); }); diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 4919eb93c77c18e2cf214b5569d701031da9fef5..e081b700472d33f791e9c558d1e3885b79197057 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -241,6 +241,7 @@ pub struct CollabPanel { pub project_row: Toggleable>, pub tree_branch: Toggleable>, pub contact_avatar: ImageStyle, + pub extra_participant_label: ContainedText, pub contact_status_free: ContainerStyle, pub contact_status_busy: ContainerStyle, pub contact_username: ContainedText, diff --git a/styles/src/style_tree/collab_panel.ts b/styles/src/style_tree/collab_panel.ts index 6cf6f9b09525a84a29aba778aaddf8ec75309e85..1d1e09075e24c78c27bbbb4b7a7efbce6ae5de9e 100644 --- a/styles/src/style_tree/collab_panel.ts +++ b/styles/src/style_tree/collab_panel.ts @@ -245,6 +245,15 @@ export default function contacts_panel(): any { corner_radius: 10, width: 20, }, + extra_participant_label: { + corner_radius: 10, + padding: { + left: 10, + right: 4, + }, + background: background(layer, "hovered"), + ...text(layer, "ui_sans", "hovered", { size: "xs" }) + }, contact_status_free: indicator({ layer, color: "positive" }), contact_status_busy: indicator({ layer, color: "negative" }), contact_username: {