map-gl-offline 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +35 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +35 -8
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +35 -8
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +2 -2
- package/dist/types/glyph.d.ts +2 -0
- package/dist/types/model.d.ts +2 -0
- package/dist/types/sprite.d.ts +2 -0
- package/dist/ui/translations/ar.d.ts +1 -0
- package/dist/ui/translations/en.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -3739,7 +3739,7 @@ class ModelService {
|
|
|
3739
3739
|
*/
|
|
3740
3740
|
async downloadModels(models, styleId, options = {}) {
|
|
3741
3741
|
const db = await this.db;
|
|
3742
|
-
const { onProgress, batchSize = 4, maxRetries = 3, skipExisting = true, timeoutMs = 30000, } = options;
|
|
3742
|
+
const { onProgress, batchSize = 4, maxRetries = 3, skipExisting = true, timeoutMs = 30000, signal, } = options;
|
|
3743
3743
|
const entries = Object.entries(models);
|
|
3744
3744
|
const progressTracker = createProgressTracker(entries.length);
|
|
3745
3745
|
const result = {
|
|
@@ -3763,6 +3763,9 @@ class ModelService {
|
|
|
3763
3763
|
}
|
|
3764
3764
|
}
|
|
3765
3765
|
await processBatch(entries, async ([modelName, url]) => {
|
|
3766
|
+
// Cancelled: let the remaining models go by without fetching them.
|
|
3767
|
+
if (signal?.aborted)
|
|
3768
|
+
return;
|
|
3766
3769
|
const key = modelKey(styleId, modelName);
|
|
3767
3770
|
const label = `${styleId}::${modelName}`;
|
|
3768
3771
|
if (skipExisting && existingKeys.has(key)) {
|
|
@@ -4564,7 +4567,7 @@ class SpriteService {
|
|
|
4564
4567
|
*/
|
|
4565
4568
|
async downloadSprites(spriteUrls, styleName, options = {}) {
|
|
4566
4569
|
const db = await this.db;
|
|
4567
|
-
const { onProgress, batchSize = 10, maxRetries = 3, skipExisting = true, timeoutMs = 15000, storageQuotaCheck = true, prioritySprites = [], bandwidthLimit, enableValidation = true, namePrefix, } = options;
|
|
4570
|
+
const { onProgress, batchSize = 10, maxRetries = 3, skipExisting = true, timeoutMs = 15000, storageQuotaCheck = true, prioritySprites = [], bandwidthLimit, enableValidation = true, namePrefix, signal, } = options;
|
|
4568
4571
|
const startTime = Date.now();
|
|
4569
4572
|
let totalSize = 0;
|
|
4570
4573
|
let downloadedSprites = 0;
|
|
@@ -4636,6 +4639,9 @@ class SpriteService {
|
|
|
4636
4639
|
spriteLogger.debug(` ${url} -> ${key}`);
|
|
4637
4640
|
});
|
|
4638
4641
|
await processBatch(urlsToDownload, async (spriteUrl) => {
|
|
4642
|
+
// Cancelled: let the remaining sprites go by without fetching them.
|
|
4643
|
+
if (signal?.aborted)
|
|
4644
|
+
return;
|
|
4639
4645
|
try {
|
|
4640
4646
|
const spriteName = namePrefix
|
|
4641
4647
|
? this.buildSpriteName(spriteUrl, namePrefix)
|
|
@@ -6439,7 +6445,8 @@ class RegionService {
|
|
|
6439
6445
|
await (await dbPromise).put('styles', styleEntry);
|
|
6440
6446
|
// 2. Sprites
|
|
6441
6447
|
const spriteResults = [];
|
|
6442
|
-
|
|
6448
|
+
// After a cancel, later phases don't start; the tile step then cleans up.
|
|
6449
|
+
if (!skipSprites && !signal?.aborted) {
|
|
6443
6450
|
const spriteSources = normalizeSpriteProperty(originalSpriteUrl);
|
|
6444
6451
|
if (spriteSources.length > 0) {
|
|
6445
6452
|
const { downloadSprites } = await Promise.resolve().then(function () { return spriteService$1; });
|
|
@@ -6481,6 +6488,7 @@ class RegionService {
|
|
|
6481
6488
|
});
|
|
6482
6489
|
try {
|
|
6483
6490
|
const result = await downloadSprites(spriteUrls, styleId, {
|
|
6491
|
+
signal,
|
|
6484
6492
|
enableValidation: true,
|
|
6485
6493
|
skipExisting: false,
|
|
6486
6494
|
namePrefix: source.id !== 'sprite' ? source.id : undefined,
|
|
@@ -6500,7 +6508,10 @@ class RegionService {
|
|
|
6500
6508
|
}
|
|
6501
6509
|
// 3. Glyphs
|
|
6502
6510
|
let glyphResult;
|
|
6503
|
-
if (!skipGlyphs &&
|
|
6511
|
+
if (!skipGlyphs &&
|
|
6512
|
+
!signal?.aborted &&
|
|
6513
|
+
originalGlyphsUrl &&
|
|
6514
|
+
!originalGlyphsUrl.startsWith('idb://')) {
|
|
6504
6515
|
const fontFamilies = new Set(extractAllFontNames(storedStyle));
|
|
6505
6516
|
if (fontFamilies.size > 0) {
|
|
6506
6517
|
const { downloadGlyphs } = await Promise.resolve().then(function () { return glyphService$1; });
|
|
@@ -6514,6 +6525,7 @@ class RegionService {
|
|
|
6514
6525
|
// jump when the real total came in).
|
|
6515
6526
|
try {
|
|
6516
6527
|
glyphResult = await downloadGlyphs(glyphsUrl, Array.from(fontFamilies), styleId, ranges, {
|
|
6528
|
+
signal,
|
|
6517
6529
|
onProgress: (progress) => {
|
|
6518
6530
|
emit('glyphs', progress.completed, progress.total, 'Downloading glyphs');
|
|
6519
6531
|
},
|
|
@@ -6528,7 +6540,7 @@ class RegionService {
|
|
|
6528
6540
|
// turbine .glb assets. Two value shapes exist in the wild
|
|
6529
6541
|
// (plain string or `{ uri }`) — we accept both.
|
|
6530
6542
|
let modelResult;
|
|
6531
|
-
if (!skipModels && storedStyle.models) {
|
|
6543
|
+
if (!skipModels && !signal?.aborted && storedStyle.models) {
|
|
6532
6544
|
// Upstream URLs, from before patching, so models that failed last time are retried.
|
|
6533
6545
|
const rawModels = (styleEntry.originalModels ?? storedStyle.models);
|
|
6534
6546
|
const alreadyStored = await storedModelNames(styleId);
|
|
@@ -6551,6 +6563,7 @@ class RegionService {
|
|
|
6551
6563
|
emit('models', 0, Object.keys(resolved).length, 'Downloading 3D models');
|
|
6552
6564
|
try {
|
|
6553
6565
|
modelResult = await downloadModels(resolved, styleId, {
|
|
6566
|
+
signal,
|
|
6554
6567
|
onProgress: (progress) => {
|
|
6555
6568
|
emit('models', progress.completed, progress.total, 'Downloading 3D models');
|
|
6556
6569
|
},
|
|
@@ -6564,7 +6577,8 @@ class RegionService {
|
|
|
6564
6577
|
// Renderer code fetched from api.mapbox.com at render time (3D decoders,
|
|
6565
6578
|
// RTL text, procedural buildings). Never throws; see cacheMapboxRuntimeAssets.
|
|
6566
6579
|
let runtimeAssetsCached;
|
|
6567
|
-
if (
|
|
6580
|
+
if (!signal?.aborted &&
|
|
6581
|
+
/mapbox:\/\/|api\.mapbox\.com/.test(`${region.styleUrl ?? ''} ${originalGlyphsUrl ?? ''}`)) {
|
|
6568
6582
|
const { cacheMapboxRuntimeAssets } = await Promise.resolve().then(function () { return runtimeAssetService; });
|
|
6569
6583
|
runtimeAssetsCached = await cacheMapboxRuntimeAssets();
|
|
6570
6584
|
}
|
|
@@ -8200,7 +8214,7 @@ class GlyphService {
|
|
|
8200
8214
|
db = dbPromise;
|
|
8201
8215
|
async downloadGlyphs(glyphUrl, fontstacks, styleName, ranges = ['0-255'], options = {}) {
|
|
8202
8216
|
const db = await this.db;
|
|
8203
|
-
const { maxConcurrency = 5, retries = 3, timeout = 10000, onProgress, enableValidation = true, priorityFonts = [], } = options;
|
|
8217
|
+
const { maxConcurrency = 5, retries = 3, timeout = 10000, onProgress, enableValidation = true, priorityFonts = [], signal, } = options;
|
|
8204
8218
|
const startTime = Date.now();
|
|
8205
8219
|
let totalSize = 0;
|
|
8206
8220
|
let downloadedGlyphs = 0;
|
|
@@ -8232,7 +8246,8 @@ class GlyphService {
|
|
|
8232
8246
|
// Process glyphs with concurrency control
|
|
8233
8247
|
const semaphore = new Array(maxConcurrency).fill(0);
|
|
8234
8248
|
const promises = semaphore.map(async () => {
|
|
8235
|
-
|
|
8249
|
+
// Once cancelled, workers stop taking tasks; those in flight finish.
|
|
8250
|
+
while (glyphTasks.length > 0 && !signal?.aborted) {
|
|
8236
8251
|
const task = glyphTasks.shift();
|
|
8237
8252
|
if (!task)
|
|
8238
8253
|
break;
|
|
@@ -10039,6 +10054,7 @@ const en = {
|
|
|
10039
10054
|
'download.status.models': '3D models: {{completed}} of {{total}}',
|
|
10040
10055
|
'download.status.tiles': 'Tiles: {{completed}} of {{total}}',
|
|
10041
10056
|
'download.status.planning': 'Planning tiles',
|
|
10057
|
+
'download.cancelRegion': 'Cancel downloading {{name}}',
|
|
10042
10058
|
'download.status.saving': 'Saving region',
|
|
10043
10059
|
// Panel Manager additional strings
|
|
10044
10060
|
'panel.downloadedRegions': 'Downloaded Regions',
|
|
@@ -10261,6 +10277,7 @@ const ar = {
|
|
|
10261
10277
|
'download.status.models': 'النماذج ثلاثية الأبعاد: {{completed}} من {{total}}',
|
|
10262
10278
|
'download.status.tiles': 'البلاطات: {{completed}} من {{total}}',
|
|
10263
10279
|
'download.status.planning': 'جارٍ تخطيط البلاطات',
|
|
10280
|
+
'download.cancelRegion': 'إلغاء تحميل {{name}}',
|
|
10264
10281
|
'download.status.saving': 'جارٍ حفظ المنطقة',
|
|
10265
10282
|
// Panel Manager additional strings - سلاسل إضافية للوحة
|
|
10266
10283
|
'panel.downloadedRegions': 'المناطق المحملة',
|
|
@@ -12002,6 +12019,15 @@ class PanelRenderer extends BaseComponent {
|
|
|
12002
12019
|
const downloads = this.downloadManager.getCurrentDownloads();
|
|
12003
12020
|
const progressHTML = this.createDownloadProgressHTML(downloads);
|
|
12004
12021
|
this.downloadProgressContainer.innerHTML = progressHTML;
|
|
12022
|
+
// The rows are redrawn on every update, so listen on the container.
|
|
12023
|
+
this.downloadProgressContainer.addEventListener('click', event => {
|
|
12024
|
+
const button = event.target.closest('[data-action="cancel-download"]');
|
|
12025
|
+
const regionId = button?.dataset.regionId;
|
|
12026
|
+
if (!regionId)
|
|
12027
|
+
return;
|
|
12028
|
+
this.downloadManager.cancelDownload(regionId);
|
|
12029
|
+
void this.refresh();
|
|
12030
|
+
});
|
|
12005
12031
|
this.element.appendChild(this.downloadProgressContainer);
|
|
12006
12032
|
}
|
|
12007
12033
|
}
|
|
@@ -12375,6 +12401,7 @@ class PanelRenderer extends BaseComponent {
|
|
|
12375
12401
|
<div class="h-full bg-blue-600" style="width: ${download.percentage || 0}%"></div>
|
|
12376
12402
|
</div>
|
|
12377
12403
|
<span class="text-blue-700 dark:text-blue-300 min-w-12">${Math.round(download.percentage || 0)}%</span>
|
|
12404
|
+
<button type="button" class="px-2 py-1 rounded-md text-xs font-medium cursor-pointer text-gray-700 dark:text-gray-200 bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600" data-action="cancel-download" data-region-id="${escapeHtml$1(download.regionId)}" aria-label="${t('download.cancelRegion', { name: String(download.regionName || download.regionId) })}">${t('app.cancel')}</button>
|
|
12378
12405
|
</div>
|
|
12379
12406
|
</div>
|
|
12380
12407
|
`)
|