Commit Graph
3806 Commits
Author SHA1 Message Date
Sameh Khamis 134239fa5a Read a view over an incomplete GeoParquet index as PARTIAL
The browser's partition index kept whether it was complete only to
schedule a rebuild and handed the partitions on without it, so a view
counted unread partitions from an index that might be missing some and
could read as complete, even empty, over an area it had never indexed.
A view over an incomplete index now reads PARTIAL until a rebuild
completes.
2026-11-12 15:51:52 -08:00
Sameh Khamis e05a9566e4 Retry a GeoParquet footer whose body fails mid-stream
Only a failed fetch() marked a footer read as worth retrying. A body cut
off after its headers arrived (a reset, the proxy's 20-second timeout)
was taken for an unparseable file: the partition was left out and the
index still read as complete, so the server cached it without that
partition for the entry's cacheSeconds (24 hours for EPC). Such a read
is now retried like any fetch failure; an oversized body is still final.
2026-11-12 15:50:46 -08:00
Sameh Khamis 7d91a1875b Cancel a view-bounded load when the camera returns to the drawn view
Moving from view A to B started B's request; moving back to A before it
finished returned early because A was already drawn, so B's request ran
on and its features replaced A's while the camera was at A. Returning to
the drawn view now cancels the request in between.
2026-11-12 15:49:56 -08:00
Sameh Khamis 0f13c0a1c2 Let a newer share switch off a library layer still switching on
A share restore skipped every entry whose settled state already matched
the share, but a layer still switching on for an earlier share reads as
off until it settles. Opening a second share in that window left the
first share's layer to come on anyway. The restore now compares with the
manager's effective visibility (the newest request), so the newer share
supersedes the earlier one.
2026-11-12 15:49:11 -08:00
Sameh Khamis d58ba23fba Refresh live Data Library datasets once older than cacheSeconds
A dataset layer loaded its features once and kept them until it was
removed: the parsed set survives disable/enable, so NWS alerts, GDACS and
EONET showed what they held when first switched on for the whole session.

A library dataset now asks the manager for a refresh every cacheSeconds.
Once its data is that old it loads again, and swaps the new set in only
when it is ready, so the old features stay drawn while the request runs
and stay if it fails. An enable after cacheSeconds also loads afresh.
Disable and destroy cancel a refresh in flight.
2026-11-12 15:48:14 -08:00
Said Turksever 1a2589d4ef Port the Data Library Browse dialog to Vue and Pinia
The dialog is now DataLibraryDialog.vue (with DataLibraryCard.vue for each
entry), placed with the Browse button by DataLibraryBrowse.vue in
LayerPanelsView and teleported to the body. It renders what the
gev-data-library store holds and sends clicks and typing to the owner.

src/ui/libraryBrowser.js is now the framework-free owner: it presents the
open state, filters, the rows they show, the stat summary and Remove all
through `publish`, and its controls answer the view. Its text helpers are
what the view renders with t(), so every label follows the locale without
rebuilding anything. Only showModal/close and focus moves stay imperative;
focus returns to Browse also when the browser closes the dialog on Escape
itself.

Component tests mount the view over the real owner (open, filters, Add to
Remove keeping focus, Zoom, Remove all, a language switch, clean view).
2026-11-12 23:01:00 +00:00
Said Turksever 24ccdd4dc3 Fix Data Library share restore, dense tile layers and EPC partition reads
- Share links: the compact /share/<code> format carries the switched-on
  library entries (field 29), so Copy Link keeps them; a share opened in the
  same tab restores them; any share decides what is on, so one with every
  library entry off no longer switches on the recipient's stored entries.
- A tile entry too dense at its minimum zoom (Norway cadastre z14, depth z11)
  is hidden below that scale via minimumTerrainLevel instead of allocating
  millions of tiles when zoomed out.
- EPC partitions keep the full extent for exclusion and the 98 % extent for
  ranking only; the old trimmed-only extents are retired.
- Partition index footers that fail transiently are retried; an incomplete
  index is never cached as complete, a complete prior index is kept, and it
  is rebuilt after five minutes.
- Views that leave touching partitions unread are partial; listing and
  footer bodies are capped and ranges validated.
- The Browse dialog relabels after a language switch.
2026-11-12 22:37:34 +00:00
Said Turksever 871b7f0fcc Remove Data Library entries whose licence or provider links are broken
A link check of every manifest found 404 licence or provider pages for
OpenSeaMap seamarks, EMODnet bathymetry and the PDOK, basemap.at, Geneva
SITG, ICGC Catalunya, Luxembourg and Vlaanderen aerial photos, and no
answer from the SEDAC GPW, Minnesota and Bangor hosts. Drop those 11
entries, renumber the unpublished share-token ledger, point the tests at
remaining entries and regenerate DATA_SOURCES.md.
2026-11-12 17:05:21 +00:00
Denis Groshev 0584292405 fix(cockpit): a train handed to another feed's copy keeps its selection time, so it never takes entry back on its own; snapshot stops are copied again when a provider updates its list in place; setCockpitSubject's return is documented as it is 2026-11-12 17:22:55 +01:00
Denis Groshev 09f3380203 docs(cockpit): a held train stays the copy drawn, the read APIs and their exports are experimental, and leaving a view does not track an earlier aircraft again 2026-11-12 17:02:37 +01:00
Denis Groshev c24352ff5e fix(cockpit): an application subject keeps its rates on a slow update interval, its ground lift eases out, and its HUD shows a speed and a progress name only when given
An application subject's camera step is now capped at its own update
interval plus 0.1 s rather than at 0.1 s, so at 500 ms its heading slew,
ground lift and anchor correction run at their configured rates; a long
stall still moves it no further than one late update. The built-in
views keep their 0.1 s cap.

When groundClamp turns false the lift the floor gave goes at the rate
it came, not at once. A HUD view with no speed has no speed readout,
and a progress line with no summary is hidden from assistive
technology instead of being an unnamed image.
2026-11-12 17:00:12 +01:00
Denis Groshev feaf59776c fix(rail): focusTrain refuses a train the layer does not draw
A ride let go with restore focuses its train again. When the train's
category was turned off during the ride, or for a copy another feed draws,
focusTrain selected and followed a train with no marker. It now returns
false for a train in a category turned off or hidden as another feed's
copy, and leaves the selection and the camera as they are.
2026-11-12 17:00:12 +01:00
Denis Groshev 4ae67fcb35 fix(rail): a held train stays the copy drawn of its train and keeps moving, hidden, when its category is turned off
The duplicate filter hid a held copy when another feed's copy outranked it
and moved the selection away, so the held train stopped playing and the
other copy's marker and card came back over the view. A copy a first-person
view holds is now drawn whatever the scores until the view lets go; the
better copy takes over at the next poll after the release. Holding a copy
that another feed drew draws it at once.

A category toggle no longer deselects a held train, and a held train keeps
playing, its marker hidden, while its category is off. Released, it is
deselected and stops as the toggle leaves any other train.
2026-11-12 17:00:12 +01:00
Denis Groshev fe7590d66a docs(application): a provider's subject takes entry when selected after every built-in subject, whose fixed order is unchanged 2026-11-12 16:59:18 +01:00
Denis Groshev 557fe7169a docs(application): the locale and rail path exports and the Rail and Transit read APIs are experimental
Says so where the cockpit subject section names them, together with
path.line, and that a snapshot read again while nothing changed is the one
read before, so a provider may read one on every update.
2026-11-12 16:58:39 +01:00
Denis Groshev a17346be6f fix(rail): a train snapshot's path.line is a frozen copy of its line, not the layer's own path
The copy keeps the path's fields with its number arrays as frozen arrays,
so pointAtS and projectOnPath read it as they read the path and nothing
written to it reaches the layer. It is built once per line and shared by
every snapshot on that line, so reading it on every frame costs nothing.
2026-11-12 16:58:39 +01:00
Denis Groshev 294ccc0ee8 perf(cockpit): a Rail or Transit snapshot read again while nothing in it changed is the one read before
getSelectedTrain, getSelectedVehicle and getCockpitSubject fill drafts and
freeze a new object only for a part whose values changed, so a view that
reads them on every frame builds nothing while the train or vehicle stands
still, and a moving one keeps its feed, stop and provenance objects. A
train's stops are copied once per list the stops provider returns, each
stop a frozen copy, instead of on every call.
2026-11-12 16:58:38 +01:00
Denis Groshev a4f321a9ef fix(cockpit): entry to the built-in views is as before: aircraft, satellite and vessel keep their fixed order whenever each was selected, and an application's subject takes entry only when it was selected after every built-in one present, so without providers nothing changes 2026-11-12 16:58:38 +01:00
Denis Groshev 6fbc98952f fix(cockpit): a provider's methods keep their this, a hold answers true or false, and a cut text never splits a surrogate pair
Provider methods and worded members are called on the provider itself,
so a class-based provider works. A hold that answers false refuses entry
and is released; any answer but true or false refuses it too, released,
with one warning. An answer whose `then` getter throws is handled as a
throw, and a text cut at its cap never leaves half an emoji.
2026-11-12 16:58:38 +01:00
Said TurkseverandMaher Kurdi 11706a68cb Add Amsterdam traffic and ANPR camera positions to the Data Library
The City of Amsterdam's verkeersinformatiesystemen register lists where
its ~500 traffic and ANPR cameras stand, with type and asset number, but
publishes no pictures. That fits a Data Library dataset better than a
CCTV pack: the register answers GeoJSON in WGS84 with CORS headers, so
the entry fetches it browser-direct with no proxy code.

The register names no licence ("public unless stated otherwise"), so the
entry stays operator opt-in, as #251 had it. The dataset and the
position-only camera idea come from @Maher-Reven's #251, which this
replaces; the entry lists them as maintainer and in its attribution.

Co-authored-by: Maher Kurdi <[email protected]>
2026-11-12 12:26:45 +00:00
Said Turksever db80d82b8d Add the Data Library: live regional datasets, tiles and packs
DATA LAYERS keeps its curated core layers; regional and niche sources
live in the Data Library, opened from Browse data library at the foot
of the panel. Each entry is a JSON manifest in src/library/entries/
pointing at a live upstream (query API, provider-hosted file or tile
endpoint), so nothing is bundled and a self-hosted instance hosts no
data. Sources without CORS go through one allowlisted /api/library
route. Kinds: dataset (GeoJSON, CSV, JSON records, ArcGIS, partitioned
GeoParquet), tiles (XYZ, WMS/ArcGIS bbox export, terrarium relief) and
pack. Selections persist and travel in share links as lib=, separate
from the core layer tokens. Library rows get Zoom and Remove icon
chips that work while the layer is off, rendered through RailChips.
Strings are translated in every locale.
2026-11-12 12:26:45 +00:00
Denis Groshev 4c33552105 fix(cockpit): an application subject's wait for the floor is bounded, a late asynchronous hold is released, and a hold never counts as the user's selection
- A subject with no height at all waits at most
  COCKPIT_GROUND_WAIT_TIMEOUT_MS for the floor, its HUD updating and
  reading ACQUIRING SURFACE; then the view ends and the provider gets its
  subject back (there is no height of its own to fall back to).
- A hold that returns a promise is refused as before and released again
  once it settles, unless that subject is being ridden by then; release
  must tolerate a second call.
- Rail and Transit stamp selectedAtMs only for a user's selection (a click,
  focusTrain or focusVehicle); a deselection clears it, and a train or
  vehicle selected only by a hold reads null.
