feat(menubar): mark badge when a paired device is unreachable in combined scope - #867
Conversation
…ined scope Under combined scope the badge falls back to the local figure whenever a paired device doesn't report (asleep / off-network), which read as a glitch. Append a dimmed "reachable/total" marker (e.g. "$95.94 /mo · 1/2") and a matching tooltip so the reduced total is legibly "peer unreachable" instead. The marker clears the instant every paired device reports again. Adds AppStore.menubarBadgeDeviceShortfall plus tests.
iamtoruk
left a comment
There was a problem hiding this comment.
Follow-up to #866 (now merged), and the diff reduces cleanly to just the indicator commit. menubarBadgeDeviceShortfall returns (reachable, total) only when combined scope is active and fewer paired devices reported than are paired — it reads menubarBadgeCombined (nil under local scope), so it is correctly silent on local scope and single-device setups, and clears the instant every peer reports again. That turns #866's graceful drop-to-local into a legible reachable/total marker instead of a number that mysteriously shrank.
On the merged tree: swift test 130 tests + all XCTest suites at 0 failures, including the two new shortfall cases (unreachable peer → marker; all reachable → no marker). Small, self-contained, and correct. Good to merge.
…he all-provider view buildDurablePeriod derived the today slice of the multi-day, all-provider headline from the unsliced whole-range parse, so a turn spanning local midnight kept its category and turn count anchored on its yesterday start. The per-call cost and calls bucketed onto today correctly, but By Activity and the JSON daily turn count lost the post-midnight half — categories summed to only the pre-midnight cost while the headline, By Model and By Project were right. Slice the today parse with filterProjectsByDays first, which re-anchors the straddling turn to its surviving today calls, so today's category cost lands on today. Category cost is the sum of the slice's own calls, so day-N + day-N+1 still equals the whole-range total (no over-count); the per-day turn-count split matches the cache side and the documented per-day semantics. Adds a regression test in the straddling-turn conservation suite (mutation-checked: fails on the pre-fix code). Also fills in the CHANGELOG Unreleased entries for the batch (#853, #856, #872, #846/#859, #866/#867, #833).
Summary
Follow-up to #866. Under Combined scope the menu bar badge falls back to the
local figure whenever a paired device doesn't report (asleep / off the
network) — which reads as a glitch ("it dropped back to local for a second").
This adds a small, dimmed
reachable/totalmarker to the badge, plus amatching tooltip, so a degraded total is legibly "a peer is unreachable"
rather than a number that mysteriously shrank.
Example badge:
🔥 $95.94 /mo · 1/2— tooltip: "CodeBurn month · 1 of 2devices reporting". The marker clears the instant every paired device reports
again.
What changed
AppStore.menubarBadgeDeviceShortfall—(reachable, total)only whenCombined scope is active and fewer paired devices reported than are
paired;
nilotherwise (all reported, single device, or Local scope).shortfall is present.
/ Local scope → no marker).
Stacked on #866
Note
This branch is stacked on top of #866 (the combined-scope fix), since the
indicator depends on the combined badge payload introduced there. Until #866
merges, this PR's diff also includes #866's commit; once #866 lands on
main, the diff reduces to just the indicator commit. Merge #866 first.Testing
swift buildclean; newAppStoreshortfall tests added (run under theXcode toolchain:
swift test).