Add support for switching between the project and collab panels

Marshall Bowers created

Change summary

crates/ui2/src/components/status_bar.rs | 32 ++++++-------
crates/ui2/src/components/workspace.rs  | 61 +++++++++++++++++++++++++-
2 files changed, 72 insertions(+), 21 deletions(-)

Detailed changes

crates/ui2/src/components/status_bar.rs 🔗

@@ -108,28 +108,24 @@ impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
             .gap_1()
             .child(
                 IconButton::new(Icon::FileTree)
-                    .when(
-                        workspace_state.show_project_panel.load(Ordering::SeqCst),
-                        |this| this.color(IconColor::Accent),
-                    )
+                    .when(workspace_state.is_project_panel_open(), |this| {
+                        this.color(IconColor::Accent)
+                    })
                     .on_click(|_, cx| {
-                        let is_showing_project_panel =
-                            workspace_state.show_project_panel.load(Ordering::SeqCst);
-
-                        workspace_state
-                            .show_project_panel
-                            .compare_exchange(
-                                is_showing_project_panel,
-                                !is_showing_project_panel,
-                                Ordering::SeqCst,
-                                Ordering::SeqCst,
-                            )
-                            .unwrap();
-
+                        workspace_state.toggle_project_panel();
+                        cx.notify();
+                    }),
+            )
+            .child(
+                IconButton::new(Icon::Hash)
+                    .when(workspace_state.is_collab_panel_open(), |this| {
+                        this.color(IconColor::Accent)
+                    })
+                    .on_click(|_, cx| {
+                        workspace_state.toggle_collab_panel();
                         cx.notify();
                     }),
             )
-            .child(IconButton::new(Icon::Hash))
             .child(ToolDivider::new())
             .child(IconButton::new(Icon::XCircle))
     }

crates/ui2/src/components/workspace.rs 🔗

@@ -8,18 +8,59 @@ use gpui3::{px, relative, rems, Size};
 use crate::prelude::*;
 use crate::{
     hello_world_rust_editor_with_status_example, random_players_with_call_status, theme, v_stack,
-    ChatMessage, ChatPanel, EditorPane, Label, LanguageSelector, Livestream, Pane, PaneGroup,
-    Panel, PanelAllowedSides, PanelSide, ProjectPanel, SplitDirection, StatusBar, Terminal,
-    TitleBar, Toast, ToastOrigin,
+    ChatMessage, ChatPanel, CollabPanel, EditorPane, Label, LanguageSelector, Livestream, Pane,
+    PaneGroup, Panel, PanelAllowedSides, PanelSide, ProjectPanel, SplitDirection, StatusBar,
+    Terminal, TitleBar, Toast, ToastOrigin,
 };
 
 pub struct WorkspaceState {
     pub show_project_panel: Arc<AtomicBool>,
+    pub show_collab_panel: Arc<AtomicBool>,
     pub show_chat_panel: Arc<AtomicBool>,
     pub show_terminal: Arc<AtomicBool>,
     pub show_language_selector: Arc<AtomicBool>,
 }
 
+impl WorkspaceState {
+    pub fn is_project_panel_open(&self) -> bool {
+        self.show_project_panel.load(Ordering::SeqCst)
+    }
+
+    pub fn toggle_project_panel(&self) {
+        let is_showing_project_panel = self.show_project_panel.load(Ordering::SeqCst);
+
+        self.show_project_panel
+            .compare_exchange(
+                is_showing_project_panel,
+                !is_showing_project_panel,
+                Ordering::SeqCst,
+                Ordering::SeqCst,
+            )
+            .unwrap();
+
+        self.show_collab_panel.store(false, Ordering::SeqCst);
+    }
+
+    pub fn is_collab_panel_open(&self) -> bool {
+        self.show_collab_panel.load(Ordering::SeqCst)
+    }
+
+    pub fn toggle_collab_panel(&self) {
+        let is_showing_collab_panel = self.show_collab_panel.load(Ordering::SeqCst);
+
+        self.show_collab_panel
+            .compare_exchange(
+                is_showing_collab_panel,
+                !is_showing_collab_panel,
+                Ordering::SeqCst,
+                Ordering::SeqCst,
+            )
+            .unwrap();
+
+        self.show_project_panel.store(false, Ordering::SeqCst);
+    }
+}
+
 /// HACK: This is just a temporary way to start hooking up interactivity until
 /// I can get an explainer on how we should actually be managing state.
 static WORKSPACE_STATE: OnceLock<WorkspaceState> = OnceLock::new();
@@ -27,6 +68,7 @@ static WORKSPACE_STATE: OnceLock<WorkspaceState> = OnceLock::new();
 pub fn get_workspace_state() -> &'static WorkspaceState {
     let state = WORKSPACE_STATE.get_or_init(|| WorkspaceState {
         show_project_panel: Arc::new(AtomicBool::new(true)),
+        show_collab_panel: Arc::new(AtomicBool::new(false)),
         show_chat_panel: Arc::new(AtomicBool::new(true)),
         show_terminal: Arc::new(AtomicBool::new(true)),
         show_language_selector: Arc::new(AtomicBool::new(false)),
@@ -155,6 +197,19 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
                         )
                         .filter(|_| workspace_state.show_project_panel.load(Ordering::SeqCst)),
                     )
+                    .children(
+                        Some(
+                            Panel::new(
+                                self.left_panel_scroll_state.clone(),
+                                |_, payload| {
+                                    vec![CollabPanel::new(ScrollState::default()).into_any()]
+                                },
+                                Box::new(()),
+                            )
+                            .side(PanelSide::Left),
+                        )
+                        .filter(|_| workspace_state.show_collab_panel.load(Ordering::SeqCst)),
+                    )
                     .child(
                         v_stack()
                             .flex_1()