refactor(usage): extract the usage-percent widgets onto a shared module - #545
Open
zachthedev wants to merge 1 commit into
Open
zachthedev wants to merge 1 commit into
zachthedev wants to merge 1 commit into
Conversation
zachthedev
force-pushed
the
refactor-usage-percent-widgets
branch
from
August 14, 2026 23:03
c568271 to
b275047
Compare
zachthedev
force-pushed
the
refactor-usage-percent-widgets
branch
2 times, most recently
from
September 3, 2026 15:21
d7b870f to
ee44c7d
Compare
SessionUsage, WeeklyUsage, WeeklySonnetUsage, WeeklyOpusUsage and FableWeeklyUsage carried five copies of one render body. Normalized for the per-widget names, the worst pair differed by three lines and two pairs were identical. Each file is now delegation, following the speed-widget.tsx and InputSpeed.ts pair. Six axes vary and are parameterized: label, preview percent, usage field, window resolver, display name and description. Default color, category, editor display, editor actions, keybinds and the three supports* flags were already uniform. The resolvers dispatch at call time rather than through a captured reference, because the widget tests spy them on the utils/usage namespace and a module-level table would bind before the spy is installed. FableWeeklyUsage's label was the one of the five that disagreed with its own display name, so 'Fable Weekly: ' becomes 'Weekly Fable: ', matching the sibling rule of display name minus ' Usage'. Raw mode prints no label and is unaffected. The widget type, class name and display name are untouched. ExtraUsageUtilization stays out: it gates on a tri-state enabled flag, has no window resolver, no time cursor and a different default color. The shared suite gains a whole-percent case. formatPercent's format argument is optional and its default reproduces the baseline, so a render path that stopped passing the resolved format rendered identically under default settings and no test could see it.
zachthedev
force-pushed
the
refactor-usage-percent-widgets
branch
from
September 4, 2026 13:58
ee44c7d to
b001d9c
Compare
zachthedev
marked this pull request as ready for review
September 4, 2026 13:58
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.
Now that #456 has merged this is a single standalone commit against
main.The extraction sits on top of that PR's
formatPercent(value, format)threadingrather than colliding with it, which is why it was sequenced this way.
Five widgets carried five copies of one render body:
SessionUsage.ts,WeeklyUsage.ts,WeeklySonnetUsage.ts,WeeklyOpusUsage.tsandFableWeeklyUsage.ts. Normalized for the per-widget names,SessionUsageandWeeklyUsageare identical, so areWeeklySonnetUsageandWeeklyOpusUsage,and the worst pair differs by three lines. Net -225 lines.
Each file is now delegation, following the existing
shared/speed-widget.tsxandInputSpeed.tspair.Six axes vary and are parameterized: label, preview percent, usage data field,
window resolver, display name, description. Default color, category, editor
display,
handleEditorAction, keybinds and the threesupports*flags werealready uniform across all five, so they live in the shared module outright.
None of the five declares
getHideableStatesorrenderEditor.One rendered string changes.
FableWeeklyUsage's label was the only one ofthe five that disagreed with its own display name:
Session UsageSession:Weekly UsageWeekly:Weekly Sonnet UsageWeekly Sonnet:Weekly Opus UsageWeekly Opus:Weekly Fable UsageFable Weekly:It becomes
Weekly Fable:, matching the sibling rule of display name minusUsage. Raw mode prints no label, so raw output is unchanged, as are the widgettype
fable-weekly-usage, the class name and the display name. Six assertions inFableWeeklyUsage.test.tsmove with it; no other assertion in the repo changed.Two things worth a look:
five test files spy their resolver on the
utils/usagenamespace. Amodule-level config table holding
resolveWeeklyOpusUsageWindowwould bind atmodule evaluation, before
beforeEachinstalls the spy, and silently bypassit.
SessionUsagealso needs a second argument (context.blockMetrics) thatthe four weekly resolvers ignore, so the parameter takes the whole context.
ExtraUsageUtilizationstays out. It gates on a tri-stateextraUsageEnabledwith its ownn/abranch, has no window resolver, no timecursor, an extra keybind and a different default color. Folding it in would mean
three optional flags that are uniformly absent from the five. It is also the one
usage widget that does not use
runUsagePercentWidgetSuite.The shared suite gains a whole-percent case, which is the one test addition
beyond the label.
formatPercent'sformatargument is optional and its defaultreproduces the baseline output, so a render path that stopped passing the
resolved format rendered identically under default settings and nothing could
catch it. Dropping the argument at all three call sites now fails all five
widgets.
Tested:
bun run lintclean;bun test1900 pass, plus theglobal-command-resolutionfailuremainalready has on this host and one hit ofthe flaky
fetchUsageDatacase.