Skip to content

Add single-provider display mode for widget - #1

Open
Jachaganhio wants to merge 3 commits into
dependentsign:masterfrom
Jachaganhio:feature/single-provider-widget
Open

Jachaganhio wants to merge 3 commits into
dependentsign:masterfrom
Jachaganhio:feature/single-provider-widget

Conversation

@Jachaganhio

@Jachaganhio Jachaganhio commented Sep 10, 2026

Copy link
Copy Markdown

Summary

Turning off Claude or Codex now hides that provider entirely instead of showing a "Disabled" placeholder. The remaining provider takes the full widget width and shows reset times in every widget size, including small.

  • UsageSnapshot.visibleProviders filters out disabled providers (both models unchanged otherwise)
  • UsageDashboardView renders a full-width single column when only one provider is visible; both providers still render exactly as before when both are enabled
  • Both-off state shows a hint instead of a blank widget; the in-app dashboard mirrors this and refuses to save with both off
  • New Xcode previews (claude-only / codex-only) and a regression test (testDisabledProviderIsHiddenInsteadOfShownAsDisabled)
  • README / README_CN document the new mode

Why

If you only have a Claude subscription (no Codex), the widget previously wasted half its space on a "Codex · Disabled" block. This makes a disabled provider disappear completely so the widget space goes to the provider you actually use.

Compatibility

The two-provider layout is unchanged — verified by existing tests plus a new one asserting visibleProviders still returns both entries, in order, when both are enabled. No changes to the network/parsing layer.

Verification

Claude-only widget on my own account (Codex disabled), full width with reset countdowns showing in every row:

Claude-only widget

swift test (13/13 pass) and xcodebuild (Debug, macOS) both succeed.

🤖 Generated with Claude Code

Summary by Sourcery

Support single-provider configurations by hiding disabled providers and expanding the remaining provider throughout the widget and dashboard.

New Features:

  • Add single-provider widget mode that hides disabled providers and expands the remaining provider across the available width.
  • Show reset countdowns for the active provider in every widget size, including small widgets.
  • Provide an in-app empty-state hint and prevent saving a configuration with both providers disabled.

Bug Fixes:

  • Remove misleading disabled-provider placeholders and unnecessary layout space when a provider is turned off.
  • Avoid requesting disabled providers while preserving visibility of enabled providers with errors.

Enhancements:

  • Keep the existing two-provider layout unchanged while sharing provider visibility behavior between the widget and in-app dashboard.

Documentation:

  • Document single-provider configuration and behavior in the English and Chinese README files.

Tests:

  • Add coverage for both-provider, Claude-only, Codex-only, both-disabled, and errored-provider visibility states.

Chores:

  • Add Claude-only and Codex-only widget previews and generated layout preview states.

Jachaganhio and others added 2 commits September 10, 2026 10:57
Turning off Claude or Codex now hides that provider entirely instead
of showing a "Disabled" placeholder. The remaining provider takes the
full widget width and shows reset times in every widget size,
including small.

- UsageSnapshot.visibleProviders filters disabled providers
- UsageDashboardView renders a full-width single column when only one
  provider is visible; both-off state shows a hint instead of blank
- In-app dashboard mirrors widget behavior; Save refuses both-off
- New previews and regression test for the disabled/hidden behavior
- README / README_CN document the new mode

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Shows the Claude-only widget (Codex disabled) with reset times
visible in every metric row, confirming the full-width single-column
layout described in the README.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 10, 2026 04:53
@sourcery-ai

sourcery-ai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR adds single-provider display mode by filtering disabled providers from shared snapshots, rendering the remaining provider at full width with reset times in all widget sizes, handling the both-disabled state in the UI and configuration flow, and covering the behavior with tests, previews, and documentation.

Sequence diagram for provider configuration and usage loading

sequenceDiagram
    actor User
    participant Dashboard as ContentView
    participant Config as Configuration
    participant Widget as UsageDashboardView
    participant Provider as UsageProvider

    User->>Dashboard: Toggle provider visibility
    Dashboard->>Dashboard: saveConfig()
    alt Both providers disabled
        Dashboard-->>User: Reject save with status message
    else At least one provider enabled
        Dashboard->>Config: Save enabled-provider settings
        Widget->>Provider: Request enabled provider usage
        Widget->>Widget: visibleProviders
        Widget-->>User: Render enabled provider(s)
    end
Loading

Flow diagram for single-provider widget rendering

flowchart TD
    Snapshot[UsageSnapshot] --> Visible[visibleProviders filters disabled providers]
    Visible --> Count{Visible provider count}
    Count -->|0| Hint[Show turn-on-provider hint]
    Count -->|1| Full[Render one provider full width]
    Count -->|2| Existing[Render existing two-provider layout]
    Full --> Reset[Show reset times in every widget size]
