workspace: Fix last removed folder from workspace used to reopen on Zed startup (#34925)

Closes #34924

Now, when `local_paths` are empty, we detach `session_id` from that
workspace serialization item. This way, when we restore it using the
default "last_session", we don't restore this workspace back. This is
same as when we use `cmd-w` to close window, which also sets
`session_id` to `None` before serialization.

Release Notes:

- Fixed an issue where last removed folder from workspace used to reopen
on Zed startup.
This commit is contained in:
Smit Barmase 2025-07-23 06:46:24 +05:30 committed by GitHub
parent 056003860a
commit e90cf0b941
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 34 deletions

View file

@ -1336,6 +1336,14 @@ impl WorkspaceDb {
} }
} }
query! {
pub(crate) async fn set_session_id(workspace_id: WorkspaceId, session_id: Option<String>) -> Result<()> {
UPDATE workspaces
SET session_id = ?2
WHERE workspace_id = ?1
}
}
pub async fn toolchain( pub async fn toolchain(
&self, &self,
workspace_id: WorkspaceId, workspace_id: WorkspaceId,

View file

@ -1016,6 +1016,15 @@ pub enum OpenVisible {
OnlyDirectories, OnlyDirectories,
} }
enum WorkspaceLocation {
// Valid local paths or SSH project to serialize
Location(SerializedWorkspaceLocation),
// No valid location found hence clear session id
DetachFromSession,
// No valid location found to serialize
None,
}
type PromptForNewPath = Box< type PromptForNewPath = Box<
dyn Fn( dyn Fn(
&mut Workspace, &mut Workspace,
@ -1135,7 +1144,6 @@ impl Workspace {
this.update_window_title(window, cx); this.update_window_title(window, cx);
this.serialize_workspace(window, cx); this.serialize_workspace(window, cx);
// This event could be triggered by `AddFolderToProject` or `RemoveFromProject`. // This event could be triggered by `AddFolderToProject` or `RemoveFromProject`.
// So we need to update the history.
this.update_history(cx); this.update_history(cx);
} }
@ -5218,7 +5226,8 @@ impl Workspace {
} }
} }
if let Some(location) = self.serialize_workspace_location(cx) { match self.serialize_workspace_location(cx) {
WorkspaceLocation::Location(location) => {
let breakpoints = self.project.update(cx, |project, cx| { let breakpoints = self.project.update(cx, |project, cx| {
project project
.breakpoint_store() .breakpoint_store()
@ -5242,24 +5251,33 @@ impl Workspace {
window_id: Some(window.window_handle().window_id().as_u64()), window_id: Some(window.window_handle().window_id().as_u64()),
}; };
return window.spawn(cx, async move |_| { window.spawn(cx, async move |_| {
persistence::DB.save_workspace(serialized_workspace).await; persistence::DB.save_workspace(serialized_workspace).await;
}); })
}
WorkspaceLocation::DetachFromSession => window.spawn(cx, async move |_| {
persistence::DB
.set_session_id(database_id, None)
.await
.log_err();
}),
WorkspaceLocation::None => Task::ready(()),
} }
Task::ready(())
} }
fn serialize_workspace_location(&self, cx: &App) -> Option<SerializedWorkspaceLocation> { fn serialize_workspace_location(&self, cx: &App) -> WorkspaceLocation {
if let Some(ssh_project) = &self.serialized_ssh_project { if let Some(ssh_project) = &self.serialized_ssh_project {
Some(SerializedWorkspaceLocation::Ssh(ssh_project.clone())) WorkspaceLocation::Location(SerializedWorkspaceLocation::Ssh(ssh_project.clone()))
} else if let Some(local_paths) = self.local_paths(cx) { } else if let Some(local_paths) = self.local_paths(cx) {
if !local_paths.is_empty() { if !local_paths.is_empty() {
Some(SerializedWorkspaceLocation::from_local_paths(local_paths)) WorkspaceLocation::Location(SerializedWorkspaceLocation::from_local_paths(
local_paths,
))
} else { } else {
None WorkspaceLocation::DetachFromSession
} }
} else { } else {
None WorkspaceLocation::None
} }
} }
@ -5267,8 +5285,9 @@ impl Workspace {
let Some(id) = self.database_id() else { let Some(id) = self.database_id() else {
return; return;
}; };
let Some(location) = self.serialize_workspace_location(cx) else { let location = match self.serialize_workspace_location(cx) {
return; WorkspaceLocation::Location(location) => location,
_ => return,
}; };
if let Some(manager) = HistoryManager::global(cx) { if let Some(manager) = HistoryManager::global(cx) {
manager.update(cx, |this, cx| { manager.update(cx, |this, cx| {