# Config Struct Analysis: cargo run vs Standalone EXE ## QUICK ANSWER **The config.toml modifications work in `cargo run` but not standalone EXE because:** 1. **Both behave identically** - neither reloads config during runtime 2. **The difference is file location** - where config.toml is searched for 3. **cargo run appears to work** because users restart the process frequently 4. **Standalone EXE appears broken** because users expect live reloading The real issue: **Config is frozen at startup and never reloaded.** --- ## THE CORE PROBLEM ### Configuration Loading (One-Time Only) **File: `src/main.rs`, Line 54** ```rust let app_config = config::load_config(); // Loaded ONCE, never again ``` ### Configuration Freezing Points **Freeze Point 1: BackgroundRenderer (`src/app.rs:28-34`)** ```rust let background_renderer = Some(Arc::new(BackgroundRenderer::new( &cc.egui_ctx, &config.appearance.background_image, config.appearance.background_opacity, // ← COPIED config.appearance.fallback_color, // ← COPIED config.appearance.fallback_color_opacity, // ← COPIED ))); ``` - Appearance values **copied** into struct once - Stored in `Arc` (immutable) - **Never updated** during application lifetime **Freeze Point 2: Config Field (`src/app.rs:49`)** ```rust Self { config, // ← Stored as owned field, never mutated // ... } ``` - Config struct **stored once** at initialization - Colors, text sizing, window settings **frozen** - **Never reloaded** from disk - **Never updated** at runtime --- ## WHY CHANGES DON'T APPEAR ### Background Changes (opacity, color) 1. User modifies `config.toml` (e.g., changes `background_opacity`) 2. Application still has original value in `BackgroundRenderer` memory 3. Every frame, `render_fullscreen()` uses **frozen opacity value** 4. No code to reload config or recreate `BackgroundRenderer` 5. **Change never takes effect** ### Color Changes 1. User modifies `config.toml` (e.g., changes text color) 2. Application still has original `Config` struct in memory 3. Every frame, `update()` reads from `self.config` 4. But `self.config` was never updated 5. `ctx.set_visuals()` applies **same frozen colors** 6. **Change never takes effect** --- ## cargo run vs Standalone: The REAL Story ### cargo run Process ``` User runs: cargo run ├─ New process created ├─ load_config() reads config.toml from repo root (fallback path) ├─ Application starts with current config ├─ User modifies config.toml while app is running │ └─ Change DOESN'T take effect (no reload mechanism) ├─ User exits app ├─ User runs: cargo run again │ ├─ New process created │ ├─ load_config() reads UPDATED config.toml │ └─ Application shows new values ✓ └─ User thinks "config changes work in cargo run!" ``` ### Standalone EXE Process ``` User runs: Create-App-Secret.exe ├─ Process created ├─ load_config() looks in EXE directory │ └─ If config.toml exists there, loads it │ └─ Otherwise falls back to ./config.toml ├─ Application starts with current config ├─ User modifies config.toml while app is running │ └─ Change DOESN'T take effect (no reload mechanism) ├─ User expects changes to appear │ └─ Nothing happens ✗ ├─ User closes app ├─ User runs: Create-App-Secret.exe again │ ├─ New process created │ ├─ load_config() reads UPDATED config.toml │ └─ Application shows new values ✓ └─ User thinks "config changes don't work in standalone!" ``` ### The Actual Difference | Aspect | cargo run | Standalone | |--------|-----------|-----------| | Config loading code | Identical | Identical | | Config freezing | Yes, identical | Yes, identical | | Hot-reload | No | No | | Updates on restart | Yes ✓ | Yes ✓ | | File location | Repo root (fallback) | EXE directory | --- ## CODE PATH: From Config Loading to Display ``` main.rs:54 ↓ config::load_config() ← Reads config.toml from disk [ONCE] ↓ Returns Config struct ↓ main.rs:76 ↓ Moved into AzureAppManager::new() ↓ app.rs:28-34: BackgroundRenderer created └─ opacity, fallback_color COPIED from config [FROZEN] └─ Stored in Arc ↓ app.rs:49: Config stored └─ self.config = config [FROZEN] ↓ eframe event loop (every frame ~60x/sec): ├─ app.rs:375-457: update() called │ ├─ app.rs:380: Read colors from self.config [frozen values] │ ├─ app.rs:467: Read text sizing from self.config [frozen values] │ ├─ app.rs:489: Read position offset from self.config [frozen values] │ └─ app.rs:505-507: Render background with frozen renderer │ └─ Every frame: Same frozen values used again (Because no code reloads or updates them) ``` --- ## What Would Be Needed to Fix ### 1. File Watching ```rust // Add to Cargo.toml notify = "6.0" // File system event watcher ``` ### 2. Config Reload Mechanism ```rust pub fn reload_config_from_disk() -> Config { config::load_config() // Re-read from disk } ``` ### 3. Mutable Config Storage ```rust // Change from: config: Config // To: config: Arc> ``` ### 4. Updatable Background Renderer ```rust // Either: // - Store as Arc> // - Or recreate it every frame with current config values ``` ### 5. Hot Reload Trigger ```rust if config_file_changed { new_config = reload_config_from_disk(); update_background_renderer(&new_config); ctx.request_repaint(); } ``` --- ## Summary Table | Component | Location | Issue | Status | |-----------|----------|-------|--------| | Config loading | `main.rs:54` | Loaded once | FROZEN | | Config movement | `main.rs:76` | Moved via ownership | FROZEN | | Background values | `app.rs:28-34` | Copied into struct | FROZEN | | Config storage | `app.rs:49` | Stored as owned field | FROZEN | | Color application | `app.rs:380-444` | Reads frozen config | EVERY FRAME | | Background rendering | `background.rs:106` | Uses frozen values | EVERY FRAME | | Reload mechanism | *Not found* | No file watching | ✗ MISSING | --- ## Key Insight **The application architecture assumes configuration is set once at startup and never changes.** This is a design choice, not a bug. The same frozen-config behavior exists in both `cargo run` and standalone EXE. The perceived difference comes from: - **cargo run**: Users frequently restart processes → see updated config - **Standalone EXE**: Users expect live updates → see frozen config Both are executing identical code with identical behavior.