Show guest only once even if they joined on two different windows

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2022-05-17 16:21:09 +02:00
parent 692be10b10
commit 2d986c7968
4 changed files with 23 additions and 15 deletions

1
Cargo.lock generated
View File

@ -768,6 +768,7 @@ dependencies = [
"anyhow", "anyhow",
"async-recursion", "async-recursion",
"async-tungstenite", "async-tungstenite",
"collections",
"futures", "futures",
"gpui", "gpui",
"image", "image",

View File

@ -8,9 +8,10 @@ path = "src/client.rs"
doctest = false doctest = false
[features] [features]
test-support = ["gpui/test-support", "rpc/test-support"] test-support = ["collections/test-support", "gpui/test-support", "rpc/test-support"]
[dependencies] [dependencies]
collections = { path = "../collections" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
util = { path = "../util" } util = { path = "../util" }
rpc = { path = "../rpc" } rpc = { path = "../rpc" }
@ -33,5 +34,6 @@ tiny_http = "0.8"
url = "2.2" url = "2.2"
[dev-dependencies] [dev-dependencies]
collections = { path = "../collections", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] }
rpc = { path = "../rpc", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] }

View File

@ -1,13 +1,11 @@
use super::{http::HttpClient, proto, Client, Status, TypedEnvelope}; use super::{http::HttpClient, proto, Client, Status, TypedEnvelope};
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use collections::{hash_map::Entry, BTreeSet, HashMap, HashSet};
use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt}; use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt};
use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task}; use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task};
use postage::{prelude::Stream, sink::Sink, watch}; use postage::{prelude::Stream, sink::Sink, watch};
use rpc::proto::{RequestMessage, UsersResponse}; use rpc::proto::{RequestMessage, UsersResponse};
use std::{ use std::sync::{Arc, Weak};
collections::{hash_map::Entry, HashMap, HashSet},
sync::{Arc, Weak},
};
use util::TryFutureExt as _; use util::TryFutureExt as _;
#[derive(Debug)] #[derive(Debug)]
@ -17,6 +15,18 @@ pub struct User {
pub avatar: Option<Arc<ImageData>>, pub avatar: Option<Arc<ImageData>>,
} }
impl PartialOrd for User {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
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 { impl PartialEq for User {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.id == other.id && self.github_login == other.github_login self.id == other.id && self.github_login == other.github_login
@ -36,7 +46,7 @@ pub struct Contact {
pub struct ProjectMetadata { pub struct ProjectMetadata {
pub id: u64, pub id: u64,
pub worktree_root_names: Vec<String>, pub worktree_root_names: Vec<String>,
pub guests: Vec<Arc<User>>, pub guests: BTreeSet<Arc<User>>,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -177,7 +187,7 @@ impl UserStore {
self.client.upgrade().unwrap().id, self.client.upgrade().unwrap().id,
message message
); );
let mut user_ids = HashSet::new(); let mut user_ids = HashSet::default();
for contact in &message.contacts { for contact in &message.contacts {
user_ids.insert(contact.user_id); user_ids.insert(contact.user_id);
user_ids.extend(contact.projects.iter().flat_map(|w| &w.guests).copied()); user_ids.extend(contact.projects.iter().flat_map(|w| &w.guests).copied());
@ -554,9 +564,9 @@ impl Contact {
.await?; .await?;
let mut projects = Vec::new(); let mut projects = Vec::new();
for project in contact.projects { for project in contact.projects {
let mut guests = Vec::new(); let mut guests = BTreeSet::new();
for participant_id in project.guests { for participant_id in project.guests {
guests.push( guests.insert(
user_store user_store
.update(cx, |user_store, cx| { .update(cx, |user_store, cx| {
user_store.fetch_user(participant_id, cx) user_store.fetch_user(participant_id, cx)

View File

@ -350,11 +350,6 @@ impl ContactsPanel {
let project = &contact.projects[project_index]; let project = &contact.projects[project_index];
let project_id = project.id; let project_id = project.id;
let is_host = Some(contact.user.id) == current_user_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 font_cache = cx.font_cache();
let host_avatar_height = theme let host_avatar_height = theme
@ -447,7 +442,7 @@ impl ContactsPanel {
CursorStyle::Arrow CursorStyle::Arrow
}) })
.on_click(move |_, cx| { .on_click(move |_, cx| {
if !is_host && !is_guest { if !is_host {
cx.dispatch_global_action(JoinProject { cx.dispatch_global_action(JoinProject {
contact: contact.clone(), contact: contact.clone(),
project_index, project_index,