Skip to main content

par_term/pane/manager/
session.rs

1//! Session restore operations for PaneManager
2//!
3//! Handles rebuilding a live pane tree from a saved session layout,
4//! including fallback CWD validation for missing directories.
5
6use super::PaneManager;
7use crate::config::Config;
8use crate::pane::types::{Pane, PaneNode};
9use crate::session::SessionPaneNode;
10use anyhow::Result;
11use std::sync::Arc;
12use tokio::runtime::Runtime;
13
14impl PaneManager {
15    // =========================================================================
16    // Session Restore
17    // =========================================================================
18
19    /// Build a pane tree from a saved session layout
20    ///
21    /// Recursively constructs live `PaneNode` tree from a `SessionPaneNode`,
22    /// creating new terminal panes for each leaf. If a leaf's CWD no longer
23    /// exists, falls back to `$HOME`.
24    pub fn build_from_layout(
25        &mut self,
26        layout: &SessionPaneNode,
27        config: &Config,
28        runtime: Arc<Runtime>,
29    ) -> Result<()> {
30        let root = self.build_node_from_layout(layout, config, runtime)?;
31        let first_id = root.all_pane_ids().first().copied();
32        self.root = Some(root);
33        self.focused_pane_id = first_id;
34        self.recalculate_bounds();
35
36        // Apply per-pane backgrounds from config to restored panes
37        let panes = self.all_panes_mut();
38        for (index, pane) in panes.into_iter().enumerate() {
39            if let Some((image_path, mode, opacity, darken)) = config.get_pane_background(index) {
40                pane.set_background(crate::pane::PaneBackground {
41                    image_path: Some(image_path),
42                    mode,
43                    opacity,
44                    darken,
45                });
46            }
47        }
48
49        Ok(())
50    }
51
52    /// Recursively build a PaneNode from a SessionPaneNode
53    fn build_node_from_layout(
54        &mut self,
55        layout: &SessionPaneNode,
56        config: &Config,
57        runtime: Arc<Runtime>,
58    ) -> Result<PaneNode> {
59        match layout {
60            SessionPaneNode::Leaf { cwd } => {
61                let id = self.next_pane_id;
62                self.next_pane_id += 1;
63
64                let validated_cwd = crate::session::restore::validate_cwd(cwd);
65                let pane = Pane::new(id, config, runtime, validated_cwd)?;
66                Ok(PaneNode::leaf(pane))
67            }
68            SessionPaneNode::Split {
69                direction,
70                ratio,
71                first,
72                second,
73            } => {
74                let first_node = self.build_node_from_layout(first, config, runtime.clone())?;
75                let second_node = self.build_node_from_layout(second, config, runtime)?;
76                Ok(PaneNode::split(*direction, *ratio, first_node, second_node))
77            }
78        }
79    }
80}