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)