forked from 1b-agent/opencadstudio-upstream
refactor(config): consolidate settings into one grouped settings.json
App preferences were spread across six flat plain-text files (settings.txt,
recent.txt, recent_limit.txt, statusbar.txt, ribbon.txt, plot.txt), each with a
bespoke line parser and no grouping. Replace them with a single grouped JSON,
serialized via serde (enabling the derive feature; serde_json was already a
dependency).
- New app/config.rs: AppConfig { settings, recent, statusbar, ribbon, plot } →
<config>/settings.json (pretty JSON), load()/save().
- Make UserSettings, StatusBarConfig/StatusPill, CollapseMode and
PlotDialogState serde-derived; #[serde(skip)] marks the plot dialog's runtime
fields so only print preferences persist. Their bespoke .txt load/save is
removed.
- App gains current_config/apply_config/save_config: one AppConfig::load at
startup distributes into live state; every settings-change site
(persist_settings_if_changed, recent add/remove/limit, status-bar pill
toggle, ribbon density, plot commit) routes through save_config, which diffs
against the last write to avoid thrashing.
- Clean start: the old flat files are ignored (no migration). ocad.pgp stays a
separate hand-editable file.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
256f9a282b
commit
dc7117f203
12 files changed
+228
-411
No files matched your search
@@ -6,10 +6,10 @@
|
||||
//! survives across sessions.
|
||||
|
||||
use rustc_hash::FxHashSet as HashSet;
|
||||
use std::path::PathBuf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Identifies a toggleable status-bar pill.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
|
||||
pub enum StatusPill {
|
||||
Coords,
|
||||
Ortho,
|
||||
@@ -99,13 +99,12 @@ impl StatusPill {
|
||||
}
|
||||
}
|
||||
|
||||
fn from_id(s: &str) -> Option<StatusPill> {
|
||||
StatusPill::ALL.iter().copied().find(|p| p.id() == s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tracks which pills the user has hidden.
|
||||
#[derive(Clone)]
|
||||
/// Tracks which pills the user has hidden. Serialized as the "statusbar" section
|
||||
/// of the app config ([`crate::app::config`]).
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct StatusBarConfig {
|
||||
hidden: HashSet<StatusPill>,
|
||||
}
|
||||
@@ -133,50 +132,15 @@ impl Default for StatusBarConfig {
|
||||
}
|
||||
|
||||
impl StatusBarConfig {
|
||||
/// Load the saved customization. When no config file exists yet, fall back
|
||||
/// to the shipped defaults ([`StatusBarConfig::default`]); an existing file
|
||||
/// (even an empty one — the user showed every pill) is authoritative.
|
||||
pub fn load() -> Self {
|
||||
match config_path().and_then(|p| std::fs::read_to_string(p).ok()) {
|
||||
Some(body) => {
|
||||
let hidden = body
|
||||
.lines()
|
||||
.filter_map(|l| StatusPill::from_id(l.trim()))
|
||||
.collect();
|
||||
Self { hidden }
|
||||
}
|
||||
None => Self::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_visible(&self, pill: StatusPill) -> bool {
|
||||
!self.hidden.contains(&pill)
|
||||
}
|
||||
|
||||
/// Flip a pill's visibility and persist the change.
|
||||
/// Flip a pill's visibility. Persistence is handled by the caller via the
|
||||
/// consolidated app config (`save_config`).
|
||||
pub fn toggle(&mut self, pill: StatusPill) {
|
||||
if !self.hidden.remove(&pill) {
|
||||
self.hidden.insert(pill);
|
||||
}
|
||||
self.save();
|
||||
}
|
||||
|
||||
fn save(&self) {
|
||||
let Some(path) = config_path() else { return };
|
||||
if let Some(dir) = path.parent() {
|
||||
let _ = std::fs::create_dir_all(dir);
|
||||
}
|
||||
let body: String = StatusPill::ALL
|
||||
.iter()
|
||||
.filter(|p| self.hidden.contains(p))
|
||||
.map(|p| p.id())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let _ = std::fs::write(path, body);
|
||||
}
|
||||
}
|
||||
|
||||
/// `<config-dir>/OpenCADStudio/statusbar.txt`, matching the recent-files store.
|
||||
fn config_path() -> Option<PathBuf> {
|
||||
Some(crate::config::config_dir()?.join("statusbar.txt"))
|
||||
}
|
||||
Reference in new issue
Block a user