mirror of
https://github.com/tiennm99/claude-code-usage-bubble.git
synced 2026-09-10 04:19:35 +00:00
Whole-project review pass over the entire crate. No new features. All function definitions preserved; layout and visibility reorganised. Bug fixes: - bubble: ExtractIconExW HICON pair was leaked per bubble toggle. Extract once into a process-wide OnceLock, reuse forever (bounded). - usage/anthropic: parse_iso8601 was stripping the UTC offset without applying it — negative-offset users saw countdowns up to 14h wrong. Now parses signed minutes and computes utc_secs = local - off*60. Also rejects y<1970, mo∉[1,12], d∉[1,max_day(mo,y)] up front so malformed API responses can't index DAYS_IN_MONTH out of bounds. - usage: clamp utilization to [0,100] at all four Window construction sites so a misbehaving server can't render "121%". - bubble: GetDC and CreateCompatibleDC results weren't checked. Guard both; release the screen DC on the CreateCompatibleDC failure path. Refactor: - Drop type TrayIconKind = ProviderId aliases (5 sites); use ProviderId directly everywhere. Inline the identity-function kind_to_provider. - Delete panel::bar_color_for shim (was just argument-reorder glue). - Replace local scale_to_dpi fns in bubble.rs and panel.rs with use crate::os::dpi::scale as scale_to_dpi (brings os::dpi into the live import graph; was unused before). - Delete dead PCWSTR import + #[allow(dead_code)] sentinel in tray/badge.rs; fold the trailing `use BOOL` into the top imports. - Inline app::primary_dpi() to crate::os::dpi::for_system(). app.rs: - Add update_settings(|s: &mut AppState|) helper that locks state, runs the closure, snapshots Settings, drops the lock, then saves to disk. Convert four pure-mutate-then-save callsites. Layering: bubble.rs no longer reaches upward into crate::app::. Introduce bubble::Callbacks (fn-pointers), OnceLock<Callbacks>, and bubble::install_callbacks(). The wnd_proc dispatches the six prior upward calls via a private dispatch() helper. app::run installs callbacks once at startup; the six on_bubble_* / recheck_theme fns are demoted from pub fn to fn. Resource-warning logs added: dispatch() warns on uninstalled callbacks; app_icons() warns when ExtractIconExW returns nulls. Build: cargo build --release clean; cargo clippy reports zero new warnings (11 pre-existing, all in untouched code).
56 lines
1.7 KiB
Rust
56 lines
1.7 KiB
Rust
// Parse Anthropic rate-limit headers into `UsageWindows`.
|
||
//
|
||
// The Messages API returns the user's remaining quota in response headers
|
||
// when the dedicated usage endpoint isn't available. Header names:
|
||
// anthropic-ratelimit-unified-5h-utilization (0.0–1.0)
|
||
// anthropic-ratelimit-unified-5h-reset (Unix seconds)
|
||
// anthropic-ratelimit-unified-7d-utilization
|
||
// anthropic-ratelimit-unified-7d-reset
|
||
|
||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||
|
||
use crate::net::Response;
|
||
use crate::usage::{UsageWindows, Window};
|
||
|
||
pub fn parse_anthropic(response: &Response) -> UsageWindows {
|
||
UsageWindows {
|
||
primary: Window {
|
||
utilization: (header_f64(response, "anthropic-ratelimit-unified-5h-utilization")
|
||
* 100.0)
|
||
.clamp(0.0, 100.0),
|
||
resets_at: unix_to_systemtime(header_i64(
|
||
response,
|
||
"anthropic-ratelimit-unified-5h-reset",
|
||
)),
|
||
},
|
||
secondary: Window {
|
||
utilization: (header_f64(response, "anthropic-ratelimit-unified-7d-utilization")
|
||
* 100.0)
|
||
.clamp(0.0, 100.0),
|
||
resets_at: unix_to_systemtime(header_i64(
|
||
response,
|
||
"anthropic-ratelimit-unified-7d-reset",
|
||
)),
|
||
},
|
||
}
|
||
}
|
||
|
||
fn header_f64(response: &Response, name: &str) -> f64 {
|
||
response
|
||
.header(name)
|
||
.and_then(|s| s.parse().ok())
|
||
.unwrap_or(0.0)
|
||
}
|
||
|
||
fn header_i64(response: &Response, name: &str) -> Option<i64> {
|
||
response.header(name).and_then(|s| s.parse().ok())
|
||
}
|
||
|
||
fn unix_to_systemtime(secs: Option<i64>) -> Option<SystemTime> {
|
||
let s = secs?;
|
||
if s < 0 {
|
||
return None;
|
||
}
|
||
Some(UNIX_EPOCH + Duration::from_secs(s as u64))
|
||
}
|