diff --git a/crates/contacts_panel/src/contacts_panel.rs b/crates/contacts_panel/src/contacts_panel.rs index a33739293fbcbb3c494e1c4d52d86af485f3cea9..91794ebf0f379fd26750ddd79a3d0e0e2431d291 100644 --- a/crates/contacts_panel/src/contacts_panel.rs +++ b/crates/contacts_panel/src/contacts_panel.rs @@ -133,8 +133,12 @@ impl ContactsPanel { if let Some(workspace) = workspace.upgrade(cx) { workspace.update(cx, |workspace, cx| { workspace.show_notification( - cx.add_view(|_| { - JoinProjectNotification::new(project, user.clone()) + cx.add_view(|cx| { + JoinProjectNotification::new( + project, + user.clone(), + cx, + ) }), cx, ) diff --git a/crates/contacts_panel/src/join_project_notification.rs b/crates/contacts_panel/src/join_project_notification.rs index 8e55396e3e31b2f77f329dbd48eb8cd72b8b135f..d8e8e670cff02da81a5b6c4afc6754d88661f2f2 100644 --- a/crates/contacts_panel/src/join_project_notification.rs +++ b/crates/contacts_panel/src/join_project_notification.rs @@ -25,7 +25,15 @@ pub struct JoinProjectNotification { } impl JoinProjectNotification { - pub fn new(project: ModelHandle, user: Arc) -> Self { + pub fn new(project: ModelHandle, user: Arc, cx: &mut ViewContext) -> Self { + cx.subscribe(&project, |this, _, event, cx| { + if let project::Event::ContactCancelledJoinRequest(user) = event { + if *user == this.user { + cx.emit(Event::Dismiss); + } + } + }) + .detach(); Self { project, user } } diff --git a/crates/workspace/src/waiting_room.rs b/crates/workspace/src/waiting_room.rs index 17efebce39c71e067a062cef32d1220a62522a84..a8b717abb9f89f57639c38d5f864adfd69d7893a 100644 --- a/crates/workspace/src/waiting_room.rs +++ b/crates/workspace/src/waiting_room.rs @@ -3,25 +3,35 @@ use crate::{ AppState, }; use anyhow::Result; -use client::Contact; -use gpui::{elements::*, ElementBox, Entity, ImageData, RenderContext, Task, View, ViewContext}; +use client::{proto, Client, Contact}; +use gpui::{ + elements::*, ElementBox, Entity, ImageData, MutableAppContext, RenderContext, Task, View, + ViewContext, +}; use project::Project; use settings::Settings; use std::sync::Arc; +use util::ResultExt; pub struct WaitingRoom { + project_id: u64, avatar: Option>, message: String, - joined: bool, + waiting: bool, + client: Arc, _join_task: Task>, } impl Entity for WaitingRoom { type Event = (); - fn release(&mut self, _: &mut gpui::MutableAppContext) { - if !self.joined { - // TODO: Cancel the join request + fn release(&mut self, _: &mut MutableAppContext) { + if self.waiting { + self.client + .send(proto::LeaveProject { + project_id: self.project_id, + }) + .log_err(); } } } @@ -66,7 +76,7 @@ impl WaitingRoom { cx: &mut ViewContext, ) -> Self { let project_id = contact.projects[project_index].id; - + let client = app_state.client.clone(); let _join_task = cx.spawn_weak({ let contact = contact.clone(); |this, mut cx| async move { @@ -81,47 +91,50 @@ impl WaitingRoom { .await; if let Some(this) = this.upgrade(&cx) { - this.update(&mut cx, |this, cx| match project { - Ok(project) => { - this.joined = true; - cx.replace_root_view(|cx| { - let mut workspace = - (app_state.build_workspace)(project, &app_state, cx); - workspace.toggle_sidebar_item( - &ToggleSidebarItem { - side: Side::Left, - item_index: 0, - }, - cx, - ); - workspace - }); - } - Err(error @ _) => { - let login = &contact.user.github_login; - let message = match error { - project::JoinProjectError::HostDeclined => { - format!("@{} declined your request.", login) - } - project::JoinProjectError::HostClosedProject => { - format!( - "@{} closed their copy of {}.", - login, - humanize_list( - &contact.projects[project_index].worktree_root_names + this.update(&mut cx, |this, cx| { + this.waiting = false; + match project { + Ok(project) => { + cx.replace_root_view(|cx| { + let mut workspace = + (app_state.build_workspace)(project, &app_state, cx); + workspace.toggle_sidebar_item( + &ToggleSidebarItem { + side: Side::Left, + item_index: 0, + }, + cx, + ); + workspace + }); + } + Err(error @ _) => { + let login = &contact.user.github_login; + let message = match error { + project::JoinProjectError::HostDeclined => { + format!("@{} declined your request.", login) + } + project::JoinProjectError::HostClosedProject => { + format!( + "@{} closed their copy of {}.", + login, + humanize_list( + &contact.projects[project_index] + .worktree_root_names + ) ) - ) - } - project::JoinProjectError::HostWentOffline => { - format!("@{} went offline.", login) - } - project::JoinProjectError::Other(error) => { - log::error!("error joining project: {}", error); - "An error occurred.".to_string() - } - }; - this.message = message; - cx.notify(); + } + project::JoinProjectError::HostWentOffline => { + format!("@{} went offline.", login) + } + project::JoinProjectError::Other(error) => { + log::error!("error joining project: {}", error); + "An error occurred.".to_string() + } + }; + this.message = message; + cx.notify(); + } } }) } @@ -131,13 +144,15 @@ impl WaitingRoom { }); Self { + project_id, avatar: contact.user.avatar.clone(), message: format!( "Asking to join @{}'s copy of {}...", contact.user.github_login, humanize_list(&contact.projects[project_index].worktree_root_names) ), - joined: false, + waiting: true, + client, _join_task, } } @@ -149,10 +164,11 @@ fn humanize_list<'a>(items: impl IntoIterator) -> String { while let Some((ix, item)) = items.next() { if ix > 0 { list.push_str(", "); + if items.peek().is_none() { + list.push_str("and "); + } } - if items.peek().is_none() { - list.push_str("and "); - } + list.push_str(item); } list