Skip to content

Deep Timeline x-axis labels, with the fine ticks kept off the Today card - #2520

Merged
ryanbr merged 3 commits into
mainfrom
timeline-xaxis-2445
Sep 27, 2026
Merged

ryanbr merged 3 commits into
mainfrom
timeline-xaxis-2445

Conversation

@ryanbr

@ryanbr ryanbr commented Sep 27, 2026

Copy link
Copy Markdown
Owner

Summary

Stacked on @andigandhi's #2445. Both of their commits are preserved with their authorship and messages unchanged.

Their change gives the Deep Timeline x-axis labels and per-minute ticks at deep zoom, on Android and Apple, with the tick positions shared between the platforms and the gridlines and label strip driven from one tick list so they cannot drift. The Android half also pins three new tiers in ChartTimeTicksTest.

The follow-up commit

chartTimeTicks is shared with the Today HR card. The Deep Timeline hands it a pinch-zoom window, but Today hands it visBuckets.first().bucket … visBuckets.last().bucket, the RENDERED extent of banked buckets rather than a nominal window. So tiers below an hour reached Today too: a morning holding ten minutes of HR drew ten 1-minute dotted gridlines on a small card. Labels are thinned by an overlap skip, the gridlines are not. The sub-hour tiers now sit behind deepZoom, off by default and set only by the surface that zooms, which also makes the retained comment about thresholds sitting below the nominal Today windows true again.

Swift keys that on zoomBounds, not zoomDomain, for the reason OverviewHRChart already records twice: zoomBounds is set once by the zooming call sites, while zoomDomain stays nil until the first pinch, so keying on it would hand a not-yet-zoomed Deep Timeline the static tiers and then switch them under the user (#829).

The Swift function formatted labels nothing read. xTicks discarded every one of them with .map { $0.date }, while the function built a fresh DateFormatter per call. xTicks is read inside body, so during a pinch that is a formatter construction plus N string formats per frame, all thrown away. It now returns dates and formats nothing, and its doc no longer claims the platforms read identically: positions are shared, labels are not, since Swift draws them with AxisValueLabel() in the viewer's locale where Kotlin formats HH:mm itself.

Also worth stating plainly for whoever reads this later: because OverviewHRChart is shared, this PR changes the Today HR card's Apple axis from .automatic(desiredCount: 5) to round wall-clock ticks. That is a deliberate keep, since Android's Today card already ticks this way, so it closes a platform difference rather than opening one.

Verification

  • ./gradlew :app:testFullDebugUnitTest --no-build-cache --rerun-tasks: 760 suites, 6479 tests, 0 failures, 0 errors. ChartTimeTicksTest is 13 of 13.
  • python3 Tools/doc_comment_lint.py: no new detached doc comments.
  • ChartTimeTicksTests is new on the Swift side, pinning all eight tiers, the Today guarantee and an inverted window. Eight thresholds written twice in two languages drift, and a drift is invisible in a build. It runs on the test (StrandDesign) leg.

Refs #575

andigandhi and others added 3 commits September 27, 2026 19:36
chartTimeTicks is shared. The Deep Timeline passes its pinch-zoom window, but
Today's HR card passes the RENDERED extent of its banked buckets rather than a
nominal window, so adding tiers below an hour reached Today as well: a morning
holding ten minutes of HR drew ten 1-minute dotted gridlines on a small card.
Labels are thinned by an overlap skip; the gridlines are not.

The sub-hour tiers now sit behind deepZoom, off by default and set only by the
surface that actually zooms. That also makes the retained comment true again,
the one about thresholds sitting below the nominal Today windows so a window
covering slightly less than nominal still lands on its intended interval.

Swift keys that on zoomBounds rather than zoomDomain, for the reason
OverviewHRChart already records twice: zoomBounds is set once by the zooming
call sites, while zoomDomain stays nil until the first pinch, so keying on it
would hand a not-yet-zoomed Deep Timeline the static tiers and then switch them
under the user (#829).

The Swift function now returns dates and no longer builds a DateFormatter per
call. Every label it formatted was discarded by the caller's map, once per body
evaluation, which during a pinch is once per frame. Its doc no longer claims the
two platforms read identically: positions are shared, labels are not, because
Swift draws them with AxisValueLabel() in the viewer's locale where the Kotlin
side formats HH:mm itself.

Tests: the three deep-zoom tiers now pass the flag, and both platforms pin the
Today guarantee. ChartTimeTicksTests is new, because eight thresholds written
twice in two languages drift, and a drift between them is invisible in a build.
@ryanbr
ryanbr merged commit 1e8ef1e into main Sep 27, 2026
17 checks passed
@ryanbr
ryanbr deleted the timeline-xaxis-2445 branch September 27, 2026 06:54
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