Files
I-SecretUpdate/ANALYSIS_SUMMARY.md
2026-02-06 12:30:13 +01:00

6.5 KiB

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

let app_config = config::load_config();  // Loaded ONCE, never again

Configuration Freezing Points

Freeze Point 1: BackgroundRenderer (src/app.rs:28-34)

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<BackgroundRenderer> (immutable)
  • Never updated during application lifetime

Freeze Point 2: Config Field (src/app.rs:49)

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<BackgroundRenderer>
  ↓
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

// Add to Cargo.toml
notify = "6.0"  // File system event watcher

2. Config Reload Mechanism

pub fn reload_config_from_disk() -> Config {
    config::load_config()  // Re-read from disk
}

3. Mutable Config Storage

// Change from:
config: Config

// To:
config: Arc<Mutex<Config>>

4. Updatable Background Renderer

// Either:
// - Store as Arc<Mutex<BackgroundRenderer>>
// - Or recreate it every frame with current config values

5. Hot Reload Trigger

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.