@jaak.ai/stamps 2.1.0-dev.8 → 2.1.0

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.
Files changed (57) hide show
  1. package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
  2. package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
  3. package/dist/cjs/{index-BfhtOB0D.js → index-Ga0t6BMe.js} +176 -119
  4. package/dist/cjs/index-Ga0t6BMe.js.map +1 -0
  5. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +5 -4
  6. package/dist/cjs/jaak-stamps-webcomponent.cjs.js.map +1 -1
  7. package/dist/cjs/jaak-stamps.cjs.entry.js +144 -409
  8. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  9. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  10. package/dist/cjs/loader.cjs.js +4 -3
  11. package/dist/cjs/loader.cjs.js.map +1 -1
  12. package/dist/collection/collection-manifest.json +1 -1
  13. package/dist/collection/components/my-component/my-component.css +1 -1
  14. package/dist/collection/components/my-component/my-component.js +53 -295
  15. package/dist/collection/components/my-component/my-component.js.map +1 -1
  16. package/dist/collection/services/CameraService.js +84 -2
  17. package/dist/collection/services/CameraService.js.map +1 -1
  18. package/dist/collection/services/DetectionService.js +7 -146
  19. package/dist/collection/services/DetectionService.js.map +1 -1
  20. package/dist/collection/services/interfaces/IDetectionService.js.map +1 -1
  21. package/dist/components/index.js +165 -113
  22. package/dist/components/index.js.map +1 -1
  23. package/dist/components/jaak-stamps.js +145 -412
  24. package/dist/components/jaak-stamps.js.map +1 -1
  25. package/dist/esm/app-globals-DQuL1Twl.js +6 -0
  26. package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
  27. package/dist/esm/{index-BP1Q4KOg.js → index-Drbzcuq-.js} +177 -119
  28. package/dist/esm/index-Drbzcuq-.js.map +1 -0
  29. package/dist/esm/jaak-stamps-webcomponent.js +5 -4
  30. package/dist/esm/jaak-stamps-webcomponent.js.map +1 -1
  31. package/dist/esm/jaak-stamps.entry.js +144 -409
  32. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  33. package/dist/esm/loader.js +4 -3
  34. package/dist/esm/loader.js.map +1 -1
  35. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  36. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js.map +1 -1
  37. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  38. package/dist/jaak-stamps-webcomponent/loader.esm.js.map +1 -1
  39. package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js +2 -0
  40. package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js.map +1 -0
  41. package/dist/jaak-stamps-webcomponent/p-Drbzcuq-.js +3 -0
  42. package/dist/jaak-stamps-webcomponent/p-Drbzcuq-.js.map +1 -0
  43. package/dist/jaak-stamps-webcomponent/p-c06e5d7b.entry.js +2 -0
  44. package/dist/jaak-stamps-webcomponent/p-c06e5d7b.entry.js.map +1 -0
  45. package/dist/types/components/my-component/my-component.d.ts +1 -27
  46. package/dist/types/components.d.ts +1 -3
  47. package/dist/types/services/CameraService.d.ts +1 -0
  48. package/dist/types/services/DetectionService.d.ts +1 -9
  49. package/dist/types/services/interfaces/IDetectionService.d.ts +0 -6
  50. package/dist/types/stencil-public-runtime.d.ts +12 -5
  51. package/package.json +3 -1
  52. package/dist/cjs/index-BfhtOB0D.js.map +0 -1
  53. package/dist/esm/index-BP1Q4KOg.js.map +0 -1
  54. package/dist/jaak-stamps-webcomponent/p-8e25497e.entry.js +0 -2
  55. package/dist/jaak-stamps-webcomponent/p-8e25497e.entry.js.map +0 -1
  56. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js +0 -3
  57. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js.map +0 -1
@@ -1,11 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-BfhtOB0D.js');
3
+ var index = require('./index-Ga0t6BMe.js');
4
+ var appGlobals = require('./app-globals-V2Kpy_OQ.js');
4
5
 
5
6
  const defineCustomElements = async (win, options) => {
6
7
  if (typeof window === 'undefined') return undefined;
7
- await index.globalScripts();
8
- return index.bootstrapLazy([["jaak-stamps.cjs",[[1,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"useDocumentDetector":[4,"use-document-detector"],"preferredCamera":[1,"preferred-camera"],"captureDelay":[2,"capture-delay"],"enableBackDocumentTimer":[4,"enable-back-document-timer"],"backDocumentTimerDuration":[2,"back-document-timer-duration"],"detectionBoxes":[32],"sideAlignment":[32],"isMaskReady":[32],"shouldMirrorVideo":[32],"showCameraSelector":[32],"isSwitchingCamera":[32],"hasDocumentDetected":[32],"cameraInfoWithAutofocus":[32],"currentStatus":[32],"performanceData":[32],"backDocumentTimerRemaining":[32],"showManualCaptureButton":[32],"performanceDegradedMode":[32],"showPerformanceMessage":[32],"captureStateVersion":[32],"processingButton":[32],"getCapturedImages":[64],"isProcessCompleted":[64],"startCapture":[64],"stopCapture":[64],"resetCapture":[64],"skipBackCapture":[64],"getStatus":[64],"preloadModel":[64],"getCameraInfo":[64],"setPreferredCamera":[64],"setCaptureDelay":[64],"getCaptureDelay":[64],"getResourceReport":[64],"forceResourceCleanup":[64]}]]]], options);
8
+ await appGlobals.globalScripts();
9
+ return index.bootstrapLazy([["jaak-stamps.cjs",[[257,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"useDocumentDetector":[4,"use-document-detector"],"preferredCamera":[1,"preferred-camera"],"captureDelay":[2,"capture-delay"],"enableBackDocumentTimer":[4,"enable-back-document-timer"],"backDocumentTimerDuration":[2,"back-document-timer-duration"],"detectionBoxes":[32],"sideAlignment":[32],"isMaskReady":[32],"shouldMirrorVideo":[32],"showCameraSelector":[32],"isSwitchingCamera":[32],"hasDocumentDetected":[32],"cameraInfoWithAutofocus":[32],"currentStatus":[32],"performanceData":[32],"backDocumentTimerRemaining":[32],"showManualCaptureButton":[32],"performanceDegradedMode":[32],"showPerformanceMessage":[32],"captureStateVersion":[32],"processingButton":[32],"getCapturedImages":[64],"isProcessCompleted":[64],"startCapture":[64],"stopCapture":[64],"resetCapture":[64],"skipBackCapture":[64],"getStatus":[64],"preloadModel":[64],"getCameraInfo":[64],"setPreferredCamera":[64],"setCaptureDelay":[64],"getCaptureDelay":[64]}]]]], options);
9
10
  };
