You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(basemaps): make the basemap control's Mapbox styles load (#1488)
* fix(basemaps): make the basemap control's Mapbox styles load
Every Mapbox basemap in the basemap control produced
`name: unknown property "name"` and a blank map.
The control applies a Mapbox style correctly — it passes MapLibre a
`transformStyle` that rewrites the `mapbox://` sprite/glyphs/source URLs
and swaps Mapbox's `projection: { name }` for the spec's `{ type }`, plus
`validate: false`. But GeoLibre is store-driven: the change is written to
`basemapStyleUrl` and MapController re-applies it with a plain
`map.setStyle(url)`, which drops both. MapLibre's validator then rejects
`projection.name`, and `Style._load` returns on the first validation
error, so the whole style is abandoned. The three styles with no
`projection` block (satellite-v9, navigation-day/night-v1) passed
validation but still rendered empty, since nothing resolves `mapbox://`.
Teach GeoLibre's own style path about Mapbox instead of relying on the
control's: `mapbox-style.ts` fetches the descriptor and converts it, and
MapController applies the result. That also covers the paths the control
is not part of — a project reopened with a Mapbox basemap, and a
split-view pane, both of which build a MapController straight from the
saved URL. The token comes back out of the URL's `access_token`
parameter, so no credential plumbing is needed to *apply* a style and a
saved project stays self-contained. A generation counter drops a
descriptor whose basemap the user has already switched away from.
Also wire `MAPBOX_TOKEN` / `VITE_MAPBOX_ACCESS_TOKEN` through to the
control's `mapboxAccessToken`, matching the bare→prefixed bridge the
Google Maps and Cesium keys use, so the panel's API-keys field is
pre-filled instead of demanding a paste. Pushed only when set, like the
other panel-enterable providers.
Verified in the browser against all of Streets/Satellite in single and
split view: sprite, fonts, TileJSON and tiles all 200, zero console
errors, and non-Mapbox styles still switch cleanly afterwards.
* Address CodeRabbit review feedback
- Don't wedge the controller when the Mapbox descriptor fetch fails.
setStyle tore down styleReady/paint values/the layer control up front,
but the Mapbox path only reaches map.setStyle after an async fetch — a
rejection left no style.load coming to rebuild any of it, so layer
syncing, basemap visibility/opacity and the layer control stayed dead
over a still-rendered old style. Teardown now happens in beginStyleSwap
immediately before each map.setStyle, so a failed fetch changes nothing.
Verified by routing the descriptor to a 500: the previous style keeps
rendering, all six control groups survive, and the next basemap switch
applies normally.
- Don't log the token-bearing style URL. The URL carries the user's
access_token, so the failure warning now logs a redacted descriptor id
via redactMapboxStyleUrl (origin + path, no query), covered by tests.
- Test that the access_token is trimmed when the query string pads it.
- Test that transformMapboxStyle leaves the nested source URL alone, not
just the top-level sprite/projection — an in-place rewrite would have
passed the old assertions.
- Document the prefixed-over-bare precedence on getMapboxAccessToken. A
Settings entry overrides a baked token under the same VITE_ name; the
bare MAPBOX_TOKEN is a fallback for when nothing was baked in, not an
override. The docstring implied otherwise.
* Address CodeRabbit review feedback
- Abort a superseded Mapbox descriptor request. The generation counter
already kept a stale style from being applied, but the fetch itself
kept running; a rapid run of basemap changes (or a request that never
settles) left several in flight, each holding a controller closure
alive. applyStyleToMap now keeps an AbortController for the active
load, aborts it when starting a newer generation and from destroy(),
and passes its signal to loadMapboxStyle — which already accepted one,
so this also retires a parameter that was left unwired.
An abort rejects with AbortError, but only ever on a generation that
has already been superseded (abort follows the ++ in applyStyleToMap,
and destroy() nulls the map first), so both handlers return before the
warning — a cancelled request is never reported as a failure.
* Cover the Mapbox descriptor abort with tests
93fe1aa wired an AbortController into applyStyleToMap but left the
behavior untested. Adds three cases against a stub map and a fetch that
never settles on its own:
- a newer Mapbox basemap aborts the request it supersedes, and the abort
rejection produces no failed-style console warning,
- a switch to a plain (non-Mapbox) style URL aborts the pending request
too, and applies synchronously without a second fetch,
- destroy() aborts a request still in flight.
0 commit comments