Introduce a `+` button in the titlebar

Antonio Scandurra created

Change summary

crates/contacts_titlebar_item/src/contacts_titlebar_item.rs | 65 ++++++
crates/room/src/room.rs                                     | 18 -
crates/theme/src/theme.rs                                   |  1 
crates/zed/src/main.rs                                      |  1 
styles/src/styleTree/workspace.ts                           | 13 +
5 files changed, 78 insertions(+), 20 deletions(-)

Detailed changes

crates/contacts_titlebar_item/src/contacts_titlebar_item.rs 🔗

@@ -4,15 +4,27 @@ use gpui::{
     color::Color,
     elements::*,
     geometry::{rect::RectF, vector::vec2f, PathBuilder},
+    impl_internal_actions,
     json::{self, ToJson},
-    Border, CursorStyle, Entity, ImageData, MouseButton, RenderContext, Subscription, View,
-    ViewContext, ViewHandle, WeakViewHandle,
+    Border, CursorStyle, Entity, ImageData, MouseButton, MutableAppContext, RenderContext,
+    Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
 };
 use settings::Settings;
 use std::{ops::Range, sync::Arc};
 use theme::Theme;
 use workspace::{FollowNextCollaborator, ToggleFollow, Workspace};
 
+impl_internal_actions!(contacts_titlebar_item, [ToggleAddContactsPopover]);
+
+pub fn init(cx: &mut MutableAppContext) {
+    cx.add_action(ContactsTitlebarItem::toggle_add_contacts_popover);
+}
+
+#[derive(Clone, PartialEq)]
+struct ToggleAddContactsPopover {
+    button_rect: RectF,
+}
+
 pub struct ContactsTitlebarItem {
     workspace: WeakViewHandle<Workspace>,
     _subscriptions: Vec<Subscription>,
@@ -36,6 +48,7 @@ impl View for ContactsTitlebarItem {
 
         let theme = cx.global::<Settings>().theme.clone();
         Flex::row()
+            .with_children(self.render_toggle_contacts_button(&workspace, &theme, cx))
             .with_children(self.render_collaborators(&workspace, &theme, cx))
             .with_children(self.render_current_user(&workspace, &theme, cx))
             .with_children(self.render_connection_status(&workspace, cx))
@@ -52,6 +65,54 @@ impl ContactsTitlebarItem {
         }
     }
 
+    fn toggle_add_contacts_popover(
+        &mut self,
+        _action: &ToggleAddContactsPopover,
+        _cx: &mut ViewContext<Self>,
+    ) {
+        dbg!("!!!!!!!!!");
+    }
+
+    fn render_toggle_contacts_button(
+        &self,
+        workspace: &ViewHandle<Workspace>,
+        theme: &Theme,
+        cx: &mut RenderContext<Self>,
+    ) -> Option<ElementBox> {
+        if !workspace.read(cx).client().status().borrow().is_connected() {
+            return None;
+        }
+
+        Some(
+            MouseEventHandler::<ToggleAddContactsPopover>::new(0, cx, |state, _| {
+                let style = theme
+                    .workspace
+                    .titlebar
+                    .add_collaborator_button
+                    .style_for(state, false);
+                Svg::new("icons/plus_8.svg")
+                    .with_color(style.color)
+                    .constrained()
+                    .with_width(style.icon_width)
+                    .aligned()
+                    .constrained()
+                    .with_width(style.button_width)
+                    .with_height(style.button_width)
+                    .contained()
+                    .with_style(style.container)
+                    .boxed()
+            })
+            .with_cursor_style(CursorStyle::PointingHand)
+            .on_click(MouseButton::Left, |event, cx| {
+                cx.dispatch_action(ToggleAddContactsPopover {
+                    button_rect: event.region,
+                });
+            })
+            .aligned()
+            .boxed(),
+        )
+    }
+
     fn render_collaborators(
         &self,
         workspace: &ViewHandle<Workspace>,

crates/room/src/room.rs 🔗

@@ -87,10 +87,10 @@ impl Room {
             return Err(anyhow!("room is offline"));
         }
 
+        cx.notify();
         self.status = RoomStatus::Offline;
         self.remote_participants.clear();
         self.client.send(proto::LeaveRoom { id: self.id })?;
-        cx.notify();
         Ok(())
     }
 
@@ -184,22 +184,6 @@ impl Room {
 
         todo!()
     }
-
-    pub fn mute(&mut self) -> Task<Result<()>> {
-        if self.status.is_offline() {
-            return Task::ready(Err(anyhow!("room is offline")));
-        }
-
-        todo!()
-    }
-
-    pub fn unmute(&mut self) -> Task<Result<()>> {
-        if self.status.is_offline() {
-            return Task::ready(Err(anyhow!("room is offline")));
-        }
-
-        todo!()
-    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq)]

crates/theme/src/theme.rs 🔗

@@ -74,6 +74,7 @@ pub struct Titlebar {
     pub avatar: ImageStyle,
     pub sign_in_prompt: Interactive<ContainedText>,
     pub outdated_warning: ContainedText,
+    pub add_collaborator_button: Interactive<IconButton>,
 }
 
 #[derive(Clone, Deserialize, Default)]

crates/zed/src/main.rs 🔗

@@ -108,6 +108,7 @@ fn main() {
         client::Channel::init(&client);
         client::init(client.clone(), cx);
         command_palette::init(cx);
+        contacts_titlebar_item::init(cx);
         editor::init(cx);
         go_to_line::init(cx);
         file_finder::init(cx);

styles/src/styleTree/workspace.ts 🔗

@@ -16,6 +16,7 @@ export function workspaceBackground(theme: Theme) {
 
 export default function workspace(theme: Theme) {
   const titlebarPadding = 6;
+  const titlebarHeight = 33;
 
   return {
     background: backgroundColor(theme, 300),
@@ -54,7 +55,7 @@ export default function workspace(theme: Theme) {
     titlebar: {
       avatarWidth: 18,
       avatarMargin: 8,
-      height: 33,
+      height: titlebarHeight,
       background: backgroundColor(theme, 100),
       padding: {
         left: 80,
@@ -118,6 +119,16 @@ export default function workspace(theme: Theme) {
         },
         cornerRadius: 6,
       },
+      addCollaboratorButton: {
+        cornerRadius: 6,
+        color: iconColor(theme, "secondary"),
+        iconWidth: 8,
+        buttonWidth: 20,
+        hover: {
+          background: backgroundColor(theme, "on300", "hovered"),
+          color: iconColor(theme, "active"),
+        },
+      },
     },
     toolbar: {
       height: 34,