fix: offline download — wait for completion, suppress transient errors
createPack() resolves when the pack is registered, not when tiles are
done downloading. Wrapping in a Promise that resolves only on
status.state === 'complete' keeps the progress modal visible and the
'Download complete' alert fires only when the pack is actually ready.
Transient tile errors ('stream was reset: CANCEL') are silently ignored
in the error listener — MapLibre retries them internally and they do not
indicate a failed download. The onError callback is removed from the
public API since it was causing spurious alerts mid-download.
This commit is contained in:
@@ -110,7 +110,6 @@ export function RecordingScreen() {
|
|||||||
dlName.trim(),
|
dlName.trim(),
|
||||||
expanded,
|
expanded,
|
||||||
(pct, _tiles, sizeBytes) => { setDlProgress(pct); setDlSize(sizeBytes); },
|
(pct, _tiles, sizeBytes) => { setDlProgress(pct); setDlSize(sizeBytes); },
|
||||||
(msg) => Alert.alert('Download error', msg),
|
|
||||||
);
|
);
|
||||||
setDlVisible(false);
|
setDlVisible(false);
|
||||||
setDlProgress(null);
|
setDlProgress(null);
|
||||||
|
|||||||
+30
-18
@@ -22,31 +22,43 @@ export interface OfflineRegion {
|
|||||||
|
|
||||||
// ── Download ──────────────────────────────────────────────────────────────────
|
// ── Download ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
export async function downloadRegion(
|
/**
|
||||||
|
* Download a region and return a Promise that resolves only when the pack
|
||||||
|
* reaches state 'complete'. Transient tile-fetch errors (e.g. "stream was
|
||||||
|
* reset: CANCEL") are silently ignored — MapLibre retries them internally
|
||||||
|
* and they do not indicate a failed download.
|
||||||
|
*/
|
||||||
|
export function downloadRegion(
|
||||||
name: string,
|
name: string,
|
||||||
bounds: LngLatBounds,
|
bounds: LngLatBounds,
|
||||||
onProgress: (pct: number, tilesDown: number, sizeBytes: number) => void,
|
onProgress: (pct: number, tilesDown: number, sizeBytes: number) => void,
|
||||||
onError: (msg: string) => void,
|
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
OfflineManager.setProgressEventThrottle(500);
|
OfflineManager.setProgressEventThrottle(500);
|
||||||
|
|
||||||
const pack = await OfflineManager.createPack(
|
return new Promise((resolve, reject) => {
|
||||||
{
|
let packId: string;
|
||||||
mapStyle: OFFLINE_STYLE_URL,
|
|
||||||
bounds,
|
|
||||||
minZoom: MIN_ZOOM,
|
|
||||||
maxZoom: MAX_ZOOM,
|
|
||||||
metadata: { name, createdAt: new Date().toISOString() },
|
|
||||||
},
|
|
||||||
(_pack, status: OfflinePackStatus) => {
|
|
||||||
onProgress(status.percentage, status.completedTileCount, status.completedTileSize);
|
|
||||||
},
|
|
||||||
(_pack, error) => {
|
|
||||||
onError(error.message);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return pack.id;
|
OfflineManager.createPack(
|
||||||
|
{
|
||||||
|
mapStyle: OFFLINE_STYLE_URL,
|
||||||
|
bounds,
|
||||||
|
minZoom: MIN_ZOOM,
|
||||||
|
maxZoom: MAX_ZOOM,
|
||||||
|
metadata: { name, createdAt: new Date().toISOString() },
|
||||||
|
},
|
||||||
|
(pack, status: OfflinePackStatus) => {
|
||||||
|
packId = pack.id;
|
||||||
|
onProgress(status.percentage, status.completedTileCount, status.completedTileSize);
|
||||||
|
if (status.state === 'complete') {
|
||||||
|
resolve(packId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(_pack, _error) => {
|
||||||
|
// Transient tile-level errors — MapLibre retries these automatically.
|
||||||
|
// Do not reject: the overall download is still in progress.
|
||||||
|
},
|
||||||
|
).catch(reject); // only rejects on createPack failure (e.g. bad style URL)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── List ──────────────────────────────────────────────────────────────────────
|
// ── List ──────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user