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.js
CHANGED
|
@@ -3762,7 +3762,7 @@ class ModelService {
|
|
|
3762
3762
|
*/
|
|
3763
3763
|
async downloadModels(models, styleId, options = {}) {
|
|
3764
3764
|
const db = await this.db;
|
|
3765
|
-
const { onProgress, batchSize = 4, maxRetries = 3, skipExisting = true, timeoutMs = 30000, } = options;
|
|
3765
|
+
const { onProgress, batchSize = 4, maxRetries = 3, skipExisting = true, timeoutMs = 30000, signal, } = options;
|
|
3766
3766
|
const entries = Object.entries(models);
|
|
3767
3767
|
const progressTracker = createProgressTracker(entries.length);
|
|
3768
3768
|
const result = {
|
|
@@ -3786,6 +3786,9 @@ class ModelService {
|
|
|
3786
3786
|
}
|
|
3787
3787
|
}
|
|
3788
3788
|
await processBatch(entries, async ([modelName, url]) => {
|
|
3789
|
+
// Cancelled: let the remaining models go by without fetching them.
|
|
3790
|
+
if (signal?.aborted)
|
|
3791
|
+
return;
|
|
3789
3792
|
const key = modelKey(styleId, modelName);
|
|
3790
3793
|
const label = `${styleId}::${modelName}`;
|
|
3791
3794
|
if (skipExisting && existingKeys.has(key)) {
|
|
@@ -4587,7 +4590,7 @@ class SpriteService {
|
|
|
4587
4590
|
*/
|
|
4588
4591
|
async downloadSprites(spriteUrls, styleName, options = {}) {
|
|
4589
4592
|
const db = await this.db;
|
|
4590
|
-
const { onProgress, batchSize = 10, maxRetries = 3, skipExisting = true, timeoutMs = 15000, storageQuotaCheck = true, prioritySprites = [], bandwidthLimit, enableValidation = true, namePrefix, } = options;
|
|
4593
|
+
const { onProgress, batchSize = 10, maxRetries = 3, skipExisting = true, timeoutMs = 15000, storageQuotaCheck = true, prioritySprites = [], bandwidthLimit, enableValidation = true, namePrefix, signal, } = options;
|
|
4591
4594
|
const startTime = Date.now();
|
|
4592
4595
|
let totalSize = 0;
|
|
4593
4596
|
let downloadedSprites = 0;
|
|
@@ -4659,6 +4662,9 @@ class SpriteService {
|
|
|
4659
4662
|
spriteLogger.debug(` ${url} -> ${key}`);
|
|
4660
4663
|
});
|
|
4661
4664
|
await processBatch(urlsToDownload, async (spriteUrl) => {
|
|
4665
|
+
// Cancelled: let the remaining sprites go by without fetching them.
|
|
4666
|
+
if (signal?.aborted)
|
|
4667
|
+
return;
|
|
4662
4668
|
try {
|
|
4663
4669
|
const spriteName = namePrefix
|
|
4664
4670
|
? this.buildSpriteName(spriteUrl, namePrefix)
|
|
@@ -6462,7 +6468,8 @@ class RegionService {
|
|
|
6462
6468
|
await (await dbPromise).put('styles', styleEntry);
|
|
6463
6469
|
// 2. Sprites
|
|
6464
6470
|
const spriteResults = [];
|
|
6465
|
-
|
|
6471
|
+
// After a cancel, later phases don't start; the tile step then cleans up.
|
|
6472
|
+
if (!skipSprites && !signal?.aborted) {
|
|
6466
6473
|
const spriteSources = normalizeSpriteProperty(originalSpriteUrl);
|
|
6467
6474
|
if (spriteSources.length > 0) {
|
|
6468
6475
|
const { downloadSprites } = await Promise.resolve().then(function () { return spriteService$1; });
|
|
@@ -6504,6 +6511,7 @@ class RegionService {
|
|
|
6504
6511
|
});
|
|
6505
6512
|
try {
|
|
6506
6513
|
const result = await downloadSprites(spriteUrls, styleId, {
|
|
6514
|
+
signal,
|
|
6507
6515
|
enableValidation: true,
|
|
6508
6516
|
skipExisting: false,
|
|
6509
6517
|
namePrefix: source.id !== 'sprite' ? source.id : undefined,
|
|
@@ -6523,7 +6531,10 @@ class RegionService {
|
|
|
6523
6531
|
}
|
|
6524
6532
|
// 3. Glyphs
|
|
6525
6533
|
let glyphResult;
|
|
6526
|
-
if (!skipGlyphs &&
|
|
6534
|
+
if (!skipGlyphs &&
|
|
6535
|
+
!signal?.aborted &&
|
|
6536
|
+
originalGlyphsUrl &&
|
|
6537
|
+
!originalGlyphsUrl.startsWith('idb://')) {
|
|
6527
6538
|
const fontFamilies = new Set(extractAllFontNames(storedStyle));
|
|
6528
6539
|
if (fontFamilies.size > 0) {
|
|
6529
6540
|
const { downloadGlyphs } = await Promise.resolve().then(function () { return glyphService$1; });
|
|
@@ -6537,6 +6548,7 @@ class RegionService {
|
|
|
6537
6548
|
// jump when the real total came in).
|
|
6538
6549
|
try {
|
|
6539
6550
|
glyphResult = await downloadGlyphs(glyphsUrl, Array.from(fontFamilies), styleId, ranges, {
|
|
6551
|
+
signal,
|
|
6540
6552
|
onProgress: (progress) => {
|
|
6541
6553
|
emit('glyphs', progress.completed, progress.total, 'Downloading glyphs');
|
|
6542
6554
|
},
|
|
@@ -6551,7 +6563,7 @@ class RegionService {
|
|
|
6551
6563
|
// turbine .glb assets. Two value shapes exist in the wild
|
|
6552
6564
|
// (plain string or `{ uri }`) — we accept both.
|
|
6553
6565
|
let modelResult;
|
|
6554
|
-
if (!skipModels && storedStyle.models) {
|
|
6566
|
+
if (!skipModels && !signal?.aborted && storedStyle.models) {
|
|
6555
6567
|
// Upstream URLs, from before patching, so models that failed last time are retried.
|
|
6556
6568
|
const rawModels = (styleEntry.originalModels ?? storedStyle.models);
|
|
6557
6569
|
const alreadyStored = await storedModelNames(styleId);
|
|
@@ -6574,6 +6586,7 @@ class RegionService {
|
|
|
6574
6586
|
emit('models', 0, Object.keys(resolved).length, 'Downloading 3D models');
|
|
6575
6587
|
try {
|
|
6576
6588
|
modelResult = await downloadModels(resolved, styleId, {
|
|
6589
|
+
signal,
|
|
6577
6590
|
onProgress: (progress) => {
|
|
6578
6591
|
emit('models', progress.completed, progress.total, 'Downloading 3D models');
|
|
6579
6592
|
},
|
|
@@ -6587,7 +6600,8 @@ class RegionService {
|
|
|
6587
6600
|
// Renderer code fetched from api.mapbox.com at render time (3D decoders,
|
|
6588
6601
|
// RTL text, procedural buildings). Never throws; see cacheMapboxRuntimeAssets.
|
|
6589
6602
|
let runtimeAssetsCached;
|
|
6590
|
-
if (
|
|
6603
|
+
if (!signal?.aborted &&
|
|
6604
|
+
/mapbox:\/\/|api\.mapbox\.com/.test(`${region.styleUrl ?? ''} ${originalGlyphsUrl ?? ''}`)) {
|
|
6591
6605
|
const { cacheMapboxRuntimeAssets } = await Promise.resolve().then(function () { return runtimeAssetService; });
|
|
6592
6606
|
runtimeAssetsCached = await cacheMapboxRuntimeAssets();
|
|
6593
6607
|
}
|
|
@@ -8223,7 +8237,7 @@ class GlyphService {
|
|
|
8223
8237
|
db = dbPromise;
|
|
8224
8238
|
async downloadGlyphs(glyphUrl, fontstacks, styleName, ranges = ['0-255'], options = {}) {
|
|
8225
8239
|
const db = await this.db;
|
|
8226
|
-
const { maxConcurrency = 5, retries = 3, timeout = 10000, onProgress, enableValidation = true, priorityFonts = [], } = options;
|
|
8240
|
+
const { maxConcurrency = 5, retries = 3, timeout = 10000, onProgress, enableValidation = true, priorityFonts = [], signal, } = options;
|
|
8227
8241
|
const startTime = Date.now();
|
|
8228
8242
|
let totalSize = 0;
|
|
8229
8243
|
let downloadedGlyphs = 0;
|
|
@@ -8255,7 +8269,8 @@ class GlyphService {
|
|
|
8255
8269
|
// Process glyphs with concurrency control
|
|
8256
8270
|
const semaphore = new Array(maxConcurrency).fill(0);
|
|
8257
8271
|
const promises = semaphore.map(async () => {
|
|
8258
|
-
|
|
8272
|
+
// Once cancelled, workers stop taking tasks; those in flight finish.
|
|
8273
|
+
while (glyphTasks.length > 0 && !signal?.aborted) {
|
|
8259
8274
|
const task = glyphTasks.shift();
|
|
8260
8275
|
if (!task)
|
|
8261
8276
|
break;
|
|
@@ -10062,6 +10077,7 @@ const en = {
|
|
|
10062
10077
|
'download.status.models': '3D models: {{completed}} of {{total}}',
|
|
10063
10078
|
'download.status.tiles': 'Tiles: {{completed}} of {{total}}',
|
|
10064
10079
|
'download.status.planning': 'Planning tiles',
|
|
10080
|
+
'download.cancelRegion': 'Cancel downloading {{name}}',
|
|
10065
10081
|
'download.status.saving': 'Saving region',
|
|
10066
10082
|
// Panel Manager additional strings
|
|
10067
10083
|
'panel.downloadedRegions': 'Downloaded Regions',
|
|
@@ -10284,6 +10300,7 @@ const ar = {
|
|
|
10284
10300
|
'download.status.models': 'النماذج ثلاثية الأبعاد: {{completed}} من {{total}}',
|
|
10285
10301
|
'download.status.tiles': 'البلاطات: {{completed}} من {{total}}',
|
|
10286
10302
|
'download.status.planning': 'جارٍ تخطيط البلاطات',
|
|
10303
|
+
'download.cancelRegion': 'إلغاء تحميل {{name}}',
|
|
10287
10304
|
'download.status.saving': 'جارٍ حفظ المنطقة',
|
|
10288
10305
|
// Panel Manager additional strings - سلاسل إضافية للوحة
|
|
10289
10306
|
'panel.downloadedRegions': 'المناطق المحملة',
|
|
@@ -12025,6 +12042,15 @@ class PanelRenderer extends BaseComponent {
|
|
|
12025
12042
|
const downloads = this.downloadManager.getCurrentDownloads();
|
|
12026
12043
|
const progressHTML = this.createDownloadProgressHTML(downloads);
|
|
12027
12044
|
this.downloadProgressContainer.innerHTML = progressHTML;
|
|
12045
|
+
// The rows are redrawn on every update, so listen on the container.
|
|
12046
|
+
this.downloadProgressContainer.addEventListener('click', event => {
|
|
12047
|
+
const button = event.target.closest('[data-action="cancel-download"]');
|
|
12048
|
+
const regionId = button?.dataset.regionId;
|
|
12049
|
+
if (!regionId)
|
|
12050
|
+
return;
|
|
12051
|
+
this.downloadManager.cancelDownload(regionId);
|
|
12052
|
+
void this.refresh();
|
|
12053
|
+
});
|
|
12028
12054
|
this.element.appendChild(this.downloadProgressContainer);
|
|
12029
12055
|
}
|
|
12030
12056
|
}
|
|
@@ -12398,6 +12424,7 @@ class PanelRenderer extends BaseComponent {
|
|
|
12398
12424
|
<div class="h-full bg-blue-600" style="width: ${download.percentage || 0}%"></div>
|
|
12399
12425
|
</div>
|
|
12400
12426
|
<span class="text-blue-700 dark:text-blue-300 min-w-12">${Math.round(download.percentage || 0)}%</span>
|
|
12427
|
+
<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>
|
|
12401
12428
|
</div>
|
|
12402
12429
|
</div>
|
|
12403
12430
|
`)
|