Detailed changes
@@ -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<proto::ParticipantLocation>) -> Result<Self> {
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<proto::ParticipantProject>,
+ pub active_project: Option<WeakModelHandle<Project>>,
}
#[derive(Clone, Debug)]
@@ -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 {
@@ -946,8 +946,8 @@ async fn test_room_location(
}
});
- let project_a_id = active_call_a
- .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
+ room_a
+ .update(cx_a, |room, cx| room.set_location(Some(&project_a), cx))
.await
.unwrap();
deterministic.run_until_parked();
@@ -959,11 +959,11 @@ 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::UnsharedProject)]
);
- let project_b_id = active_call_b
- .update(cx_b, |call, cx| call.share_project(project_b.clone(), cx))
+ let project_a_id = active_call_a
+ .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
.await
.unwrap();
deterministic.run_until_parked();
@@ -975,11 +975,16 @@ 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
+ }
+ )]
);
- room_a
- .update(cx_a, |room, cx| room.set_location(Some(&project_a), cx))
+ let project_b_id = active_call_b
+ .update(cx_b, |call, cx| call.share_project(project_b.clone(), cx))
.await
.unwrap();
deterministic.run_until_parked();
@@ -993,7 +998,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
}
)]
@@ -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
}
)]
@@ -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!(
@@ -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<Self>) {
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::<JoinProject>::new(peer_id.0 as usize, cx, move |_, _| content)
.with_cursor_style(CursorStyle::PointingHand)
@@ -4687,6 +4687,12 @@ impl<T> PartialEq for WeakModelHandle<T> {
impl<T> Eq for WeakModelHandle<T> {}
+impl<T: Entity> PartialEq<ModelHandle<T>> for WeakModelHandle<T> {
+ fn eq(&self, other: &ModelHandle<T>) -> bool {
+ self.model_id == other.model_id
+ }
+}
+
impl<T> Clone for WeakModelHandle<T> {
fn clone(&self) -> Self {
Self {
@@ -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 {}
}
@@ -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!(