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.umd.js CHANGED
@@ -4022,7 +4022,7 @@
4022
4022
  */
4023
4023
  async downloadModels(models, styleId, options = {}) {
4024
4024
  const db = await this.db;
4025
- const { onProgress, batchSize = 4, maxRetries = 3, skipExisting = true, timeoutMs = 30000, } = options;
4025
+ const { onProgress, batchSize = 4, maxRetries = 3, skipExisting = true, timeoutMs = 30000, signal, } = options;
4026
4026
  const entries = Object.entries(models);
4027
4027
  const progressTracker = createProgressTracker(entries.length);
4028
4028
  const result = {
@@ -4046,6 +4046,9 @@
4046
4046
  }
4047
4047
  }
4048
4048
  await processBatch(entries, async ([modelName, url]) => {
4049
+ // Cancelled: let the remaining models go by without fetching them.
4050
+ if (signal?.aborted)
4051
+ return;
4049
4052
  const key = modelKey(styleId, modelName);
4050
4053
  const label = `${styleId}::${modelName}`;
4051
4054
  if (skipExisting && existingKeys.has(key)) {
@@ -4878,7 +4881,7 @@
4878
4881
  */
4879
4882
  async downloadSprites(spriteUrls, styleName, options = {}) {
4880
4883
  const db = await this.db;
4881
- const { onProgress, batchSize = 10, maxRetries = 3, skipExisting = true, timeoutMs = 15000, storageQuotaCheck = true, prioritySprites = [], bandwidthLimit, enableValidation = true, namePrefix, } = options;
4884
+ const { onProgress, batchSize = 10, maxRetries = 3, skipExisting = true, timeoutMs = 15000, storageQuotaCheck = true, prioritySprites = [], bandwidthLimit, enableValidation = true, namePrefix, signal, } = options;
4882
4885
  const startTime = Date.now();
4883
4886
  let totalSize = 0;
4884
4887
  let downloadedSprites = 0;
@@ -4950,6 +4953,9 @@
4950
4953
  spriteLogger.debug(` ${url} -> ${key}`);
4951
4954
  });
4952
4955
  await processBatch(urlsToDownload, async (spriteUrl) => {
4956
+ // Cancelled: let the remaining sprites go by without fetching them.
4957
+ if (signal?.aborted)
4958
+ return;
4953
4959
  try {
4954
4960
  const spriteName = namePrefix
4955
4961
  ? this.buildSpriteName(spriteUrl, namePrefix)
@@ -6753,7 +6759,8 @@
6753
6759
  await (await dbPromise).put('styles', styleEntry);
6754
6760
  // 2. Sprites
6755
6761
  const spriteResults = [];
6756
- if (!skipSprites) {
6762
+ // After a cancel, later phases don't start; the tile step then cleans up.
6763
+ if (!skipSprites && !signal?.aborted) {
6757
6764
  const spriteSources = normalizeSpriteProperty(originalSpriteUrl);
6758
6765
  if (spriteSources.length > 0) {
6759
6766
  const { downloadSprites } = await Promise.resolve().then(function () { return spriteService$1; });
@@ -6795,6 +6802,7 @@
6795
6802
  });
6796
6803
  try {
6797
6804
  const result = await downloadSprites(spriteUrls, styleId, {
6805
+ signal,
6798
6806
  enableValidation: true,
6799
6807
  skipExisting: false,
6800
6808
  namePrefix: source.id !== 'sprite' ? source.id : undefined,
@@ -6814,7 +6822,10 @@
6814
6822
  }
6815
6823
  // 3. Glyphs
6816
6824
  let glyphResult;
6817
- if (!skipGlyphs && originalGlyphsUrl && !originalGlyphsUrl.startsWith('idb://')) {
6825
+ if (!skipGlyphs &&
6826
+ !signal?.aborted &&
6827
+ originalGlyphsUrl &&
6828
+ !originalGlyphsUrl.startsWith('idb://')) {
6818
6829
  const fontFamilies = new Set(extractAllFontNames(storedStyle));
6819
6830
  if (fontFamilies.size > 0) {
6820
6831
  const { downloadGlyphs } = await Promise.resolve().then(function () { return glyphService$1; });
@@ -6828,6 +6839,7 @@
6828
6839
  // jump when the real total came in).
6829
6840
  try {
6830
6841
  glyphResult = await downloadGlyphs(glyphsUrl, Array.from(fontFamilies), styleId, ranges, {
6842
+ signal,
6831
6843
  onProgress: (progress) => {
6832
6844
  emit('glyphs', progress.completed, progress.total, 'Downloading glyphs');
6833
6845
  },
@@ -6842,7 +6854,7 @@
6842
6854
  // turbine .glb assets. Two value shapes exist in the wild
6843
6855
  // (plain string or `{ uri }`) — we accept both.
6844
6856
  let modelResult;
6845
- if (!skipModels && storedStyle.models) {
6857
+ if (!skipModels && !signal?.aborted && storedStyle.models) {
6846
6858
  // Upstream URLs, from before patching, so models that failed last time are retried.
6847
6859
  const rawModels = (styleEntry.originalModels ?? storedStyle.models);
6848
6860
  const alreadyStored = await storedModelNames(styleId);
@@ -6865,6 +6877,7 @@
6865
6877
  emit('models', 0, Object.keys(resolved).length, 'Downloading 3D models');
6866
6878
  try {
6867
6879
  modelResult = await downloadModels(resolved, styleId, {
6880
+ signal,
6868
6881
  onProgress: (progress) => {
6869
6882
  emit('models', progress.completed, progress.total, 'Downloading 3D models');
6870
6883
  },
@@ -6878,7 +6891,8 @@
6878
6891
  // Renderer code fetched from api.mapbox.com at render time (3D decoders,
6879
6892
  // RTL text, procedural buildings). Never throws; see cacheMapboxRuntimeAssets.
6880
6893
  let runtimeAssetsCached;
6881
- if (/mapbox:\/\/|api\.mapbox\.com/.test(`${region.styleUrl ?? ''} ${originalGlyphsUrl ?? ''}`)) {
6894
+ if (!signal?.aborted &&
6895
+ /mapbox:\/\/|api\.mapbox\.com/.test(`${region.styleUrl ?? ''} ${originalGlyphsUrl ?? ''}`)) {
6882
6896
  const { cacheMapboxRuntimeAssets } = await Promise.resolve().then(function () { return runtimeAssetService; });
6883
6897
  runtimeAssetsCached = await cacheMapboxRuntimeAssets();
6884
6898
  }
@@ -8514,7 +8528,7 @@
8514
8528
  db = dbPromise;
8515
8529
  async downloadGlyphs(glyphUrl, fontstacks, styleName, ranges = ['0-255'], options = {}) {
8516
8530
  const db = await this.db;
8517
- const { maxConcurrency = 5, retries = 3, timeout = 10000, onProgress, enableValidation = true, priorityFonts = [], } = options;
8531
+ const { maxConcurrency = 5, retries = 3, timeout = 10000, onProgress, enableValidation = true, priorityFonts = [], signal, } = options;
8518
8532
  const startTime = Date.now();
8519
8533
  let totalSize = 0;
8520
8534
  let downloadedGlyphs = 0;
@@ -8546,7 +8560,8 @@
8546
8560
  // Process glyphs with concurrency control
8547
8561
  const semaphore = new Array(maxConcurrency).fill(0);
8548
8562
  const promises = semaphore.map(async () => {
8549
- while (glyphTasks.length > 0) {
8563
+ // Once cancelled, workers stop taking tasks; those in flight finish.
8564
+ while (glyphTasks.length > 0 && !signal?.aborted) {
8550
8565
  const task = glyphTasks.shift();
8551
8566
  if (!task)
8552
8567
  break;
@@ -12799,6 +12814,7 @@
12799
12814
  'download.status.models': '3D models: {{completed}} of {{total}}',
12800
12815
  'download.status.tiles': 'Tiles: {{completed}} of {{total}}',
12801
12816
  'download.status.planning': 'Planning tiles',
12817
+ 'download.cancelRegion': 'Cancel downloading {{name}}',
12802
12818
  'download.status.saving': 'Saving region',
12803
12819
  // Panel Manager additional strings
12804
12820
  'panel.downloadedRegions': 'Downloaded Regions',
@@ -13021,6 +13037,7 @@
13021
13037
  'download.status.models': 'النماذج ثلاثية الأبعاد: {{completed}} من {{total}}',
13022
13038
  'download.status.tiles': 'البلاطات: {{completed}} من {{total}}',
13023
13039
  'download.status.planning': 'جارٍ تخطيط البلاطات',
13040
+ 'download.cancelRegion': 'إلغاء تحميل {{name}}',
13024
13041
  'download.status.saving': 'جارٍ حفظ المنطقة',
13025
13042
  // Panel Manager additional strings - سلاسل إضافية للوحة
13026
13043
  'panel.downloadedRegions': 'المناطق المحملة',
@@ -14762,6 +14779,15 @@
14762
14779
  const downloads = this.downloadManager.getCurrentDownloads();
14763
14780
  const progressHTML = this.createDownloadProgressHTML(downloads);
14764
14781
  this.downloadProgressContainer.innerHTML = progressHTML;
14782
+ // The rows are redrawn on every update, so listen on the container.
14783
+ this.downloadProgressContainer.addEventListener('click', event => {
14784
+ const button = event.target.closest('[data-action="cancel-download"]');
14785
+ const regionId = button?.dataset.regionId;
14786
+ if (!regionId)
14787
+ return;
14788
+ this.downloadManager.cancelDownload(regionId);
14789
+ void this.refresh();
14790
+ });
14765
14791
  this.element.appendChild(this.downloadProgressContainer);
14766
14792
  }
14767
14793
  }
@@ -15135,6 +15161,7 @@
15135
15161
  <div class="h-full bg-blue-600" style="width: ${download.percentage || 0}%"></div>
15136
15162
  </div>
15137
15163
  <span class="text-blue-700 dark:text-blue-300 min-w-12">${Math.round(download.percentage || 0)}%</span>
15164
+ <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>
15138
15165
  </div>
15139
15166
  </div>
15140
15167
  `)