Skip to content

Commit d987cc8

Browse files
committed
Settings: rename settings-v2.json to settings.json
- No users on the old v1 format, so remove the fallback cascade - Rename `parse_settings_v2` → `parse_settings` - Update all docs and CLAUDE.md files
1 parent 00249f4 commit d987cc8

6 files changed

Lines changed: 16 additions & 30 deletions

File tree

apps/desktop/src-tauri/src/settings/CLAUDE.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Thin read-only settings loader used during Rust startup. The frontend owns all s
77
| File | Purpose |
88
|---|---|
99
| `mod.rs` | Re-exports `load_settings` from `legacy` |
10-
| `legacy.rs` | `Settings` struct + `load_settings`: tries `settings-v2.json` first, falls back to `settings.json`, then uses defaults |
10+
| `legacy.rs` | `Settings` struct + `load_settings`: reads `settings.json`, falls back to defaults |
1111

1212
## Settings struct
1313

@@ -21,35 +21,30 @@ Settings {
2121
}
2222
```
2323

24-
## File formats
24+
## File format
2525

26-
**`settings-v2.json`** (current): flat JSON with literal dot-notation string keys.
26+
**`settings.json`**: flat JSON with literal dot-notation string keys, written by `tauri-plugin-store`.
2727

2828
```json
2929
{ "showHiddenFiles": true, "developer.mcpEnabled": true, "developer.mcpPort": 9224 }
3030
```
3131

32-
These are top-level keys — the dot is part of the key name, not a nesting separator. `parse_settings_v2` reads them manually (serde can't express dot-notation field names as struct fields).
33-
34-
**`settings.json`** (legacy): nested JSON with camelCase keys, parsed via serde aliases.
32+
These are top-level keys — the dot is part of the key name, not a nesting separator. `parse_settings` reads them manually (serde can't express dot-notation field names as struct fields).
3533

3634
## Key decisions
3735

3836
**Decision**: Rust reads the settings file directly instead of receiving values via IPC from the frontend.
3937
**Why**: Several backend systems (MCP server, hidden files filter, indexing) need their config *before* any frontend window loads. Waiting for the frontend to boot and push settings would create a race condition or require delaying backend initialization. Reading the file directly means the backend is configured immediately at launch.
4038

41-
**Decision**: Manual JSON field extraction in `parse_settings_v2` instead of serde auto-derivation.
39+
**Decision**: Manual JSON field extraction in `parse_settings` instead of serde auto-derivation.
4240
**Why**: `tauri-plugin-store` writes flat JSON with literal dot-notation string keys like `"developer.mcpEnabled"`. Serde's `rename` attribute can handle this per-field, but the dot is part of the key name, not a nesting separator. The manual extraction makes this non-obvious format explicit and avoids confusion about nested vs. flat structure.
4341

44-
**Decision**: Try `settings-v2.json` first, then fall back to `settings.json`, then defaults.
45-
**Why**: The app migrated from a nested JSON format (v1) to the flat dot-notation format (v2) written by `tauri-plugin-store`. Users upgrading from older versions still have the v1 file. The cascade ensures settings survive across app updates without requiring an explicit migration step.
46-
4742
## Key patterns
4843

4944
- **One-way read only.** This module never writes. All writes go through the frontend's settings store.
5045
- Module is named `legacy` because ideally the frontend would push relevant values via IPC at startup rather than requiring Rust to parse the store file directly.
5146
- `full_disk_access_choice` is marked `#[allow(dead_code)]` — it is persisted by the frontend but the backend takes no action on it.
52-
- Falls back gracefully at every step: missing file → try next format → use `Default`.
47+
- Falls back gracefully: missing file → use `Default`.
5348

5449
## Dependencies
5550

apps/desktop/src-tauri/src/settings/legacy.rs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Settings loading from tauri-plugin-store JSON file.
22
//!
3-
//! Reads settings from the settings-v2.json file created by tauri-plugin-store.
3+
//! Reads settings from the settings.json file created by tauri-plugin-store.
44
//! Used to initialize app state (menu checkboxes, MCP config) on startup.
55
66
use serde::Deserialize;
@@ -21,7 +21,7 @@ pub enum FullDiskAccessChoice {
2121
}
2222