10
11
 
11
12
  exports.setNonce = index.setNonce;
@@ -1 +1 @@
1
- {"version":3,"file":"loader.cjs.js","sources":["@lazy-external-entrypoint?app-data=conditional"],"sourcesContent":["export { setNonce } from '@stencil/core';\nimport { bootstrapLazy } from '@stencil/core';\nimport { globalScripts } from '@stencil/core/internal/app-globals';\nexport const defineCustomElements = async (win, options) => {\n if (typeof window === 'undefined') return undefined;\n await globalScripts();\n return bootstrapLazy([/*!__STENCIL_LAZY_DATA__*/], options);\n};\n"],"names":["globalScripts","bootstrapLazy"],"mappings":";;;;AAGY,MAAC,oBAAoB,GAAG,OAAO,GAAG,EAAE,OAAO,KAAK;AAC5D,EAAE,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,OAAO,SAAS;AACrD,EAAE,MAAMA,mBAAa,EAAE;AACvB,EAAE,OAAOC,mBAAa,CAAC,4BAA4B,EAAE,OAAO,CAAC;AAC7D;;;;;"}
1
+ {"version":3,"file":"loader.cjs.js","sources":["@lazy-external-entrypoint?app-data=conditional"],"sourcesContent":["export { setNonce } from '@stencil/core';\nimport { bootstrapLazy } from '@stencil/core';\nimport { globalScripts } from '@stencil/core/internal/app-globals';\nexport const defineCustomElements = async (win, options) => {\n if (typeof window === 'undefined') return undefined;\n await globalScripts();\n return bootstrapLazy([/*!__STENCIL_LAZY_DATA__*/], options);\n};\n"],"names":["globalScripts","bootstrapLazy"],"mappings":";;;;;AAGY,MAAC,oBAAoB,GAAG,OAAO,GAAG,EAAE,OAAO,KAAK;AAC5D,EAAE,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,OAAO,SAAS;AACrD,EAAE,MAAMA,wBAAa,EAAE;AACvB,EAAE,OAAOC,mBAAa,CAAC,4BAA4B,EAAE,OAAO,CAAC;AAC7D;;;;;"}
@@ -4,7 +4,7 @@
4
4
  ],
5
5
  "compiler": {
6
6
  "name": "@stencil/core",
7
- "version": "4.33.1",
7
+ "version": "4.36.3",
8
8
  "typescriptVersion": "5.5.4"
9
9
  },
10
10
  "collections": [],
@@ -439,7 +439,7 @@ video {
439
439
  border-top: none;
440
440
  border-left: none;
441
441
  transform: rotate(45deg);
442
- animation: drawCheck 0.4s ease-out 0.2s both;
442
+ /* animation: drawCheck 0.4s ease-out 0.2s both; */ /* Deshabilitado - check aparece completo */
443
443
  }
444
444
 