2026-11-12 12:31:04 +01:00
Denis Groshev 1e4060f6ba docs(changelog): add the #1686 fragment 2026-11-12 11:36:31 +01:00
Denis Groshev 57d87d2bbf fix(cockpit): application subjects follow a change of language, never stand on the ellipsoid, and are guarded on every call; a re-selected subject takes entry again
- Labels, entry face and look may be functions, read again on every use
  and on a locale change; a failing read keeps the last good value.
- A frame with no height keeps the eye's last height, or waits
  (surfaceAcquiring) until the floor is known; heights outside
  -1,000..50,000 m read as null.
- Provider methods are synchronous: a returned promise is refused like a
  throw, and a hold that fails is released.
- A candidate may carry selectedAt; Rail and Transit stamp selectedAtMs
  on every selection, so re-selecting moves a subject to the front.
- A released Transit vehicle leaves the visible set at once.
- docs/CURRENT-STATE.md states the new entry order; docs/APPLICATION.md
  documents cockpit subjects, ./i18n/locale and ./layers/rail/paths.
2026-11-12 11:13:58 +01:00
Denis Groshev 01a74fceec fix(cockpit): an application subject's eye eases off the floor instead of jumping: its anchor is no longer clamped to the floor, and the eye's clearance above it changes at most 1.5 m/s (easeCockpitLift) 2026-11-12 10:50:27 +01:00
Denis Groshev f75179eea0 feat(cockpit): an application can add its own cockpit subjects; the Rail and Transit layers expose the read and hold APIs such a subject needs
GEV itself registers no new subject: with no provider, the Cockpit offers
aircraft, satellites and vessels as before, except that the most recently
selected of them now wins entry.

