Skip to content

Ade Usage Bar#327

Merged
arul28 merged 1 commit into
mainfrom
ade/ade-usage-bar-e4a838fb
May 21, 2026
Merged

Ade Usage Bar#327
arul28 merged 1 commit into
mainfrom
ade/ade-usage-bar-e4a838fb

Conversation

@arul28
Copy link
Copy Markdown
Owner

@arul28 arul28 commented May 21, 2026

Summary

Describe the change.

What Changed

Key files and behaviors.

Validation

How you tested.

Risks

Anything to watch.

ADE   Open in ADE  ·  ade/ade-usage-bar-e4a838fb branch  ·  PR #327

Summary by CodeRabbit

Release Notes

  • Refactor

    • Improved usage snapshot fetching with better caching and automatic refresh on window focus
    • Enhanced usage percentage display and threshold-based visual indicators for better clarity
  • Tests

    • Expanded test coverage for usage tracking and quota components to ensure reliability

Review Change Stack

Greptile Summary

This PR upgrades the header usage bar from a single weekly-percent chip to a dual-window chip (5-hour + plan window), and replaces the startup-delay polling model with continuous 120s interval refreshes, focus-triggered refresh (when data is older than 60s), and serial-request deduplication to prevent stale cached reads from overwriting a fresher forced refresh.

  • HeaderUsageControl.tsx: New windowPercentFor / headerUsageFor helpers drive HeaderProviderUsageChip, which renders the 5h and plan (wk/mo) percentages with threshold colouring. The useEffect refresh logic gains snapshotRef-backed serial ordering, a window focus listener, and a setInterval — all cleaned up on unmount.
  • usage.test.tsx (replaces UsageQuotaPanel.test.tsx): Migrates existing UsageQuotaPanel tests and adds new HeaderUsageControl tests covering cold-start rendering, request-serial race protection, and interval polling with fake timers.

Confidence Score: 5/5

Safe to merge — all changed paths are UI display and polling logic with no data-mutation side-effects, and the new tests cover the trickiest race scenario.

The serial-request deduplication logic is well-reasoned and directly tested. Cleanup is complete (interval, focus listener, onUpdate subscription all removed on unmount). The only notable issue is a local variable named window that shadows the browser global — a lint-level naming concern with no runtime consequence.

No files require special attention.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx Major refactor: replaces a single weekly-percent chip with a dual 5h/plan-window chip, adds 120s polling + focus-refresh with serial-request deduplication, and removes the hasAnyChip loading guard. The race-deduplication logic (isLatestRequest / isInitialCachedSnapshot) is correct and covered by the new tests. One minor shadowing nit: the local window variable in windowPercentFor masks the global window.
apps/desktop/src/renderer/components/usage/usage.test.tsx Replaces the deleted UsageQuotaPanel.test.tsx with a combined test file covering both UsageQuotaPanel and HeaderUsageControl. New HeaderUsageControl tests verify cold-start rendering, request-serial ordering, and interval polling. Existing QuotaPanel tests are faithfully migrated.
apps/desktop/src/renderer/components/usage/UsageQuotaPanel.test.tsx File deleted; its tests were migrated verbatim into usage.test.tsx.
docs/features/onboarding-and-settings/README.md Documentation updated to reflect the new header-bar usage chip (5h + plan window, focus/interval refresh) and removal of the Usage Settings tab. Accurate to the implementation.

Sequence Diagram

sequenceDiagram
    participant C as Component (mount)
    participant B as usageBridge
    participant W as window events

    C->>B: onUpdate?.subscribe
    C->>B: getSnapshot() [serial 1, cached]
    C->>B: refresh() [serial 2, forced]
    Note over C: whichever resolves first wins<br/>(serial deduplication)
    B-->>C: snapshot (serial 2 latest → apply)
    B-->>C: snapshot (serial 1 stale → discard if ref≠null)

    W->>C: focus event
    C->>C: lastPolledAt ≥ 60s stale?
    C->>B: refresh() [force]

    loop every 120s
        C->>B: refresh() [force]
        B-->>C: snapshot (apply if latest serial)
    end

    C->>C: unmount / cleanup
    C->>W: removeEventListener focus
    C->>C: "clearInterval, cancelled=true"
    C->>B: unsubscribe()
Loading

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx:49-51
`window` shadows the global `window` object here. In browser code this is especially confusing since `window` is the top-level global; most ESLint configs flag this with `no-shadow`. Renaming the local to `win` or `entry` avoids the collision.

```suggestion
  const win = snapshot.windows.find((w) => w.provider === provider && w.windowType === windowType);
  if (!win) return null;
  return clampPercent(win.percentUsed);
```

Reviews (2): Last reviewed commit: "ship: prepare lane for review" | Re-trigger Greptile

@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview May 21, 2026 9:03pm

@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 21, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@arul28
Copy link
Copy Markdown
Owner Author

arul28 commented May 21, 2026

@copilot review but do not make fixes

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

Refactored HeaderUsageControl component's usage-per-provider computation with new helpers and unified snapshot derivation, consolidated fetch/polling effects using snapshotRef and applySnapshot, and updated drawer integration. Migrated test suite from UsageQuotaPanel.test.tsx to usage.test.tsx with fixtures and comprehensive behavior tests.

Changes

Header Usage Control Refactoring and Test Migration

