Skip to content

Promote dev → staging: drawer peek spacing, US state borders, DT indicator stability - #916

Merged
patrickrb merged 6 commits into
stagingfrom
dev
Sep 26, 2026
Merged

patrickrb merged 6 commits into
stagingfrom
dev

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Promotes the current dev into staging — three UI/behaviour fixes merged since the last promotion (#913, #914, #915).

What's in it

  • Collapsed controls drawer spacing (Even out the collapsed controls drawer's spacing #913) — the peek's 120.dp height was a flat constant that left 0 dp above the 72 dp Call CQ / Hunt row and 6 dp below it, so the buttons read as jammed onto the tab bar and the docked status line looked clipped by the sheet's rounded top edge. The peek height is now derived from its parts (handle + gap + the shared primary-row height + bottom padding → 10 dp above, 14 dp below, 10 dp under the status line), with unit-tested invariants so it can't clip the primary row or leak the row below. Handle strip 42 → 36 dp, and the "More controls" hint no longer bobs — a caption drifting against fixed buttons reads as uneven spacing rather than as an affordance.

  • US state borders on the standard map (Draw US state borders on the standard map view #914) — the state layer existed but sat behind a scale >= 3 zoom gate, and the map auto-frames a grid-holding operator at ~2.9, a hair under it, so the lines never appeared. Zoom was the wrong measure anyway: the map COVERs its card, so the same scale means very different detail in the flat map vs the azimuthal disc. Now gated on basemap density (longitude px per degree) with a 3 → 6 px/deg fade: on throughout the standard projection, still off on the azimuthal world disc, fading rather than snapping into existence on a pinch.

  • DT indicator stability (Stop the DT indicator jumping on a well-synced rig #915) — the clock-sync pill showed the raw per-slot mean decode DT, re-posted on every decode pass, so one station transmitting late (or a marginal deep-pass decode) could make a rig that was working stations perfectly announce "+2.5 s" in red. ClockSelfSync, which actually corrects the clock, has always used a median + MAD rejection + multi-slot confirmation, so the display and the correction openly disagreed. New DecodeDtDisplay puts the display on the same footing: MAD-rejected median per slot, passes accumulating into their slot instead of replacing the reading, median of the last 3 slots, a 0.05 s publish deadband, and a window reset when the clock is deliberately corrected. A genuine drift is still followed within ~2 slots.

Test plan

  • CI passes on staging
  • Collapsed drawer looks right on a real phone (emulator-verified only: clearance under the buttons 6.1 dp → 14.1 dp)
  • State lines visible on the Map tab at its default framing, and absent on the azimuthal world view
  • On the air: watch the DT pill over a few minutes of real decodes and pull debug.log — the new DT: raw=… shown=… n=… line per slot shows whether a wandering raw mean is being smoothed or a clock is genuinely drifting. This is the one change with no live-signal verification; the emulator decodes nothing and no rig was attached.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Lbd9brnZDMCzipgsu9n8Xg

patrickrb and others added 6 commits September 26, 2026 10:01
The collapsed peek looked cramped and lopsided. The 120.dp peek height was a
flat constant that happened to sit 6.dp past the bottom of the 72.dp Call CQ /
Hunt row, while the row itself butted straight against the 42.dp handle strip:
0.dp of padding above the buttons, 6.dp below, and the buttons effectively
jammed onto the tab bar. The status line above had no gap either, so the
sheet's rounded top edge read as clipping it.

- Derive OperateDrawerPeekHeight from its parts (handle + top gap + the shared
  OperatePrimaryRowHeight + bottom padding) instead of hard-coding it, so the
  peek can neither clip the primary row nor reveal the row below it when any of
  those change. Row spacing is now larger than the bottom padding, which is what
  keeps the next row hidden; both invariants are unit-tested.
- 10.dp above the primary row, 14.dp below it (was 0 / 6), and a 10.dp gap
  between the docked status line and the sheet's top edge.
- Shrink the handle strip 42 -> 36.dp and stop the "More controls" hint bobbing.
  A caption drifting up and down directly above fixed buttons reads as uneven
  spacing, not as an affordance; the up-chevron already says "pulls up".

Measured on an emulator (1080x2400, xhdpi): clearance under the Call CQ row
goes from 6.1.dp to 14.1.dp.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lbd9brnZDMCzipgsu9n8Xg
The Map redesign already loads us_states.json and strokes it, but behind a
`scale >= 3` zoom gate. That gate hides the layer in exactly the view a US
operator sees: with a grid set and no decodes yet, the map auto-frames the
operator at scale ~2.9 — a hair under the threshold — so the state lines
never appear.

Zoom was the wrong measure anyway. The map COVERs its card, so the same
`scale` means very different detail in the two projections: the standard map
spends ~6.3 px per degree of longitude at zoom 1 (the lower 48 are ~370 px
across — their borders read cleanly), while the azimuthal disc squeezes the
whole globe into the card at ~2.8 px per degree, where state outlines really
are noise.

Gate on that density instead, and fade rather than snap so a pinch doesn't
pop a whole layer into existence: stateBorderAlpha() ramps 0 -> 1 between 3
and 6 longitude px per degree, fed by EquirectViewport.pxPerLonDegree for the
standard map and azimuthalPxPerLonDegree() for the disc. Net effect: state
borders are on throughout the standard projection, still off on the azimuthal
world view, and the stroke stays a shade under the national borders so the
basemap hierarchy holds.

Verified on an emulator: state lines visible at the standard map's default
zoom (screenshot in the PR).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lbd9brnZDMCzipgsu9n8Xg
The clock-sync pill showed the raw arithmetic MEAN of a slot's decode DTs,
re-posted on every decode pass. On a rig working stations perfectly it would
announce "+2.5 s" and turn red, which reads as an unstable app.

Three separate reasons it did that:

- A mean has no defence against one bad decode. DT is per-station: a station
  transmitting late, or a marginal decode placed a couple of seconds off,
  carries its own large DT. Three good decodes at +0.1 s plus one at +7 s
  average to +1.8 s — a red "clock off" verdict produced entirely by somebody
  else's clock.
- Every pass re-posted. A slot is decoded several times (fast, then deep and
  late passes that dig out the weakest signals — exactly the ones with the
  sloppiest DT), so the number visibly jumped several times per slot.
- No slot-to-slot smoothing at all.

Meanwhile the estimator that actually corrects the clock (ClockSelfSync) has
always been robust — median, MAD rejection, multi-slot confirmation — so the
display and the correction openly disagreed: the pill flashed "clock off"
while auto-sync, reading the same decodes, correctly did nothing.

New DecodeDtDisplay puts the display on the same footing: MAD-rejected median
per slot, passes accumulating into their slot instead of replacing the
reading, the median of the last 3 slots, and a 0.05 s publish deadband so the
last digit stops twitching. A deliberate clock change (manual, GPS/NTP or
self-sync) drops the window so the reading re-acquires instead of averaging
across a correction. A real, sustained error is still followed within ~2 slots.

Also logs "DT: raw=... shown=... n=..." once per slot, so a debug.log shows
directly whether a wandering raw mean is being smoothed or a clock is
genuinely drifting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lbd9brnZDMCzipgsu9n8Xg
Even out the collapsed controls drawer's spacing
Draw US state borders on the standard map view
Stop the DT indicator jumping on a well-synced rig
@codecov

codecov Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 36.58537% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.51%. Comparing base (c603d1c) to head (0677e40).
⚠️ Report is 25 commits behind head on staging.

Files with missing lines Patch % Lines
...main/kotlin/radio/ks3ckc/ft8af/ui/map/MapScreen.kt 38.88% 11 Missing ⚠️
...s3ckc/ft8af/ui/components/OperateControlsDrawer.kt 42.85% 8 Missing ⚠️
...app/src/main/kotlin/radio/ks3ckc/ft8af/FT8AFApp.kt 0.00% 5 Missing ⚠️
...kotlin/radio/ks3ckc/ft8af/ui/components/TxStrip.kt 33.33% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##             staging     #916      +/-   ##
=============================================
+ Coverage      41.50%   41.51%   +0.01%     
  Complexity       252      252              
=============================================
  Files            280      280              
  Lines          33973    33993      +20     
  Branches        4033     4034       +1     
=============================================
+ Hits           14100    14112      +12     
- Misses         19584    19592       +8     
  Partials         289      289              
Flag Coverage Δ
android 17.63% <36.58%> (+0.04%) ⬆️
desktop 63.95% <ø> (ø)
ios 97.71% <ø> (ø)
native 9.93% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...tlin/radio/ks3ckc/ft8af/ui/components/ClockSync.kt 25.31% <ø> (ø)
...in/kotlin/radio/ks3ckc/ft8af/ui/map/MapViewport.kt 100.00% <100.00%> (ø)
...n/radio/ks3ckc/ft8af/ui/settings/TimeCorrection.kt 100.00% <ø> (ø)
...radio/ks3ckc/ft8af/ui/settings/TimeSyncSettings.kt 0.00% <ø> (ø)
...kotlin/radio/ks3ckc/ft8af/ui/components/TxStrip.kt 5.17% <33.33%> (+0.18%) ⬆️
...app/src/main/kotlin/radio/ks3ckc/ft8af/FT8AFApp.kt 0.37% <0.00%> (-0.01%) ⬇️
...s3ckc/ft8af/ui/components/OperateControlsDrawer.kt 7.53% <42.85%> (+3.36%) ⬆️
...main/kotlin/radio/ks3ckc/ft8af/ui/map/MapScreen.kt 7.79% <38.88%> (+0.32%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@patrickrb
patrickrb merged commit 9b37980 into staging Sep 26, 2026
38 checks passed
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.

1 participant