- services.cockpitSubjects: providers ({kind, layerId, entryFace, priority,
  isEntryAllowed, read, hold, release, hud}) are checked once by the
  coordinator; frames and HUD views on every update; a throwing provider
  ends its view or keeps the last HUD.
- Entry: the most recently selected subject wins, across all kinds.
- Camera: a frame may turn the ground clamp off, anchor exactly on the
  subject and update every frame.
- A generic HUD: kicker, title, cards, always-visible source rows, banner,
  a veil with light streaks (off under reduced motion) and a bottom
  progress line whose close ticks merge.
- Text comes from the provider, already in the page's language
  (./i18n/locale: getLocale, onLocaleChange).
- Rail and Transit read and hold APIs (getSelectedTrain/Vehicle,
  getCockpitSubject, setCockpitSubject, focusTrain/Vehicle); a held
  train's marker, card and route line are hidden, and its feed keeps
  polling while held.
- ./layers/rail/paths is exported.
2026-11-12 10:50:26 +01:00
Sameh Khamis 10a788db78 Merge pull request #1683 from bilawalsidhu/sameh/news-cards-every-height
fix(news): an application's picture cards stay at every height
2026-11-11 19:52:44 -08:00
Sameh Khamis a105e819e0 fix(news): an application's picture cards stay at every height
Zoomed out, a hotspot's reports give way to its beacon, and the cards an application draws through pictureCards went with them; they came back only once the camera had stopped after zooming in. The cards now come from every report the close-up view would mark, at any height; the layer's own markers and beacons are unchanged.
2026-11-11 19:43:06 -08:00
Sameh Khamis 202cb8c3dc Merge pull request #1677 from ZloyS/denis/news-world-clock
feat(news): the News layer reads its time from the world clock
2026-11-11 15:28:35 -08:00
Sameh Khamis 2b1784d7ed Merge remote-tracking branch 'upstream/main' into denis/news-world-clock 2026-11-11 15:17:44 -08:00
Sameh Khamis beeb29f0fa Merge pull request #1675 from ZloyS/denis/rail-layer
feat(rail): add a Rail layer with keyless live trains
2026-11-11 15:07:54 -08:00
Sameh Khamis b7015f8819 Merge remote-tracking branch 'upstream/main' into denis/news-world-clock
# Conflicts:
#	docs/CURRENT-STATE.md
#	src/app/constructCatalog.js
2026-11-11 15:03:45 -08:00
Sameh Khamis 283890cee0 fix(rail): trip-update delays are as old as the server's read
The browser stamped every trip-updates answer as just read. While an
operator's feed fails, the rail proxy replays its last good copy for up to
ten minutes, and a cached copy can be a TTL old, so those delays never
reached RAIL_UPDATES_MAX_AGE_MS and a selected train's card showed them as
current. Delays now take their age from the snapshot's fetchedAt (capped
at now), as positions do in ingestion.js, so they stop applying 75 s after
the server last read the operator.
2026-11-11 14:57:02 -08:00
Sameh Khamis ace2160002 fix(rail): Montpellier tram speeds are converted from km/h
TaM publishes km/h where GTFS-Realtime asks m/s, and the Transit layer's
entry for the same feed already sets speedUnit: 'km/h'. The Rail entry did
not, so the proxy passed the readings through and the card multiplied them
by 3.6 again: a tram at 30 km/h read about 108 km/h. A registry test now
requires a Rail feed that Transit also reads to declare the same unit.
2026-11-11 14:54:01 -08:00
Sameh Khamis 0f18c03041 chore(news): credit the #1677 changelog fragment 2026-11-11 14:48:05 -08:00
Denis Groshev 9b3ca481ce Merge upstream main into denis/rail-layer 2026-11-11 23:23:58 +01:00
Sameh Khamis 632da1cebd Merge pull request #1680 from bilawalsidhu/sameh/news-host-cards
feat(news): an application may draw the News picture cards itself
2026-11-11 14:01:22 -08:00
Sameh Khamis 99a1e06b61 feat(news): an application may draw the News picture cards itself
createNewsLayer takes a pictureCards(cards, { selectedId }) function; createApplicationCatalog passes it through newsOptions. With it, the layer paints no picture cards of its own and hands the function one card per pictured event on the map, most severe then newest first, with the selected report's id; it hands no cards when the layer turns off.
2026-11-11 13:53:10 -08:00
German Khokhlov c19495644d Merge pull request #1509 from quanticsoul4772/upstream/route-outage-unavailable
fix(routes): report an upstream routing outage as unavailable
2026-11-11 23:14:47 +04:00
Kevin Rajan ca58e113c0 test(routes): cover HTML 502 outage in MCP plan_route (#1509)
Preserve quanticsoul4772's routing-outage fix and add a focused voice-facing regression for a non-JSON gateway response.
2026-11-11 09:44:24 -08:00
German Khokhlov 94ff78be3b refactor(routes): inline the single-use 502 responder
The outage branch is the only caller, so it writes its 502 directly.
Same status, headers and body.
2026-11-11 21:23:35 +04:00
German Khokhlov 82e2b716bc docs(routes): tighten the outage comments and notes
Shorter comments, changelog and CURRENT-STATE text for the 502 outage
path; the CURRENT-STATE paragraph now also names the 429 exception and
which budget expiry answers busy and which answers 502. Text only.
2026-11-11 21:21:07 +04:00
German Khokhlov a29611ca17 Merge branch 'main' into upstream/route-outage-unavailable 2026-11-11 21:16:50 +04:00
Denis Groshev 72c24a86d1 chore(news): name the changelog fragment for #1677 2026-11-11 18:06:15 +01:00
Denis Groshev 13818d0b9f Merge upstream main into denis/rail-layer 2026-11-11 18:02:52 +01:00
Denis Groshev 44d2c0695c feat(news): the News layer reads its time from the world clock
Core's catalog passes worldClock.timeFor('news') as the layer's now, so a host that follows the clock for News can show a past time's reports with their ages, window and counts as they were then. Core does not follow the clock for the layer, so it keeps reading the wall clock.
2026-11-11 18:00:24 +01:00
German Khokhlov aa95c2c25f Merge pull request #1531 from quanticsoul4772/upstream/firms-age-rounding
fix(fires): show a 47.6-hour-old detection as 2d, not 48h
2026-11-11 20:24:53 +04:00
German Khokhlov 1c08482fa8 Merge branch 'main' into upstream/firms-age-rounding 2026-11-11 20:14:57 +04:00
German Khokhlov 98b642869e Merge pull request #1113 from asturksever/pr/street-level-show-action
feat(street-level): "show me X on Street View" — assistant action, view field and share link
2026-11-11 19:13:30 +04:00
Denis Groshev d793406aef docs(changelog): add the #1675 fragment 2026-11-11 16:08:24 +01:00