35 Commits

Author SHA1 Message Date
tiennm99 4022d3f2de feat: drop WSL and multi-language support 2026-06-02 16:32:21 +07:00
tiennm99 67f3b8a7ec chore: bump version to 0.4.1 2026-06-02 15:52:03 +07:00
tiennm99 c46ab57f73 fix(update): use self-replace for portable updates 2026-06-02 15:50:45 +07:00
tiennm99 0ac698e2d1 chore: bump version to 0.4.0 2026-06-02 15:11:26 +07:00
tiennm99 38752ae5c5 chore: bump version to 0.3.13 2026-06-02 11:09:35 +07:00
tiennm99 4e9a66cbc8 chore: bump version to 0.3.12 2026-06-01 16:55:59 +07:00
tiennm99 1d9c59b43b chore: bump version to 0.3.11 2026-06-01 16:10:43 +07:00
tiennm99 cc73c3f9b4 chore: bump version to 0.3.10 2026-06-01 15:36:26 +07:00
tiennm99 a68d80415b chore: bump version to 0.3.9 2026-06-01 15:05:35 +07:00
tiennm99 5e00009e5a chore: bump version to 0.3.8 2026-06-01 14:37:26 +07:00
tiennm99 b2e48cc119 chore: bump version to 0.3.7 2026-05-25 11:37:34 +07:00
tiennm99 860eb62d1b chore: bump version to 0.3.6 2026-05-25 11:15:13 +07:00
tiennm99 3b0f96f51c chore: bump version to 0.3.5 2026-05-23 23:36:41 +07:00
tiennm99 f2b31d3211 fix(ui): align tail bar text layout 2026-05-23 22:53:36 +07:00
tiennm99 5c2b14fc03 feat(ui): show remaining time progress 2026-05-23 22:31:37 +07:00
tiennm99 51889d3c39 fix(ui): scale weekly bar thickness 2026-05-23 21:43:11 +07:00
tiennm99 6661a7a10b chore: bump version to 0.3.1 2026-05-23 21:07:05 +07:00
tiennm99 b58811bfe0 chore: bump version to 0.3.0 2026-05-23 20:33:10 +07:00
tiennm99 a3f1323154 chore: bump version to 0.2.0 2026-05-23 18:18:34 +07:00
tiennm99 391ad0cba2 chore: bump version to 0.1.15 2026-05-23 12:54:46 +07:00
tiennm99 c3d01f36d2 chore: bump version to 0.1.14 2026-05-23 12:30:52 +07:00
tiennm99 8cbc3dda5b chore: bump version to 0.1.13 2026-05-23 12:09:36 +07:00
tiennm99 f96d88074a chore: bump version to 0.1.12 2026-05-23 11:23:14 +07:00
tiennm99 4e0f32591b chore: bump version to 0.1.11 2026-05-21 16:51:46 +07:00
tiennm99 27aa935a9b chore: bump version to 0.1.10 2026-05-21 16:29:05 +07:00
tiennm99 858d7f1139 chore: bump version to 0.1.9 2026-05-18 11:28:26 +07:00
tiennm99 bcce939f72 chore: bump version to 0.1.8 2026-05-18 10:46:16 +07:00
tiennm99 eca430ccc6 feat(menu): show current version on the Check-for-Updates entry
Appends ' · v{CARGO_PKG_VERSION}' to every state of the version-action
menu item so users can see what they are running without opening an
About dialog. Reads as 'Check for updates · v0.1.7', 'Up to date ·
v0.1.7', etc. Winget channel decoration is preserved as a trailing
parenthetical.

Bumps version to 0.1.7.
2026-05-16 14:10:02 +07:00
tiennm99 2791022e7a chore: drop dead ureq + native-tls deps
The legacy poller.rs and updater.rs modules they served were deleted
in the clean-room rewrite; everything now goes through net::winhttp.
Grep confirms no source references to either crate. Removing them
trims the dep graph noticeably.

