terminal: Persist pinned tabs in terminal (#31921)

Piotr Osiewicz created

Closes #31098

Release Notes:

- Fixed terminal pinned tab state not persisting across restarts.

Change summary

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(-)

Detailed changes

crates/terminal_view/src/persistence.rs 🔗

@@ -74,10 +74,12 @@ fn serialize_pane(pane: &Entity<Pane>, 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<u64>,
     pub active_item: Option<u64>,
+    #[serde(default)]
+    pub pinned_count: usize,
 }
 
 #[derive(Debug)]

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);
+            }
 
             _ => {}
         }

crates/workspace/src/pane.rs 🔗

@@ -230,6 +230,8 @@ pub enum Event {
         item: Box<dyn ItemHandle>,
     },
     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(())
         });