#![allow(dead_code)]
use anyhow::Result;
use std::path::PathBuf;
pub struct ScreenshotCapture {
save_dir: PathBuf,
interval_secs: u64,
latest_path: Option<PathBuf>,
}
impl ScreenshotCapture {
pub fn new(save_dir: PathBuf, interval_secs: u64) -> Result<Self> {
std::fs::create_dir_all(&save_dir)?;
Ok(Self {
save_dir,
interval_secs,
latest_path: None,
})
}
pub async fn capture(&mut self) -> Result<Option<PathBuf>> {
let timestamp = chrono::Utc::now().format("%Y%m%d_%H%M%S").to_string();
let filename = format!("screenshot_{}.png", timestamp);
let path = self.save_dir.join(&filename);
#[cfg(target_os = "macos")]
{
let output = std::process::Command::new("screencapture")
.arg("-x")
.arg(&path)
.output()?;
if output.status.success() && path.exists() {
self.latest_path = Some(path.clone());
return Ok(Some(path));
}
}
#[cfg(target_os = "linux")]
{
let output = std::process::Command::new("gnome-screenshot")
.arg("-f")
.arg(&path)
.output()?;
if output.status.success() && path.exists() {
self.latest_path = Some(path.clone());
return Ok(Some(path));
}
let output = std::process::Command::new("import")
.arg("-window")
.arg("root")
.arg(&path)
.output()?;
if output.status.success() && path.exists() {
self.latest_path = Some(path.clone());
return Ok(Some(path));
}
}
#[cfg(target_os = "windows")]
{
use std::process::Command;
let script = format!(
"Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::PrimaryScreen.Bitmap.Save('{}')",
path.display()
);
Command::new("powershell")
.args(["-Command", &script])
.output()?;
if path.exists() {
self.latest_path = Some(path.clone());
return Ok(Some(path));
}
}
Ok(None)
}
pub fn get_latest_path(&self) -> Option<PathBuf> {
self.latest_path.clone()
}
pub fn get_save_dir(&self) -> &PathBuf {
&self.save_dir
}
pub fn cleanup_old_screenshots(&self, keep_last: u32) -> Result<u32> {
let mut entries: Vec<_> = std::fs::read_dir(&self.save_dir)?
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().map(|ext| ext == "png").unwrap_or(false))
.collect();
entries.sort_by_key(|e| std::cmp::Reverse(e.metadata().ok().and_then(|m| m.modified().ok())));
let mut removed = 0;
for entry in entries.iter().skip(keep_last as usize) {
if std::fs::remove_file(entry.path()).is_ok() {
removed += 1;
}
}
Ok(removed)
}
}