Dismiss project shared notifications when a project was unshared

Antonio Scandurra created

Change summary

crates/call/src/room.rs                             | 32 +++++++++++++-
crates/collab_ui/src/project_shared_notification.rs | 15 ++++++
2 files changed, 43 insertions(+), 4 deletions(-)

Detailed changes

crates/call/src/room.rs 🔗

@@ -18,6 +18,10 @@ pub enum Event {
         project_id: u64,
         worktree_root_names: Vec<String>,
     },
+    RemoteProjectUnshared {
+        project_id: u64,
+    },
+    Left,
 }
 
 pub struct Room {
@@ -148,6 +152,7 @@ impl Room {
         }
 
         cx.notify();
+        cx.emit(Event::Left);
         self.status = RoomStatus::Offline;
         self.remote_participants.clear();
         self.pending_participants.clear();
@@ -223,15 +228,21 @@ impl Room {
                         let peer_id = PeerId(participant.peer_id);
                         this.participant_user_ids.insert(participant.user_id);
 
-                        let existing_projects = this
+                        let old_projects = this
                             .remote_participants
                             .get(&peer_id)
                             .into_iter()
                             .flat_map(|existing| &existing.projects)
                             .map(|project| project.id)
                             .collect::<HashSet<_>>();
+                        let new_projects = participant
+                            .projects
+                            .iter()
+                            .map(|project| project.id)
+                            .collect::<HashSet<_>>();
+
                         for project in &participant.projects {
-                            if !existing_projects.contains(&project.id) {
+                            if !old_projects.contains(&project.id) {
                                 cx.emit(Event::RemoteProjectShared {
                                     owner: user.clone(),
                                     project_id: project.id,
@@ -240,6 +251,12 @@ impl Room {
                             }
                         }
 
+                        for unshared_project_id in old_projects.difference(&new_projects) {
+                            cx.emit(Event::RemoteProjectUnshared {
+                                project_id: *unshared_project_id,
+                            });
+                        }
+
                         this.remote_participants.insert(
                             peer_id,
                             RemoteParticipant {
@@ -252,7 +269,16 @@ impl Room {
                     }
 
                     this.remote_participants.retain(|_, participant| {
-                        this.participant_user_ids.contains(&participant.user.id)
+                        if this.participant_user_ids.contains(&participant.user.id) {
+                            true
+                        } else {
+                            for project in &participant.projects {
+                                cx.emit(Event::RemoteProjectUnshared {
+                                    project_id: project.id,
+                                });
+                            }
+                            false
+                        }
                     });
 
                     cx.notify();

crates/collab_ui/src/project_shared_notification.rs 🔗

@@ -1,5 +1,6 @@
 use call::{room, ActiveCall};
 use client::User;
+use collections::HashMap;
 use gpui::{
     actions,
     elements::*,
@@ -18,6 +19,7 @@ pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(ProjectSharedNotification::dismiss);
 
     let active_call = ActiveCall::global(cx);
+    let mut notification_windows = HashMap::default();
     cx.subscribe(&active_call, move |_, event, cx| match event {
         room::Event::RemoteProjectShared {
             owner,
@@ -29,7 +31,7 @@ pub fn init(cx: &mut MutableAppContext) {
 
             let theme = &cx.global::<Settings>().theme.project_shared_notification;
             let window_size = vec2f(theme.window_width, theme.window_height);
-            cx.add_window(
+            let (window_id, _) = cx.add_window(
                 WindowOptions {
                     bounds: WindowBounds::Fixed(RectF::new(
                         vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
@@ -48,6 +50,17 @@ pub fn init(cx: &mut MutableAppContext) {
                     )
                 },
             );
+            notification_windows.insert(*project_id, window_id);
+        }
+        room::Event::RemoteProjectUnshared { project_id } => {
+            if let Some(window_id) = notification_windows.remove(&project_id) {
+                cx.remove_window(window_id);
+            }
+        }
+        room::Event::Left => {
+            for (_, window_id) in notification_windows.drain() {
+                cx.remove_window(window_id);
+            }
         }
     })
     .detach();