From 3759e0bf556e58b4732e0203a7fa65524fa842e5 Mon Sep 17 00:00:00 2001 From: smit <0xtimsb@gmail.com> Date: Sat, 22 Feb 2025 00:05:52 +0530 Subject: [PATCH] terminal: Update terminal reopening from global to per-workspace (#25336) Closes #7145 Currently, terminal persistence is global, i.e. split configurations are restored across all workspaces. This PR changes it to per-workspace, so configurations are restored only within the same workspace. Opening a new window will start with a fresh terminal. https://github.com/user-attachments/assets/d43fe747-9f28-4723-b409-e8dbb3a23912 Release Notes: - Improved terminal reopening to be per workspace instead of global. --- crates/terminal_view/src/terminal_panel.rs | 92 ++++++++++++++++------ crates/workspace/src/workspace.rs | 4 + 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index 9f278fb7f625f5..4237d27349aee3 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -217,35 +217,67 @@ impl TerminalPanel { }); } + fn serialization_key(workspace: &Workspace) -> Option { + workspace + .database_id() + .map(|id| i64::from(id).to_string()) + .or(workspace.session_id()) + .map(|id| format!("{:?}-{:?}", TERMINAL_PANEL_KEY, id)) + } + pub async fn load( workspace: WeakEntity, mut cx: AsyncWindowContext, ) -> Result> { - let serialized_panel = cx - .background_spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) }) - .await - .log_err() + let mut terminal_panel = None; + + match workspace + .read_with(&mut cx, |workspace, _| { + workspace + .database_id() + .zip(TerminalPanel::serialization_key(workspace)) + }) + .ok() .flatten() - .map(|panel| serde_json::from_str::(&panel)) - .transpose() - .log_err() - .flatten(); - - let terminal_panel = workspace - .update_in(&mut cx, |workspace, window, cx| { - match serialized_panel.zip(workspace.database_id()) { - Some((serialized_panel, database_id)) => deserialize_terminal_panel( - workspace.weak_handle(), - workspace.project().clone(), - database_id, - serialized_panel, - window, - cx, - ), - None => Task::ready(Ok(cx.new(|cx| TerminalPanel::new(workspace, window, cx)))), + { + Some((database_id, serialization_key)) => { + if let Some(serialized_panel) = cx + .background_spawn(async move { KEY_VALUE_STORE.read_kvp(&serialization_key) }) + .await + .log_err() + .flatten() + .map(|panel| serde_json::from_str::(&panel)) + .transpose() + .log_err() + .flatten() + { + if let Ok(serialized) = workspace + .update_in(&mut cx, |workspace, window, cx| { + deserialize_terminal_panel( + workspace.weak_handle(), + workspace.project().clone(), + database_id, + serialized_panel, + window, + cx, + ) + })? + .await + { + terminal_panel = Some(serialized); + } } + } + _ => {} + } + + let terminal_panel = if let Some(panel) = terminal_panel { + panel + } else { + workspace.update_in(&mut cx, |workspace, window, cx| { + cx.new(|cx| TerminalPanel::new(workspace, window, cx)) })? - .await?; + }; if let Some(workspace) = workspace.upgrade() { terminal_panel @@ -727,6 +759,16 @@ impl TerminalPanel { fn serialize(&mut self, cx: &mut Context) { let height = self.height; let width = self.width; + let Some(serialization_key) = self + .workspace + .update(cx, |workspace, _| { + TerminalPanel::serialization_key(workspace) + }) + .ok() + .flatten() + else { + return; + }; self.pending_serialization = cx.spawn(|terminal_panel, mut cx| async move { cx.background_executor() .timer(Duration::from_millis(50)) @@ -745,7 +787,7 @@ impl TerminalPanel { async move { KEY_VALUE_STORE .write_kvp( - TERMINAL_PANEL_KEY.into(), + serialization_key, serde_json::to_string(&SerializedTerminalPanel { items, active_item_id: None, @@ -1351,8 +1393,10 @@ impl Panel for TerminalPanel { DockPosition::Left | DockPosition::Right => self.width = size, DockPosition::Bottom => self.height = size, } - self.serialize(cx); cx.notify(); + cx.defer_in(window, |this, _, cx| { + this.serialize(cx); + }) } fn is_zoomed(&self, _window: &Window, cx: &App) -> bool { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 8098450ef4405d..126e1306077b2b 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -4385,6 +4385,10 @@ impl Workspace { self.database_id } + pub fn session_id(&self) -> Option { + self.session_id.clone() + } + fn local_paths(&self, cx: &App) -> Option>> { let project = self.project().read(cx);