use crate::content::Mode;
use crate::ui::theme::{Theme, ThemeName};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub theme: String,
pub default_mode: String,
pub default_language: String,
pub default_duration: u64,
}
impl Default for Config {
fn default() -> Self {
Self {
theme: "pastel".to_string(),
default_mode: "text".to_string(),
default_language: "english".to_string(),
default_duration: 60,
}
}
}
impl Config {
#[must_use]
pub fn config_dir() -> PathBuf {
dirs::config_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("typetui")
}
#[must_use]
pub fn config_path() -> PathBuf {
Self::config_dir().join("config.json")
}
#[must_use]
pub fn results_path() -> PathBuf {
Self::config_dir().join("results.jsonl")
}
#[must_use]
pub fn load() -> Self {
let path = Self::config_path();
if path.exists() {
match std::fs::read_to_string(&path) {
Ok(content) => serde_json::from_str(&content).unwrap_or_default(),
Err(_) => Self::default(),
}
} else {
Self::default()
}
}
pub fn save(&self) -> Result<(), std::io::Error> {
let dir = Self::config_dir();
if !dir.exists() {
std::fs::create_dir_all(&dir)?;
}
let content = serde_json::to_string_pretty(self)?;
std::fs::write(Self::config_path(), content)
}
pub fn theme(&self) -> Theme {
ThemeName::from_str(&self.theme)
.map(Theme::from_name)
.unwrap_or_default()
}
pub fn set_theme(&mut self, theme: ThemeName) {
self.theme = theme.as_str().to_string();
}
#[must_use]
pub fn mode(&self) -> Mode {
Mode::from_str(&self.default_mode).unwrap_or(Mode::Text)
}
pub fn set_mode(&mut self, mode: Mode) {
self.default_mode = mode.as_str().to_string();
}
#[must_use]
pub fn duration(&self) -> u64 {
match self.default_duration {
15 | 30 | 60 | 120 => self.default_duration,
_ => 60,
}
}
pub fn set_duration(&mut self, duration: u64) {
if [15, 30, 60, 120].contains(&duration) {
self.default_duration = duration;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = Config::default();
assert_eq!(config.theme, "pastel");
assert_eq!(config.default_mode, "text");
assert_eq!(config.default_duration, 60);
}
#[test]
fn test_duration_validation() {
let mut config = Config::default();
config.set_duration(45);
assert_eq!(config.duration(), 60); config.set_duration(30);
assert_eq!(config.duration(), 30);
}
}