Repository navigation
fix(today): say what the heart-rate read returned, not why - #2749
Merged
Merged
Conversation
The Today HR card's empty state opened "Calibrating" and asserted "no heart
rate banked yet today", then offered "your curve fills in as the strap
offloads". None of that is established on that branch. The only thing the
card knows is that the active-strap-plus-imports union came back with fewer
than two 5-minute buckets for the window. It does not know whether a strap is
calibrating, whether it has offloaded, or whether rows are banked under a
source the union cannot reach, and naming an unchecked cause sends a reader
looking in the wrong place.
The same line also fired on a day holding exactly one bucket, where "no heart
rate" is simply false.
So the state now splits in two and describes the stored rows:
0 buckets No heart rate stored for today yet. The curve draws once the
strap offloads, or once an import brings one in.
1 bucket Only one five-minute block of heart rate is stored for today.
The curve needs two of them to draw a line.
Both platforms, all nine locales. The split reads the DAY's bucket count
rather than the windowed subset, because both lines speak about today: a
narrow rolling window that happens to exclude the one stored block must not
make the card claim the day holds nothing.
Android's selection is extracted into a pure hrEmptyMessageRes so it can be
pinned without a Compose host; Apple's is hoisted into hrEmptyTitle and
hrEmptyDetail rather than nested as ternaries, since TodayView already sits
near the type-check budget. HrEmptyMessageTest covers all six selections and
carries source tripwires for the Apple twin, the retired resource key and the
call site, none of which a JVM test can otherwise reach.
Refs #863
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.
The problem
The Today heart-rate card's empty state said:
The branch that renders it checks one thing: whether the active-strap-plus-imports union came back with fewer than two 5-minute buckets for the window. It does not know whether a strap is calibrating. It does not know whether a strap has offloaded. It does not know whether rows are banked under a source the union cannot reach. It asserted all three.
That matters because the card is the first thing a reader consults when a curve is missing, and naming an unchecked cause sends them to the strap when the answer may be somewhere else entirely.
The same line also fired on a day holding exactly one bucket, where "no heart rate" is simply false.
The change
The state splits in two and describes the stored rows:
The past-day and narrow-window lines are unchanged.
The split reads the day's bucket count, never the windowed subset, because both new lines speak about today. A rolling 1h window that happens to exclude the one stored block must not make the card claim the day holds nothing, which would be the same over-claim in a new place. That rule has its own test.
Android's selection is extracted into a pure
hrEmptyMessageRes(isToday, windowIsWholeDay, dayBucketCount)so it can be pinned without a Compose host. Apple's lives inhrEmptyTitle/hrEmptyDetail, hoisted out of the view body rather than nested as ternaries, sinceTodayViewalready sits near the type-check budget.Localisation
today_hr_calibratingis replaced bytoday_hr_none_todayandtoday_hr_one_blockacross the default resources and all eight Android locale files, so nothing is left behind to trip ExtraTranslation. Four new keys land inStrand/Resources/Localizable.xcstringswith all nine non-English locales filled, inserted in place rather than through a rewrite, so the catalog diff is 232 added lines and nothing touched.Verification
:app:compileFullDebugKotlinand:app:compileFullDebugUnitTestKotlincleanHrEmptyMessageTest, six cases: the past-day line regardless of count, the 0 and 1 cases, the window case, and the two that pin the day-count rule against a narrow windowTools/doc_comment_lint.pycleanTools/i18n_audit.py --ci origin/mainclean, with no new focus-locale gaps on either platformWhat this does not do
It does not make the card able to tell a strap that has never offloaded apart from rows banked where the union cannot see them. That needs a diagnostic the card does not have, and inventing one here would repeat the mistake. What it does is stop the card from guessing.
Refs #863