Skip to main content

taskers_core/
terminal_session_manager.rs

1use std::{
2    collections::HashMap,
3    sync::{Arc, Mutex},
4};
5
6use anyhow::Result;
7use taskers_domain::{AppModel, PaneKind, SessionId, SurfaceId};
8use taskers_runtime::TerminalSessionClient;
9
10#[derive(Clone)]
11pub struct TerminalSessionManager {
12    client: Option<TerminalSessionClient>,
13    inner: Arc<Mutex<HashMap<SurfaceId, SessionId>>>,
14}
15
16impl TerminalSessionManager {
17    pub fn new(client: Option<TerminalSessionClient>) -> Self {
18        Self {
19            client,
20            inner: Arc::new(Mutex::new(HashMap::new())),
21        }
22    }
23
24    pub fn sync_model(&self, model: &AppModel) -> Result<()> {
25        let current = model_terminal_sessions(model);
26        let removed = {
27            let mut inner = self
28                .inner
29                .lock()
30                .expect("terminal session manager mutex poisoned");
31            let removed = inner
32                .iter()
33                .filter_map(|(surface_id, session_id)| {
34                    (!current.contains_key(surface_id)).then_some(*session_id)
35                })
36                .collect::<Vec<_>>();
37            *inner = current;
38            removed
39        };
40
41        let Some(client) = self.client.as_ref() else {
42            return Ok(());
43        };
44        for session_id in removed {
45            if let Err(error) = client.terminate_session(&session_id.to_string()) {
46                eprintln!(
47                    "terminal session cleanup failed for {}: {error:#}",
48                    session_id
49                );
50            }
51        }
52        Ok(())
53    }
54}
55
56fn model_terminal_sessions(model: &AppModel) -> HashMap<SurfaceId, SessionId> {
57    model
58        .workspaces
59        .values()
60        .flat_map(|workspace| workspace.panes.values())
61        .flat_map(|pane| pane.surfaces.values())
62        .filter(|surface| surface.kind == PaneKind::Terminal)
63        .map(|surface| (surface.id, surface.session_id))
64        .collect()
65}