From 4504b36c8f4f9257ff19fc3f6d7172002071cf31 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 11 Oct 2022 15:24:31 +0200 Subject: [PATCH] Show a different message when participant is active on unshared project Co-Authored-By: Nathan Sobo --- crates/call/src/participant.rs | 19 +++++--- crates/call/src/room.rs | 26 +++++++++-- crates/collab/src/integration_tests.rs | 47 +++++++++++--------- crates/collab/src/rpc/store.rs | 2 +- crates/collab_ui/src/collab_titlebar_item.rs | 25 +++-------- crates/gpui/src/app.rs | 6 +++ crates/rpc/proto/zed.proto | 9 ++-- crates/workspace/src/pane_group.rs | 17 ++++++- 8 files changed, 97 insertions(+), 54 deletions(-) diff --git a/crates/call/src/participant.rs b/crates/call/src/participant.rs index 7e031f907f..a5be5b4af2 100644 --- a/crates/call/src/participant.rs +++ b/crates/call/src/participant.rs @@ -1,28 +1,37 @@ use anyhow::{anyhow, Result}; use client::{proto, User}; +use gpui::WeakModelHandle; +use project::Project; use std::sync::Arc; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ParticipantLocation { - Project { project_id: u64 }, + SharedProject { project_id: u64 }, + UnsharedProject, External, } impl ParticipantLocation { pub fn from_proto(location: Option) -> Result { match location.and_then(|l| l.variant) { - Some(proto::participant_location::Variant::Project(project)) => Ok(Self::Project { - project_id: project.id, - }), + Some(proto::participant_location::Variant::SharedProject(project)) => { + Ok(Self::SharedProject { + project_id: project.id, + }) + } + Some(proto::participant_location::Variant::UnsharedProject(_)) => { + Ok(Self::UnsharedProject) + } Some(proto::participant_location::Variant::External(_)) => Ok(Self::External), None => Err(anyhow!("participant location was not provided")), } } } -#[derive(Clone, Debug, Default)] +#[derive(Clone, Default)] pub struct LocalParticipant { pub projects: Vec, + pub active_project: Option>, } #[derive(Clone, Debug)] diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs index a3b49c2a4f..572f512d1c 100644 --- a/crates/call/src/room.rs +++ b/crates/call/src/room.rs @@ -395,13 +395,26 @@ impl Room { }) .collect(), }); - cx.spawn_weak(|_, mut cx| async move { + cx.spawn(|this, mut cx| async move { let response = request.await?; + project .update(&mut cx, |project, cx| { project.shared(response.project_id, cx) }) .await?; + + // If the user's location is in this project, it changes from UnsharedProject to SharedProject. + this.update(&mut cx, |this, cx| { + let active_project = this.local_participant.active_project.as_ref(); + if active_project.map_or(false, |location| *location == project) { + this.set_location(Some(&project), cx) + } else { + Task::ready(Ok(())) + } + }) + .await?; + Ok(response.project_id) }) } @@ -418,17 +431,22 @@ impl Room { let client = self.client.clone(); let room_id = self.id; let location = if let Some(project) = project { + self.local_participant.active_project = Some(project.downgrade()); if let Some(project_id) = project.read(cx).remote_id() { - proto::participant_location::Variant::Project( - proto::participant_location::Project { id: project_id }, + proto::participant_location::Variant::SharedProject( + proto::participant_location::SharedProject { id: project_id }, ) } else { - return Task::ready(Err(anyhow!("project is not shared"))); + proto::participant_location::Variant::UnsharedProject( + proto::participant_location::UnsharedProject {}, + ) } } else { + self.local_participant.active_project = None; proto::participant_location::Variant::External(proto::participant_location::External {}) }; + cx.notify(); cx.foreground().spawn(async move { client .request(proto::UpdateParticipantLocation { diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 27fb1a9bfb..29d1c1b833 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -946,6 +946,22 @@ async fn test_room_location( } }); + room_a + .update(cx_a, |room, cx| room.set_location(Some(&project_a), cx)) + .await + .unwrap(); + deterministic.run_until_parked(); + assert!(a_notified.take()); + assert_eq!( + participant_locations(&room_a, cx_a), + vec![("user_b".to_string(), ParticipantLocation::External)] + ); + assert!(b_notified.take()); + assert_eq!( + participant_locations(&room_b, cx_b), + vec![("user_a".to_string(), ParticipantLocation::UnsharedProject)] + ); + let project_a_id = active_call_a .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) .await @@ -959,7 +975,12 @@ async fn test_room_location( assert!(b_notified.take()); assert_eq!( participant_locations(&room_b, cx_b), - vec![("user_a".to_string(), ParticipantLocation::External)] + vec![( + "user_a".to_string(), + ParticipantLocation::SharedProject { + project_id: project_a_id + } + )] ); let project_b_id = active_call_b @@ -973,27 +994,11 @@ async fn test_room_location( vec![("user_b".to_string(), ParticipantLocation::External)] ); assert!(b_notified.take()); - assert_eq!( - participant_locations(&room_b, cx_b), - vec![("user_a".to_string(), ParticipantLocation::External)] - ); - - room_a - .update(cx_a, |room, cx| room.set_location(Some(&project_a), cx)) - .await - .unwrap(); - deterministic.run_until_parked(); - assert!(a_notified.take()); - assert_eq!( - participant_locations(&room_a, cx_a), - vec![("user_b".to_string(), ParticipantLocation::External)] - ); - assert!(b_notified.take()); assert_eq!( participant_locations(&room_b, cx_b), vec![( "user_a".to_string(), - ParticipantLocation::Project { + ParticipantLocation::SharedProject { project_id: project_a_id } )] @@ -1009,7 +1014,7 @@ async fn test_room_location( participant_locations(&room_a, cx_a), vec![( "user_b".to_string(), - ParticipantLocation::Project { + ParticipantLocation::SharedProject { project_id: project_b_id } )] @@ -1019,7 +1024,7 @@ async fn test_room_location( participant_locations(&room_b, cx_b), vec![( "user_a".to_string(), - ParticipantLocation::Project { + ParticipantLocation::SharedProject { project_id: project_a_id } )] @@ -1040,7 +1045,7 @@ async fn test_room_location( participant_locations(&room_b, cx_b), vec![( "user_a".to_string(), - ParticipantLocation::Project { + ParticipantLocation::SharedProject { project_id: project_a_id } )] diff --git a/crates/collab/src/rpc/store.rs b/crates/collab/src/rpc/store.rs index 9b2661abca..cc34094782 100644 --- a/crates/collab/src/rpc/store.rs +++ b/crates/collab/src/rpc/store.rs @@ -684,7 +684,7 @@ impl Store { .rooms .get_mut(&room_id) .ok_or_else(|| anyhow!("no such room"))?; - if let Some(proto::participant_location::Variant::Project(project)) = + if let Some(proto::participant_location::Variant::SharedProject(project)) = location.variant.as_ref() { anyhow::ensure!( diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index c46861b5ab..a2d7249b57 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -121,14 +121,11 @@ impl CollabTitlebarItem { let room = ActiveCall::global(cx).read(cx).room().cloned(); if let Some((workspace, room)) = workspace.zip(room) { let workspace = workspace.read(cx); - let project = if !active { - None - } else if workspace.project().read(cx).remote_id().is_some() { + let project = if active { Some(workspace.project().clone()) } else { None }; - room.update(cx, |room, cx| { room.set_location(project.as_ref(), cx) .detach_and_log_err(cx); @@ -139,20 +136,10 @@ impl CollabTitlebarItem { fn share_project(&mut self, _: &ShareProject, cx: &mut ViewContext) { if let Some(workspace) = self.workspace.upgrade(cx) { let active_call = ActiveCall::global(cx); - - let window_id = cx.window_id(); let project = workspace.read(cx).project().clone(); - let share = active_call.update(cx, |call, cx| call.share_project(project.clone(), cx)); - cx.spawn_weak(|_, mut cx| async move { - share.await?; - if cx.update(|cx| cx.window_is_active(window_id)) { - active_call.update(&mut cx, |call, cx| { - call.set_location(Some(&project), cx).detach_and_log_err(cx); - }); - } - anyhow::Ok(()) - }) - .detach_and_log_err(cx); + active_call + .update(cx, |call, cx| call.share_project(project, cx)) + .detach_and_log_err(cx); } } @@ -363,7 +350,7 @@ impl CollabTitlebarItem { let mut avatar_style; if let Some((_, _, location)) = peer.as_ref() { - if let ParticipantLocation::Project { project_id } = *location { + if let ParticipantLocation::SharedProject { project_id } = *location { if Some(project_id) == workspace.read(cx).project().read(cx).remote_id() { avatar_style = theme.workspace.titlebar.avatar; } else { @@ -428,7 +415,7 @@ impl CollabTitlebarItem { cx, ) .boxed() - } else if let ParticipantLocation::Project { project_id } = location { + } else if let ParticipantLocation::SharedProject { project_id } = location { let user_id = user.id; MouseEventHandler::::new(peer_id.0 as usize, cx, move |_, _| content) .with_cursor_style(CursorStyle::PointingHand) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 765501368c..ed351cdefe 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -4687,6 +4687,12 @@ impl PartialEq for WeakModelHandle { impl Eq for WeakModelHandle {} +impl PartialEq> for WeakModelHandle { + fn eq(&self, other: &ModelHandle) -> bool { + self.model_id == other.model_id + } +} + impl Clone for WeakModelHandle { fn clone(&self) -> Self { Self { diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 2a358113e9..283b11fd78 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -174,14 +174,17 @@ message ParticipantProject { message ParticipantLocation { oneof variant { - Project project = 1; - External external = 2; + SharedProject shared_project = 1; + UnsharedProject unshared_project = 2; + External external = 3; } - message Project { + message SharedProject { uint64 id = 1; } + message UnsharedProject {} + message External {} } diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index 83ce28fdf0..707526c1d6 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -138,7 +138,7 @@ impl Member { border.overlay = true; match leader.location { - call::ParticipantLocation::Project { + call::ParticipantLocation::SharedProject { project_id: leader_project_id, } => { if Some(leader_project_id) == project.read(cx).remote_id() { @@ -183,6 +183,21 @@ impl Member { ) } } + call::ParticipantLocation::UnsharedProject => Some( + Label::new( + format!( + "{} is viewing an unshared Zed project", + leader.user.github_login + ), + theme.workspace.external_location_message.text.clone(), + ) + .contained() + .with_style(theme.workspace.external_location_message.container) + .aligned() + .bottom() + .right() + .boxed(), + ), call::ParticipantLocation::External => Some( Label::new( format!(