Skip to main content

lore_engine/engine/
settings.rs

1//! App settings persistence — JSON file in platform config directory.
2//!
3//! Settings file location:
4//! - Windows: %APPDATA%/lore/settings.json
5//! - Linux/Mac: $HOME/.config/lore/settings.json
6
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::path::PathBuf;
10
11/// Persisted application settings (window geometry, theme, recent vaults, etc.).
12///
13/// Serialized as JSON. Unknown fields are silently ignored for forward
14/// compatibility — newer GUI versions can add settings without breaking
15/// older CLI/MCP clients.
16#[derive(Debug, Clone, Serialize, Deserialize, Default)]
17#[serde(default)]
18pub struct AppSettings {
19    pub window_x: Option<i32>,
20    pub window_y: Option<i32>,
21    pub window_width: Option<i32>,
22    pub window_height: Option<i32>,
23    pub theme: Option<String>,
24    pub last_vault: Option<String>,
25    pub sidebar_visible: Option<bool>,
26    pub recent_vaults: Option<Vec<String>>,
27    pub last_page_per_vault: Option<HashMap<String, String>>,
28    pub open_tabs_per_vault: Option<HashMap<String, Vec<String>>>,
29    pub active_tab_per_vault: Option<HashMap<String, i32>>,
30}
31
32fn settings_path() -> PathBuf {
33    let dir = if cfg!(windows) {
34        std::env::var("APPDATA").map_or_else(|_| PathBuf::from("."), PathBuf::from)
35            .join("lore")
36    } else {
37        std::env::var("HOME").map_or_else(|_| PathBuf::from("."), PathBuf::from)
38            .join(".config")
39            .join("lore")
40    };
41    dir.join("settings.json")
42}
43
44/// Load settings from disk. Returns defaults on any error.
45pub fn load() -> AppSettings {
46    let path = settings_path();
47    match std::fs::read_to_string(&path) {
48        Ok(content) => match serde_json::from_str(&content) {
49            Ok(settings) => settings,
50            Err(e) => {
51                log::warn!("Failed to parse settings at {}: {e}", path.display());
52                AppSettings::default()
53            }
54        },
55        Err(_) => AppSettings::default(),
56    }
57}
58
59/// Save settings to disk. Creates directory if needed.
60pub fn save(settings: &AppSettings) -> Result<(), String> {
61    let path = settings_path();
62    if let Some(dir) = path.parent() {
63        std::fs::create_dir_all(dir)
64            .map_err(|e| format!("Failed to create settings dir: {e}"))?;
65    }
66    let json =
67        serde_json::to_string_pretty(settings).map_err(|e| format!("Failed to serialize: {e}"))?;
68    std::fs::write(&path, json).map_err(|e| format!("Failed to write settings: {e}"))?;
69    log::info!("Settings saved to {}", path.display());
70    Ok(())
71}