- P0: pull blocking HTTPS out from under the global mutex. AppState's
http and registry now live behind Arc<Client> and Arc<Mutex<Registry>>;
do_poll, attempt_refresh, and version_action's Apply branch clone
these out, drop lock_state, then do their I/O. Apply now spawns a
worker thread that posts WM_APP_UPDATE_APPLIED back to the message-
only window when the cmd handoff is launched, so the UI no longer
freezes for the duration of the download.
- P1: bubble.rs paint_text_layer saves and restores the DC's previous
HFONT before DeleteObject. The old code's DeleteObject on a still-
selected HFONT silently failed and leaked one handle per paint frame
(up to ~12/s under the ≥95% pulse animation).
- P1: replace 5x CreatePopupMenu().unwrap() with let-else early returns
that destroy any half-built menus and log. GDI exhaustion no longer
panics the UI thread.
- P1: at-most-one-in-flight gate (static AtomicBool) on the poll thread
so rapid Refresh clicks don't stack concurrent HTTPS calls.
- P1: token-expired balloon now picks the title/body for the provider
that actually failed, instead of always falling back to Claude when
show_claude_code is on.
- P1: panel place_near honors SM_XVIRTUALSCREEN / SM_YVIRTUALSCREEN so
multi-monitor setups with a secondary display left of the primary
no longer mis-clamp the panel position.
- P1: COUNTDOWN_TEMPLATE bumped from "999d" to "999시간" — Korean has
the widest suffix among shipped locales and was overflowing the
countdown column.
Bumps version to 0.1.4.
GitHub's Releases API exposes a `digest: "sha256:..."` field on every
asset since 2024. We now parse it, hash the downloaded bytes locally,
and abort with ChecksumMismatch if they disagree. Releases that predate
the field (none currently exist for this repo) skip verification rather
than fail, so v0.1.0 / v0.1.1 / v0.1.2 still update normally.
cmd.exe expands `%var%` even inside double-quoted arguments, which
would let a path like `C:\Users\%PATHEXT%\bubble.exe` substitute the
expansion. Real Windows paths with `%` are vanishingly rare, so we
fail fast with UnsafePath rather than ship a bespoke cmd-escape
implementation.
Bumps version to 0.1.3.
Rust's std::process::Command escapes inner double quotes as \" when
wrapping the args(["/c", &cmd]) array. cmd.exe does not understand the
\" escape, so the swap-and-restart command got mangled: `start ""
"PATH"` arrived as `start \"\" \"PATH\"`, which the cmd parser
collapsed into `start \ PATH` — producing the "Windows cannot find
'\'" dialog and aborting the update.
Switching to raw_arg lets us hand cmd.exe the literal command line it
expects. The two quote characters cmd needs to keep are the outer pair
wrapping the whole /c argument; cmd's "more than two quotes, special
chars present" branch then preserves the inner path quotes intact.
Bumps version to 0.1.2 since this is the first updater fix that ships
through the updater itself for any future v0.1.2+ user.