use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::config::StatusIcons;
use crate::git::GitStatus;
use crate::multiplexer::{AgentPane, AgentStatus};
use super::app::SidebarLayoutMode;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SidebarSnapshot {
pub layout_mode: SidebarLayoutMode,
pub active_windows: HashSet<(String, String)>,
#[serde(default)]
pub active_pane_ids: HashSet<String>,
#[serde(default)]
pub window_pane_counts: HashMap<String, usize>,
#[serde(default)]
pub git_statuses: HashMap<PathBuf, GitStatus>,
#[serde(default)]
pub interrupted_pane_ids: HashMap<String, u64>,
pub agents: Vec<AgentPane>,
}
#[allow(clippy::too_many_arguments)]
pub fn build_snapshot(
mut agents: Vec<AgentPane>,
tmux_statuses: &HashMap<String, Option<String>>,
pane_window_ids: &HashMap<String, String>,
active_windows: HashSet<(String, String)>,
active_pane_ids: HashSet<String>,
window_pane_counts: HashMap<String, usize>,
layout_mode: SidebarLayoutMode,
status_icons: &StatusIcons,
git_statuses: HashMap<PathBuf, GitStatus>,
) -> SidebarSnapshot {
let done_icon = status_icons.done();
let waiting_icon = status_icons.waiting();
for agent in &mut agents {
if let Some(observed) = tmux_statuses.get(&agent.pane_id) {
match agent.status {
Some(AgentStatus::Done) if observed.as_deref() != Some(done_icon) => {
agent.status = None;
}
Some(AgentStatus::Waiting) if observed.as_deref() != Some(waiting_icon) => {
agent.status = None;
}
_ => {}
}
}
}
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
agents.sort_by_cached_key(|a| {
let elapsed = a
.status_ts
.map(|ts| now.saturating_sub(ts))
.unwrap_or(u64::MAX);
let pane_num: u64 = a
.pane_id
.strip_prefix('%')
.unwrap_or(&a.pane_id)
.parse()
.unwrap_or(u64::MAX);
(elapsed, pane_num)
});
for agent in &mut agents {
if let Some(wid) = pane_window_ids.get(&agent.pane_id) {
agent.window_id = wid.clone();
}
}
SidebarSnapshot {
layout_mode,
active_windows,
active_pane_ids,
window_pane_counts,
git_statuses,
interrupted_pane_ids: HashMap::new(),
agents,
}
}