Surface GPX/FIT parse errors instead of silently rendering nothing
_addLayers handed MapLibre a URL and let it fetch the GeoJSON internally — a 422 (a file REXML/Fit can't parse) just meant the layer never appeared, with nothing telling the user why. It now fetches the file itself first, alerts with the actual error and un-checks the box on failure.
This commit is contained in:
1 parent
a0476f1204
commit
11fc14824e
2 files changed
+41
-7
No files matched your search
+34
-6
@@ -206,7 +206,7 @@ export class GpxPanelControl {
|
||||
const checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
checkbox.checked = this._visible.has(file.path);
|
||||
checkbox.addEventListener("change", () => this._toggleFile(file.path, checkbox.checked));
|
||||
checkbox.addEventListener("change", () => this._toggleFile(file.path, checkbox.checked, checkbox));
|
||||
const name = document.createElement("span");
|
||||
name.className = "gpx-tree__file-name";
|
||||
name.textContent = file.name;
|
||||
@@ -269,21 +269,48 @@ export class GpxPanelControl {
|
||||
});
|
||||
}
|
||||
|
||||
_toggleFile(path, visible) {
|
||||
async _toggleFile(path, visible, checkbox) {
|
||||
if (visible) {
|
||||
this._visible.add(path);
|
||||
this._addLayers(path);
|
||||
const ok = await this._addLayers(path);
|
||||
if (!ok) {
|
||||
// Loading failed (see _addLayers) — don't leave the box checked
|
||||
// for a file that isn't actually showing anything.
|
||||
this._visible.delete(path);
|
||||
if (checkbox) checkbox.checked = false;
|
||||
}
|
||||
} else {
|
||||
this._visible.delete(path);
|
||||
this._removeLayers(path);
|
||||
}
|
||||
}
|
||||
|
||||
_addLayers(path) {
|
||||
// Fetches the file's GeoJSON itself (rather than handing maplibre a URL
|
||||
// to fetch internally) so a parse failure — a real GPX a device/app
|
||||
// wrote in some way REXML doesn't like, say — surfaces as an alert
|
||||
// instead of the layer just silently never appearing. Returns whether it
|
||||
// succeeded.
|
||||
async _addLayers(path) {
|
||||
const id = sourceId(path);
|
||||
if (this._map.getSource(id)) return;
|
||||
if (this._map.getSource(id)) return true;
|
||||
|
||||
this._map.addSource(id, { type: "geojson", data: gpxFileUrl(path) });
|
||||
let geojson;
|
||||
try {
|
||||
const response = await fetch(gpxFileUrl(path));
|
||||
if (!response.ok) {
|
||||
const { error } = await response.json().catch(() => ({}));
|
||||
window.alert(error || `Could not load "${path}".`);
|
||||
return false;
|
||||
}
|
||||
geojson = await response.json();
|
||||
} catch (err) {
|
||||
window.alert(`Could not load "${path}": ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._map.getSource(id)) return true; // added concurrently (e.g. a style.load race) while this was fetching
|
||||
|
||||
this._map.addSource(id, { type: "geojson", data: geojson });
|
||||
this._map.addLayer({
|
||||
id: `${id}-line`,
|
||||
type: "line",
|
||||
@@ -307,6 +334,7 @@ export class GpxPanelControl {
|
||||
|
||||
this._registerPointInteractivity(`${id}-points`);
|
||||
this._registerLineInteractivity(`${id}-line`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Registered once per layer id, ever — map.on(type, layerId, fn) is a
|
||||
|
||||
Reference in new issue
Block a user