use crate::model::settings;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, path::PathBuf};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Kind {
Session,
Board,
Article,
Table,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entry {
pub kind: Kind,
pub id: String,
}
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct State {
#[serde(default)]
pub projects: Vec<PathBuf>,
#[serde(default)]
pub active: usize,
#[serde(default)]
pub collapsed: Vec<PathBuf>,
#[serde(default)]
pub last: BTreeMap<PathBuf, Entry>,
#[serde(default)]
pub order: BTreeMap<PathBuf, Vec<Entry>>,
#[serde(default)]
pub pinned: BTreeMap<PathBuf, Vec<Entry>>,
}
pub(crate) fn path() -> Option<PathBuf> {
settings::dir().ok().map(|dir| dir.join("state.toml"))
}
pub fn restore() -> State {
let stored: State = path()
.and_then(|path| std::fs::read_to_string(path).ok())
.and_then(|body| toml::from_str(&body).ok())
.unwrap_or_default();
let active = stored.projects.get(stored.active).cloned();
let projects: Vec<PathBuf> = stored
.projects
.into_iter()
.filter(|path| path.is_dir())
.collect();
let active = active
.and_then(|path| projects.iter().position(|open| *open == path))
.unwrap_or(0);
State {
projects,
active,
collapsed: stored.collapsed,
last: stored.last,
order: stored.order,
pinned: stored.pinned,
}
}
pub fn save(state: &State) {
let Some(path) = path() else {
return;
};
if let Ok(body) = toml::to_string_pretty(state)
&& let Some(dir) = path.parent()
{
let _ = std::fs::create_dir_all(dir);
let _ = std::fs::write(&path, body);
}
}