fix: show the sidebar progress bar on the five slowest tabs - #2114
Merged
Conversation
NavItem forwards ViewModelBase.IsBusy to the slim progress bar under a tab's name, which is the only sign -- while the user is on another tab -- that this one is working. Five view-models kept their own running flag and never assigned IsBusy, so their bar never appeared, and they are the slowest screens in the app: Speed Test (up to a minute), Traceroute (up to thirty hops), Network Repair (three netsh resets), About (an ~85 MB download) and DNS & Hosts. One generated hook each, copying the idiom DeepCleanupViewModel already uses, so the existing flag stays the single source of truth. Scope came from a corrected measurement. Looking for On...Changed hooks reported 16 unforwarded flags, which was wrong -- several tabs assign IsBusy inline in the command body, which is equally correct. Re-measured as "assigns IsBusy anywhere" the real list was three, plus two more once the flag pattern covered Running/Loading suffixes. Guarded by EveryViewModelThatTracksRunningState_ForwardsItToIsBusy, indifferent to HOW the assignment happens so the inline tabs keep passing, with the one non-tab match (AudioSessionRowViewModel.IsUserAdjusting, a slider drag) excluded with its reason. This also makes the README's progress-bar sentence true, which #2113 left standing on purpose rather than weakening it.
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.
Closes the behaviour half of #2108 — the one claim the docs PR (#2113) deliberately left in place, because weakening the sentence would have documented a gap instead of closing it.
What was wrong
NavItemforwardsViewModelBase.IsBusyto the slim progress bar under a tab's name in the sidebar. It is the only sign, while the user is looking at a different tab, that this one is still working.Five view-models kept their own running flag and never assigned
IsBusy, so their bar never appeared — and they are the slowest screens in the app:IsSpeedTestingIsTracingIsRepairingIsDownloadingIsDnsApplyingThe fix
One generated hook per view-model, copying the idiom
DeepCleanupViewModelalready uses:The existing flag stays the single source of truth — no second flag set alongside the first.
How the scope was decided, and a correction to my own first pass
My first measurement looked for
On…Changedhooks assigningIsBusyand reported 16 unforwarded flags. That was wrong: several tabs predate the hook idiom and assignIsBusyinline in the command body, which is equally correct. Re-measured as "does this view-model assignIsBusyanywhere at all", the real list was three, plus two more found by widening the flag pattern toRunning/Loadingsuffixes — the five above.The one remaining match is excluded with a reason:
AudioSessionRowViewModel.IsUserAdjustingis a row inside the Volume Control list with no sidebar entry to draw a bar under, and the flag means "the user is dragging this slider", not work in progress.The guard
EveryViewModelThatTracksRunningState_ForwardsItToIsBusy— a view-model declaring an[ObservableProperty] bool _is…ing/Running/Loadingmust assignIsBusysomewhere. Deliberately indifferent to how, so the tabs that set it inline keep passing. Vacuity floor at 12 (fourteen such view-models exist today), and the exclusion list carries its reason inline.Verification
Mutation proof, all five files restored byte-for-byte and re-hashed. Removing any one hook:
TrueException: a repair is running and the shell was never told— proving the generated hook actually fires, which a source-shape guard cannot showBaseline and post-restore green in both proofs. Regression sweep: 184 named tests across
ArchitectureTestsand the five tabs' test files — 213 cases green. The two reds in that run are aDisposemethod my name-extraction grep picked up and the harness-only author-header case for the throwaway runner.Builds 0 errors / 0 warnings (app + tests),
dotnet format --verify-no-changesclean on both, version consistency csproj 1.76.13 = CHANGELOG 1.76.13 = SECURITY 1.76.x.Not verified here: that the bar renders correctly on those five tabs. That needs the app running, which this machine does not do. The binding path is unchanged and shared with the 41 tabs already using it, so the risk is in the flag wiring — which is what the two proofs cover.