carriera-intern 1.1.119 → 1.1.121

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.
@@ -177,7 +177,7 @@ const INPUT_CHARACTER_SETS = {
177
177
 
178
178
  const PDFJS_ASSET_BASE = new InjectionToken('PDFJS_ASSET_BASE', {
179
179
  providedIn: 'root',
180
- factory: () => '/pdfjs/',
180
+ factory: () => '/assets/pdfjs/',
181
181
  });
182
182
 
183
183
  class DocumentThumbnailHelper {
@@ -4646,7 +4646,8 @@ class DocumentService {
4646
4646
  workerPool = [];
4647
4647
  workerPoolSize = Math.max(1, Math.min((navigator.hardwareConcurrency || 2) - 1, 3));
4648
4648
  workerCursor = 0;
4649
- isWorkerSrcConfigured = false;
4649
+ workerSrcReady = null;
4650
+ workerSrcBlobUrl = null;
4650
4651
  constructor() {
4651
4652
  this.destroyRef.onDestroy(() => this.destroyWorkers());
4652
4653
  }
@@ -4700,6 +4701,7 @@ class DocumentService {
4700
4701
  */
4701
4702
  async analyzePdf(file) {
4702
4703
  const data = new Uint8Array(await file.arrayBuffer());
4704
+ await this.ensureWorkerSrc();
4703
4705
  const loadingTask = pdfjsLib.getDocument({
4704
4706
  data,
4705
4707
  worker: this.getWorker(),
@@ -4719,10 +4721,6 @@ class DocumentService {
4719
4721
  }
4720
4722
  }
4721
4723
  getWorker() {
4722
- if (!this.isWorkerSrcConfigured) {
4723
- pdfjsLib.GlobalWorkerOptions.workerSrc = `${this.assetBase}pdf.worker.min.mjs`;
4724
- this.isWorkerSrcConfigured = true;
4725
- }
4726
4724
  const index = this.workerCursor++ % this.workerPoolSize;
4727
4725
  if (!this.workerPool[index] || this.workerPool[index].destroyed) {
4728
4726
  this.workerPool[index] = pdfjsLib.PDFWorker.create({
@@ -4731,6 +4729,36 @@ class DocumentService {
4731
4729
  }
4732
4730
  return this.workerPool[index];
4733
4731
  }
4732
+ ensureWorkerSrc() {
4733
+ this.workerSrcReady ??= this.configureWorkerSrc();
4734
+ return this.workerSrcReady;
4735
+ }
4736
+ async configureWorkerSrc() {
4737
+ const remoteWorkerUrl = `${this.assetBase}pdf.worker.min.mjs`;
4738
+ pdfjsLib.GlobalWorkerOptions.workerSrc =
4739
+ await this.workerSrcAsJavascriptModule(remoteWorkerUrl);
4740
+ }
4741
+ async workerSrcAsJavascriptModule(url) {
4742
+ const response = await fetch(url);
4743
+ if (!response.ok) {
4744
+ throw new Error(`Failed to load PDF worker (${response.status})`);
4745
+ }
4746
+ const source = await response.text();
4747
+ if (!this.isPdfWorkerSource(source)) {
4748
+ throw new Error(`PDF worker at ${url} was not JavaScript`);
4749
+ }
4750
+ const javascriptBlob = new Blob([source], {
4751
+ type: 'application/javascript',
4752
+ });
4753
+ this.workerSrcBlobUrl = URL.createObjectURL(javascriptBlob);
4754
+ return this.workerSrcBlobUrl;
4755
+ }
4756
+ isPdfWorkerSource(source) {
4757
+ const start = source.trimStart().slice(0, 80);
4758
+ return (start.startsWith('/*') ||
4759
+ start.startsWith('import ') ||
4760
+ start.startsWith('('));
4761
+ }
4734
4762
  destroyWorkers() {
4735
4763
  for (const worker of this.workerPool) {
4736
4764
  if (!worker.destroyed) {
@@ -4738,6 +4766,11 @@ class DocumentService {
4738
4766
  }
4739
4767
  }
4740
4768
  this.workerPool.length = 0;
4769
+ if (this.workerSrcBlobUrl) {
4770
+ URL.revokeObjectURL(this.workerSrcBlobUrl);
4771
+ this.workerSrcBlobUrl = null;
4772
+ }
4773
+ this.workerSrcReady = null;
4741
4774
  }
4742
4775
  async cleanupQuietly(teardown) {
4743
4776
  try {
@@ -4959,6 +4992,28 @@ class DropZoneDocumentsHelper {
4959
4992
  reader.readAsDataURL(file);
4960
4993
  });
4961
4994
  }
4995
+ static mapFileResponseToAppFile(fileResponse, extras) {
4996
+ const fileName = fileResponse.fileName ?? '';
4997
+ const fileExtension = fileName.split('.').pop()?.toLowerCase() || '';
4998
+ const serverFileId = fileResponse.fileId;
4999
+ return {
5000
+ fileName,
5001
+ baseName: fileName.split('.').slice(0, -1).join('.') || '',
5002
+ fileId: serverFileId,
5003
+ uid: serverFileId != null ? String(serverFileId) : crypto.randomUUID(),
5004
+ type: fileExtension,
5005
+ size: fileResponse.fileSize || 0,
5006
+ url: fileResponse.url || '',
5007
+ imagePreviewUrl: fileResponse.thumbnailUrl ?? '',
5008
+ file: fileResponse.file ?? null,
5009
+ pageCount: fileResponse.pageCount ?? undefined,
5010
+ tags: extras.tags,
5011
+ tagChanged: false,
5012
+ fileNameChanged: false,
5013
+ categoryTag: extras.categoryTag,
5014
+ base64Url: null,
5015
+ };
5016
+ }
4962
5017
  static async resolveFile(fileResponse) {
4963
5018
  return (fileResponse.file ??
4964
5019
  (await DropZoneDocumentsHelper.fetchFileAsFile(fileResponse)));
@@ -5226,7 +5281,7 @@ class DropZoneComponent {
5226
5281
  // Variables
5227
5282
  docsRatios = new Map();
5228
5283
  categoryTag = null;
5229
- clientFileId = 0;
5284
+ nextClientFileId = -1;
5230
5285
  lastFilesSignature = null;
5231
5286
  // Computed Signals
5232
5287
  cropDimensions = computed(() => {
@@ -5283,7 +5338,8 @@ class DropZoneComponent {
5283
5338
  const width = this.drawerViewportWidth();
5284
5339
  const fitted = width <= 0
5285
5340
  ? 1
5286
- : Math.max(1, Math.floor((width + DROP_ZONE_CARD_SLIDER.GAP_PX) / DROP_ZONE_CARD_SLIDER_ITEM_WITH_GAP_PX));
5341
+ : Math.max(1, Math.floor((width + DROP_ZONE_CARD_SLIDER.GAP_PX) /
5342
+ DROP_ZONE_CARD_SLIDER_ITEM_WITH_GAP_PX));
5287
5343
  return this.isCardSlider()
5288
5344
  ? Math.min(fitted, DROP_ZONE_CARD_SLIDER.MAX_VISIBLE_COUNT)
5289
5345
  : fitted;
@@ -5469,47 +5525,21 @@ class DropZoneComponent {
5469
5525
  return;
5470
5526
  }
5471
5527
  this.skeletonCount.set(currentFiles.length);
5472
- const newlyProcessed = await DropZoneConcurrencyHelper.mapWithConcurrency(currentFiles, FILE_PROCESSING_CONCURRENCY, async (fileResp) => {
5528
+ const mappedFiles = await DropZoneConcurrencyHelper.mapWithConcurrency(currentFiles, FILE_PROCESSING_CONCURRENCY, async (fileResp) => {
5473
5529
  if (fileResp.imagePreviewUrl)
5474
5530
  return fileResp;
5475
- const fileExtension = fileResp.fileName?.split('.').pop()?.toLowerCase() || 'pdf';
5476
- let previewUrl = fileResp?.url || '';
5477
- let pageCount;
5478
- const file = await DropZoneDocumentsHelper.resolveFile(fileResp);
5479
- const supportedBase64 = this.isImagePreviewVariant();
5480
- const base64Url = supportedBase64 && file
5481
- ? await DropZoneDocumentsHelper.fileToBase64(file)
5482
- : null;
5483
- if (file) {
5484
- const { thumbnailUrl, pageCount: pages } = await this.documentService.generateThumbnail(file);
5485
- previewUrl = DropZonePreviewUrlsHelper.track(this.previewUrlsState, thumbnailUrl);
5486
- pageCount = pages;
5487
- }
5488
- const serverFileId = fileResp.fileId || 0;
5489
- return {
5490
- fileName: fileResp.fileName || '',
5491
- baseName: fileResp.fileName?.split('.').slice(0, -1).join('.') || '',
5492
- fileId: serverFileId,
5493
- uid: serverFileId ? String(serverFileId) : crypto.randomUUID(),
5494
- type: fileExtension,
5495
- size: fileResp.fileSize || 0,
5496
- url: fileResp.url || '',
5497
- imagePreviewUrl: previewUrl,
5498
- file: file,
5499
- pageCount: pageCount,
5500
- tags: this.getTagIds(fileResp.tags || [], fileResp.tagGeneratedByUser ?? false),
5501
- tagChanged: false,
5502
- fileNameChanged: false,
5531
+ const serverFile = fileResp;
5532
+ const appFile = DropZoneDocumentsHelper.mapFileResponseToAppFile(serverFile, {
5533
+ tags: this.getTagIds(serverFile.tags || [], serverFile.tagGeneratedByUser ?? false),
5503
5534
  categoryTag: this.categoryTag,
5504
- base64Url,
5505
- };
5535
+ });
5536
+ if (appFile.imagePreviewUrl)
5537
+ return appFile;
5538
+ return this.hydrateMissingPreview(appFile, serverFile);
5506
5539
  });
5507
- const validNewFiles = newlyProcessed.filter(Boolean) || [];
5508
- if (validNewFiles.length > 0) {
5509
- this.releaseUnusedPreviewUrls(validNewFiles);
5510
- this.docs.set(validNewFiles);
5511
- this.setImagePreviewUrl(validNewFiles[0]?.imagePreviewUrl || '');
5512
- }
5540
+ this.releaseUnusedPreviewUrls(mappedFiles);
5541
+ this.docs.set(mappedFiles);
5542
+ this.setImagePreviewUrl(mappedFiles[0]?.imagePreviewUrl || '');
5513
5543
  if (this.crop()) {
5514
5544
  this.submitCrop(true);
5515
5545
  }
@@ -5521,6 +5551,21 @@ class DropZoneComponent {
5521
5551
  ]);
5522
5552
  }
5523
5553
  }
5554
+ async hydrateMissingPreview(appFile, serverFile) {
5555
+ const file = await DropZoneDocumentsHelper.resolveFile(serverFile);
5556
+ if (!file)
5557
+ return appFile;
5558
+ const { thumbnailUrl, pageCount } = await this.documentService.generateThumbnail(file);
5559
+ return {
5560
+ ...appFile,
5561
+ file,
5562
+ imagePreviewUrl: DropZonePreviewUrlsHelper.track(this.previewUrlsState, thumbnailUrl),
5563
+ pageCount: appFile.pageCount ?? pageCount,
5564
+ base64Url: this.isImagePreviewVariant()
5565
+ ? await DropZoneDocumentsHelper.fileToBase64(file)
5566
+ : appFile.base64Url,
5567
+ };
5568
+ }
5524
5569
  updateRangeBackground(input) {
5525
5570
  if (!input)
5526
5571
  return;
@@ -5652,7 +5697,7 @@ class DropZoneComponent {
5652
5697
  return;
5653
5698
  }
5654
5699
  const processedFiles = await DropZoneConcurrencyHelper.mapWithConcurrency(toProcess, FILE_PROCESSING_CONCURRENCY, async (file) => {
5655
- const fileId = this.clientFileId++;
5700
+ const fileId = this.nextClientFileId--;
5656
5701
  const fileExtension = file.name.split('.').pop()?.toLowerCase() || '';
5657
5702
  let pageCount;
5658
5703
  const supportedBase64 = this.isImagePreviewVariant();