mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 14:21:46 +00:00
fix: prevent splash-forever on slow first-load after clearing storage
Three changes: - tripSyncManager: add interrupt() so trip page load can stop competing background bundle sync requests; also try clearing blobCache before falling back to full clearAll() on QuotaExceededError - TripPlannerPage: call tripSyncManager.interrupt() when mounting so loadTrip gets network priority over background syncAll - TripPlannerPage: show a 'go back to dashboard' link after 12 seconds on the splash screen so users are never stuck with no escape
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
upsertCategories,
|
||||
upsertSyncMeta,
|
||||
clearTripData,
|
||||
clearBlobCache,
|
||||
clearAll,
|
||||
} from '../db/offlineDb'
|
||||
import { prefetchTilesForTrip } from './tilePrefetcher'
|
||||
@@ -135,6 +136,7 @@ async function cacheFilesForTrip(files: TripFile[]): Promise<void> {
|
||||
// ── Public API ────────────────────────────────────────────────────────────────
|
||||
|
||||
let _syncing = false
|
||||
let _interrupted = false
|
||||
|
||||
export const tripSyncManager = {
|
||||
/**
|
||||
@@ -145,6 +147,7 @@ export const tripSyncManager = {
|
||||
async syncAll(): Promise<void> {
|
||||
if (_syncing || !navigator.onLine) return
|
||||
_syncing = true
|
||||
_interrupted = false
|
||||
try {
|
||||
const { trips } = await tripsApi.list() as { trips: Trip[] }
|
||||
|
||||
@@ -152,9 +155,10 @@ export const tripSyncManager = {
|
||||
const stale = trips.filter(isStale)
|
||||
await Promise.all(stale.map(t => clearTripData(t.id).catch(console.error)))
|
||||
|
||||
// Sync eligible trips
|
||||
// Sync eligible trips — stop early if interrupted (e.g. user navigated to a trip page)
|
||||
const toSync = trips.filter(shouldCache)
|
||||
for (const trip of toSync) {
|
||||
if (_interrupted) break
|
||||
try {
|
||||
await syncTrip(trip.id)
|
||||
} catch (err) {
|
||||
@@ -165,11 +169,19 @@ export const tripSyncManager = {
|
||||
await syncTrip(trip.id)
|
||||
} catch (retryErr) {
|
||||
if (isQuotaError(retryErr)) {
|
||||
console.warn('[tripSync] quota still exceeded after eviction — clearing all IDB data')
|
||||
await clearAll()
|
||||
return
|
||||
// Trip data + blob cache — free largest storage first before nuking everything
|
||||
console.warn('[tripSync] quota still exceeded — clearing blob cache and retrying')
|
||||
await clearBlobCache()
|
||||
try {
|
||||
await syncTrip(trip.id)
|
||||
} catch {
|
||||
console.warn('[tripSync] quota still exceeded after blob eviction — clearing all IDB data')
|
||||
await clearAll()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
console.error(`[tripSync] failed for trip ${trip.id} after eviction:`, retryErr)
|
||||
}
|
||||
console.error(`[tripSync] failed for trip ${trip.id} after eviction:`, retryErr)
|
||||
}
|
||||
} else {
|
||||
console.error(`[tripSync] failed for trip ${trip.id}:`, err)
|
||||
@@ -177,6 +189,8 @@ export const tripSyncManager = {
|
||||
}
|
||||
}
|
||||
|
||||
if (_interrupted) return
|
||||
|
||||
// Cache global user data (tags + categories) — fire-and-forget
|
||||
tagsApi.list().then(d => upsertTags(d.tags)).catch(() => {})
|
||||
categoriesApi.list().then(d => upsertCategories(d.categories)).catch(() => {})
|
||||
@@ -184,6 +198,7 @@ export const tripSyncManager = {
|
||||
// Cache file blobs + map tiles in background (don't block syncAll)
|
||||
const tileUrl = useSettingsStore.getState().settings.map_tile_url || undefined
|
||||
for (const trip of toSync) {
|
||||
if (_interrupted) break
|
||||
const files = await offlineDb.tripFiles.where('trip_id').equals(trip.id).toArray()
|
||||
cacheFilesForTrip(files).catch(console.error)
|
||||
|
||||
@@ -195,8 +210,17 @@ export const tripSyncManager = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Signal syncAll to stop after the current in-flight bundle request.
|
||||
* Call when the user navigates to a trip page so loadTrip gets priority.
|
||||
*/
|
||||
interrupt(): void {
|
||||
_interrupted = true
|
||||
},
|
||||
|
||||
/** Reset syncing flag — useful in tests. */
|
||||
_resetSyncing(): void {
|
||||
_syncing = false
|
||||
_interrupted = false
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user