Add Idle Hours and Pacing Indicator#13
Open
owovouo wants to merge 13 commits intoCodeZeno:mainfrom
Open
Conversation
|
Hah, I've completely missed that =) feel free to close #14 then. |
Replace preset quiet hours selection with a custom HH:MM input dialog, allowing users to set any start/end time for quiet hours.
Fix non-reentrant mutex deadlock where MoveWindow dispatches WM_PAINT synchronously, causing wnd_proc to re-enter lock_state() on the same thread. Credit: aa333 (PR CodeZeno#14)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shows a green zone between actual usage and expected usage based on elapsed time within the 5h/7d rolling windows. Updated at each poll interval so the indicator grows in discrete steps matching the chosen update frequency. Toggle via Settings > Show Pacing Indicator. Also add Win32_System_SystemInformation feature (required for GetLocalTime) and TIMER_QUIET_BOUNDARY constant to native_interop. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Green pacing zone is now suppressed in both render paths when quiet hours are active, consistent with the quiet-hours design intent of pausing all live activity indicators.
Merged upstream changes: - v1.3.6-v1.3.9: token expiry notifications, Dutch localization, UI improvements - v1.4.0: Codex model support via model menu Resolved conflicts by preserving both: - Our features: quiet hours, pacing indicator, Traditional Chinese localization - Upstream features: Codex model support, Dutch localization, new UI fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three related fixes: 1. Fix thread deadlock during drag (root cause of stuck cursor): WM_MOUSEMOVE held lock_state() mutex and called total_widget_width(), which also called lock_state(). Rust's std::sync::Mutex (SRWLOCK on Windows) is non-reentrant, causing the message thread to deadlock. Fixed by using total_widget_width_for() with active_models read from the already-held state. 2. Add WM_CAPTURECHANGED and WM_CANCELMODE handlers: Reset dragging state whenever mouse capture is transferred away for any reason, providing a safety net beyond WM_LBUTTONUP. 3. Add left_button_held() self-correction in WM_SETCURSOR and WM_MOUSEMOVE: If dragging=true but the left button is not physically held, cancel the drag immediately rather than waiting for a message that may never arrive. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codex now has the same behavior as Claude Code during quiet hours: - Usage bar frozen at last polled value before reset_at - Pacing bar (green) continues growing time-based during quiet hours - At reset_at: both bars go to 0% (window reset, no conversation started) - After reset_at (still quiet): both bars stay at 0% Also adds codex_session_pacing_pct / codex_weekly_pacing_pct fields so the Codex pacing indicator updates correctly on every poll and when the user toggles the pacing setting. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The feature is fundamentally about time periods when the user is not actively using Claude Code — the reset clock is unaffected because no conversation is started. "Idle Hours" conveys this intent more clearly than "Quiet Hours" (which implies only notification silencing). Translations: en: Idle Hours nl: Inactieve uren fr: Heures inactives de: Inaktive Stunden ja: アイドル時間 ko: 유휴 시간 es: Horas inactivas zh-TW: 閒置時段 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two independent features plus a bug fix, contributed on top of upstream v1.4.0.
1. Idle Hours
Suppresses Windows toast notifications during a user-configured time window — without affecting the widget display.
Concept: "Idle Hours" describes a period when the user is not actively using Claude Code. Because no conversation is started during this window, the rate-limit reset clock is unaffected — it fires at its scheduled time regardless. The name was chosen to communicate this intent more clearly than "Quiet Hours" (which implies only notification silencing).
Behaviour during Idle Hours:
resets_atresets_atresets_at(still idle)Applies to both Claude Code and Codex widgets.
Localization: en · nl · fr · de · ja · ko · es · zh-TW
2. Pacing Indicator
A green overlay on each progress bar showing the expected usage at the current point in time, based on how much of the 5-hour (or 7-day) window has elapsed.
This addresses the concern raised in issue #21 (Estimated Time to Depletion): rather than a numeric ETD, it gives an at-a-glance visual answer to "am I on track?".
Toggled via right-click menu → Show Pacing Indicator.
Applies to both Claude Code and Codex widgets.
3. Bug fix: widget drag freezes taskbar
Root cause:
WM_MOUSEMOVEheld theAppStatemutex while callingtotal_widget_width(), which internally calledlock_state()again. Rust'sstd::sync::Mutex(backed bySRWLOCKon Windows) is not re-entrant — the second acquisition deadlocked the message thread.Symptoms: After clicking the drag handle, the resize cursor (↔) became permanently stuck, the widget position did not move, and all other taskbar icons became unclickable.
Fix: replaced the inner
total_widget_width()call withtotal_widget_width_for(active_model_count(...))using values already read from the locked state — no second lock needed.Additional safety:
WM_CAPTURECHANGEDandWM_CANCELMODEhandlers reset drag state if capture is lost for any reason;WM_SETCURSORandWM_MOUSEMOVEself-correct if the left button is no longer held.This bug is present in upstream v1.4.0 as well.