diff --git a/Cargo.lock b/Cargo.lock index 9b1f2f7f1b..c12a15ec57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -768,6 +768,7 @@ dependencies = [ "anyhow", "async-recursion", "async-tungstenite", + "collections", "futures", "gpui", "image", diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index f4f85b64d0..45e8547c2c 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -8,9 +8,10 @@ path = "src/client.rs" doctest = false [features] -test-support = ["gpui/test-support", "rpc/test-support"] +test-support = ["collections/test-support", "gpui/test-support", "rpc/test-support"] [dependencies] +collections = { path = "../collections" } gpui = { path = "../gpui" } util = { path = "../util" } rpc = { path = "../rpc" } @@ -33,5 +34,6 @@ tiny_http = "0.8" url = "2.2" [dev-dependencies] +collections = { path = "../collections", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index 296c0cf9ae..08092f46f1 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -1,13 +1,11 @@ use super::{http::HttpClient, proto, Client, Status, TypedEnvelope}; use anyhow::{anyhow, Context, Result}; +use collections::{hash_map::Entry, BTreeSet, HashMap, HashSet}; use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt}; use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task}; use postage::{prelude::Stream, sink::Sink, watch}; use rpc::proto::{RequestMessage, UsersResponse}; -use std::{ - collections::{hash_map::Entry, HashMap, HashSet}, - sync::{Arc, Weak}, -}; +use std::sync::{Arc, Weak}; use util::TryFutureExt as _; #[derive(Debug)] @@ -17,6 +15,18 @@ pub struct User { pub avatar: Option>, } +impl PartialOrd for User { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} + +impl Ord for User { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.github_login.cmp(&other.github_login) + } +} + impl PartialEq for User { fn eq(&self, other: &Self) -> bool { self.id == other.id && self.github_login == other.github_login @@ -36,7 +46,7 @@ pub struct Contact { pub struct ProjectMetadata { pub id: u64, pub worktree_root_names: Vec, - pub guests: Vec>, + pub guests: BTreeSet>, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -177,7 +187,7 @@ impl UserStore { self.client.upgrade().unwrap().id, message ); - let mut user_ids = HashSet::new(); + let mut user_ids = HashSet::default(); for contact in &message.contacts { user_ids.insert(contact.user_id); user_ids.extend(contact.projects.iter().flat_map(|w| &w.guests).copied()); @@ -554,9 +564,9 @@ impl Contact { .await?; let mut projects = Vec::new(); for project in contact.projects { - let mut guests = Vec::new(); + let mut guests = BTreeSet::new(); for participant_id in project.guests { - guests.push( + guests.insert( user_store .update(cx, |user_store, cx| { user_store.fetch_user(participant_id, cx) diff --git a/crates/contacts_panel/src/contacts_panel.rs b/crates/contacts_panel/src/contacts_panel.rs index 91794ebf0f..df6d85712b 100644 --- a/crates/contacts_panel/src/contacts_panel.rs +++ b/crates/contacts_panel/src/contacts_panel.rs @@ -350,11 +350,6 @@ impl ContactsPanel { let project = &contact.projects[project_index]; let project_id = project.id; let is_host = Some(contact.user.id) == current_user_id; - let is_guest = !is_host - && project - .guests - .iter() - .any(|guest| Some(guest.id) == current_user_id); let font_cache = cx.font_cache(); let host_avatar_height = theme @@ -447,7 +442,7 @@ impl ContactsPanel { CursorStyle::Arrow }) .on_click(move |_, cx| { - if !is_host && !is_guest { + if !is_host { cx.dispatch_global_action(JoinProject { contact: contact.clone(), project_index,