@@ -281,6 +281,25 @@ impl From<WindowBoundsJson> for WindowBounds {
}
}
+const DEFAULT_DOCK_STATE_KEY: &str = "default_dock_state";
+
+pub fn read_default_dock_state() -> Option<DockStructure> {
+ let json_str = KEY_VALUE_STORE
+ .read_kvp(DEFAULT_DOCK_STATE_KEY)
+ .log_err()
+ .flatten()?;
+
+ serde_json::from_str::<DockStructure>(&json_str).ok()
+}
+
+pub async fn write_default_dock_state(docks: DockStructure) -> anyhow::Result<()> {
+ let json_str = serde_json::to_string(&docks)?;
+ KEY_VALUE_STORE
+ .write_kvp(DEFAULT_DOCK_STATE_KEY.to_string(), json_str)
+ .await?;
+ Ok(())
+}
+
#[derive(Debug)]
pub struct Breakpoint {
pub position: u32,
@@ -15,6 +15,7 @@ use gpui::{AsyncWindowContext, Entity, WeakEntity};
use language::{Toolchain, ToolchainScope};
use project::{Project, debugger::breakpoint_store::SourceBreakpoint};
use remote::RemoteConnectionOptions;
+use serde::{Deserialize, Serialize};
use std::{
collections::BTreeMap,
path::{Path, PathBuf},
@@ -64,7 +65,7 @@ pub(crate) struct SerializedWorkspace {
pub(crate) window_id: Option<u64>,
}
-#[derive(Debug, PartialEq, Clone, Default)]
+#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
pub struct DockStructure {
pub(crate) left: DockData,
pub(crate) right: DockData,
@@ -114,7 +115,7 @@ impl Bind for DockStructure {
}
}
-#[derive(Debug, PartialEq, Clone, Default)]
+#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
pub struct DockData {
pub(crate) visible: bool,
pub(crate) active_panel: Option<String>,
@@ -1823,6 +1823,15 @@ impl Workspace {
};
notify_if_database_failed(window, cx);
+ // Check if this is an empty workspace (no paths to open)
+ // An empty workspace is one where project_paths is empty
+ let is_empty_workspace = project_paths.is_empty();
+ // Check if serialized workspace has paths before it's moved
+ let serialized_workspace_has_paths = serialized_workspace
+ .as_ref()
+ .map(|ws| !ws.paths.is_empty())
+ .unwrap_or(false);
+
let opened_items = window
.update(cx, |_workspace, window, cx| {
open_items(serialized_workspace, project_paths, window, cx)
@@ -1830,6 +1839,32 @@ impl Workspace {
.await
.unwrap_or_default();
+ // Restore default dock state for empty workspaces
+ // Only restore if:
+ // 1. This is an empty workspace (no paths), AND
+ // 2. The serialized workspace either doesn't exist or has no paths
+ if is_empty_workspace && !serialized_workspace_has_paths {
+ if let Some(default_docks) = persistence::read_default_dock_state() {
+ window
+ .update(cx, |workspace, window, cx| {
+ for (dock, serialized_dock) in [
+ (&mut workspace.right_dock, default_docks.right),
+ (&mut workspace.left_dock, default_docks.left),
+ (&mut workspace.bottom_dock, default_docks.bottom),
+ ]
+ .iter_mut()
+ {
+ dock.update(cx, |dock, cx| {
+ dock.serialized_dock = Some(serialized_dock.clone());
+ dock.restore_state(window, cx);
+ });
+ }
+ cx.notify();
+ })
+ .log_err();
+ }
+ }
+
window
.update(cx, |workspace, window, cx| {
window.activate_window();
@@ -5858,6 +5893,8 @@ impl Workspace {
WorkspaceLocation::DetachFromSession => {
let window_bounds = SerializedWindowBounds(window.window_bounds());
let display = window.display(cx).and_then(|d| d.uuid().ok());
+ // Save dock state for empty local workspaces
+ let docks = build_serialized_docks(self, window, cx);
window.spawn(cx, async move |_| {
persistence::DB
.set_window_open_status(
@@ -5871,9 +5908,16 @@ impl Workspace {
.set_session_id(database_id, None)
.await
.log_err();
+ persistence::write_default_dock_state(docks).await.log_err();
+ })
+ }
+ WorkspaceLocation::None => {
+ // Save dock state for empty non-local workspaces
+ let docks = build_serialized_docks(self, window, cx);
+ window.spawn(cx, async move |_| {
+ persistence::write_default_dock_state(docks).await.log_err();
})
}
- WorkspaceLocation::None => Task::ready(()),
}
}