From f1aab1120da215f7a34cc678506cbd8441eedcc8 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 2 Jun 2025 22:36:57 +0200 Subject: [PATCH] terminal: Persist pinned tabs in terminal (#31921) Closes #31098 Release Notes: - Fixed terminal pinned tab state not persisting across restarts. --- crates/terminal_view/src/persistence.rs | 7 ++++++- crates/terminal_view/src/terminal_panel.rs | 4 +++- crates/workspace/src/pane.rs | 11 +++++++++-- crates/workspace/src/workspace.rs | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/crates/terminal_view/src/persistence.rs b/crates/terminal_view/src/persistence.rs index 5186a08b50422b5436c034158b5de906926174c5..55259c143fa8b912600c065676b2a17799585d55 100644 --- a/crates/terminal_view/src/persistence.rs +++ b/crates/terminal_view/src/persistence.rs @@ -74,10 +74,12 @@ fn serialize_pane(pane: &Entity, active: bool, cx: &mut App) -> Serialized .map(|item| item.item_id().as_u64()) .filter(|active_id| items_to_serialize.contains(active_id)); + let pinned_count = pane.pinned_count(); SerializedPane { active, children, active_item, + pinned_count, } } @@ -229,10 +231,11 @@ async fn deserialize_pane_group( }) .log_err()?; let active_item = serialized_pane.active_item; - + let pinned_count = serialized_pane.pinned_count; let terminal = pane .update_in(cx, |pane, window, cx| { populate_pane_items(pane, new_items, active_item, window, cx); + pane.set_pinned_count(pinned_count); // Avoid blank panes in splits if pane.items_len() == 0 { let working_directory = workspace @@ -339,6 +342,8 @@ pub(crate) struct SerializedPane { pub active: bool, pub children: Vec, pub active_item: Option, + #[serde(default)] + pub pinned_count: usize, } #[derive(Debug)] diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index a67ef707df2cc5b8d302d438215109e08b1fea43..f7b9a31275e4931a241ae0b91f7e3f668256b5a8 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -325,7 +325,6 @@ impl TerminalPanel { .ok(); } } - Ok(terminal_panel) } @@ -393,6 +392,9 @@ impl TerminalPanel { pane::Event::Focus => { self.active_pane = pane.clone(); } + pane::Event::ItemPinned | pane::Event::ItemUnpinned => { + self.serialize(cx); + } _ => {} } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 7cfc8c85b079c255c2bad44f9276822e7b743522..58627fda9768dfc95df47e4bd4610246aa2ca85e 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -230,6 +230,8 @@ pub enum Event { item: Box, }, Split(SplitDirection), + ItemPinned, + ItemUnpinned, JoinAll, JoinIntoNext, ChangeItemTitle, @@ -274,6 +276,8 @@ impl fmt::Debug for Event { .field("item", &item.id()) .field("save_intent", save_intent) .finish(), + Event::ItemPinned => f.write_str("ItemPinned"), + Event::ItemUnpinned => f.write_str("ItemUnpinned"), } } } @@ -780,11 +784,12 @@ impl Pane { } } - pub(crate) fn set_pinned_count(&mut self, count: usize) { + /// Should only be used when deserializing a pane. + pub fn set_pinned_count(&mut self, count: usize) { self.pinned_tab_count = count; } - pub(crate) fn pinned_count(&self) -> usize { + pub fn pinned_count(&self) -> usize { self.pinned_tab_count } @@ -2074,6 +2079,7 @@ impl Pane { }) .ok()?; } + cx.emit(Event::ItemPinned); Some(()) }); @@ -2098,6 +2104,7 @@ impl Pane { }) .ok()?; } + cx.emit(Event::ItemUnpinned); Some(()) }); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index de63247f3b74f158b104c20e91c75851d71dfebc..fc2a93cb0df81a67d0249d4d77d214adb7e8f354 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3761,6 +3761,7 @@ impl Workspace { } cx.notify(); } + pane::Event::ItemPinned | pane::Event::ItemUnpinned => {} } if serialize_workspace {