Skip to content

refactor(map): consolidate overlay style lifecycle - #493

Merged
Medformatik merged 1 commit into
mainfrom
refactor/map-style-sync-cleanup
Oct 17, 2026
Merged

Medformatik merged 1 commit into
mainfrom
refactor/map-style-sync-cleanup

Conversation

@Medformatik

@Medformatik Medformatik commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

What changed and why

Follow-up to fix(map): install layers without waiting for source tiles. That fix was correct, but it moved about 20 overlays onto subscribeStyleLoaded, which called getStyle() (a full serialization of the style) on every styledata event, for every subscriber. It also left a lot of hand-written lifecycle code in place. This PR consolidates map layer lifecycles on shared primitives.

  • Hot paths. subscribeStyleLoaded checks whether the stylesheet is parsed once per stylesheet, and invalidates on styledataloading. Layer ordering (addLayerInSlot and anchorMapLayers) and map label localization now read getLayersOrder() and getLayer() instead of copying the whole style.

  • useMapLayerGroup / applyGroup.

    • Paint, layout, filter and zoom-range changes update the live layer in place, so recolouring or refiltering no longer drops its tiles and blinks.
    • Asynchronous image loaders start once per style instead of on every render.
    • Reconciliation pauses while a replacement stylesheet is parsing.
    • EMPTY_FEATURE_COLLECTION gives sources fed by the GeoJSON data bridge a stable placeholder.
  • Teardown.

    • removeSlottedLayers replaces removeLayerAndSource and about 20 hand-written remove/unregister blocks, and keeps sources that another layer still reads.
    • useSlottedLayersCleanup removes an imperative overlay's layers when it unmounts. Before, they were left on the map when an integration was switched off.
  • Migrations to useMapLayerGroup:

    • environment, natural events, weather alerts, earthquakes, airports, wildfires, hiking shelters, road conditions, MOTIS transit, live transit, sun time, measurement, travel time;
    • the app layers saved places, vehicle live, transit route, transit itinerary and selected-stop infrastructure.

    Raster acquisition, basemap-vector, WebGL and basemap-relative layers stay imperative on subscribeStyleLoaded. The three standalone mini-maps share useStandaloneMap. The integration docs now explain how to choose between these primitives.

  • Guards.

    • The slot-uniqueness scan now also reads group descriptors. Most migrated layers were invisible to it before. It found 13 ties that already existed on main, resolved by giving the colliding layers distinct orders. Half-step orders keep each layer next to the one it used to tie with.
    • A new static test rejects isStyleLoaded(), idle waits and raw styledata listeners in integrations.
  • Fixes that fall out of this.

    • A changed minZoom or colour now reaches the installed layer.
    • The earthquake heatmap no longer stays missing when it was enabled while the style was loading.
    • Airports send one request when shown instead of two.
    • Live vehicles and transit layers no longer flicker on each update.
    • The transit route no longer re-frames the camera on a theme change.
    • The radar sync only writes opacity that changed.
    • Nautical charts follow the viewport without firing synthetic styledata events.

Verification

Checks recorded during the original PR:

Validated locally:

lint (0 errors), full type checks, and the full Vitest suite in the pre-push hook. Three independent read-only reviews found no high-confidence regressions. All checks used the fake test map; nothing has been verified in a browser against real MapLibre style swaps.

Release and upgrade impact

Shared map-layer lifecycle refactor. Imperative raster/vector/WebGL paths keep their stated boundaries. Real-browser MapLibre style-swap verification was not performed.

@Medformatik Medformatik added enhancement integration New or changed provider, source or backend integration labels Oct 17, 2026
@Medformatik Medformatik self-assigned this Oct 17, 2026
Overlays now reconcile through one declarative layer group or a cached
style subscription instead of hand-written styledata listeners.

- subscribeStyleLoaded probes the parsed style once per stylesheet;
  layer ordering and label localization read layers directly instead of
  serializing the whole style after every mutation.
- applyGroup updates paint, layout, filter and zoom range in place,
  starts asynchronous image loads once per style, and useMapLayerGroup
  skips passes while a replacement stylesheet is parsing.
- removeSlottedLayers and useSlottedLayersCleanup replace hand-written
  teardowns; imperative overlays now remove their layers on unmount.
- Most overlays and several app layers move to useMapLayerGroup; the
  standalone mini-maps share useStandaloneMap.
- The slot uniqueness scan now reads group descriptors and found
  pre-existing ties, resolved with distinct orders.
@Medformatik
Medformatik force-pushed the refactor/map-style-sync-cleanup branch from bc533f8 to f616c66 Compare October 17, 2026 06:49
@Medformatik
Medformatik merged commit 159f760 into main Oct 17, 2026
21 checks passed
@Medformatik
Medformatik deleted the refactor/map-style-sync-cleanup branch October 17, 2026 07:00
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 17, 2026
@Medformatik Medformatik added documentation Documentation content, tooling or workspace dependencies and removed enhancement labels Oct 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

documentation Documentation content, tooling or workspace dependencies integration New or changed provider, source or backend integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant