Files
epub-read/src/persistence.rs

74 lines
2.3 KiB
Rust

use crate::theme::Settings;
use std::path::Path;
const SETTINGS_FILE: &str = "settings.json";
pub fn settings_dir() -> std::path::PathBuf {
if let Ok(exe) = std::env::current_exe() {
if let Some(dir) = exe.parent() {
return dir.to_path_buf();
}
}
std::path::PathBuf::from(".")
}
pub fn save_settings(dir: &Path, settings: &Settings) -> Result<(), String> {
let path = dir.join(SETTINGS_FILE);
let json = serde_json::to_string_pretty(settings)
.map_err(|e| format!("序列化设置失败: {}", e))?;
std::fs::write(&path, json)
.map_err(|e| format!("保存设置失败: {}", e))?;
Ok(())
}
pub fn load_settings(dir: &Path) -> Result<Settings, String> {
let path = dir.join(SETTINGS_FILE);
let json = std::fs::read_to_string(&path)
.map_err(|e| format!("读取设置失败: {}", e))?;
let mut settings: Settings = serde_json::from_str(&json)
.map_err(|e| format!("解析设置失败: {}", e))?;
// Always refresh profiles from code-defined presets so that updated
// preset values (font size, spacing, etc.) take effect even when
// an older settings.json is present on disk.
let preset_names: Vec<String> = crate::style::StyleProfile::presets()
.iter()
.map(|p| p.name.clone())
.collect();
settings.profiles = crate::style::StyleProfile::presets();
if !preset_names.contains(&settings.active_profile) {
settings.active_profile = "Kindle 默认".into();
}
Ok(settings)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::theme::{Settings, Theme};
#[test]
fn test_save_and_load_settings() {
let dir = std::env::temp_dir().join("epub-read-test");
let _ = std::fs::create_dir_all(&dir);
let mut s = Settings::default();
s.font_size = 24.0;
s.theme = Theme::Dark;
save_settings(&dir, &s).unwrap();
let loaded = load_settings(&dir).unwrap();
assert_eq!(loaded.font_size, 24.0);
assert_eq!(loaded.theme, Theme::Dark);
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn test_load_settings_nonexistent() {
let dir = std::env::temp_dir().join("epub-read-test-nonexistent");
let _ = std::fs::remove_dir_all(&dir);
let result = load_settings(&dir);
assert!(result.is_err());
}
}