Create chat panel settings

Max Brunsfeld created

Change summary

assets/settings/default.json           |  8 +++++
crates/collab_ui/src/chat_panel.rs     | 43 ++++++++++++++-------------
crates/collab_ui/src/collab_panel.rs   | 27 +++-------------
crates/collab_ui/src/collab_ui.rs      |  8 ++++
crates/collab_ui/src/panel_settings.rs | 35 ++++++++++++++++------
crates/workspace/src/dock.rs           |  6 ++-
6 files changed, 73 insertions(+), 54 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -131,6 +131,14 @@
     // Default width of the channels panel.
     "default_width": 240
   },
+  "chat_panel": {
+    // Whether to show the collaboration panel button in the status bar.
+    "button": true,
+    // Where to dock channels panel. Can be 'left' or 'right'.
+    "dock": "right",
+    // Default width of the channels panel.
+    "default_width": 240
+  },
   "assistant": {
     // Whether to show the assistant panel button in the status bar.
     "button": true,

crates/collab_ui/src/chat_panel.rs 🔗

@@ -1,4 +1,4 @@
-use crate::collab_panel::{CollaborationPanelDockPosition, CollaborationPanelSettings};
+use crate::ChatPanelSettings;
 use anyhow::Result;
 use channel::{ChannelChat, ChannelChatEvent, ChannelMessage, ChannelStore};
 use client::Client;
@@ -17,6 +17,7 @@ use language::language_settings::SoftWrap;
 use menu::Confirm;
 use project::Fs;
 use serde::{Deserialize, Serialize};
+use settings::SettingsStore;
 use std::sync::Arc;
 use theme::Theme;
 use time::{OffsetDateTime, UtcOffset};
@@ -40,6 +41,7 @@ pub struct ChatPanel {
     fs: Arc<dyn Fs>,
     width: Option<f32>,
     pending_serialization: Task<Option<()>>,
+    subscriptions: Vec<gpui::Subscription>,
     has_focus: bool,
 }
 
@@ -124,9 +126,23 @@ impl ChatPanel {
                 channel_select,
                 local_timezone: cx.platform().local_timezone(),
                 has_focus: false,
+                subscriptions: Vec::new(),
                 width: None,
             };
 
+            let mut old_dock_position = this.position(cx);
+            this.subscriptions
+                .push(
+                    cx.observe_global::<SettingsStore, _>(move |this: &mut Self, cx| {
+                        let new_dock_position = this.position(cx);
+                        if new_dock_position != old_dock_position {
+                            old_dock_position = new_dock_position;
+                            cx.emit(Event::DockPositionChanged);
+                        }
+                        cx.notify();
+                    }),
+                );
+
             this.init_active_channel(cx);
             cx.observe(&this.channel_store, |this, _, cx| {
                 this.init_active_channel(cx);
@@ -446,10 +462,7 @@ impl View for ChatPanel {
 
 impl Panel for ChatPanel {
     fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
-        match settings::get::<CollaborationPanelSettings>(cx).dock {
-            CollaborationPanelDockPosition::Left => DockPosition::Left,
-            CollaborationPanelDockPosition::Right => DockPosition::Right,
-        }
+        settings::get::<ChatPanelSettings>(cx).dock
     }
 
     fn position_is_valid(&self, position: DockPosition) -> bool {
@@ -457,24 +470,14 @@ impl Panel for ChatPanel {
     }
 
     fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
-        settings::update_settings_file::<CollaborationPanelSettings>(
-            self.fs.clone(),
-            cx,
-            move |settings| {
-                let dock = match position {
-                    DockPosition::Left | DockPosition::Bottom => {
-                        CollaborationPanelDockPosition::Left
-                    }
-                    DockPosition::Right => CollaborationPanelDockPosition::Right,
-                };
-                settings.dock = Some(dock);
-            },
-        );
+        settings::update_settings_file::<ChatPanelSettings>(self.fs.clone(), cx, move |settings| {
+            settings.dock = Some(position)
+        });
     }
 
     fn size(&self, cx: &gpui::WindowContext) -> f32 {
         self.width
-            .unwrap_or_else(|| settings::get::<CollaborationPanelSettings>(cx).default_width)
+            .unwrap_or_else(|| settings::get::<ChatPanelSettings>(cx).default_width)
     }
 
     fn set_size(&mut self, size: Option<f32>, cx: &mut ViewContext<Self>) {
@@ -484,7 +487,7 @@ impl Panel for ChatPanel {
     }
 
     fn icon_path(&self, cx: &gpui::WindowContext) -> Option<&'static str> {
-        settings::get::<CollaborationPanelSettings>(cx)
+        settings::get::<ChatPanelSettings>(cx)
             .button
             .then(|| "icons/conversations.svg")
     }

crates/collab_ui/src/collab_panel.rs 🔗

@@ -1,16 +1,17 @@
 mod channel_modal;
 mod contact_finder;
-mod panel_settings;
 
 use crate::{
     channel_view::{self, ChannelView},
     face_pile::FacePile,
+    CollaborationPanelSettings,
 };
 use anyhow::Result;
 use call::ActiveCall;
 use channel::{Channel, ChannelEvent, ChannelId, ChannelStore};
 use channel_modal::ChannelModal;
 use client::{proto::PeerId, Client, Contact, User, UserStore};
+use contact_finder::ContactFinder;
 use context_menu::{ContextMenu, ContextMenuItem};
 use db::kvp::KEY_VALUE_STORE;
 use editor::{Cancel, Editor};
@@ -47,10 +48,6 @@ use workspace::{
     Workspace,
 };
 
-pub use panel_settings::{CollaborationPanelDockPosition, CollaborationPanelSettings};
-
-use self::contact_finder::ContactFinder;
-
 #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
 struct RemoveChannel {
     channel_id: u64,
@@ -113,7 +110,6 @@ impl_actions!(
 const COLLABORATION_PANEL_KEY: &'static str = "CollaborationPanel";
 
 pub fn init(cx: &mut AppContext) {
-    settings::register::<panel_settings::CollaborationPanelSettings>(cx);
     contact_finder::init(cx);
     channel_modal::init(cx);
     channel_view::init(cx);
@@ -451,7 +447,7 @@ impl CollabPanel {
             let mut old_dock_position = this.position(cx);
             this.subscriptions
                 .push(
-                    cx.observe_global::<SettingsStore, _>(move |this: &mut CollabPanel, cx| {
+                    cx.observe_global::<SettingsStore, _>(move |this: &mut Self, cx| {
                         let new_dock_position = this.position(cx);
                         if new_dock_position != old_dock_position {
                             old_dock_position = new_dock_position;
@@ -2555,10 +2551,7 @@ impl View for CollabPanel {
 
 impl Panel for CollabPanel {
     fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
-        match settings::get::<CollaborationPanelSettings>(cx).dock {
-            CollaborationPanelDockPosition::Left => DockPosition::Left,
-            CollaborationPanelDockPosition::Right => DockPosition::Right,
-        }
+        settings::get::<CollaborationPanelSettings>(cx).dock
     }
 
     fn position_is_valid(&self, position: DockPosition) -> bool {
@@ -2569,15 +2562,7 @@ impl Panel for CollabPanel {
         settings::update_settings_file::<CollaborationPanelSettings>(
             self.fs.clone(),
             cx,
-            move |settings| {
-                let dock = match position {
-                    DockPosition::Left | DockPosition::Bottom => {
-                        CollaborationPanelDockPosition::Left
-                    }
-                    DockPosition::Right => CollaborationPanelDockPosition::Right,
-                };
-                settings.dock = Some(dock);
-            },
+            move |settings| settings.dock = Some(position),
         );
     }
 
@@ -2595,7 +2580,7 @@ impl Panel for CollabPanel {
     fn icon_path(&self, cx: &gpui::WindowContext) -> Option<&'static str> {
         settings::get::<CollaborationPanelSettings>(cx)
             .button
-            .then(|| "icons/conversations.svg")
+            .then(|| "icons/user_group_16.svg")
     }
 
     fn icon_tooltip(&self) -> (String, Option<Box<dyn gpui::Action>>) {

crates/collab_ui/src/collab_ui.rs 🔗

@@ -6,11 +6,11 @@ mod contact_notification;
 mod face_pile;
 mod incoming_call_notification;
 mod notifications;
+mod panel_settings;
 mod project_shared_notification;
 mod sharing_status_indicator;
 
 use call::{ActiveCall, Room};
-pub use collab_titlebar_item::CollabTitlebarItem;
 use gpui::{
     actions,
     geometry::{
@@ -24,12 +24,18 @@ use std::{rc::Rc, sync::Arc};
 use util::ResultExt;
 use workspace::AppState;
 
+pub use collab_titlebar_item::CollabTitlebarItem;
+pub use panel_settings::{ChatPanelSettings, CollaborationPanelSettings};
+
 actions!(
     collab,
     [ToggleScreenSharing, ToggleMute, ToggleDeafen, LeaveCall]
 );
 
 pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
+    settings::register::<CollaborationPanelSettings>(cx);
+    settings::register::<ChatPanelSettings>(cx);
+
     vcs_menu::init(cx);
     collab_titlebar_item::init(cx);
     collab_panel::init(cx);

crates/collab_ui/src/collab_panel/panel_settings.rs → crates/collab_ui/src/panel_settings.rs 🔗

@@ -2,32 +2,47 @@ use anyhow;
 use schemars::JsonSchema;
 use serde_derive::{Deserialize, Serialize};
 use settings::Setting;
+use workspace::dock::DockPosition;
 
-#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum CollaborationPanelDockPosition {
-    Left,
-    Right,
+#[derive(Deserialize, Debug)]
+pub struct CollaborationPanelSettings {
+    pub button: bool,
+    pub dock: DockPosition,
+    pub default_width: f32,
 }
 
 #[derive(Deserialize, Debug)]
-pub struct CollaborationPanelSettings {
+pub struct ChatPanelSettings {
     pub button: bool,
-    pub dock: CollaborationPanelDockPosition,
+    pub dock: DockPosition,
     pub default_width: f32,
 }
 
 #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
-pub struct CollaborationPanelSettingsContent {
+pub struct PanelSettingsContent {
     pub button: Option<bool>,
-    pub dock: Option<CollaborationPanelDockPosition>,
+    pub dock: Option<DockPosition>,
     pub default_width: Option<f32>,
 }
 
 impl Setting for CollaborationPanelSettings {
     const KEY: Option<&'static str> = Some("collaboration_panel");
 
-    type FileContent = CollaborationPanelSettingsContent;
+    type FileContent = PanelSettingsContent;
+
+    fn load(
+        default_value: &Self::FileContent,
+        user_values: &[&Self::FileContent],
+        _: &gpui::AppContext,
+    ) -> anyhow::Result<Self> {
+        Self::load_via_json_merge(default_value, user_values)
+    }
+}
+
+impl Setting for ChatPanelSettings {
+    const KEY: Option<&'static str> = Some("chat_panel");
+
+    type FileContent = PanelSettingsContent;
 
     fn load(
         default_value: &Self::FileContent,

crates/workspace/src/dock.rs 🔗

@@ -4,7 +4,8 @@ use gpui::{
     elements::*, platform::CursorStyle, platform::MouseButton, Action, AnyViewHandle, AppContext,
     Axis, Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
 };
-use serde::Deserialize;
+use schemars::JsonSchema;
+use serde::{Deserialize, Serialize};
 use std::rc::Rc;
 use theme::ThemeSettings;
 
@@ -132,7 +133,8 @@ pub struct Dock {
     active_panel_index: usize,
 }
 
-#[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
+#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
+#[serde(rename_all = "lowercase")]
 pub enum DockPosition {
     Left,
     Bottom,