feat(maps): live data layers — setLayerSource, glyph points and satellites in orbit - #44
Merged
Merged
Conversation
…nches and satellites
# Conflicts: # website/src/components/MapsWorkbench/LayersPanel.contourLabels.test.tsx # website/src/components/MapsWorkbench/LayersPanel.contourWindow.test.tsx # website/src/components/MapsWorkbench/LayersPanel.dockRows.test.tsx # website/src/components/MapsWorkbench/LayersPanel.glyphPalette.test.tsx # website/src/components/MapsWorkbench/LayersPanel.modelShape.test.tsx # website/src/components/MapsWorkbench/LayersPanel.osm.test.tsx # website/src/components/MapsWorkbench/LayersPanel.osmDensity.test.tsx # website/src/components/MapsWorkbench/LayersPanel.osmLabels.test.tsx # website/src/components/MapsWorkbench/LayersPanel.osmTooltips.test.tsx # website/src/components/MapsWorkbench/LayersPanel.renderMode.test.tsx # website/src/components/MapsWorkbench/LayersPanel.terrainWindow.test.tsx # website/src/components/MapsWorkbench/MapsWorkbench.tsx # website/src/components/MapsWorkbench/mapsKit.tsx # website/src/components/MapsWorkbench/mapsUrlState.layers.test.ts # website/src/components/MapsWorkbench/mapsUrlState.legacyLayerLink.test.ts # website/src/components/MapsWorkbench/mapsUrlState.ts
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.
A Live card on
/maps: earthquakes, disasters, launch sites and satellites, drawn as glyphs in the grid and refreshed on their own clocks.One new package primitive:
map.setLayerSource(id, source). Every layer was static once mounted, so a live feed had nowhere to go. The clock stays on the page, deliberately — arefreshMsoption counted inwidgetBusy()would makemap.idle()never resolve, and excluded from it would be stateidle()hides.setLayerSourcedispatches through the sametrackUpdatecounteraddLayeruses, soidle()keeps its exact meaning. It rejects the field-source kinds (raster,contour,background,model) with aRangeErrornaming the id.A third point layer,
type: "glyph".circleandsymbolare DOM by contract —textAnchoris a CSS percentage,radiusScalewritesstyle.width— so a mode flag on either would be two disjoint runtimes inside one interface. The new runtime is thelineruntime with a point where the polyline was: stamped through the same composedtransformCellshook, sharing the stroke's depth test (lifted into oneglyphMapSurfaceOccludesrather than copied), cell ownership across detail<pre>s, and the globe horizon. So a live feature is occluded by terrain, survives Copy ASCII and appears in an SVG export. The four live rows use it; every existingsymbol/circleconsumer is untouched.Size is a radius in cell rows, rasterised as a disc, each cell's glyph picked by its own coverage — one rule, no threshold. The ramp is
· • ●: one shape at three sizes, all centred in the cell, all present in the font atlas and in system monospace stacks.Satellites orbit at their real altitude. SGP4's altitude is a true-metre quantity like a building's height, so it is exempt from the terrain's exaggeration — at the page default the exempt answer is 8.6% of a radius and the un-exempt one is 207%, two radii past the far side. Limb occlusion needed no new code: the raised-point silhouette test already existed for extrusion walls, so a satellite round the back is correctly hidden while one just past the horizon still shows.
Earthquake labels are rationed by magnitude and recency —
mag + 1.5·exp(−ageHours/12)fed to the existing declutter arbiter as a priority, so labels thin smoothly as the view zooms out while every quake keeps its mark. The weight is checkable rather than magic: at 1.5 a fresh quake beats one up to 1.5 magnitudes larger from earlier in the week; at 2.0 an M4.1 from two hours ago outranks every M5.5 on the planet. Clicking a quake opens its USGS page — hit-tested against the marks the last render actually drew, inside the existing "did not drag" guard, with the URL's scheme checked beforewindow.open.A time window per row, which swaps the feed rather than filtering the payload. USGS publishes each window separately, so "last hour" is an 11 KB download, not a filtered 265 KB one. The magnitude floor rides with the window because it is the price of it —
all_monthis 7.8 MB and 10,988 events — so each button's tooltip names the floor it carries. Launch sites take the same control pointing forwards, wherenet__ltegenuinely shrinks the response. Disasters and satellites get no control: measured on a real capture, not one GDACS event began in the previous seven days, so every window a reader would pick empties the row, and a live position has no recency axis at all.Cadence follows the window and the publishers' measured limits — Launch Library allows 15 requests an hour and this uses one.
Failure degrades and says why. A failed refresh publishes nothing, so the previous frame stands with its count and a second line explains. Several of these services omit CORS headers on error responses, so a readable 429 reaches the browser as an opaque network failure; an unexplained failure is reported as probably rate limiting rather than silently blank.
fetchhas no timeout, so there is a 45 s deadline reported as its own failure.Also fixed along the way:
destroy()never disposed feature-kind runtimes, leaking every hotspot and both registry entries; a placement transform persisted across rebuilds so markers created afterwards never received it; and the OSM label-anchor toggle used bubble-phasepreventDefault, which React's root delegation runs after the event has already reached the<label>, so clicking a button flipped the row's own switch.