use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct Snapshot {
pub id: u64,
pub timestamp: Duration,
pub action: Option<String>,
pub state_summary: StateSummary,
}
#[derive(Debug, Clone, Default)]
pub struct StateSummary {
pub focus: String,
pub status_count: usize,
pub commit_count: usize,
pub branch_count: usize,
pub feedback: Option<String>,
pub error: Option<String>,
pub running: bool,
}
pub struct SnapshotManager {
snapshots: Vec<Snapshot>,
max_snapshots: usize,
start_time: Instant,
next_id: u64,
}
impl SnapshotManager {
pub fn new(max_snapshots: usize) -> Self {
Self {
snapshots: Vec::with_capacity(max_snapshots),
max_snapshots,
start_time: Instant::now(),
next_id: 0,
}
}
pub fn take_snapshot(&mut self, action: Option<String>, summary: StateSummary) -> u64 {
let id = self.next_id;
self.next_id += 1;
let snapshot = Snapshot {
id,
timestamp: self.start_time.elapsed(),
action,
state_summary: summary,
};
if self.snapshots.len() >= self.max_snapshots {
self.snapshots.remove(0);
}
self.snapshots.push(snapshot);
id
}
pub fn recent(&self, count: usize) -> Vec<&Snapshot> {
self.snapshots.iter().rev().take(count).collect()
}
pub fn get(&self, id: u64) -> Option<&Snapshot> {
self.snapshots.iter().find(|s| s.id == id)
}
pub fn count(&self) -> usize {
self.snapshots.len()
}
pub fn clear(&mut self) {
self.snapshots.clear();
}
pub fn summarize(state: &crate::app::AppState) -> StateSummary {
StateSummary {
focus: format!("{:?}", state.focus),
status_count: state.status_entries.len(),
commit_count: state.commits.len(),
branch_count: state.branches.len(),
feedback: state.feedback_message.clone(),
error: state.last_status_error.clone(),
running: state.running,
}
}
}
impl Default for SnapshotManager {
fn default() -> Self {
Self::new(100) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_snapshot_creation() {
let mut manager = SnapshotManager::new(10);
let summary = StateSummary {
focus: "Status".to_string(),
status_count: 5,
..Default::default()
};
let id = manager.take_snapshot(Some("Tick".to_string()), summary);
assert_eq!(id, 0);
assert_eq!(manager.count(), 1);
}
#[test]
fn test_snapshot_eviction() {
let mut manager = SnapshotManager::new(3);
for i in 0..5 {
manager.take_snapshot(
Some(format!("Action {}", i)),
StateSummary::default(),
);
}
assert_eq!(manager.count(), 3);
let recent = manager.recent(10);
assert_eq!(recent.len(), 3);
}
}