use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::path::PathBuf;
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct InboxState {
pub read: HashSet<String>,
pub archived: HashSet<String>,
}
impl InboxState {
pub fn path() -> PathBuf {
dirs::data_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("thor")
.join("state.json")
}
pub async fn load() -> Self {
let path = Self::path();
if path.exists() {
tokio::fs::read_to_string(&path)
.await
.ok()
.and_then(|s| serde_json::from_str(&s).ok())
.unwrap_or_default()
} else {
Self::default()
}
}
pub async fn save(&self) -> std::io::Result<()> {
let path = Self::path();
if let Some(parent) = path.parent() {
tokio::fs::create_dir_all(parent).await?;
}
let json = serde_json::to_string_pretty(self)?;
tokio::fs::write(path, json).await
}
pub fn mark_read(&mut self, id: &str) {
self.read.insert(id.to_string());
}
pub fn mark_archived(&mut self, id: &str) {
self.archived.insert(id.to_string());
}
pub fn is_read(&self, id: &str) -> bool {
self.read.contains(id)
}
pub fn is_archived(&self, id: &str) -> bool {
self.archived.contains(id)
}
pub fn unread_count(&self, ids: &[String]) -> usize {
ids.iter().filter(|id| !self.is_read(id) && !self.is_archived(id)).count()
}
}