Show "sign in" prompt when opening the chat panel while signed out

Antonio Scandurra created

Change summary

zed/assets/themes/_base.toml |  8 ++++++
zed/src/chat_panel.rs        | 49 ++++++++++++++++++++++++++++++++-----
zed/src/theme.rs             |  2 +
zed/src/workspace.rs         |  1 
zed/src/workspace/sidebar.rs |  6 +---
5 files changed, 55 insertions(+), 11 deletions(-)

Detailed changes

zed/assets/themes/_base.toml 🔗

@@ -76,6 +76,14 @@ placeholder_text = "$text.2.color"
 background = "$surface.1"
 selection = "$selection.host"
 
+[chat_panel.sign_in_prompt]
+extends = "$text.0"
+underline = true
+
+[chat_panel.hovered_sign_in_prompt]
+extends = "$chat_panel.sign_in_prompt"
+color = "$text.1.color"
+
 [selector]
 background = "$surface.2"
 text = "$text.0"

zed/src/chat_panel.rs 🔗

@@ -1,14 +1,18 @@
+use std::sync::Arc;
+
 use crate::{
     channel::{Channel, ChannelEvent, ChannelList, ChannelMessage},
     editor::Editor,
+    rpc::Client,
     theme,
-    util::ResultExt,
+    util::{ResultExt, TryFutureExt},
     Settings,
 };
 use gpui::{
     action,
     elements::*,
     keymap::Binding,
+    platform::CursorStyle,
     views::{ItemType, Select, SelectStyle},
     AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Subscription, View,
     ViewContext, ViewHandle,
@@ -19,6 +23,7 @@ use time::{OffsetDateTime, UtcOffset};
 const MESSAGE_LOADING_THRESHOLD: usize = 50;
 
 pub struct ChatPanel {
+    rpc: Arc<Client>,
     channel_list: ModelHandle<ChannelList>,
     active_channel: Option<(ModelHandle<Channel>, Subscription)>,
     message_list: ListState,
@@ -42,6 +47,7 @@ pub fn init(cx: &mut MutableAppContext) {
 
 impl ChatPanel {
     pub fn new(
+        rpc: Arc<Client>,
         channel_list: ModelHandle<ChannelList>,
         settings: watch::Receiver<Settings>,
         cx: &mut ViewContext<Self>,
@@ -94,6 +100,7 @@ impl ChatPanel {
         });
 
         let mut this = Self {
+            rpc,
             channel_list,
             active_channel: Default::default(),
             message_list,
@@ -307,9 +314,38 @@ impl View for ChatPanel {
         "ChatPanel"
     }
 
-    fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
+    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
         let theme = &self.settings.borrow().theme;
-        ConstrainedBox::new(
+        let element = if self.rpc.user_id().borrow().is_none() {
+            enum SignInPromptLabel {}
+
+            Align::new(
+                MouseEventHandler::new::<SignInPromptLabel, _, _, _>(0, cx, |mouse_state, _| {
+                    Label::new(
+                        "Sign in to use chat".to_string(),
+                        if mouse_state.hovered {
+                            theme.chat_panel.hovered_sign_in_prompt.clone()
+                        } else {
+                            theme.chat_panel.sign_in_prompt.clone()
+                        },
+                    )
+                    .boxed()
+                })
+                .with_cursor_style(CursorStyle::PointingHand)
+                .on_click({
+                    let rpc = self.rpc.clone();
+                    move |cx| {
+                        let rpc = rpc.clone();
+                        cx.spawn(|cx| async move {
+                            rpc.authenticate_and_connect(cx).log_err().await;
+                        })
+                        .detach();
+                    }
+                })
+                .boxed(),
+            )
+            .boxed()
+        } else {
             Container::new(
                 Flex::column()
                     .with_child(
@@ -322,10 +358,9 @@ impl View for ChatPanel {
                     .boxed(),
             )
             .with_style(&theme.chat_panel.container)
-            .boxed(),
-        )
-        .with_min_width(150.)
-        .boxed()
+            .boxed()
+        };
+        ConstrainedBox::new(element).with_min_width(150.).boxed()
     }
 
     fn on_focus(&mut self, cx: &mut ViewContext<Self>) {

zed/src/theme.rs 🔗

@@ -70,6 +70,8 @@ pub struct ChatPanel {
     pub channel_select: ChannelSelect,
     pub input_editor_container: ContainerStyle,
     pub input_editor: InputEditorStyle,
+    pub sign_in_prompt: TextStyle,
+    pub hovered_sign_in_prompt: TextStyle,
 }
 
 #[derive(Deserialize)]

zed/src/workspace.rs 🔗

@@ -376,6 +376,7 @@ impl Workspace {
             "icons/comment-16.svg",
             cx.add_view(|cx| {
                 ChatPanel::new(
+                    app_state.rpc.clone(),
                     app_state.channel_list.clone(),
                     app_state.settings.clone(),
                     cx,

zed/src/workspace/sidebar.rs 🔗

@@ -37,7 +37,7 @@ impl Sidebar {
             side,
             items: Default::default(),
             active_item_ix: None,
-            width: Rc::new(RefCell::new(200.)),
+            width: Rc::new(RefCell::new(220.)),
         }
     }
 
@@ -123,9 +123,7 @@ impl Sidebar {
                     )
                     .on_after_layout({
                         let width = self.width.clone();
-                        move |size, _| {
-                            *width.borrow_mut() = size.x();
-                        }
+                        move |size, _| *width.borrow_mut() = size.x()
                     })
                     .boxed(),
                 )