Bumps version to 0.1.6.
2026-05-16 13:59:18 +07:00
tiennm99 ed9b8b2042 feat: threshold balloons + dark/light auto-follow
- Threshold balloons fire the cycle utilization crosses 80% or 95%
  on either provider, with the title showing "{Provider} · {N}%" and
  body translated per shipped locale. Reuses the existing
  BALLOON_COOLDOWN so notifications stay calm.
- Dark/light auto-follow: bubble's WM_SETTINGCHANGE handler now calls
  app::recheck_theme(), which re-reads HKCU\…\Personalize, updates
  state.is_dark if changed, and triggers a UI repaint + tray refresh.
  Windows posts WM_SETTINGCHANGE to every top-level window when the
  user toggles light/dark in Settings, so the bubble repaints in
  near-real-time.
- Adds 2 new i18n keys (threshold_80_body, threshold_95_body) across
  all eight shipped locales.

Bumps version to 0.1.5.
2026-05-16 13:57:15 +07:00
tiennm99 1ef1bfa7b2 fix: phase 2 — UI-freeze + GDI-leak + panic-on-GDI-exhaustion fixes
- 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.
2026-05-16 13:51:16 +07:00
tiennm99 0f3acd40d4 feat(update): SHA-256 verification + reject paths containing '%'
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.
2026-05-16 13:37:37 +07:00
tiennm99 a132c02711 fix(update): bypass Rust arg escaping in cmd.exe handoff
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.
2026-05-16 13:04:08 +07:00
tiennm99 ca9ab4ea97 chore: bump version to 0.1.1 2026-05-16 12:58:18 +07:00
tiennm99 ee4e1c9b26 feat: redesign bubble as two-bar rounded rect, finish port wiring
Bubble shape changes from circle to rounded rectangle showing two stacked
horizontal bars — top: session (5h), bottom: weekly (7d) — each followed
by a right-aligned "X% · Yh Zm" string (percent + countdown).

Bubble surface:
- BubbleConfig/BubbleState carry session+weekly percents and texts (mirrors
  PanelData); update_percentage renamed to update_data
- Aspect ratio fixed at 3:1; size_logical is interpreted as width with
  height derived. Clamp is 120..360 (was 32..128 square)
- Hit-testing uses a rounded-rect predicate (point_in_rounded_rect) shared
  with the alpha mask so paint and click area can't drift
- New rgb_to_dib helper for direct DIB writes — BI_RGB 32bpp stores B,G,R,X
  in memory which is the opposite of COLORREF. The previous code wrote
  COLORREF-packed u32 straight into DIB pixels; invisible while every color
  was gray, but the new orange/red bar fills would have rendered blue
- bar_h capped at h/4 (range 6..18) so the text font derived from it stays
  small enough that "100% · 23h" fits in right_text_w (= 6×bar_h, min 56);
  the first iteration had a 19-px font in a 60-px column and ellipsized
  away the countdown
- Initial session_text/weekly_text seeded with "…" so the bubble has
  visible feedback during the first poll instead of two empty grey tracks

Compile + cleanup needed to make the port build at all:
- Color::from_hex added back as an infallible wrapper around parse_hex
  (15 call sites in bubble.rs/panel.rs assumed the old infallible API)
- Color::to_colorref → into_colorref at 5 call sites
- GetModuleFileNameW added to the LibraryLoader import in bubble.rs
- usage::Error gains Creds(#[from] creds::Error) so `?` works in the
  Anthropic and ChatGPT providers
- FlattenBoxed::flatten renamed to flatten_box — the std Option::flatten
  was shadowing it and yielding Option<Box<T>> instead of Option<T>
- PanelState marked unsafe Send (HWND has *mut c_void; state is only
  touched from the UI thread, Mutex is for OnceLock satisfaction)
- Crate-level #![allow(dead_code)] for in-progress port API surface
  (creds, usage, update, os::dpi); unused pub-use re-exports removed

App wiring:
- propagate_to_ui now feeds both windows + their formatted texts into
  update_data (was a single percent)
2026-05-16 11:11:34 +07:00