mirror of
https://github.com/tiennm99/claude-code-usage-bubble.git
synced 2026-10-23 00:15:38 +00:00
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)
39 lines
1.1 KiB
Rust
39 lines
1.1 KiB
Rust
// Usage subsystem: trait + per-provider implementations + registry.
|
|
//
|
|
// Phase 2 stubs out only `types`. Phase 4 fills in `anthropic`, `chatgpt`,
|
|
// `refresh`, `registry`, and `headers`. The trait below is the contract
|
|
// every provider must satisfy.
|
|
|
|
pub mod anthropic;
|
|
pub mod chatgpt;
|
|
pub mod headers;
|
|
pub mod refresh;
|
|
pub mod registry;
|
|
pub mod types;
|
|
|
|
pub use registry::Registry;
|
|
pub use types::{ProviderId, UsageWindows, Window};
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum Error {
|
|
#[error("authentication required")]
|
|
AuthRequired,
|
|
#[error("no credentials configured")]
|
|
NoCredentials,
|
|
#[error("token expired after refresh attempt")]
|
|
TokenExpired,
|
|
#[error("network: {0}")]
|
|
Network(#[from] crate::net::Error),
|
|
#[error("credentials: {0}")]
|
|
Creds(#[from] crate::creds::Error),
|
|
#[error("unexpected response shape: {0}")]
|
|
BadResponse(String),
|
|
}
|
|
|
|
/// Every provider exposes a stable identity and a sync `poll` that performs
|
|
/// HTTP calls against the supplied client.
|
|
pub trait UsageProvider: Send {
|
|
fn id(&self) -> ProviderId;
|
|
fn poll(&mut self, http: &crate::net::Client) -> Result<UsageWindows, Error>;
|
|
}
|