Trey T d6fb73db2c Live tab: stable refresh loop, replace dead Type filter with Altitude
Two reported bugs:

1) Bottom bar appeared to be constantly refreshing. Cause:
   .task(id: refreshTick) restarted every time isLoading flipped
   (twice per refresh cycle) AND every time aircraft.count changed.
   On top of that, on-pan refresh fired on every map camera settlement
   — including the micro-settlements that happen when annotations
   re-render after each fetch. The cumulative effect looked like a
   tight loop.

   Replaced the cascade with a single long-lived .task running a
   while-loop that sleeps refreshInterval then refreshes. SwiftUI
   cancels it when the view disappears. Added a bbox-delta gate
   (refreshIfRegionChanged) so pan-triggered refreshes only fire
   when the visible center moved >15% of the box width or the zoom
   changed >20%. Removed nextFetchAllowedAt — the throttle is now
   structural rather than time-based.

2) Tapping the "Type" filter did nothing. Cause: OpenSky's anonymous
   tier returns the ADS-B emitter category as null/0 for the vast
   majority of aircraft, so cachedCategoryItems was empty and the
   menu opened with no rows. Replaced the Type filter with an
   Altitude filter (below 10k / 10–25k / 25–40k / above 40k ft),
   driven by data we always have (baroAltitude / geoAltitude). The
   menu always has 4 rows with live counts.

Also: tightened boundingBox(of:) to return a labeled tuple so the
delta-gate code can use .latMin / .lonMax directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 07:01:54 -05:00
2026-04-08 15:01:07 -05:00
2026-04-08 15:01:07 -05:00
2026-04-08 15:01:07 -05:00
S
Description
No description provided
9.7 MiB
Languages
Swift 57.9%
HTML 33.9%
JavaScript 4.5%
Python 3.5%
Shell 0.2%