Loading

File-Level Changes

Change Details Files
Introduces provider filtering and single-provider layout behavior across widget and in-app dashboard surfaces.
  • Adds visibleProviders while preserving Claude/Codex ordering and both-enabled behavior.
  • Hides disabled providers, removes the disabled placeholder, and expands a solo provider to full width.
  • Shows reset times for solo providers in every widget size and provides a both-hidden hint.
Shared/UsageModels.swift
Shared/UsageViews.swift
ClaudeUsageWidget/ContentView.swift
Prevents invalid both-disabled configuration and adds coverage for provider visibility states.
  • Rejects saves when both provider toggles are off.
  • Tests both-enabled ordering, Claude-only, Codex-only, both-off, and errored-provider visibility.
ClaudeUsageWidget/ContentView.swift
Tests/UsageCoreTests/UsageCoreTests.swift
Adds visual validation and documents single-provider mode for users and maintainers.
  • Adds Claude-only and Codex-only Xcode previews and rendered layout states.
  • Documents configuration, layout, reset-time behavior, and disabled-provider request semantics in English and Chinese README files.
ClaudeUsageWidgetExtension/ClaudeUsageWidget.swift
scripts/RenderPreviews.swift
README.md
README_CN.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The changes are cohesive and covered by tests/docs, with only minor performance nits (redundant computed-array recomputation) called out in review comments.

Pull request overview

This PR adds a single-provider display mode for the widget and in-app dashboard by hiding disabled providers (instead of showing a “Disabled” placeholder), expanding the remaining provider to full width, and ensuring reset times appear when a single provider is shown.

Changes:

  • Introduce UsageSnapshot.visibleProviders to filter out disabled providers and drive UI rendering.
  • Update widget/in-app layouts to support full-width single-provider rendering plus a both-off “turn one on” hint.
  • Add regression coverage, new previews, and documentation updates (EN/CN) for the new configuration behavior.
File summaries
File Description
Tests/UsageCoreTests/UsageCoreTests.swift Adds a regression test for filtering/hiding disabled providers and preserving order.
Shared/UsageViews.swift Reworks dashboard layout to render 0/1/2 visible providers appropriately (including solo reset times).
Shared/UsageModels.swift Makes ProviderUsage Identifiable and adds UsageSnapshot.visibleProviders for shared visibility logic.
scripts/RenderPreviews.swift Extends preview rendering to include claude-only/codex-only states and updates the count output.
README.md Documents single-provider mode behavior/config and updates preview generation notes.
README_CN.md Mirrors the single-provider documentation updates in Chinese.
ClaudeUsageWidgetExtension/ClaudeUsageWidget.swift Adds medium widget previews for claude-only/codex-only states.
ClaudeUsageWidget/ContentView.swift Mirrors widget visibility behavior in-app and prevents saving config with both providers disabled.
Review details
  • Files reviewed: 8/9 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +37 to +46
if snapshot.visibleProviders.isEmpty {
Text("Both providers are hidden. Turn one on below to fill the widget.")
.font(.caption).foregroundStyle(.secondary)
Spacer()
} else {
ForEach(snapshot.visibleProviders) { usage in
if usage.id != snapshot.visibleProviders.first?.id { Divider() }
ProviderUsageView(usage: usage)
}
}
Comment thread Shared/UsageViews.swift
Comment on lines +154 to +157
ForEach(providers) { usage in
if usage.id != providers.first?.id { Divider() }
ProviderUsageView(usage: usage, compact: compact, showReset: showReset)
}
The refactor to ForEach-based provider rendering passed showReset:
false for the medium two-column layout. The original code passed no
argument there, so it used ProviderUsageView's default of true — the
medium widget has always shown reset countdowns with both providers
enabled, as the README states.

The result was a medium widget whose rows collapsed into the top half
with no countdowns and a large empty area below. Single-provider and
small/large layouts were unaffected; verified against renders from
master.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Jachaganhio

Copy link
Copy Markdown
Author

Follow-up fix pushed (4ecddaf).

While testing the built widget I hit a regression I introduced in this PR: the refactor from hand-written provider columns to a ForEach helper passed showReset: false for the medium two-column layout. The original code passed no argument there, so it inherited ProviderUsageView's default of true — medium has always shown reset countdowns with both providers enabled, as the README states.

The visible effect was a medium widget whose rows collapsed into the top half with no countdowns and a large empty area below.

Verified by rendering scripts/RenderPreviews.swift from master and comparing against this branch: medium/small/large with both providers now match the baseline, and the single-provider layouts are unchanged. My earlier "renders exactly as before" claim in the description was based on renders of the modified code only, without a master baseline to compare against — that was the gap.

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