Fix panel deserialization (#4198)

In the old world, panel loading happened strictly before workspace
deserialization. Now it's inverted.

Fix this by storing on the dock the serialized state so they can restore
state as panels are loaded.

[[PR Description]]

Release Notes:

- Fixed Zed forgetting which panels were open on boot.
([#2406](https://github.com/zed-industries/community/issues/2406)).
This commit is contained in:
Conrad Irwin 2024-01-22 12:37:38 -07:00 committed by GitHub
commit c5465d26f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 46 additions and 48 deletions

View file

@ -1,3 +1,4 @@
use crate::persistence::model::DockData;
use crate::DraggedDock; use crate::DraggedDock;
use crate::{status_bar::StatusItemView, Workspace}; use crate::{status_bar::StatusItemView, Workspace};
use gpui::{ use gpui::{
@ -141,6 +142,7 @@ pub struct Dock {
is_open: bool, is_open: bool,
active_panel_index: usize, active_panel_index: usize,
focus_handle: FocusHandle, focus_handle: FocusHandle,
pub(crate) serialized_dock: Option<DockData>,
_focus_subscription: Subscription, _focus_subscription: Subscription,
} }
@ -201,6 +203,7 @@ impl Dock {
is_open: false, is_open: false,
focus_handle: focus_handle.clone(), focus_handle: focus_handle.clone(),
_focus_subscription: focus_subscription, _focus_subscription: focus_subscription,
serialized_dock: None,
} }
}); });
@ -408,10 +411,26 @@ impl Dock {
}), }),
]; ];
let name = panel.persistent_name().to_string();
self.panel_entries.push(PanelEntry { self.panel_entries.push(PanelEntry {
panel: Arc::new(panel), panel: Arc::new(panel),
_subscriptions: subscriptions, _subscriptions: subscriptions,
}); });
if let Some(serialized) = self.serialized_dock.clone() {
if serialized.active_panel == Some(name) {
self.activate_panel(self.panel_entries.len() - 1, cx);
if serialized.visible {
self.set_open(true, cx);
}
if serialized.zoom {
if let Some(panel) = self.active_panel() {
panel.set_zoomed(true, cx)
};
}
}
}
cx.notify() cx.notify()
} }

View file

@ -1681,6 +1681,18 @@ impl Workspace {
None None
} }
/// Open the panel of the given type
pub fn open_panel<T: Panel>(&mut self, cx: &mut ViewContext<Self>) {
for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] {
if let Some(panel_index) = dock.read(cx).panel_index_for_type::<T>() {
dock.update(cx, |dock, cx| {
dock.activate_panel(panel_index, cx);
dock.set_open(true, cx);
});
}
}
}
pub fn panel<T: Panel>(&self, cx: &WindowContext) -> Option<View<T>> { pub fn panel<T: Panel>(&self, cx: &WindowContext) -> Option<View<T>> {
for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] {
let dock = dock.read(cx); let dock = dock.read(cx);
@ -3175,49 +3187,19 @@ impl Workspace {
} }
let docks = serialized_workspace.docks; let docks = serialized_workspace.docks;
workspace.left_dock.update(cx, |dock, cx| {
dock.set_open(docks.left.visible, cx);
if let Some(active_panel) = docks.left.active_panel {
if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) {
dock.activate_panel(ix, cx);
}
}
dock.active_panel()
.map(|panel| panel.set_zoomed(docks.left.zoom, cx));
if docks.left.visible && docks.left.zoom {
cx.focus_self()
}
});
// TODO: I think the bug is that setting zoom or active undoes the bottom zoom or something
workspace.right_dock.update(cx, |dock, cx| {
dock.set_open(docks.right.visible, cx);
if let Some(active_panel) = docks.right.active_panel {
if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) {
dock.activate_panel(ix, cx);
}
}
dock.active_panel()
.map(|panel| panel.set_zoomed(docks.right.zoom, cx));
if docks.right.visible && docks.right.zoom { let right = docks.right.clone();
cx.focus_self() workspace
} .right_dock
}); .update(cx, |dock, _| dock.serialized_dock = Some(right));
workspace.bottom_dock.update(cx, |dock, cx| { let left = docks.left.clone();
dock.set_open(docks.bottom.visible, cx); workspace
if let Some(active_panel) = docks.bottom.active_panel { .left_dock
if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) { .update(cx, |dock, _| dock.serialized_dock = Some(left));
dock.activate_panel(ix, cx); let bottom = docks.bottom.clone();
} workspace
} .bottom_dock
.update(cx, |dock, _| dock.serialized_dock = Some(bottom));
dock.active_panel()
.map(|panel| panel.set_zoomed(docks.bottom.zoom, cx));
if docks.bottom.visible && docks.bottom.zoom {
cx.focus_self()
}
});
cx.notify(); cx.notify();
})?; })?;

View file

@ -32,11 +32,11 @@ use util::{
}; };
use uuid::Uuid; use uuid::Uuid;
use welcome::BaseKeymap; use welcome::BaseKeymap;
use workspace::Pane;
use workspace::{ use workspace::{
create_and_open_local_file, notifications::simple_message_notification::MessageNotification, create_and_open_local_file, notifications::simple_message_notification::MessageNotification,
open_new, AppState, NewFile, NewWindow, Workspace, WorkspaceSettings, open_new, AppState, NewFile, NewWindow, Workspace, WorkspaceSettings,
}; };
use workspace::{dock::Panel, Pane};
use zed_actions::{OpenBrowser, OpenSettings, OpenZedURL, Quit}; use zed_actions::{OpenBrowser, OpenSettings, OpenZedURL, Quit};
actions!( actions!(
@ -178,10 +178,7 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
)?; )?;
workspace_handle.update(&mut cx, |workspace, cx| { workspace_handle.update(&mut cx, |workspace, cx| {
let (position, was_deserialized) = { let was_deserialized = project_panel.read(cx).was_deserialized();
let project_panel = project_panel.read(cx);
(project_panel.position(cx), project_panel.was_deserialized())
};
workspace.add_panel(project_panel, cx); workspace.add_panel(project_panel, cx);
workspace.add_panel(terminal_panel, cx); workspace.add_panel(terminal_panel, cx);
workspace.add_panel(assistant_panel, cx); workspace.add_panel(assistant_panel, cx);
@ -200,7 +197,7 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
.map_or(false, |entry| entry.is_dir()) .map_or(false, |entry| entry.is_dir())
}) })
{ {
workspace.toggle_dock(position, cx); workspace.open_panel::<ProjectPanel>(cx);
} }
cx.focus_self(); cx.focus_self();
}) })