Desktop: global UI scale (egui zoom_factor), persisted

The card-density slider only resized the channel-grid cards — the
sidebar, settings, detail panel, and all text stayed fixed. Add a real
global scale that grows/shrinks the *entire* UI crisply.

egui already handles Ctrl + / Ctrl - / Ctrl 0 via zoom_factor (it
re-rasterizes fonts rather than bitmap-stretching), but it wasn't
persisted and had no visible control. Now:

- New `[ui] ui_scale` config (default 1.0), applied with
  set_zoom_factor at startup.
- update() mirrors ctx.zoom_factor() back into config each frame and
  saves on a 500ms debounce, so both the slider and the built-in
  keyboard zoom persist across restarts without writing config.toml
  every frame of a drag.
- A "UI scale" slider (0.5–3.0×) + Reset button in the Settings screen,
  driving set_zoom_factor live.

The card-density "Size:" slider stays as a separate grid-density
preference (it composes with the global zoom). 95 tests pass; GUI
verified running with the per-frame zoom-sync path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-06-04 19:14:23 -07:00
parent fd9063b5cb
commit b8a742535b
2 changed files with 61 additions and 0 deletions

View file

@ -161,13 +161,22 @@ pub struct UiSection {
/// hidden window.
#[serde(default)]
pub minimize_to_tray: bool,
/// Global egui zoom factor — scales the *entire* desktop UI (fonts,
/// spacing, widgets), not just the card grid. 1.0 = native. Persisted
/// here so the chosen size survives restarts and is kept in sync with
/// the built-in Ctrl + / Ctrl - / Ctrl 0 keyboard zoom.
#[serde(default = "default_ui_scale")]
pub ui_scale: f32,
}
fn default_ui_scale() -> f32 { 1.0 }
impl Default for UiSection {
fn default() -> Self {
Self {
theme: default_theme(),
minimize_to_tray: false,
ui_scale: default_ui_scale(),
}
}
}