Limit number of participants shown in channel face piles

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Max Brunsfeld 2023-08-14 17:11:03 -07:00
parent 13982fe2f4
commit 71454ba27c
4 changed files with 43 additions and 13 deletions

View file

@ -1514,6 +1514,8 @@ impl CollabPanel {
) -> AnyElement<Self> { ) -> AnyElement<Self> {
let channel_id = channel.id; let channel_id = channel.id;
const FACEPILE_LIMIT: usize = 4;
MouseEventHandler::<Channel, Self>::new(channel.id as usize, cx, |state, cx| { MouseEventHandler::<Channel, Self>::new(channel.id as usize, cx, |state, cx| {
Flex::row() Flex::row()
.with_child( .with_child(
@ -1532,20 +1534,37 @@ impl CollabPanel {
.left() .left()
.flex(1., true), .flex(1., true),
) )
.with_child( .with_children({
FacePile::new(theme.face_overlap).with_children( let participants = self.channel_store.read(cx).channel_participants(channel_id);
self.channel_store if !participants.is_empty() {
.read(cx) let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT);
.channel_participants(channel_id)
Some(
FacePile::new(theme.face_overlap)
.with_children(
participants
.iter() .iter()
.filter_map(|user| { .filter_map(|user| {
Some( Some(
Image::from_data(user.avatar.clone()?) Image::from_data(user.avatar.clone()?)
.with_style(theme.contact_avatar), .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() .align_children_center()
.constrained() .constrained()
.with_height(theme.row_height) .with_height(theme.row_height)

View file

@ -68,6 +68,7 @@ impl<V: View> Element<V> for FacePile<V> {
for face in self.faces.iter_mut().rev() { for face in self.faces.iter_mut().rev() {
let size = face.size(); let size = face.size();
origin_x -= size.x(); origin_x -= size.x();
let origin_y = origin_y + (bounds.height() - size.y()) / 2.0;
scene.paint_layer(None, |scene| { scene.paint_layer(None, |scene| {
face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx); face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx);
}); });

View file

@ -241,6 +241,7 @@ pub struct CollabPanel {
pub project_row: Toggleable<Interactive<ProjectRow>>, pub project_row: Toggleable<Interactive<ProjectRow>>,
pub tree_branch: Toggleable<Interactive<TreeBranch>>, pub tree_branch: Toggleable<Interactive<TreeBranch>>,
pub contact_avatar: ImageStyle, pub contact_avatar: ImageStyle,
pub extra_participant_label: ContainedText,
pub contact_status_free: ContainerStyle, pub contact_status_free: ContainerStyle,
pub contact_status_busy: ContainerStyle, pub contact_status_busy: ContainerStyle,
pub contact_username: ContainedText, pub contact_username: ContainedText,

View file

@ -245,6 +245,15 @@ export default function contacts_panel(): any {
corner_radius: 10, corner_radius: 10,
width: 20, 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_free: indicator({ layer, color: "positive" }),
contact_status_busy: indicator({ layer, color: "negative" }), contact_status_busy: indicator({ layer, color: "negative" }),
contact_username: { contact_username: {