Change the default panel layout (#52232)

Mikayla Maki created

This PR adjusts the default panel layout for anyone on the agent v2
feature flag.

Note that this changes the right status bar items to show in reverse
priority order, and then adjusts priorities so that the "project
management" buttons appear to the right, and the outline panel appears
to the far left. The reversal "cancels out" most of the priority
changes, except the outline panel and the collab panel.


## Self-Review Checklist

<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Swapped the order of the collab and outline status bar buttons

Change summary

crates/agent_ui/src/agent_panel.rs         |  2 
crates/agent_ui/src/agent_ui.rs            | 29 ++++++++++++++++++++++-
crates/collab_ui/src/collab_panel.rs       |  2 
crates/collab_ui/src/notification_panel.rs |  2 
crates/outline_panel/src/outline_panel.rs  |  2 
crates/settings/src/settings_store.rs      | 11 +++++++++
crates/workspace/src/dock.rs               | 10 ++++++-
crates/zed/src/zed.rs                      |  4 +-
8 files changed, 52 insertions(+), 10 deletions(-)

Detailed changes

crates/agent_ui/src/agent_ui.rs 🔗

@@ -47,7 +47,7 @@ use client::Client;
 use command_palette_hooks::CommandPaletteFilter;
 use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt as _};
 use fs::Fs;
-use gpui::{Action, App, Context, Entity, SharedString, Window, actions};
+use gpui::{Action, App, Context, Entity, SharedString, UpdateGlobal, Window, actions};
 use language::{
     LanguageRegistry,
     language_settings::{AllLanguageSettings, EditPredictionProvider},
@@ -59,7 +59,7 @@ use project::{AgentId, DisableAiSettings};
 use prompt_store::PromptBuilder;
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
-use settings::{LanguageModelSelection, Settings as _, SettingsStore};
+use settings::{DockPosition, DockSide, LanguageModelSelection, Settings as _, SettingsStore};
 use std::any::TypeId;
 use workspace::Workspace;
 
@@ -415,6 +415,31 @@ pub fn init(
         update_command_palette_filter(cx);
     })
     .detach();
+
+    cx.observe_flag::<AgentV2FeatureFlag, _>(|is_enabled, cx| {
+        SettingsStore::update_global(cx, |store, cx| {
+            store.update_default_settings(cx, |defaults| {
+                if is_enabled {
+                    defaults.agent.get_or_insert_default().dock = Some(DockPosition::Left);
+                    defaults.project_panel.get_or_insert_default().dock = Some(DockSide::Right);
+                    defaults.outline_panel.get_or_insert_default().dock = Some(DockSide::Right);
+                    defaults.collaboration_panel.get_or_insert_default().dock =
+                        Some(DockPosition::Right);
+                    defaults.git_panel.get_or_insert_default().dock = Some(DockPosition::Right);
+                    defaults.notification_panel.get_or_insert_default().button = Some(false);
+                } else {
+                    defaults.agent.get_or_insert_default().dock = Some(DockPosition::Right);
+                    defaults.project_panel.get_or_insert_default().dock = Some(DockSide::Left);
+                    defaults.outline_panel.get_or_insert_default().dock = Some(DockSide::Left);
+                    defaults.collaboration_panel.get_or_insert_default().dock =
+                        Some(DockPosition::Left);
+                    defaults.git_panel.get_or_insert_default().dock = Some(DockPosition::Left);
+                    defaults.notification_panel.get_or_insert_default().button = Some(true);
+                }
+            });
+        });
+    })
+    .detach();
 }
 
 fn update_command_palette_filter(cx: &mut App) {

crates/settings/src/settings_store.rs 🔗

@@ -793,6 +793,17 @@ impl SettingsStore {
         edits
     }
 
+    /// Mutates the default settings in place and recomputes all setting values.
+    pub fn update_default_settings(
+        &mut self,
+        cx: &mut App,
+        update: impl FnOnce(&mut SettingsContent),
+    ) {
+        let default_settings = Rc::make_mut(&mut self.default_settings);
+        update(default_settings);
+        self.recompute_values(None, cx);
+    }
+
     /// Sets the default settings via a JSON string.
     ///
     /// The string should contain a JSON object with a default value for every setting.

crates/workspace/src/dock.rs 🔗

@@ -911,7 +911,7 @@ impl Render for PanelButtons {
             DockPosition::Bottom | DockPosition::Right => (Corner::BottomRight, Corner::TopRight),
         };
 
-        let buttons: Vec<_> = dock
+        let mut buttons: Vec<_> = dock
             .panel_entries
             .iter()
             .enumerate()
@@ -1004,12 +1004,18 @@ impl Render for PanelButtons {
             })
             .collect();
 
+        if dock_position == DockPosition::Right {
+            buttons.reverse();
+        }
+
         let has_buttons = !buttons.is_empty();
 
         h_flex()
             .gap_1()
             .when(
-                has_buttons && dock.position == DockPosition::Bottom,
+                has_buttons
+                    && (dock.position == DockPosition::Bottom
+                        || dock.position == DockPosition::Right),
                 |this| this.child(Divider::vertical().color(DividerColor::Border)),
             )
             .children(buttons)

crates/zed/src/zed.rs 🔗

@@ -2461,7 +2461,7 @@ mod tests {
             .update(cx, |multi_workspace, window, cx| {
                 multi_workspace.workspace().update(cx, |workspace, cx| {
                     assert_eq!(workspace.worktrees(cx).count(), 2);
-                    assert!(workspace.left_dock().read(cx).is_open());
+                    assert!(workspace.right_dock().read(cx).is_open());
                     assert!(
                         workspace
                             .active_pane()
@@ -2520,7 +2520,7 @@ mod tests {
                         .collect::<Vec<_>>(),
                     &[Path::new(path!("/root/e")).into()]
                 );
-                assert!(workspace.left_dock().read(cx).is_open());
+                assert!(workspace.right_dock().read(cx).is_open());
                 assert!(workspace.active_pane().focus_handle(cx).is_focused(window));
             })
             .unwrap();