Layer / File(s) Summary
Usage helpers and HeaderProviderUsageChip component
apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx
New percent-clamping and window-lookup helpers, headerUsageFor() to derive per-provider 5h and plan percentages/labels, and HeaderProviderUsageChip component with threshold-based coloring for rendering provider usage values.
Snapshot fetching and polling refactor
apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx
Replaced staged "delay-on-boot / hydrate-on-open" logic with snapshotRef + applySnapshot callback. Single effect loads cached snapshot, refreshes periodically, refreshes on focus when stale, and serializes concurrent reads. Separate provider status polling via ai.getStatus. Removed prior drawer-open refresh trigger.
UI data derivation and drawer wiring
apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx
providersWithUsage now computed via headerUsageFor(). Title parts derived from chip summary logic. Rendering condition changed from hasAnyChip to providersWithUsage.length. Header button chips directly map providersWithUsage to HeaderProviderUsageChip instances. UsageQuotaPanel receives applySnapshot callback instead of setSnapshot.
Test setup, fixtures, and mocking
apps/desktop/src/renderer/components/usage/usage.test.tsx
Test fixture factories for usage snapshots and provider/AI status objects. Utility deferred() for controlled async timing. Mocked window.ade.usage and window.ade.ai methods in beforeEach with cleanup in afterEach.
UsageQuotaPanel and HeaderUsageControl behavior tests
apps/desktop/src/renderer/components/usage/usage.test.tsx
UsageQuotaPanel tests verify meter rendering per provider, weekly/monthly window handling, auto-refresh on mount, manual refresh behavior, CLI detection and auth visibility rules, and absence of Cursor UI. HeaderUsageControl tests verify forced refresh on mount, stale-result prevention via deferred promises, and polling continuation while drawer closed via fake timers. Old UsageQuotaPanel.test.tsx removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • arul28/ADE#276: Implements the underlying usage panel and header usage control feature; this PR refactors and consolidates the polling/snapshot logic and test structure for the same components.

Suggested labels

desktop

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Ade Usage Bar' is vague and generic, using non-descriptive terms that don't clearly convey the specific changes made in this pull request. Consider using a more descriptive title that explains the primary change, such as 'Refactor HeaderUsageControl component with improved snapshot polling and UI rendering' or 'Add dedicated HeaderProviderUsageChip component and rework usage polling logic'.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ade/ade-usage-bar-e4a838fb

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI commented May 21, 2026

@copilot review but do not make fixes

Reviewed commit 3be022c with a review-only pass (no fixes applied as requested). I don’t see any new blocking issues in the usage bar/header usage changes.

Copilot finished work on behalf of arul28 May 21, 2026 20:59
Comment thread apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx
Comment thread apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review

Scope: 4 file(s), +507 / −323
Verdict: Minor issues

This PR surfaces 5-hour and weekly/monthly usage in the header, starts polling as soon as the app loads (cached snapshot + forced refresh), and keeps the header in sync with the drawer via applySnapshot. The main concern is extra main-process usage work on a timer that largely duplicates the existing background poller.


⚡ Performance

[Medium] Header timer duplicates background usage polling

File: apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx:L143-L174
Issue: The header now calls usage.refresh() on mount, every 120s, and on window focus when data is older than 60s. The main process already runs createUsageTrackingService with pollIntervalMs: 120_000 and pushes updates through onUpdate (see apps/desktop/src/main/main.ts:L3875-L3887). Each renderer refresh() maps to forceRefresh(), which invalidates the 60s cost-log cache and re-runs Claude/Codex polls.
Impact: Up to ~2× poll cadence when the header interval and the service timer align; focus churn can add more. inFlightPoll dedupes concurrent polls, but forceRefresh() still forces extra cost scans versus a cached getSnapshot()/onUpdate-only path.
Fix: Rely on onUpdate for steady-state header updates; call refresh() only for the initial cold-start path and user-driven stale cases (e.g. focus) with a longer stale threshold, or expose a cheap snapshot read that does not invalidate the cost cache.


🎨 UI/UX

[Low] Plan window label shows wk before weekly/monthly data exists

File: apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx:L65-L72
Issue: planLabel defaults to "wk" whenever a weekly window is absent, even if only the 5-hour window is present (both planPercent values null). The chip then reads wk …, which implies a weekly quota is loading rather than “no plan window for this provider.”
Fix: Use a neutral label (e.g. omit the plan segment or show plan …) when weeklyPercent and monthlyPercent are both null.

[Low] Header usage chips are denser and no longer collapse to the gauge while loading

File: apps/desktop/src/renderer/components/usage/HeaderUsageControl.tsx:L299-L303
Issue: Removing hasAnyChip means detected providers always render logo + 5h … + wk … chips (9px mono text) instead of the single gauge icon during the first poll. With two tracked providers this widens the top-bar control versus the prior one-percent chip.
Fix: Restore a gauge fallback until at least one of fiveHourPercent or planPercent is non-null, or truncate/hide the plan segment until data arrives.


Notes

  • Good fix: UsageQuotaPanel now uses onSnapshotChange={applySnapshot} so drawer updates keep snapshotRef aligned for focus-stale checks and race guards.
  • Tests cover the cached-vs-forced refresh race and the 120s interval; consolidated usage.test.tsx matches the new behavior.
  • Security: no new trust boundaries; data stays on local IPC from the usage service.
Open in Web View Automation 

Sent by Cursor Automation: BUGBOT in Versic

@arul28 arul28 force-pushed the ade/ade-usage-bar-e4a838fb branch from 3be022c to 898e8f8 Compare May 21, 2026 21:03
@arul28
Copy link
Copy Markdown
Owner Author

arul28 commented May 21, 2026

@copilot review but do not make fixes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants