Fix panic opening branch picker in commit modal (#26407)

Conrad Irwin created

Closes #ISSUE

Release Notes:

- N/A

Change summary

crates/workspace/src/dock.rs        | 19 ++++++++++++++-----
crates/workspace/src/modal_layer.rs |  1 +
crates/workspace/src/workspace.rs   | 15 +++++++--------
3 files changed, 22 insertions(+), 13 deletions(-)

Detailed changes

crates/workspace/src/dock.rs 🔗

@@ -1,6 +1,6 @@
 use crate::persistence::model::DockData;
 use crate::{status_bar::StatusItemView, Workspace};
-use crate::{DraggedDock, Event, Pane};
+use crate::{DraggedDock, Event, ModalLayer, Pane};
 use client::proto;
 use gpui::{
     deferred, div, px, Action, AnyView, App, Axis, Context, Corner, Entity, EntityId, EventEmitter,
@@ -189,7 +189,8 @@ pub struct Dock {
     active_panel_index: Option<usize>,
     focus_handle: FocusHandle,
     pub(crate) serialized_dock: Option<DockData>,
-    resizeable: bool,
+    zoom_layer_open: bool,
+    modal_layer: Entity<ModalLayer>,
     _subscriptions: [Subscription; 2],
 }
 
@@ -236,6 +237,7 @@ pub struct PanelButtons {
 impl Dock {
     pub fn new(
         position: DockPosition,
+        modal_layer: Entity<ModalLayer>,
         window: &mut Window,
         cx: &mut Context<Workspace>,
     ) -> Entity<Self> {
@@ -251,7 +253,7 @@ impl Dock {
             let zoom_subscription = cx.subscribe(&workspace, |dock, workspace, e: &Event, cx| {
                 if matches!(e, Event::ZoomChanged) {
                     let is_zoomed = workspace.read(cx).zoomed.is_some();
-                    dock.resizeable = !is_zoomed;
+                    dock.zoom_layer_open = is_zoomed;
                 }
             });
             Self {
@@ -263,7 +265,8 @@ impl Dock {
                 focus_handle: focus_handle.clone(),
                 _subscriptions: [focus_subscription, zoom_subscription],
                 serialized_dock: None,
-                resizeable: true,
+                zoom_layer_open: false,
+                modal_layer,
             }
         });
 
@@ -320,6 +323,10 @@ impl Dock {
         self.is_open
     }
 
+    fn resizable(&self, cx: &App) -> bool {
+        !(self.zoom_layer_open || self.modal_layer.read(cx).has_active_modal())
+    }
+
     pub fn panel<T: Panel>(&self) -> Option<Entity<T>> {
         self.panel_entries
             .iter()
@@ -777,7 +784,9 @@ impl Render for Dock {
                                 .cached(StyleRefinement::default().v_flex().size_full()),
                         ),
                 )
-                .when(self.resizeable, |this| this.child(create_resize_handle()))
+                .when(self.resizable(cx), |this| {
+                    this.child(create_resize_handle())
+                })
         } else {
             div()
                 .key_context(dispatch_context)

crates/workspace/src/workspace.rs 🔗

@@ -35,7 +35,7 @@ use futures::{
     Future, FutureExt, StreamExt,
 };
 use gpui::{
-    action_as, actions, canvas, deferred, impl_action_as, impl_actions, point, relative, size,
+    action_as, actions, canvas, impl_action_as, impl_actions, point, relative, size,
     transparent_black, Action, AnyView, AnyWeakView, App, AsyncApp, AsyncWindowContext, Bounds,
     Context, CursorStyle, Decorations, DragMoveEvent, Entity, EntityId, EventEmitter, FocusHandle,
     Focusable, Global, Hsla, KeyContext, Keystroke, ManagedView, MouseButton, PathPromptOptions,
@@ -1019,10 +1019,12 @@ impl Workspace {
         });
 
         cx.emit(Event::WorkspaceCreated(weak_handle.clone()));
+        let modal_layer = cx.new(|_| ModalLayer::new());
+        let toast_layer = cx.new(|_| ToastLayer::new());
 
-        let left_dock = Dock::new(DockPosition::Left, window, cx);
-        let bottom_dock = Dock::new(DockPosition::Bottom, window, cx);
-        let right_dock = Dock::new(DockPosition::Right, window, cx);
+        let left_dock = Dock::new(DockPosition::Left, modal_layer.clone(), window, cx);
+        let bottom_dock = Dock::new(DockPosition::Bottom, modal_layer.clone(), window, cx);
+        let right_dock = Dock::new(DockPosition::Right, modal_layer.clone(), window, cx);
         let left_dock_buttons = cx.new(|cx| PanelButtons::new(left_dock.clone(), cx));
         let bottom_dock_buttons = cx.new(|cx| PanelButtons::new(bottom_dock.clone(), cx));
         let right_dock_buttons = cx.new(|cx| PanelButtons::new(right_dock.clone(), cx));
@@ -1034,9 +1036,6 @@ impl Workspace {
             status_bar
         });
 
-        let modal_layer = cx.new(|_| ModalLayer::new());
-        let toast_layer = cx.new(|_| ToastLayer::new());
-
         let session_id = app_state.session.read(cx).id().to_owned();
 
         let mut active_call = None;
@@ -5542,7 +5541,7 @@ impl Render for Workspace {
                                 .children(self.render_notifications(window, cx)),
                         )
                         .child(self.status_bar.clone())
-                        .child(deferred(self.modal_layer.clone()))
+                        .child(self.modal_layer.clone())
                         .child(self.toast_layer.clone()),
                 ),
             window,