Add call status indicator to the status bar

Kay Simmons created

Change summary

crates/call/src/call.rs                      | 37 +++++++++++++++++++-
crates/call/src/indicator.rs                 | 39 ++++++++++++++++++++++
crates/collab_ui/src/collab_titlebar_item.rs | 21 +----------
script/start-local-collaboration             |  5 +-
4 files changed, 79 insertions(+), 23 deletions(-)

Detailed changes

crates/call/src/call.rs 🔗

@@ -1,3 +1,4 @@
+mod indicator;
 pub mod participant;
 pub mod room;
 
@@ -5,18 +6,22 @@ use anyhow::{anyhow, Result};
 use client::{proto, Client, TypedEnvelope, User, UserStore};
 use collections::HashSet;
 use gpui::{
-    AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
-    Subscription, Task, WeakModelHandle,
+    actions, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
+    Subscription, Task, ViewHandle, WeakModelHandle,
 };
+use indicator::SharingStatusIndicator;
 pub use participant::ParticipantLocation;
 use postage::watch;
 use project::Project;
 pub use room::Room;
 use std::sync::Arc;
 
+actions!(collab, [ToggleScreenSharing]);
+
 pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut MutableAppContext) {
     let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx));
     cx.set_global(active_call);
+    cx.add_global_action(toggle_screen_sharing);
 }
 
 #[derive(Clone)]
@@ -37,6 +42,7 @@ pub struct ActiveCall {
     ),
     client: Arc<Client>,
     user_store: ModelHandle<UserStore>,
+    sharing_status_indicator: Option<(usize, ViewHandle<SharingStatusIndicator>)>,
     _subscriptions: Vec<client::Subscription>,
 }
 
@@ -61,6 +67,7 @@ impl ActiveCall {
             ],
             client,
             user_store,
+            sharing_status_indicator: None,
         }
     }
 
@@ -279,6 +286,8 @@ impl ActiveCall {
                                 this.set_room(None, cx).detach_and_log_err(cx);
                             }
 
+                            this.set_sharing_status(room.read(cx).is_screen_sharing(), cx);
+
                             cx.notify();
                         }),
                         cx.subscribe(&room, |_, _, event, cx| cx.emit(event.clone())),
@@ -303,4 +312,28 @@ impl ActiveCall {
     pub fn pending_invites(&self) -> &HashSet<u64> {
         &self.pending_invites
     }
+
+    pub fn set_sharing_status(&mut self, is_screen_sharing: bool, cx: &mut MutableAppContext) {
+        if is_screen_sharing {
+            if self.sharing_status_indicator.is_none() {
+                self.sharing_status_indicator =
+                    Some(cx.add_status_bar_item(|_| SharingStatusIndicator));
+            }
+        } else if let Some((window_id, _)) = self.sharing_status_indicator.take() {
+            cx.remove_status_bar_item(window_id);
+        }
+    }
+}
+
+pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext) {
+    if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
+        let toggle_screen_sharing = room.update(cx, |room, cx| {
+            if room.is_screen_sharing() {
+                Task::ready(room.unshare_screen(cx))
+            } else {
+                room.share_screen(cx)
+            }
+        });
+        toggle_screen_sharing.detach_and_log_err(cx);
+    }
 }

crates/call/src/indicator.rs 🔗

@@ -0,0 +1,39 @@
+use gpui::{
+    color::Color,
+    elements::{MouseEventHandler, Svg},
+    Appearance, Element, ElementBox, Entity, MouseButton, RenderContext, View,
+};
+
+use crate::ToggleScreenSharing;
+
+pub struct SharingStatusIndicator;
+
+impl Entity for SharingStatusIndicator {
+    type Event = ();
+}
+
+impl View for SharingStatusIndicator {
+    fn ui_name() -> &'static str {
+        "SharingStatusIndicator"
+    }
+
+    fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox {
+        let color = match cx.appearance {
+            Appearance::Light | Appearance::VibrantLight => Color::black(),
+            Appearance::Dark | Appearance::VibrantDark => Color::white(),
+        };
+
+        MouseEventHandler::<Self>::new(0, cx, |_, _| {
+            Svg::new("icons/disable_screen_sharing_12.svg")
+                .with_color(color)
+                .constrained()
+                .with_width(18.)
+                .aligned()
+                .boxed()
+        })
+        .on_click(MouseButton::Left, |_, cx| {
+            cx.dispatch_action(ToggleScreenSharing);
+        })
+        .boxed()
+    }
+}

crates/collab_ui/src/collab_titlebar_item.rs 🔗

@@ -1,5 +1,5 @@
 use crate::{contact_notification::ContactNotification, contacts_popover};
-use call::{ActiveCall, ParticipantLocation};
+use call::{ActiveCall, ParticipantLocation, ToggleScreenSharing};
 use client::{proto::PeerId, Authenticate, ContactEventKind, User, UserStore};
 use clock::ReplicaId;
 use contacts_popover::ContactsPopover;
@@ -17,14 +17,10 @@ use std::ops::Range;
 use theme::Theme;
 use workspace::{FollowNextCollaborator, JoinProject, ToggleFollow, Workspace};
 
-actions!(
-    collab,
-    [ToggleCollaborationMenu, ToggleScreenSharing, ShareProject]
-);
+actions!(collab, [ToggleCollaborationMenu, ShareProject]);
 
 pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(CollabTitlebarItem::toggle_contacts_popover);
-    cx.add_action(CollabTitlebarItem::toggle_screen_sharing);
     cx.add_action(CollabTitlebarItem::share_project);
 }
 
@@ -172,19 +168,6 @@ impl CollabTitlebarItem {
         cx.notify();
     }
 
-    pub fn toggle_screen_sharing(&mut self, _: &ToggleScreenSharing, cx: &mut ViewContext<Self>) {
-        if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
-            let toggle_screen_sharing = room.update(cx, |room, cx| {
-                if room.is_screen_sharing() {
-                    Task::ready(room.unshare_screen(cx))
-                } else {
-                    room.share_screen(cx)
-                }
-            });
-            toggle_screen_sharing.detach_and_log_err(cx);
-        }
-    }
-
     fn render_toggle_contacts_button(
         &self,
         theme: &Theme,

script/start-local-collaboration 🔗

@@ -31,9 +31,10 @@ scale_factor=1
 if [[ $resolution_line =~ Retina ]]; then scale_factor=2; fi
 width=$(expr ${screen_size[0]} / 2 / $scale_factor)
 height=${screen_size[1] / $scale_factor}
+y=$(expr $height / 2)
 
-position_1=0,0
-position_2=${width},0
+position_1=0,${y}
+position_2=${width},${y}
 
 # Authenticate using the collab server's admin secret.
 export ZED_STATELESS=1