use std::path::Path; use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::mirror::snapshot::BoardLayer; #[derive(Debug, Error)] pub enum SettingsError { #[error("io error: {0}")] Io(#[from] std::io::Error), #[error("json error: {0}")] Json(#[from] serde_json::Error), } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Settings { pub schema_version: u32, pub hide_stash_layer: BoardLayer, pub snapshot_ring_size: usize, pub snapshot_mem_budget_bytes: usize, pub poll_interval_ms: u64, #[serde(default = "default_track_non_active")] pub track_non_active_layers: bool, #[serde(default = "default_grid_mm")] pub grid_snap_x_mm: f64, #[serde(default = "default_grid_mm")] pub grid_snap_y_mm: f64, #[serde(default = "default_true_bool")] pub grid_snap_link_axes: bool, #[serde(default = "default_true_bool")] pub grid_snap_refill_zones: bool, pub ui: UiSettings, pub keybinds: KeybindSettings, } fn default_track_non_active() -> bool { true } fn default_grid_mm() -> f64 { 0.254 } fn default_true_bool() -> bool { true } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UiSettings { pub dark_mode: Option, pub preview_size_px: u32, pub show_item_counts: bool, pub show_icons: bool, } impl Default for UiSettings { fn default() -> Self { Self { dark_mode: None, preview_size_px: 192, show_item_counts: true, show_icons: true, } } } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct KeybindSettings { pub new_layer_from_selection: Option, } impl Default for Settings { fn default() -> Self { Self { schema_version: 1, hide_stash_layer: BoardLayer::Eco2User, snapshot_ring_size: 50, snapshot_mem_budget_bytes: 256 * 1024 * 1024, poll_interval_ms: 100, track_non_active_layers: true, grid_snap_x_mm: 0.254, grid_snap_y_mm: 0.254, grid_snap_link_axes: true, grid_snap_refill_zones: true, ui: UiSettings::default(), keybinds: KeybindSettings::default(), } } } impl Settings { pub const SCHEMA_VERSION: u32 = 1; pub fn load_from(path: &Path) -> Result { let bytes = std::fs::read(path)?; Ok(serde_json::from_slice(&bytes)?) } pub fn save_to(&self, path: &Path) -> Result<(), SettingsError> { if let Some(parent) = path.parent() { std::fs::create_dir_all(parent)?; } let tmp = path.with_extension("json.tmp"); let bytes = serde_json::to_vec_pretty(self)?; std::fs::write(&tmp, &bytes)?; std::fs::rename(&tmp, path)?; Ok(()) } }