bluerobotics / bluerobotics/cockpit
Offline tiles downloaded before v1.19.0-beta.1 are silently ignored (cache key includes the full tile URL)
- Dominant language
- TypeScript
- Stars
- 198
- Forks
- 63
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 57
Description
## Problem
A user downloaded offline map tiles ahead of a mission and found them missing in the field. The tiles are still in IndexedDB — they are just no longer reachable.
## Cause
`leaflet.offline` keys each stored tile by its fully resolved URL, built from the layer's URL template (`node_modules/leaflet.offline/src/TileLayerOffline.ts`):
```ts
_getStorageKey(coords) {
return getTileUrl(this._url, { ...coords, ...this.options, s: this.options.subdomains['0'] });
}
```
So any change to a provider's URL template invalidates every tile previously downloaded from it. That happened in 856b29c9b3 ("map: integrate procedural-noise fallback into base maps", first released in `v1.19.0-beta.1`), which appended a query parameter to the Esri World Imagery template:
```diff
-'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
+'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}?blankTile=false',
```
The parameter is needed for the network request (it makes ArcGIS return 404 instead of a placeholder image, which drives the noise fallback), but it does not need to be part of the storage key. Every satellite tile downloaded on <= 1.18 became a cache miss on update, with no warning and no way to tell from the UI.
## Suggested fix
Normalize the storage key so it ignores the query string, and fall back to the legacy key on lookup so tiles already downloaded under either scheme keep working. Provider URL tweaks should not be able to strand a user's downloads.
## Related, same symptom
Which base layer the map opens on, and where, is profile-scoped: `cockpit-user-last-map-tile-provider`, `cockpit-user-last-map-center` and `cockpit-user-last-map-zoom` are all `useBlueOsStorage` keys read once at setup (`src/components/widgets/Map.vue:302-303`, `src/composables/map/useMapTileLayerSelection.ts:45-51`). Connecting to a different vehicle can therefore bring the map up on a layer or an area that was never downloaded, which is indistinguishable from a lost cache. The tile cache itself is not profile-scoped and is never wiped by a profile switch.
Worth considering whether the map should indicate that the current view has no cached coverage, rather than showing empty tiles.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in node_modules/leaflet.offline/src/TileLayerOffline.ts and trace how tile storage keys are generated and looked up. Check the map setup references in src/components/widgets/Map.vue:302-303 and src/composables/map/useMapTileLayerSelection.ts:45-51 to understand the related profile-scoped state. Done means tiles downloaded with both the current and legacy URL forms remain reachable after provider URL changes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100