445
445
  .success-text {
@@ -71,6 +71,7 @@ export class JaakStamps {
71
71
  alignmentStartTime;
72
72
  alignmentTimer;
73
73
  backDocumentTimer;
74
+ orientationTimer;
74
75
  // Performance monitoring
75
76
  performanceMetrics = {
76
77
  fps: 0,
@@ -174,7 +175,7 @@ export class JaakStamps {
174
175
  if (!window.ort) {
175
176
  this.updateStatus('Preparando herramientas...', 'Configurando funciones de captura', 'initializing');
176
177
  const script = document.createElement('script');
177
- script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js';
178
+ script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.min.js';
178
179
  document.head.appendChild(script);
179
180
  await new Promise((resolve) => {
180
181
  script.onload = () => {
@@ -255,6 +256,18 @@ export class JaakStamps {
255
256
  });
256
257
  resizeObserver.observe(this.detectionContainer.parentElement);
257
258
  }
259
+ // Handle mobile device orientation changes
260
+ window.addEventListener('orientationchange', () => {
261
+ // Clear any existing orientation timer
262
+ if (this.orientationTimer) {
263
+ clearTimeout(this.orientationTimer);
264
+ }
265
+ // Add delay to ensure video dimensions are updated after rotation
266
+ this.orientationTimer = window.setTimeout(() => {
267
+ this.handleResize();
268
+ this.orientationTimer = undefined;
269
+ }, 300);
270
+ });
258
271
  }
259
272
  handleResize() {
260
273
  if (this.detectionContainer) {
@@ -411,13 +424,7 @@ export class JaakStamps {
411
424
  }
412
425
  try {
413
426
  this.exitSession();
414
- // Aggressive cleanup when stopping capture
415
- const cleanupResult = await this.aggressiveResourceCleanup();
416
- return {
417
- success: true,
418
- resourcesFreed: cleanupResult.freed,
419
- cleanupErrors: cleanupResult.errors
420
- };
427
+ return { success: true };
421
428
  }
422
429
  catch (error) {
423
430
  return { success: false, error: error.message };
@@ -642,60 +649,11 @@ export class JaakStamps {
642
649
  // Always allow getting capture delay, even during initialization
643
650
  return this.captureDelay;
644
651
  }
645
- async getResourceReport() {
646
- // Public method to get resource usage report
647
- return this.getResourceReportInternal();
648
- }
649
- async forceResourceCleanup() {
650
- // Public method to force aggressive resource cleanup
651
- const readyCheck = this.isComponentReady();
652
- if (!readyCheck.ready) {
653
- return { success: false, error: readyCheck.message };
654
- }
655
- try {
656
- const cleanupResult = await this.aggressiveResourceCleanup();
657
- return {
658
- success: true,
659
- resourcesFreed: cleanupResult.freed,
660
- errors: cleanupResult.errors,
661
- timestamp: new Date().toISOString()
662
- };
663
- }
664
- catch (error) {
665
- return { success: false, error: error.message };
666
- }
667
- }
668
652
  // Memory and device capability detection
669
653
  checkDeviceCapabilities() {
670
654
  const deviceMemory = navigator.deviceMemory;
671
- const hardwareConcurrency = navigator.hardwareConcurrency || 1;
672
- const isLowEndDevice = hardwareConcurrency <= 2;
673
- const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
674
- const isSafari = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
675
- // Si tenemos info de memoria del dispositivo
676
- if (deviceMemory && deviceMemory < 4) {
677
- return {
678
- canUseML: false,
679
- reason: `Memoria del dispositivo (${deviceMemory}GB) insuficiente para detección automática. Modo manual activado para mejor rendimiento.`,
680
- memoryMB: deviceMemory * 1024
681
- };
682
- }
683
- // Dispositivos móviles de gama baja
684
- if (isMobile && isLowEndDevice) {
685
- return {
686
- canUseML: false,
687
- reason: 'Dispositivo móvil optimizado detectado. Modo manual activado para mejor rendimiento y duración de batería.',
688
- memoryMB: null
689
- };
690
- }
691
- // Safari tiene limitaciones conocidas con WASM
692
- if (isSafari) {
693
- return {
694
- canUseML: false,
695
- reason: 'Safari detectado. Modo manual activado por compatibilidad optimizada con este navegador.',
696
- memoryMB: null
697
- };
698
- }
655
+ // Siempre intentar usar ML, independientemente del dispositivo
656
+ // Las restricciones anteriores no eran confiables
699
657
  return {
700
658
  canUseML: true,
701
659
  reason: 'Dispositivo compatible con detección automática.',
@@ -821,6 +779,12 @@ export class JaakStamps {
821
779
  this.videoRef.onloadedmetadata = async () => {
822
780
  await this.videoRef.play();
823
781
  this.stateManager.updateCaptureState({ isVideoActive: true });
782
+ // Recalculate mask dimensions when new camera stream loads
783
+ if (this.detectionContainer) {
784
+ const container = this.detectionContainer.parentElement;
785
+ const rect = container.getBoundingClientRect();
786
+ this.updateMaskDimensions(rect);
787
+ }
824
788
  resolve();
825
789
  };
826
790
  });
@@ -992,6 +956,10 @@ export class JaakStamps {
992
956
  clearTimeout(this.alignmentTimer);
993
957
  this.alignmentTimer = undefined;
994
958
  }
959
+ if (this.orientationTimer) {
960
+ clearTimeout(this.orientationTimer);
961
+ this.orientationTimer = undefined;
962
+ }
995
963
  // Liberar recursos de ONNX al limpiar el componente
996
964
  this.releaseOnnxResources();
997
965
  if (this.performanceUpdateInterval) {
@@ -1000,182 +968,11 @@ export class JaakStamps {
1000
968
  }
1001
969
  // Clear canvas pool
1002
970
  this.canvasPool = [];
1003
- // Clean DOM references and memory leaks
1004
- this.cleanupDOMReferences();
1005
971
  this.detectionBoxes = [];
1006
972
  this.alignmentStartTime = undefined;
1007
973
  this.hasDocumentDetected = false;
1008
974
  this.serviceContainer?.cleanup();
1009
975
  }
1010
- // AGGRESSIVE RESOURCE CLEANUP METHODS
1011
- // Clean DOM references and memory leaks
1012
- cleanupDOMReferences() {
1013
- // Remove event listeners that could maintain references
1014
- if (this.videoRef) {
1015
- // Remove common event listeners (if any were added)
1016
- this.videoRef.srcObject = null;
1017
- this.videoRef = undefined;
1018
- }
1019
- // Clean detection container
1020
- if (this.detectionContainer) {
1021
- this.detectionContainer = undefined;
1022
- }
1023
- // Clean references to images in the DOM and revoke blob URLs
1024
- const images = this.el.shadowRoot?.querySelectorAll('img');
1025
- images?.forEach(img => {
1026
- if (img.src.startsWith('blob:')) {
1027
- URL.revokeObjectURL(img.src);
1028
- }
1029
- img.src = '';
1030
- });
1031
- }
1032
- // Clear browser cache and storage
1033
- async clearBrowserCache() {
1034
- try {
1035
- // 1. Clear Service Worker cache if exists
1036
- if ('serviceWorker' in navigator) {
1037
- const registrations = await navigator.serviceWorker.getRegistrations();
1038
- await Promise.all(registrations.map(registration => registration.unregister()));
1039
- }
1040
- // 2. Clear Cache API specific to the component
1041
- const cacheNames = await caches.keys();
1042
- const componentCaches = cacheNames.filter(name => name.includes('jaak') || name.includes('stamps'));
1043
- await Promise.all(componentCaches.map(cacheName => caches.delete(cacheName)));
1044
- // 3. Force garbage collection if available (only in dev)
1045
- if (this.debug && window.gc) {
1046
- window.gc();
1047
- }
1048
- }
1049
- catch (error) {
1050
- console.warn('Error clearing browser cache:', error);
1051
- }
1052
- }
1053
- // Clear local storage specific to the component
1054
- async clearLocalStorage() {
1055
- try {
1056
- // Clear localStorage specific to the component
1057
- const keysToRemove = [];
1058
- for (let i = 0; i < localStorage.length; i++) {
1059
- const key = localStorage.key(i);
1060
- if (key && (key.includes('jaak') || key.includes('onnx') || key.includes('stamps'))) {
1061
- keysToRemove.push(key);
1062
- }
1063
- }
1064
- keysToRemove.forEach(key => localStorage.removeItem(key));
1065
- // Clear sessionStorage
1066
- const sessionKeysToRemove = [];
1067
- for (let i = 0; i < sessionStorage.length; i++) {
1068
- const key = sessionStorage.key(i);
1069
- if (key && (key.includes('jaak') || key.includes('onnx'))) {
1070
- sessionKeysToRemove.push(key);
1071
- }
1072
- }
1073
- sessionKeysToRemove.forEach(key => sessionStorage.removeItem(key));
1074
- }
1075
- catch (error) {
1076
- console.warn('Error clearing local storage:', error);
1077
- }
1078
- }
1079
- // Aggressive resource cleanup combining all strategies
1080
- async aggressiveResourceCleanup() {
1081
- const freed = [];
1082
- const errors = [];
1083
- try {
1084
- // 1. Release ONNX resources
1085
- this.releaseOnnxResources();
1086
- freed.push('ONNX models');
1087
- // 2. Clear model cache in detection service
1088
- if (this.detectionService) {
1089
- await this.detectionService.clearModelCache();
1090
- freed.push('Model cache');
1091
- }
1092
- // 3. Clear browser cache
1093
- await this.clearBrowserCache();
1094
- freed.push('Browser cache');
1095
- // 4. Clear local storage
1096
- await this.clearLocalStorage();
1097
- freed.push('Local storage');
1098
- // 5. Clean DOM references
1099
- this.cleanupDOMReferences();
1100
- freed.push('DOM references');
1101
- // 6. Optimize canvas pools
1102
- if (this.detectionService) {
1103
- this.detectionService.optimizeCanvasPool(0);
1104
- freed.push('Canvas pools');
1105
- }
1106
- // 7. Clear component canvas pool
1107
- this.canvasPool = [];
1108
- freed.push('Component canvas pool');
1109
- // 8. Force garbage collection (if available)
1110
- if (this.debug && window.gc) {
1111
- window.gc();
1112
- freed.push('Garbage collection');
1113
- }
1114
- }
1115
- catch (error) {
1116
- errors.push(error.message);
1117
- }
1118
- return { freed, errors };
1119
- }
1120
- // Progressive resource release after front capture
1121
- async onFrontCaptureComplete() {
1122
- try {
1123
- // Release classification model if not needed for back
1124
- if (this.detectionService && !this.useDocumentClassification) {
1125
- await this.detectionService.releaseMobileNetResources();
1126
- }
1127
- // Optimize canvas pool to minimum needed for back capture
1128
- if (this.detectionService) {
1129
- this.detectionService.optimizeCanvasPool(1);
1130
- }
1131
- // Reduce component canvas pool
1132
- while (this.canvasPool.length > 1) {
1133
- const canvas = this.canvasPool.pop();
1134
- if (canvas) {
1135
- const ctx = canvas.getContext('2d');
1136
- if (ctx) {
1137
- ctx.clearRect(0, 0, canvas.width, canvas.height);
1138
- }
1139
- }
1140
- }
1141
- if (this.debug) {
1142
- console.log('🧹 Progressive cleanup after front capture completed');
1143
- }
1144
- }
1145
- catch (error) {
1146
- console.warn('Error in progressive cleanup:', error);
1147
- }
1148
- }
1149
- // Resource reporting for debugging
1150
- getResourceReportInternal() {
1151
- const report = {
1152
- timestamp: new Date().toISOString(),
1153
- component: {
1154
- hasVideoStream: !!this.videoStream,
1155
- hasAnimationFrame: !!this.animationId,
1156
- canvasPoolSize: this.canvasPool.length,
1157
- detectionBoxesCount: this.detectionBoxes.length,
1158
- performanceMonitorActive: !!this.performanceUpdateInterval
1159
- }
1160
- };
1161
- // Add detection service stats if available
1162
- if (this.detectionService) {
1163
- report.detectionService = {
1164
- isModelLoaded: this.detectionService.isModelLoaded(),
1165
- canvasPoolStats: this.detectionService.getPoolStats()
1166
- };
1167
- }
1168
- // Add memory info if available
1169
- if ('memory' in performance) {
1170
- const memInfo = performance.memory;
1171
- report.memory = {
1172
- usedJSHeapSize: Math.round(memInfo.usedJSHeapSize / 1048576), // MB
1173
- totalJSHeapSize: Math.round(memInfo.totalJSHeapSize / 1048576), // MB
1174
- jsHeapSizeLimit: Math.round(memInfo.jsHeapSizeLimit / 1048576) // MB
1175
- };
1176
- }
1177
- return report;
1178
- }
1179
976
  render() {
1180
977
  const captureState = this.stateManager?.getCaptureState() || {
1181
978
  isVideoActive: false,
@@ -1186,7 +983,7 @@ export class JaakStamps {
1186
983
  isCapturing: false
1187
984
  };
1188
985
  const cameraInfo = this.cameraInfoWithAutofocus;
1189
- return (h("div", { key: 'ca44b9eacbde9f688f2c41aa21ad35a2b882002b', class: "detector-container" }, h("div", { key: '86c7b5d31ed69276b62fa43e01c92b0c0b9f298d', class: "video-container" }, h("video", { key: 'bb310544c17ae734d8b42ed2617748c2f69743ff', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '078a79a0c6386ca6c040e629acbf4f52f12d8e29', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
986
+ return (h("div", { key: 'f9cbca2fd6b8548a29ace7fcb972b53f402f61af', class: "detector-container" }, h("div", { key: '4f3cac734eb6bfd44a8de644eadca17e7893e11a', class: "video-container" }, h("video", { key: '5e15a38c989a72d5274281272d41ba064447ca6f', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '38c8ad8b691db60e9b5a2a8b641fe6febbeacfca', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
1190
987
  position: 'absolute',
1191
988
  left: `${box.x}px`,
1192
989
  top: `${box.y}px`,
@@ -1195,9 +992,9 @@ export class JaakStamps {
1195
992
  border: '2px solid #32406C',
1196
993
  pointerEvents: 'none',
1197
994
  boxSizing: 'border-box'
1198
- } })))), this.isMaskReady && (h("div", { key: '990015ff5b2ded89405dd2b891c027aad8788f3e', class: "overlay-mask" }, h("div", { key: 'dd9145140987addb1b6e4cc2119b8e9f89003726', class: "card-outline" }, h("div", { key: 'e8f4ec692a8b80c7a98075e4f708b79a272db67b', class: "side side-top" }), h("div", { key: '2577253b40425ecdcb3dd51b2f4a43c15c83ca79', class: "side side-right" }), h("div", { key: '30f4454020c00cf4fb92308af5ecf1843ec24005', class: "side side-bottom" }), h("div", { key: '3459f634987b8396106fff23fa1c99b295ee7d0a', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '84f4d70947e211a9c6b296531d53420223d2ca34', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '7c28e86e8de6c33bf7d7baab3083c5f6a0ab060f', class: "back-capture-section" }, h("div", { key: '27bdcf9cfe9790c4bbad484423f6f4c353ccf0b3', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode) && (h("button", { key: 'ed0320b1df412bf53cbe4e4119f6d769926eb2c5', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: '0bba706c8ebda59c33faca8e97b7536146462d21', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: 'b072c46b25d16a04c5e0a8f3975d8aa8d24576d5', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: 'efd0827d0f19c9072d49d1b3c0046ef6c95a842c', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
995
+ } })))), this.isMaskReady && (h("div", { key: 'c56fde56b7a86a4e8a4cf558745291ea5cde12fd', class: "overlay-mask" }, h("div", { key: '04ed3f01f271dc84eed594cb4b60c2453645bd41', class: "card-outline" }, h("div", { key: '648bd423a5e886d4768115237de5896c7223b30b', class: "side side-top" }), h("div", { key: 'b8878059493ca61961b9b3c82ecc18b50b79ac85', class: "side side-right" }), h("div", { key: '09e5ad64ff33dbd5c112bf52b71e14409ab6aa65', class: "side side-bottom" }), h("div", { key: 'b8ba3d83c9bc1b4a0da859d7ed4b9a15eaddcc2a', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '3279701a240f77ac96e68a34ad95c099340c9a6a', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '2adf96d0a57e482372fd9586229dac2301b64fd4', class: "back-capture-section" }, h("div", { key: '305a147c9cfee854c60ac946a48a1d21b2792725', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: '43270a0647f39307229c540dd5130fb58b1ff4fb', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: 'eb4666603774564eef95a120ac13faeb9e10c8b4', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: 'cac667d9548ae2314ad5a677c5ed90f25184f728', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: '0af7aa4106ce189ae2d79bec78ede01abe25b1e7', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
1199
996
  ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
1200
- : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'bd0303e8ce85211e4c68fc3cd79545db7c74288b', class: "camera-controls" }, h("button", { key: 'e4327d260b988b67e0de3654c72f24455cd3bbbd', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '35da16baf4c62466c2a66650209a1daf842c0db2', class: "camera-selector-dropdown" }, h("div", { key: '7035dd0e22f614cf239a015c6d59531b68fa74a9', class: "camera-selector-header" }, h("span", { key: 'ae026f31931f52ea0daf72391a9de4ff9e4b88f1' }, "Seleccionar C\u00E1mara"), h("button", { key: '40f2ba0770bafea71fedbf849938010e743be776', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '6f26927094a724a35ebb07ef701caf14f296a837', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '082236981c369f8fd487f036439b16e6560514be', class: "device-info" }, h("small", { key: 'ccbbfa0bca96395f574bda71103338ae9226f709' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '6baa487409503777e90453b39fd30649941cbbe4', class: "manual-capture-section" }, h("button", { key: '893f4715ca3315613f779603f178459955f686f0', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: '7c30b680fe84f4c8227beba45d8416f1edb8348f', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: 'd8ef052cf67d7bda4b3534febf96efa2cdcc6bf7', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '3dae7634e770dda2655b1042ec8fb997b3cb2220', class: "flip-animation" }, h("div", { key: 'a977fc5e889369121bacc06cf5213dfee39d858d', class: "id-card-icon" }), h("div", { key: '4f052cdc8c7b493cddce90e108e976325c9bab8e', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '5117cd6e63e1e0763c1503f6f60f3c7ef60dd665', class: "success-animation" }, h("div", { key: 'd11128c45c7118915cc0dd9c25845bb55b4b3eb2', class: "check-icon" }), h("div", { key: '693e197bf8a4c91ac7ddedb457d15aa3aa46a5d5', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '89caaa9d78eb522e0fadfd1c0e844e05d29b8286', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '3f41d40b05b71e13e7e1d0c0e980b48308cba9d6', class: "status-spinner" })), h("div", { key: '8674480928f4f4a77099c0600ed84f0e27903379', class: "status-content" }, h("div", { key: 'e88f4044ab8115a6a5cbb78cc4030975eef9149a', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: 'ad581e42c30c304b837711549148c11b801dee5e', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '1b371c1b47f3ba699885db00fef52eb448f9e245', class: "performance-monitor" }, h("div", { key: '8b9ac60449a15e9fb966c329b2e6c9285c0228c0', class: "performance-expanded" }, h("div", { key: '760c11a3ed28e248a144d53a92fd8adee6822ff2', class: "metrics-row" }, h("div", { key: '858ab8b106f1d12210e4e15c423ab3bab11bdb60', class: "metric-compact" }, h("span", { key: '65fe2479c3822d99452e7e5faa93c25a80765024', class: "metric-label" }, "FPS"), h("span", { key: '9faf7763d1284a6f3c1e15fb0f3c99f1d45bb4dc', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'c95ed8fa8101f42bfba5cc8ca7debbad028caf42', class: "metric-compact" }, h("span", { key: '3555b3778cb71e959d132d6aa563f58f757915d8', class: "metric-label" }, "MEM"), h("span", { key: 'd72b0491147a6f80dcf33f5d72dd8dae5898f44a', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'cd4dc81f28f9e59a36a0295dde7bfee89f50d3e2', class: "metrics-row" }, h("div", { key: 'c43d8624c5da256ce3e97f67b022bdd98fb04e07', class: "metric-compact" }, h("span", { key: 'adb402d83809a90580b81544f31b5331bdff59dd', class: "metric-label" }, "INF"), h("span", { key: 'e48c9814c08acbe321460a29e42cb49b0eab38ff', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '71517f9279e9a6aa0d5b02e2169db868ca3fb676', class: "metric-compact" }, h("span", { key: '3ddbcc56b137aea702a40f900178e8e16efd146e', class: "metric-label" }, "FRAME"), h("span", { key: 'd3a70afb511d3f72b485b3a1cb922876faa62b11', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'a3b62cdbe830b1024ab96f7fb726825df24fecdc', class: "metrics-row" }, h("div", { key: '95471e5cdde748d1ce6bdee3540740dd3aa66865', class: "metric-compact" }, h("span", { key: 'c93e01c0bdc67621c3a666357d2477b7a5275d52', class: "metric-label" }, "DET"), h("span", { key: 'ef33c86a83101b0989b14c7f1ab0ce0b331b397f', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'e14d56128bf96337e4c3859f8e4003e001e8e953', class: "metric-compact" }, h("span", { key: '8aa828632f0a977a27ed377f103bb8d5e7e0ed1a', class: "metric-label" }, "RATE"), h("span", { key: '59035c473b5a747a27f774e2554322a084b6d19f', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '4d0c2de00954416faac30ab622fb21f36c932aca', class: "watermark" }, h("img", { key: 'd8f775428ebb3ba86a943ca73b074db2180d0c29', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
997
+ : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'de6e5c4fad4d4d996b894457c9af52bc71e533fb', class: "camera-controls" }, h("button", { key: 'cfddcf2420d5f5923a6b02ca446bbe1b8e9fc5e4', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '5fb73f958b9a5a6f9242032c4530b0bdab84f6c5', class: "camera-selector-dropdown" }, h("div", { key: '8ee2d26b1001e571e7b6c326e927926fa08287fd', class: "camera-selector-header" }, h("span", { key: '78350b0fb1bd933f7c8c59d8dab0b7122ffbe363' }, "Seleccionar C\u00E1mara"), h("button", { key: 'bb750e0ddd5a1ee5ff96bd57805a7f90b8821e9f', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'd0f6343cf1b7367f3da33ec8cf64891109d923b8', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'c9642fbfb0acea766d3f0542f4cc9f17f4af4d7b', class: "device-info" }, h("small", { key: 'b6e9507ff7addf011f339f6c22a88a96b40db68a' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '04ae9262409284782850b90945eb7038673e2097', class: "manual-capture-section" }, h("button", { key: '27c315e503ccba468b89ebd58d6b70f40ddd06ba', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: '8f2dcd2df9a218b37eb0b8204a8724362cfeaa53', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: '6fd6fe1d0213b01c8119a67fb8108f73227feee1', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: 'fba3816b48b99ca64510ecbefc0d41431569c9ae', class: "flip-animation" }, h("div", { key: 'beea1c8245b5d81f1008efc6d1b079a61c821e7f', class: "id-card-icon" }), h("div", { key: 'f0fbc34f619a653e2c0ade764ca99e7aa582d157', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'e4a0e6d31112e3a50024d1d0430b4ad997049fe7', class: "success-animation" }, h("div", { key: '5dd3f781f55630bc904c81207548ae35bc79b452', class: "check-icon" }), h("div", { key: 'a10ebc557582325091efb0abd12d62b27a43b98c', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '975865955dee1803b5215ecf049701c98b324855', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '84f6f67202e26ce80f7fc5d5f321e23b5bc55c57', class: "status-spinner" })), h("div", { key: 'a1ae56ed156e8feb279a1bf160f749c5d0b5ce45', class: "status-content" }, h("div", { key: 'd62932554cea257ce19763df26e0ba702e50eeca', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: 'c5506fa12dd0d37d26dc26c9f2381c843330451f', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '2097eda63185f336f7319014fae2ef6db1e41761', class: "performance-monitor" }, h("div", { key: 'd611c494c6b1a5930ef64aebdcba41e5d94c9ee6', class: "performance-expanded" }, h("div", { key: '800d46831e7b9bec260d9c5e67ea1a3eb9c2933e', class: "metrics-row" }, h("div", { key: 'dd0db1faa9050d98e71da4b5cd26a4a484c37c64', class: "metric-compact" }, h("span", { key: 'f0e6ea61a35ddb2ae5c2a6aff8c255a02c5c1219', class: "metric-label" }, "FPS"), h("span", { key: 'cbf4df4d142f6f01e45f566a8ede8fbbf29ad673', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: '83861ad31fa46c8199a5583e4b3f8eefd44bacd6', class: "metric-compact" }, h("span", { key: '41b8de4cda47959dfc9df393e95fdadde534dd21', class: "metric-label" }, "MEM"), h("span", { key: 'b268f13cc78066e240ed158f1443113a94827aff', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: '9f9a9d0690906b186492af23b900c5fa0f5cff89', class: "metrics-row" }, h("div", { key: '84fa6e453dc36e4a74e8b573447b17230766229e', class: "metric-compact" }, h("span", { key: 'f17d52899090c89f532d74c552dd8c5338fc2d83', class: "metric-label" }, "INF"), h("span", { key: '2beca0d7ce55ed574f6b01efc086c5846983e024', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '981e300cf076e81bfe946974f6cffd63619eacde', class: "metric-compact" }, h("span", { key: '3dfb0c996a69eb87b0f711322675cad69c471146', class: "metric-label" }, "FRAME"), h("span", { key: '3ae2ac6e90cda77f23e559f3197c3b761f9bdc40', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '2c51216838d87728d9d7764e5ba8a50fa02eb493', class: "metrics-row" }, h("div", { key: 'eda810ffb80ec38ab84583f59b26706f90a50fc9', class: "metric-compact" }, h("span", { key: '978ba9c0c67d6da6b29b3535af33a314bab9276a', class: "metric-label" }, "DET"), h("span", { key: '3e5e169fd4a3906283d8f918b5bbc7c5df6ccd0f', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'b4b915c745e35c09470a4dc5edfc112d32cfb8b6', class: "metric-compact" }, h("span", { key: '3e2a7b88a4446813c955efb0dfa9e2958e8e1448', class: "metric-label" }, "RATE"), h("span", { key: 'f4f073f7ee622167a241c6a1c535ef580c13d9ab', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '76c556e92f6d7980539f1a30efe8751f665164fb', class: "watermark" }, h("img", { key: 'af23e115d6b4e92a72e55d6d98fde0e4b1d09e9b', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
1201
998
  }
1202
999
  // Utility methods
1203
1000
  updateDetectionBoxes(boxes) {
@@ -1394,8 +1191,8 @@ export class JaakStamps {
1394
1191
  if (captureState.step === 'front') {
1395
1192
  this.stateManager.setCapturedImages({
1396
1193
  front: {
1397
- fullFrame: captureCanvas.toDataURL('image/png'),
1398
- cropped: croppedCanvas.toDataURL('image/png')
1194
+ fullFrame: captureCanvas.toDataURL('image/jpeg'),
1195
+ cropped: croppedCanvas.toDataURL('image/jpeg')
1399
1196
  }
1400
1197
  });
1401
1198
  // Check if document classification is enabled (independent of detector)
@@ -1421,8 +1218,6 @@ export class JaakStamps {
1421
1218
  showFlipAnimation: true
1422
1219
  });
1423
1220
  this.triggerRerender();
1424
- // Progressive resource cleanup after front capture
1425
- await this.onFrontCaptureComplete();
1426
1221
  setTimeout(() => {
1427
1222
  this.stateManager.updateCaptureState({
1428
1223
  showFlipAnimation: false,
@@ -1437,8 +1232,8 @@ export class JaakStamps {
1437
1232
  else if (captureState.step === 'back') {
1438
1233
  this.stateManager.setCapturedImages({
1439
1234
  back: {
1440
- fullFrame: captureCanvas.toDataURL('image/png'),
1441
- cropped: croppedCanvas.toDataURL('image/png')
1235
+ fullFrame: captureCanvas.toDataURL('image/jpeg'),
1236
+ cropped: croppedCanvas.toDataURL('image/jpeg')
1442
1237
  }
1443
1238
  });
1444
1239
  this.completeProcess(false);
@@ -1476,8 +1271,8 @@ export class JaakStamps {
1476
1271
  if (captureState.step === 'front') {
1477
1272
  this.stateManager.setCapturedImages({
1478
1273
  front: {
1479
- fullFrame: captureCanvas.toDataURL('image/png'),
1480
- cropped: croppedCanvas.toDataURL('image/png')
1274
+ fullFrame: captureCanvas.toDataURL('image/jpeg'),
1275
+ cropped: croppedCanvas.toDataURL('image/jpeg')
1481
1276
  }
1482
1277
  });
1483
1278
  // Check if document classification is enabled
@@ -1498,8 +1293,6 @@ export class JaakStamps {
1498
1293
  isDetectionPaused: true,
1499
1294
  showFlipAnimation: true
1500
1295
  });
1501
- // Progressive resource cleanup after front capture
1502
- await this.onFrontCaptureComplete();
1503
1296
  setTimeout(() => {
1504
1297
  this.stateManager.updateCaptureState({
1505
1298
  showFlipAnimation: false,
@@ -1511,8 +1304,8 @@ export class JaakStamps {
1511
1304
  else if (captureState.step === 'back') {
1512
1305
  this.stateManager.setCapturedImages({
1513
1306
  back: {
1514
- fullFrame: captureCanvas.toDataURL('image/png'),
1515
- cropped: croppedCanvas.toDataURL('image/png')
1307
+ fullFrame: captureCanvas.toDataURL('image/jpeg'),
1308
+ cropped: croppedCanvas.toDataURL('image/jpeg')
1516
1309
  }
1517
1310
  });
1518
1311
  this.completeProcess(false);
@@ -1638,10 +1431,13 @@ export class JaakStamps {
1638
1431
  this.useDocumentDetector = false; // Desactivar detector automático
1639
1432
  // Actualizar el estado con mensaje de error
1640
1433
  this.updateStatus('Modo manual activado', errorMessage, 'error');
1641
- // Ocultar mensaje después de 5 segundos
1642
- setTimeout(() => {
1643
- this.updateStatus('Captura manual', 'Use el botón para capturar', 'ready');
1644
- }, 5000);
1434
+ // Continuar con la configuración de cámara para mostrar el video
1435
+ this.continueWithCameraSetup().catch(() => {
1436
+ // Si falla la configuración de cámara, mantener el mensaje de error pero cambiar el estado
1437
+ setTimeout(() => {
1438
+ this.updateStatus('Captura manual', 'Use el botón para capturar', 'ready');
1439
+ }, 5000);
1440
+ });
1645
1441
  }
1646
1442
  stopPerformanceMonitoring() {
1647
1443
  // Nota: No necesitamos limpiar más variables porque ya no se usarán
@@ -1677,16 +1473,6 @@ export class JaakStamps {
1677
1473
  setTimeout(() => {
1678
1474
  this.stateManager.updateCaptureState({ showSuccessAnimation: false });
1679
1475
  }, 3000);
1680
- // Aggressive cleanup after process completion with delay
1681
- setTimeout(async () => {
1682
- const cleanupResult = await this.aggressiveResourceCleanup();
1683
- if (this.debug) {
1684
- console.log('🧹 Post-completion cleanup:', cleanupResult.freed);
1685
- if (cleanupResult.errors.length > 0) {
1686
- console.warn('⚠️ Cleanup errors:', cleanupResult.errors);
1687
- }
1688
- }
1689
- }, 1000); // Wait 1 second after completion
1690
1476
  }
1691
1477
  stopDetection() {
1692
1478
  if (this.animationId) {
@@ -1738,6 +1524,12 @@ export class JaakStamps {
1738
1524
  try {
1739
1525
  // Close the selector immediately when user selects a camera
1740
1526
  this.showCameraSelector = false;
1527
+ // Check if user selected the same camera that's already active
1528
+ const currentCameraId = this.cameraService.getSelectedCameraId();
1529
+ if (currentCameraId === cameraId) {
1530
+ // Same camera selected, just close the selector without switching
1531
+ return;
1532
+ }
1741
1533
  this.isSwitchingCamera = true;
1742
1534
  // Stop current video stream
1743
1535
  if (this.videoStream) {
@@ -2268,7 +2060,7 @@ export class JaakStamps {
2268
2060
  },
2269
2061
  "stopCapture": {
2270
2062
  "complexType": {
2271
- "signature": "() => Promise<{ success: boolean; resourcesFreed: string[]; cleanupErrors: string[]; error?: undefined; } | { success: boolean; error: any; resourcesFreed?: undefined; cleanupErrors?: undefined; }>",
2063
+ "signature": "() => Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>",
2272
2064
  "parameters": [],
2273
2065
  "references": {
2274
2066
  "Promise": {
@@ -2276,7 +2068,7 @@ export class JaakStamps {
2276
2068
  "id": "global::Promise"
2277
2069
  }
2278
2070
  },
2279
- "return": "Promise<{ success: boolean; resourcesFreed: string[]; cleanupErrors: string[]; error?: undefined; } | { success: boolean; error: any; resourcesFreed?: undefined; cleanupErrors?: undefined; }>"
2071
+ "return": "Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>"
2280
2072
  },
2281
2073
  "docs": {
2282
2074
  "text": "",
@@ -2436,40 +2228,6 @@ export class JaakStamps {
2436
2228
  "text": "",
2437
2229
  "tags": []
2438
2230
  }
2439
- },
2440
- "getResourceReport": {
2441
- "complexType": {
2442
- "signature": "() => Promise<any>",
2443
- "parameters": [],
2444
- "references": {
2445
- "Promise": {
2446
- "location": "global",
2447
- "id": "global::Promise"
2448
- }
2449
- },
2450
- "return": "Promise<any>"
2451
- },
2452
- "docs": {
2453
- "text": "",
2454
- "tags": []
2455
- }
2456
- },
2457
- "forceResourceCleanup": {
2458
- "complexType": {
2459
- "signature": "() => Promise<{ success: boolean; resourcesFreed: string[]; errors: string[]; timestamp: string; error?: undefined; } | { success: boolean; error: any; resourcesFreed?: undefined; errors?: undefined; timestamp?: undefined; }>",
2460
- "parameters": [],
2461
- "references": {
2462
- "Promise": {
2463
- "location": "global",
2464
- "id": "global::Promise"
2465
- }
2466
- },
2467
- "return": "Promise<{ success: boolean; resourcesFreed: string[]; errors: string[]; timestamp: string; error?: undefined; } | { success: boolean; error: any; resourcesFreed?: undefined; errors?: undefined; timestamp?: undefined; }>"
2468
- },
2469
- "docs": {
2470
- "text": "",
2471
- "tags": []
2472
- }
2473
2231
  }
2474
2232
  };
2475
2233
  }