2323
/// User settings structure, matching the frontend settings-store.ts
24-
/// Note: Uses serde aliases to support both camelCase (settings-v2.json) and snake_case
24+
/// Note: Uses serde aliases to support both camelCase (settings.json) and snake_case
2525
#[derive(Debug, Deserialize)]
2626
pub struct Settings {
2727
#[serde(alias = "showHiddenFiles", default = "default_show_hidden")]
@@ -53,35 +53,26 @@ impl Default for Settings {
5353
}
5454
}
5555

56-
/// Loads settings from the persistent store file (settings-v2.json).
56+
/// Loads settings from the persistent store file (settings.json).
5757
/// Returns defaults if the file doesn't exist or can't be parsed.
5858
pub fn load_settings<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> Settings {
5959
// Get the app data directory (like ~/Library/Application Support/com.veszelovszki.cmdr/)
6060
let Some(data_dir) = crate::config::resolved_app_data_dir(app).ok() else {
6161
return Settings::default();
6262
};
6363

64-
// Try settings-v2.json first (new format from tauri-plugin-store)
65-
let settings_v2_path: PathBuf = data_dir.join("settings-v2.json");
66-
if let Ok(contents) = fs::read_to_string(&settings_v2_path)
67-
&& let Ok(settings) = parse_settings_v2(&contents)
68-
{
69-
return settings;
70-
}
71-
72-
// Fall back to legacy settings.json
7364
let settings_path: PathBuf = data_dir.join("settings.json");
7465
if let Ok(contents) = fs::read_to_string(&settings_path)
75-
&& let Ok(settings) = serde_json::from_str(&contents)
66+
&& let Ok(settings) = parse_settings(&contents)
7667
{
7768
return settings;
7869
}
7970

8071
Settings::default()
8172
}
8273

83-
/// Parse settings-v2.json which uses dot notation for keys (like "developer.mcpEnabled")
84-
fn parse_settings_v2(contents: &str) -> Result<Settings, serde_json::Error> {
74+
/// Parse settings.json which uses dot notation for keys (like "developer.mcpEnabled")
75+
fn parse_settings(contents: &str) -> Result<Settings, serde_json::Error> {
8576
// tauri-plugin-store uses flat JSON with dot notation keys
8677
let json: serde_json::Value = serde_json::from_str(contents)?;
8778

apps/desktop/src/lib/logging/logger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ let loggerInitialized = false
6464
async function getVerboseLoggingSetting(): Promise<boolean> {
6565
try {
6666
// Use empty defaults since we just want to read existing values
67-
const store: Store = await load('settings-v2.json', {
67+
const store: Store = await load('settings.json', {
6868
autoSave: false,
6969
defaults: {},
7070
})

apps/desktop/src/lib/settings/CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Single source of truth for all settings. Each `SettingDefinition` contains:
2020

2121
### Store (`settings-store.ts`)
2222

23-
- Uses `tauri-plugin-store` for persistence to `~/Library/Application Support/com.veszelovszki.cmdr/settings-v2.json`
23+
- Uses `tauri-plugin-store` for persistence to `~/Library/Application Support/com.veszelovszki.cmdr/settings.json`
2424
- Debounced saves: 500ms after last change, atomic write (temp file + rename)
2525
- In-memory cache for synchronous reads via `getSetting()`
2626
- Cross-window sync: emits `settings:changed` events when values change

apps/desktop/src/lib/settings/settings-store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface SettingChangedPayload {
2323
// Store Configuration
2424
// ============================================================================
2525

26-
const STORE_NAME = 'settings-v2.json'
26+
const STORE_NAME = 'settings.json'
2727
const SCHEMA_VERSION = 1
2828

2929
let storeInstance: Store | null = null

docs/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ zero-permission entries with fallback metadata.
210210
### Persistence
211211

212212
- **App status** (`app-status.json`): ephemeral state — paths, focused pane, view modes, last-used paths per volume
213-
- **Settings** (`settings-v2.json`): preferences — hidden files, density, date format. Registry-validated.
213+
- **Settings** (`settings.json`): preferences — hidden files, density, date format. Registry-validated.
214214
- **Shortcuts** (`shortcuts.json`): delta-only — only customizations stored, defaults in code
215215
- **License** (`license.json`): activation state, timestamps
216216
- **Window state**: `@tauri-apps/plugin-window-state` for size/position per window label

0 commit comments

Comments
 (0)