mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 21:31:46 +00:00
fix(pwa): persist offline storage + Mapbox offline policy (H8, H9) (#1184)
H8: prefetched tiles and file blobs could be evicted under storage pressure (worsened by opaque tile responses inflating the quota ~7MB each), blanking the offline map right when a traveler needs it. Request persistent storage at app init so the browser exempts our caches from eviction. We deliberately keep tile requests no-cors (a cors switch would break self-hosted/custom tile providers without CORS headers), so persistence is the safe mitigation rather than de-opaquing responses. H9: Mapbox GL users had no offline map at all — no runtimeCaching matched the Mapbox hosts. Add a StaleWhileRevalidate rule for api.mapbox.com / *.tiles.mapbox.com so visited areas are available offline (best-effort; full pre-download still requires the Leaflet renderer, now documented). - new sync/persistentStorage.ts requestPersistentStorage(), called from main.tsx - vite.config: mapbox-tiles SW cache rule - MapViewAuto / tilePrefetcher comments document the offline-maps policy - tests for the persist helper (granted / already-persisted / absent / rejects)
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Ask the browser for persistent storage so our offline data — prefetched map
|
||||
* tiles, cached file blobs, the IndexedDB caches — is exempt from eviction under
|
||||
* storage pressure. Without this the browser may purge tiles right when a
|
||||
* traveler goes offline and needs them (audit H8 / M6).
|
||||
*
|
||||
* Best-effort and idempotent: returns whether persistence is (now) granted.
|
||||
*/
|
||||
export async function requestPersistentStorage(): Promise<boolean> {
|
||||
try {
|
||||
if (typeof navigator === 'undefined' || !navigator.storage?.persist) return false
|
||||
// Already persisted? Avoid re-prompting where the API distinguishes.
|
||||
if (navigator.storage.persisted && (await navigator.storage.persisted())) return true
|
||||
return await navigator.storage.persist()
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -189,8 +189,11 @@ export async function prefetchTilesForTrip(
|
||||
// their lower zooms cached instead of being skipped entirely.
|
||||
//
|
||||
// NOTE: opaque (no-cors) tile responses are padded by Chromium to ~7 MB each
|
||||
// for quota accounting, so the real on-disk budget is far below 180 MB. That
|
||||
// (audit H8) and navigator.storage.persist() (M6) are tracked separately.
|
||||
// for quota accounting, so the real on-disk budget is far below 180 MB. We
|
||||
// keep no-cors deliberately: switching to cors would break self-hosted/custom
|
||||
// tile providers that don't send CORS headers. To stop the browser evicting
|
||||
// these tiles under the inflated quota, we request persistent storage at app
|
||||
// init instead (sync/persistentStorage.ts).
|
||||
const fetched = await prefetchTiles(bbox, template)
|
||||
|
||||
// Update syncMeta with bbox and tile count
|
||||
|
||||
Reference in New Issue
Block a user