@jaak.ai/stamps 2.0.0-dev.31 → 2.0.0-dev.33
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/cjs/jaak-stamps-webcomponent.cjs.js +1 -1
- package/dist/cjs/jaak-stamps.cjs.entry.js +212 -19
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/my-component/my-component.css +248 -115
- package/dist/collection/components/my-component/my-component.js +205 -15
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/collection/services/DetectionService.js +10 -4
- package/dist/collection/services/DetectionService.js.map +1 -1
- package/dist/components/jaak-stamps.js +215 -19
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/jaak-stamps-webcomponent.js +1 -1
- package/dist/esm/jaak-stamps.entry.js +212 -19
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/p-9d1c45a9.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-9d1c45a9.entry.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +22 -0
- package/package.json +3 -3
- package/dist/jaak-stamps-webcomponent/p-5051b84e.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-5051b84e.entry.js.map +0 -1
|
@@ -16,7 +16,7 @@ var patchBrowser = () => {
|
|
|
16
16
|
|
|
17
17
|
patchBrowser().then(async (options) => {
|
|
18
18
|
await globalScripts();
|
|
19
|
-
return bootstrapLazy([["jaak-stamps",[[1,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"preferredCamera":[1,"preferred-camera"],"detectionBoxes":[32],"sideAlignment":[32],"isMaskReady":[32],"shouldMirrorVideo":[32],"showCameraSelector":[32],"currentStatus":[32],"getCapturedImages":[64],"isProcessCompleted":[64],"startCapture":[64],"stopCapture":[64],"resetCapture":[64],"skipBackCapture":[64],"getStatus":[64],"preloadModel":[64],"getCameraInfo":[64],"setPreferredCamera":[64]}]]]], options);
|
|
19
|
+
return bootstrapLazy([["jaak-stamps",[[1,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"preferredCamera":[1,"preferred-camera"],"detectionBoxes":[32],"sideAlignment":[32],"isMaskReady":[32],"shouldMirrorVideo":[32],"showCameraSelector":[32],"isSwitchingCamera":[32],"currentStatus":[32],"performanceData":[32],"isPerformanceMonitorMinimized":[32],"getCapturedImages":[64],"isProcessCompleted":[64],"startCapture":[64],"stopCapture":[64],"resetCapture":[64],"skipBackCapture":[64],"getStatus":[64],"preloadModel":[64],"getCameraInfo":[64],"setPreferredCamera":[64]}]]]], options);
|
|
20
20
|
});
|
|
21
21
|
//# sourceMappingURL=jaak-stamps-webcomponent.js.map
|
|
22
22
|
|
|
@@ -818,11 +818,17 @@ class DetectionService {
|
|
|
818
818
|
}
|
|
819
819
|
// Tolerancia para considerar que un lado está alineado (en píxeles)
|
|
820
820
|
const tolerance = alignmentTolerance;
|
|
821
|
+
// Verificar alineación de esquinas más estricta
|
|
822
|
+
// Una esquina está alineada solo si AMBOS bordes que la forman están alineados
|
|
823
|
+
const topAligned = Math.abs(docTop - maskTop) <= tolerance;
|
|
824
|
+
const rightAligned = Math.abs(docRight - maskRight) <= tolerance;
|
|
825
|
+
const bottomAligned = Math.abs(docBottom - maskBottom) <= tolerance;
|
|
826
|
+
const leftAligned = Math.abs(docLeft - maskLeft) <= tolerance;
|
|
821
827
|
return {
|
|
822
|
-
top:
|
|
823
|
-
right:
|
|
824
|
-
bottom:
|
|
825
|
-
left:
|
|
828
|
+
top: topAligned && leftAligned, // Esquina superior izquierda: borde top Y left alineados
|
|
829
|
+
right: topAligned && rightAligned, // Esquina superior derecha: borde top Y right alineados
|
|
830
|
+
bottom: bottomAligned && leftAligned, // Esquina inferior izquierda: borde bottom Y left alineados
|
|
831
|
+
left: bottomAligned && rightAligned // Esquina inferior derecha: borde bottom Y right alineados
|
|
826
832
|
};
|
|
827
833
|
}
|
|
828
834
|
isCardInFrame(box) {
|
|
@@ -974,7 +980,7 @@ class ServiceContainer {
|
|
|
974
980
|
}
|
|
975
981
|
}
|
|
976
982
|
|
|
977
|
-
const myComponentCss = ":host{display:block;width:100%;height:100%;font-family:system-ui, -apple-system, sans-serif;color:#1a1a1a}.detector-container{display:flex;flex-direction:column;align-items:center;width:100%;height:100%}h1{font-size:24px;font-weight:500;color:#333;margin:0 0 24px 0}.video-container{position:relative;width:100%;height:100%;background:#333;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}video,.detection-overlay{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,.detection-overlay.mirror{transform:rotateY(180deg)}.detection-overlay{z-index:1;pointer-events:none}video{z-index:0}.detection-box{transition:opacity 0.2s ease}.status{margin-top:16px;font-size:12px;color:#666}.overlay-mask{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:block;pointer-events:none}.card-outline{position:absolute;top:var(--mask-center-y, 50%);left:var(--mask-center-x, 50%);transform:translate(-50%, -50%);width:var(--mask-width, 88%);height:var(--mask-height, 55%);border:none;border-radius:4px;background:transparent;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7);opacity:0.8}.card-outline.perfect-match{box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7)}.side{position:absolute;background:#999;transition:background-color 0.3s ease}.side.aligned{background:#28a745}.side-top{top:0;left:0;width:100%;height:3px}.side-right{top:0;right:0;width:3px;height:100%}.side-bottom{bottom:0;left:0;width:100%;height:3px}.side-left{top:0;left:0;width:3px;height:100%}.corner{position:absolute;width:20px;height:20px;border:2px solid #999;z-index:12}.corner-tl{top:-10px;left:-10px;border-right:none;border-bottom:none}.corner-tr{top:-10px;right:-10px;border-left:none;border-bottom:none}.corner-bl{bottom:-10px;left:-10px;border-right:none;border-top:none}.corner-br{bottom:-10px;right:-10px;border-left:none;border-top:none}.corner.perfect-match{border-color:#28a745}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);color:#fff;font-size:14px;font-weight:600;text-align:center;white-space:normal;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;z-index:20}.capture-animation{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;z-index:30;pointer-events:none;animation:captureFlash 0.6s ease-out}@keyframes captureFlash{0%{opacity:0}15%{opacity:0.8}30%{opacity:0}45%{opacity:0.4}60%{opacity:0}100%{opacity:0}}.card-outline.capturing{animation:pulseGreen 0.6s ease-out}@keyframes pulseGreen{0%{border-color:#28a745;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 4px rgba(40, 167, 69, 0)}}.flip-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showFlipInstruction 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.id-card-icon{width:80px;height:50px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:8px;position:relative;animation:flipCard 2s ease-in-out infinite;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.id-card-icon::before{content:'';position:absolute;top:8px;left:8px;width:16px;height:12px;background:rgba(255, 255, 255, 0.9);border-radius:2px}.id-card-icon::after{content:'';position:absolute;top:25px;left:8px;width:64px;height:3px;background:rgba(255, 255, 255, 0.7);border-radius:1px;box-shadow:0 6px 0 rgba(255, 255, 255, 0.7), 0 12px 0 rgba(255, 255, 255, 0.7)}.flip-text{margin-top:12px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px}@keyframes showFlipInstruction{0%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}}@keyframes flipCard{0%{transform:rotateY(0deg)}50%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}.success-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showSuccessMessage 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.check-icon{width:80px;height:80px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:50%;position:relative;animation:bounceSuccess 0.6s ease-out;box-shadow:0 4px 16px rgba(108, 117, 125, 0.4);display:flex;align-items:center;justify-content:center}.check-icon::before{content:'';position:absolute;width:20px;height:35px;border:4px solid #fff;border-top:none;border-left:none;transform:rotate(45deg);animation:drawCheck 0.4s ease-out 0.2s both}.success-text{margin-top:16px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;animation:fadeInUp 0.5s ease-out 0.4s both}@keyframes showSuccessMessage{0%{opacity:0;transform:translate(-50%, -50%) scale(0.5)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.9)}}@keyframes bounceSuccess{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}@keyframes drawCheck{0%{width:0;height:0}50%{width:20px;height:0}100%{width:20px;height:35px}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}.skip-button{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateX(-50%) translateY(0)}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto}.camera-selector-button{height:40px;padding:0 16px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.6);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid rgba(255, 255, 255, 0.1)}.camera-selector-header span{font-weight:500;color:#ffffff;font-size:13px;opacity:0.9}.close-selector{width:20px;height:20px;border:none;background:none;color:rgba(255, 255, 255, 0.7);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all 0.2s ease}.close-selector:hover{background:rgba(255, 255, 255, 0.1);color:#ffffff}.camera-list{padding:4px 0;max-height:240px;overflow-y:auto}.camera-option{width:100%;padding:10px 16px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:space-between;align-items:center;color:rgba(255, 255, 255, 0.9)}.camera-option:hover{background:rgba(255, 255, 255, 0.08)}.camera-option.selected{background:rgba(255, 255, 255, 0.12);color:#ffffff}.camera-label{font-size:13px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px;font-weight:400}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9}.device-info{padding:8px 16px;border-top:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.05)}.device-info small{color:rgba(255, 255, 255, 0.6);font-size:11px;text-transform:capitalize;font-weight:400}@media (max-width: 480px){.camera-controls{top:12px;right:12px;gap:6px}.camera-selector-button{height:36px;padding:0 12px;font-size:11px;border-radius:6px}.camera-selector-dropdown{right:12px;top:48px;min-width:240px;max-width:calc(100vw - 24px)}.camera-selector-header{padding:10px 14px}.camera-option{padding:8px 14px}.device-info{padding:6px 14px}}.watermark{position:absolute;bottom:12px;right:12px;z-index:15;pointer-events:none;opacity:0.7}.watermark img{height:24px;width:auto;filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.component-status{position:absolute;top:16px;left:16px;right:16px;background:rgba(26, 26, 26, 0.95);backdrop-filter:blur(8px);display:flex;align-items:center;gap:12px;padding:12px 16px;border-radius:12px;z-index:40;transition:all 0.3s ease;min-height:48px;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.component-status.status-initializing{background:rgba(26, 26, 26, 0.95)}.component-status.status-loading{background:rgba(26, 26, 26, 0.95)}.component-status.status-ready{background:rgba(26, 26, 26, 0.95)}.component-status.status-error{background:rgba(26, 26, 26, 0.95)}.status-spinner{width:24px;height:24px;border:2px solid rgba(255, 255, 255, 0.2);border-top:2px solid #ffffff;border-radius:50%;animation:statusSpin 1.2s cubic-bezier(0.68, -0.55, 0.265, 1.55) infinite;flex-shrink:0}.status-content{display:flex;flex-direction:column;gap:2px}.status-message{color:#e6edf3;font-size:14px;font-weight:600;opacity:0.95;letter-spacing:0.3px;margin:0}.status-description{color:#8b949e;font-size:12px;line-height:1.3;opacity:0.9;margin:0}@keyframes statusSpin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@media (max-width: 480px){.component-status{top:12px;left:12px;right:12px;padding:10px 14px;gap:10px;min-height:44px}.status-spinner{width:20px;height:20px}.status-message{font-size:13px}.status-description{font-size:11px}}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(4px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:8px}.loading-spinner{width:50px;height:50px;border:3px solid rgba(255, 255, 255, 0.15);border-top:3px solid #28a745;border-radius:50%;animation:spin 1s ease-in-out infinite;margin-bottom:16px}.loading-text{color:#ffffff;font-size:14px;font-weight:500;text-align:center;opacity:0.9;margin-bottom:4px}.loading-description{color:rgba(255, 255, 255, 0.7);font-size:12px;text-align:center;opacity:0.8}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";
|
|
983
|
+
const myComponentCss = ":host{display:block;width:100%;height:100%;font-family:system-ui, -apple-system, sans-serif;color:#1a1a1a}.detector-container{display:flex;flex-direction:column;align-items:center;width:100%;height:100%}h1{font-size:24px;font-weight:500;color:#333;margin:0 0 24px 0}.video-container{position:relative;width:100%;height:100%;background:#333;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}video,.detection-overlay{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,.detection-overlay.mirror{transform:rotateY(180deg)}.detection-overlay{z-index:1;pointer-events:none}video{z-index:0}.detection-box{transition:opacity 0.2s ease}.status{margin-top:16px;font-size:12px;color:#666}.overlay-mask{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:block;pointer-events:none}.card-outline{position:absolute;top:var(--mask-center-y, 50%);left:var(--mask-center-x, 50%);transform:translate(-50%, -50%);width:var(--mask-width, 88%);height:var(--mask-height, 55%);border:none;border-radius:4px;background:transparent;opacity:0.8}.side{position:absolute;background:#999;transition:background-color 0.3s ease;border-radius:1px}.side-top.aligned{border-left-color:#28a745;border-top-color:#28a745}.side-right.aligned{border-right-color:#28a745;border-top-color:#28a745}.side-bottom.aligned{border-left-color:#28a745;border-bottom-color:#28a745}.side-left.aligned{border-right-color:#28a745;border-bottom-color:#28a745}.side-top{top:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-right{top:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-bottom{bottom:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.side-left{bottom:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);color:#fff;font-size:14px;font-weight:600;text-align:center;white-space:normal;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;z-index:20}.capture-animation{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;z-index:30;pointer-events:none;animation:captureFlash 0.6s ease-out}@keyframes captureFlash{0%{opacity:0}15%{opacity:0.8}30%{opacity:0}45%{opacity:0.4}60%{opacity:0}100%{opacity:0}}.card-outline.capturing{animation:pulseGreen 0.6s ease-out}@keyframes pulseGreen{0%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}}.flip-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showFlipInstruction 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.id-card-icon{width:80px;height:50px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:8px;position:relative;animation:flipCard 2s ease-in-out infinite;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.id-card-icon::before{content:'';position:absolute;top:8px;left:8px;width:16px;height:12px;background:rgba(255, 255, 255, 0.9);border-radius:2px}.id-card-icon::after{content:'';position:absolute;top:25px;left:8px;width:64px;height:3px;background:rgba(255, 255, 255, 0.7);border-radius:1px;box-shadow:0 6px 0 rgba(255, 255, 255, 0.7), 0 12px 0 rgba(255, 255, 255, 0.7)}.flip-text{margin-top:12px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px}@keyframes showFlipInstruction{0%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}}@keyframes flipCard{0%{transform:rotateY(0deg)}50%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}.success-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showSuccessMessage 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.check-icon{width:80px;height:80px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:50%;position:relative;animation:bounceSuccess 0.6s ease-out;box-shadow:0 4px 16px rgba(108, 117, 125, 0.4);display:flex;align-items:center;justify-content:center}.check-icon::before{content:'';position:absolute;width:20px;height:35px;border:4px solid #fff;border-top:none;border-left:none;transform:rotate(45deg);animation:drawCheck 0.4s ease-out 0.2s both}.success-text{margin-top:16px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;animation:fadeInUp 0.5s ease-out 0.4s both}@keyframes showSuccessMessage{0%{opacity:0;transform:translate(-50%, -50%) scale(0.5)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.9)}}@keyframes bounceSuccess{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}@keyframes drawCheck{0%{width:0;height:0}50%{width:20px;height:0}100%{width:20px;height:35px}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}.skip-button{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateX(-50%) translateY(0)}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto}.camera-selector-button{height:32px;padding:0 10px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-button:disabled,.camera-selector-button.loading{opacity:0.7;cursor:not-allowed;pointer-events:none}.camera-selector-button:disabled:hover,.camera-selector-button.loading:hover{transform:none;background:rgba(0, 0, 0, 0.6);border-color:rgba(255, 255, 255, 0.1)}.button-spinner{width:16px;height:16px;border:2px solid rgba(255, 255, 255, 0.3);border-top:2px solid #ffffff;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-bottom:1px solid rgba(255, 255, 255, 0.1)}.camera-selector-header span{font-weight:500;color:#ffffff;font-size:13px;opacity:0.9}.close-selector{width:20px;height:20px;border:none;background:none;color:rgba(255, 255, 255, 0.7);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all 0.2s ease}.close-selector:hover{background:rgba(255, 255, 255, 0.1);color:#ffffff}.camera-list{padding:4px 0;max-height:240px;overflow-y:auto}.camera-option{width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:space-between;align-items:center;color:rgba(255, 255, 255, 0.9)}.camera-option:hover{background:rgba(255, 255, 255, 0.08)}.camera-option.selected{background:rgba(255, 255, 255, 0.12);color:#ffffff}.camera-label{font-size:13px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px;font-weight:400}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9}.device-info{padding:6px 12px;border-top:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.05)}.device-info small{color:rgba(255, 255, 255, 0.6);font-size:11px;text-transform:capitalize;font-weight:400}@media (max-width: 480px){.camera-controls{top:12px;right:12px;gap:6px}.camera-selector-button{height:36px;padding:0 12px;font-size:11px;border-radius:6px}.camera-selector-dropdown{right:12px;top:48px;min-width:240px;max-width:calc(100vw - 24px)}.camera-selector-header{padding:6px 10px}.camera-option{padding:6px 10px}.device-info{padding:4px 10px}}.watermark{position:absolute;bottom:12px;right:12px;z-index:15;pointer-events:none;opacity:0.7}.watermark img{height:24px;width:auto;filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.component-status{position:absolute;top:16px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);display:flex;align-items:center;gap:6px;padding:6px 10px;z-index:40;height:32px;width:fit-content;animation:slideInFromTop 0.3s ease-out}.status-spinner{width:16px;height:16px;border:1px solid rgba(255, 255, 255, 0.3);border-top:1px solid #ffffff;border-radius:50%;animation:statusSpin 1s linear infinite;flex-shrink:0}.status-content{display:flex;flex-direction:column;gap:1px}.status-message{color:#ffffff;font-size:12px;font-weight:500;margin:0}.status-description{color:rgba(255, 255, 255, 0.7);font-size:10px;line-height:1.2;margin:0}@keyframes statusSpin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@media (max-width: 480px){.component-status{top:12px;left:12px;padding:4px 8px;gap:4px;height:28px;border-radius:8px}.status-spinner{width:14px;height:14px}.status-message{font-size:11px}.status-description{font-size:9px}}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(4px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:8px}.loading-spinner{width:50px;height:50px;border:3px solid rgba(255, 255, 255, 0.15);border-top:3px solid #28a745;border-radius:50%;animation:spin 1s ease-in-out infinite;margin-bottom:16px}.loading-text{color:#ffffff;font-size:14px;font-weight:500;text-align:center;opacity:0.9;margin-bottom:4px}.loading-description{color:rgba(255, 255, 255, 0.7);font-size:12px;text-align:center;opacity:0.8}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.performance-monitor{position:absolute;top:70px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromLeft 0.3s ease-out;transition:all 0.3s ease}@keyframes slideInFromLeft{0%{opacity:0;transform:translateX(-20px) scale(0.95)}100%{opacity:1;transform:translateX(0) scale(1)}}.performance-expanded{padding:6px 10px}.metrics-row{display:flex;gap:8px;margin-bottom:4px}.metrics-row:last-child{margin-bottom:0}.metric-compact{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:50px}.metric-label{font-size:9px;color:rgba(255, 255, 255, 0.6);font-weight:500;text-transform:uppercase;letter-spacing:0.3px}.metric-value{font-size:10px;font-weight:600;font-family:'Monaco', 'Menlo', 'Consolas', monospace;padding:2px 4px;border-radius:3px;text-align:center;white-space:nowrap}.metric-value.good{color:#4ade80;background:rgba(74, 222, 128, 0.1);border:1px solid rgba(74, 222, 128, 0.2)}.metric-value.warning{color:#fbbf24;background:rgba(251, 191, 36, 0.1);border:1px solid rgba(251, 191, 36, 0.2)}.metric-value.danger{color:#f87171;background:rgba(248, 113, 113, 0.1);border:1px solid rgba(248, 113, 113, 0.2)}@media (max-width: 480px){.performance-monitor{top:60px;left:12px;width:fit-content}.performance-expanded{padding:4px 8px}.metrics-row{gap:6px;margin-bottom:3px}.metric-compact{min-width:45px;gap:1px}.metric-label{font-size:8px}.metric-value{font-size:9px;padding:1px 3px}}@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.7}}.metric-value.danger{animation:pulse 2s infinite}";
|
|
978
984
|
|
|
979
985
|
const JaakStamps = class {
|
|
980
986
|
constructor(hostRef) {
|
|
@@ -999,12 +1005,24 @@ const JaakStamps = class {
|
|
|
999
1005
|
isMaskReady = false;
|
|
1000
1006
|
shouldMirrorVideo = true;
|
|
1001
1007
|
showCameraSelector = false;
|
|
1008
|
+
isSwitchingCamera = false;
|
|
1002
1009
|
currentStatus = {
|
|
1003
1010
|
message: 'Inicializando componente...',
|
|
1004
1011
|
description: 'Configurando servicios y cargando recursos',
|
|
1005
1012
|
type: 'initializing',
|
|
1006
1013
|
isInitialized: false
|
|
1007
1014
|
};
|
|
1015
|
+
performanceData = {
|
|
1016
|
+
fps: 0,
|
|
1017
|
+
inferenceTime: 0,
|
|
1018
|
+
memoryUsage: 0,
|
|
1019
|
+
onnxLoadTime: 0,
|
|
1020
|
+
frameProcessingTime: 0,
|
|
1021
|
+
totalDetections: 0,
|
|
1022
|
+
successfulDetections: 0,
|
|
1023
|
+
detectionRate: 0
|
|
1024
|
+
};
|
|
1025
|
+
isPerformanceMonitorMinimized = false;
|
|
1008
1026
|
// Services
|
|
1009
1027
|
serviceContainer;
|
|
1010
1028
|
logger;
|
|
@@ -1021,6 +1039,22 @@ const JaakStamps = class {
|
|
|
1021
1039
|
lastDetectedBox;
|
|
1022
1040
|
startTime;
|
|
1023
1041
|
hasScreenshotTaken = false;
|
|
1042
|
+
alignmentStartTime;
|
|
1043
|
+
alignmentTimer;
|
|
1044
|
+
// Performance monitoring
|
|
1045
|
+
performanceMetrics = {
|
|
1046
|
+
fps: 0,
|
|
1047
|
+
inferenceTime: 0,
|
|
1048
|
+
memoryUsage: 0,
|
|
1049
|
+
cpuUsage: 0,
|
|
1050
|
+
onnxLoadTime: 0,
|
|
1051
|
+
frameProcessingTime: 0,
|
|
1052
|
+
totalDetections: 0,
|
|
1053
|
+
successfulDetections: 0,
|
|
1054
|
+
detectionRate: 0,
|
|
1055
|
+
lastUpdateTime: 0
|
|
1056
|
+
};
|
|
1057
|
+
performanceUpdateInterval;
|
|
1024
1058
|
// Performance optimization
|
|
1025
1059
|
frameSkipCounter = 0;
|
|
1026
1060
|
FRAME_SKIP = 2;
|
|
@@ -1035,6 +1069,9 @@ const JaakStamps = class {
|
|
|
1035
1069
|
await this.setupEventListeners();
|
|
1036
1070
|
this.updateStatus('Inicializando cámara...', 'Detectando dispositivos disponibles', 'initializing');
|
|
1037
1071
|
await this.initializeComponent();
|
|
1072
|
+
if (this.debug) {
|
|
1073
|
+
this.initializePerformanceMonitor();
|
|
1074
|
+
}
|
|
1038
1075
|
}
|
|
1039
1076
|
async initializeServices() {
|
|
1040
1077
|
const config = {
|
|
@@ -1269,17 +1306,24 @@ const JaakStamps = class {
|
|
|
1269
1306
|
return { success: true, message: 'Model already loaded' };
|
|
1270
1307
|
}
|
|
1271
1308
|
try {
|
|
1309
|
+
const loadStartTime = performance.now();
|
|
1272
1310
|
this.updateStatus('Descargando modelo de detección...', 'Obteniendo red neuronal para reconocimiento de documentos', 'loading');
|
|
1273
1311
|
this.stateManager.updateCaptureState({ isLoading: true });
|
|
1274
1312
|
await this.detectionService.loadModel();
|
|
1275
1313
|
this.updateStatus('Cargando clasificador...', 'Preparando modelo de clasificación de tipos de documento', 'loading');
|
|
1276
1314
|
await this.detectionService.loadClassificationModel();
|
|
1315
|
+
const loadEndTime = performance.now();
|
|
1316
|
+
const loadTime = loadEndTime - loadStartTime;
|
|
1317
|
+
// Record ONNX load time
|
|
1318
|
+
if (this.debug) {
|
|
1319
|
+
this.recordOnnxPerformance(loadTime, 0);
|
|
1320
|
+
}
|
|
1277
1321
|
this.updateStatus('Optimizando modelos...', 'Configurando parámetros de rendimiento', 'loading');
|
|
1278
1322
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
1279
1323
|
this.updateStatus('Modelos precargados', '', 'ready');
|
|
1280
1324
|
this.stateManager.updateCaptureState({ isLoading: false });
|
|
1281
1325
|
this.emitReadyEvent();
|
|
1282
|
-
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE');
|
|
1326
|
+
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE', { loadTime: Math.round(loadTime) });
|
|
1283
1327
|
return { success: true, message: 'Models preloaded successfully' };
|
|
1284
1328
|
}
|
|
1285
1329
|
catch (error) {
|
|
@@ -1315,11 +1359,19 @@ const JaakStamps = class {
|
|
|
1315
1359
|
try {
|
|
1316
1360
|
// Paso 1: Verificar y cargar modelos si es necesario
|
|
1317
1361
|
if (!this.detectionService.isModelLoaded()) {
|
|
1362
|
+
const loadStartTime = performance.now();
|
|
1318
1363
|
this.updateStatus('Cargando modelo de detección...', 'Descargando red neuronal para reconocimiento', 'loading');
|
|
1319
1364
|
this.stateManager.updateCaptureState({ isLoading: true });
|
|
1320
1365
|
await this.detectionService.loadModel();
|
|
1321
1366
|
this.updateStatus('Cargando clasificador...', 'Preparando modelo de clasificación de documentos', 'loading');
|
|
1322
1367
|
await this.detectionService.loadClassificationModel();
|
|
1368
|
+
const loadEndTime = performance.now();
|
|
1369
|
+
const loadTime = loadEndTime - loadStartTime;
|
|
1370
|
+
// Record ONNX load time
|
|
1371
|
+
if (this.debug) {
|
|
1372
|
+
this.recordOnnxPerformance(loadTime, 0);
|
|
1373
|
+
}
|
|
1374
|
+
this.logger.state('MODELOS_CARGADOS_EN_DETECCION', { loadTime: Math.round(loadTime) });
|
|
1323
1375
|
}
|
|
1324
1376
|
// Paso 2: Detectar y configurar dispositivos
|
|
1325
1377
|
this.updateStatus('Detectando cámaras...', 'Buscando dispositivos de captura disponibles', 'loading');
|
|
@@ -1371,6 +1423,7 @@ const JaakStamps = class {
|
|
|
1371
1423
|
}
|
|
1372
1424
|
async detectFrame() {
|
|
1373
1425
|
try {
|
|
1426
|
+
const frameStartTime = performance.now();
|
|
1374
1427
|
const captureState = this.stateManager.getCaptureState();
|
|
1375
1428
|
if (!this.videoRef || !this.detectionContainer || !this.detectionService.isModelLoaded())
|
|
1376
1429
|
return;
|
|
@@ -1398,8 +1451,15 @@ const JaakStamps = class {
|
|
|
1398
1451
|
return;
|
|
1399
1452
|
}
|
|
1400
1453
|
this.lastInferenceTime = currentTime;
|
|
1454
|
+
// Measure preprocessing and inference time
|
|
1455
|
+
const inferenceStartTime = performance.now();
|
|
1401
1456
|
const inputTensor = this.detectionService.preprocess(this.videoRef);
|
|
1402
1457
|
const detections = await this.detectionService.runInference(inputTensor);
|
|
1458
|
+
const inferenceTime = performance.now() - inferenceStartTime;
|
|
1459
|
+
// Record ONNX performance metrics
|
|
1460
|
+
if (this.debug) {
|
|
1461
|
+
this.recordOnnxPerformance(0, inferenceTime);
|
|
1462
|
+
}
|
|
1403
1463
|
// Update best score logic
|
|
1404
1464
|
if (this.startTime && Date.now() - this.startTime < 5000) {
|
|
1405
1465
|
detections.forEach(detection => {
|
|
@@ -1425,6 +1485,12 @@ const JaakStamps = class {
|
|
|
1425
1485
|
this.detectionBoxes = [];
|
|
1426
1486
|
}
|
|
1427
1487
|
this.updateMaskColor(detections);
|
|
1488
|
+
// Record frame processing metrics
|
|
1489
|
+
if (this.debug) {
|
|
1490
|
+
const frameEndTime = performance.now();
|
|
1491
|
+
const totalFrameTime = frameEndTime - frameStartTime;
|
|
1492
|
+
this.recordFrameProcessing(totalFrameTime, detections.length);
|
|
1493
|
+
}
|
|
1428
1494
|
// Continue detection loop
|
|
1429
1495
|
if (captureState.step !== 'completed') {
|
|
1430
1496
|
if (this.consecutiveFailures > this.MAX_FAILURES) {
|
|
@@ -1455,7 +1521,16 @@ const JaakStamps = class {
|
|
|
1455
1521
|
if (this.videoStream) {
|
|
1456
1522
|
this.videoStream.getTracks().forEach(track => track.stop());
|
|
1457
1523
|
}
|
|
1524
|
+
if (this.alignmentTimer) {
|
|
1525
|
+
clearTimeout(this.alignmentTimer);
|
|
1526
|
+
this.alignmentTimer = undefined;
|
|
1527
|
+
}
|
|
1528
|
+
if (this.performanceUpdateInterval) {
|
|
1529
|
+
clearInterval(this.performanceUpdateInterval);
|
|
1530
|
+
this.performanceUpdateInterval = undefined;
|
|
1531
|
+
}
|
|
1458
1532
|
this.detectionBoxes = [];
|
|
1533
|
+
this.alignmentStartTime = undefined;
|
|
1459
1534
|
this.serviceContainer?.cleanup();
|
|
1460
1535
|
}
|
|
1461
1536
|
render() {
|
|
@@ -1470,7 +1545,7 @@ const JaakStamps = class {
|
|
|
1470
1545
|
availableCameras: [],
|
|
1471
1546
|
selectedCameraId: null,
|
|
1472
1547
|
deviceType: 'desktop'};
|
|
1473
|
-
return (h("div", { key: '
|
|
1548
|
+
return (h("div", { key: '6d83055c7dcfc6c6f77e99d8439866aaca31f323', class: "detector-container" }, h("div", { key: '89d95da0fbee2bf03a455da911103d13f2d55a64', class: "video-container" }, h("video", { key: 'a06b3df2a0c2de21c4c3113ca5357a0518168214', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: 'a11ae04dd825208d069a02368708811a718a5b68', 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: {
|
|
1474
1549
|
position: 'absolute',
|
|
1475
1550
|
left: `${box.x}px`,
|
|
1476
1551
|
top: `${box.y}px`,
|
|
@@ -1479,10 +1554,7 @@ const JaakStamps = class {
|
|
|
1479
1554
|
border: '2px solid #32406C',
|
|
1480
1555
|
pointerEvents: 'none',
|
|
1481
1556
|
boxSizing: 'border-box'
|
|
1482
|
-
} })))), this.isMaskReady && (h("div", { key: '
|
|
1483
|
-
this.cameraService.switchCamera(camera.id);
|
|
1484
|
-
this.toggleCameraSelector();
|
|
1485
|
-
}, type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'afd0e161367e9dcf9105bef6fa3510a8fa25d221', class: "device-info" }, h("small", { key: 'fd57d4bfaba32b77d441d163491655468b0263d2' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: 'dcb69cad03369a87e2834e1cd04cbab5dc052866', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '899ef764d10497b023140b296c3fc72a7e762607', class: "flip-animation" }, h("div", { key: 'ec7449b92e28dcbd40d956e435c3a0ebc65d16ff', class: "id-card-icon" }), h("div", { key: 'f086a238ecc3b3fa91fc1010380676e9b3bc7429', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '4d6f0030db7a14c403b4b6fd00714aa04fd5abed', class: "success-animation" }, h("div", { key: 'c08babe375bbc94c9403ef264739016bbfac13ae', class: "check-icon" }), h("div", { key: '24393d75b67dd27da6520dd2b7a223dc9dfa73e4', class: "success-text" }, "\u00A1Proceso completado!"))), this.currentStatus.type !== 'active' && (h("div", { key: '20820f96090471728b9ed654e0b92f0a503e2052', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '0709abb333b47085e4c48ff162e58226e2204978', class: "status-spinner" })), h("div", { key: '5eb17314e376a5e0db32a6f00023d2f502c55fe4', class: "status-content" }, h("div", { key: 'fd98ef9b6889de7ca5cce0befd05285d7247795c', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '3aa93673546a06137f407aafd2933bf09d6814b0', class: "status-description" }, this.currentStatus.description))))), h("div", { key: '2247b9245bc8ecf265cb03c6c518583ae49a3e6d', class: "watermark" }, h("img", { key: '7a50ec51fe6c08a6d7907f5d4bda85b3d9a5b48b', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
1557
|
+
} })))), this.isMaskReady && (h("div", { key: '58c0a0bdd8088835c677c9b455e01ffd8a28bcc0', class: "overlay-mask" }, h("div", { key: '52f87e8837f82a4ab6fd75bd22f8c178ff5670c4', class: "card-outline" }, h("div", { key: '0f503ec7ab610342e01d2b976fff0a5ff1b01845', class: "side side-top" }), h("div", { key: '305c980c5d638270c348ce2fc7bf762515557ea1', class: "side side-right" }), h("div", { key: '201531d41aa8fab1782bc3045bda313bfac14929', class: "side side-bottom" }), h("div", { key: 'acaa082133217e2b4aa807571d6f7f8e5f225530', class: "side side-left" }), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '17246f4264074dfae7fdef963120a2d3756b0f64', class: "guide-text" }, "Alinee su identificaci\u00F3n con el marco"))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("button", { key: '9f21b022b3601f2b8f9898f72683e33b86f433a6', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), captureState.isVideoActive && (h("div", { key: '3c9d8e3b2135dd14414463a6ada636b425385583', class: "camera-controls" }, h("button", { key: 'b287e1dab5a98f2eb6e05e924b1af9bb6616f947', 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: 'd8dca3049cbdf827d03cd432ac183a1651f77ab6', class: "camera-selector-dropdown" }, h("div", { key: '3a4200b5624f5d96de4ae8acb821a47d31a34c93', class: "camera-selector-header" }, h("span", { key: '14f8e8618d9404cdfd3f9cc150e54b510507c977' }, "Seleccionar C\u00E1mara"), h("button", { key: '98367e182d227093742e0fc9118f81db32352bdd', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '172471ef3c0d55cb619a061eafe37205c3a0bee4', 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}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'e08ced0c02b5662be31c60b2ba35c83fac46bb80', class: "device-info" }, h("small", { key: '8489f10c13a0a528abc878cc66d71dc769890b90' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: '89f6c5a9bc1efb9bd8af190ae0821dabe992a2be', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: 'ead4d0cf0751097220572a4946bf4dcb3d7f4f33', class: "flip-animation" }, h("div", { key: '357e981fd9b2f616e9b1b90c8454555dceac6fbd', class: "id-card-icon" }), h("div", { key: '4abfecbb5ee0165b720d6ad8398984b25ecec7a1', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'cdeedd36903c8467e7ebb406e3414ecd92abf47c', class: "success-animation" }, h("div", { key: '8731f318d490ff67fa7f68edf264acb762632604', class: "check-icon" }), h("div", { key: '2e21ce0921fedfaa0b90c56ec44d289426ea7708', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '6cf678c79f8e57fde12202a932fe855905ae770f', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: 'f9e888616736c26624bd3de7c2f1eee297d0a2f5', class: "status-spinner" })), h("div", { key: 'b849c5187ed8e66b4cf62113d2f93c006cf9f836', class: "status-content" }, h("div", { key: '64a2dac4cb5e4c17fc2aa161c8faa389c64a0458', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '64e85a98129f791d6784a98129f2411607360fff', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '1d41d3139d7d486bdf9225f584d6de250faeddf7', class: "performance-monitor" }, h("div", { key: '75bf3d45d869c4b0365f994444292de2245d391c', class: "performance-expanded" }, h("div", { key: '762c977e7125202103aba84c568c0fefee43d6b2', class: "metrics-row" }, h("div", { key: '51b03d882f84e835664af11d409fc01a5363c0ce', class: "metric-compact" }, h("span", { key: '21767c803c2fda9fe8653881cb8dfdcaa992fe3b', class: "metric-label" }, "FPS"), h("span", { key: '5467ba22adb75668a0acadd4ffcbaa25117fd8ae', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'a6c020d500a72f330a7cbb01cfdddc1fff63f1bb', class: "metric-compact" }, h("span", { key: '5034e33c12ad454368e4fa32567c307bce6ffe0e', class: "metric-label" }, "MEM"), h("span", { key: '19f691984f9e6aac29067fc983561b701b9080de', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'c2a11b8dc156b90a4ba18020e5a62ff87c29f624', class: "metrics-row" }, h("div", { key: '7af9c2c1286bb32d6c166d3487c8ea4a02f14490', class: "metric-compact" }, h("span", { key: 'b34e54ac6b4e387ee8155176f999dd2b721a8617', class: "metric-label" }, "INF"), h("span", { key: 'ada2f913ac6c97661a054f9bf596f4ac52eb918e', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: 'cc2d819a7e75af4e03d2521756c23110785076ad', class: "metric-compact" }, h("span", { key: 'b2f7e528be88eafcc66d801e8f547b4d274e0cf8', class: "metric-label" }, "FRAME"), h("span", { key: '1bcddf221b960018fb5505553e9f8cfd3717c349', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'cb80b6198f621fab68b13c4992578ef2e548ae99', class: "metrics-row" }, h("div", { key: 'b752b65906c92eff86cad2d0ffdc1420f03a8932', class: "metric-compact" }, h("span", { key: '96af746b42a101c6bfe4c197b652837ecc66fc06', class: "metric-label" }, "DET"), h("span", { key: 'f2038ae4943ebd9ae2ec1d8b907ae23f04c8fd90', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'c2e6b9380928b30b1a879a6abc43eb7053da9ac1', class: "metric-compact" }, h("span", { key: '096268d19a7ac7471c5dafd5adc3103d30433a55', class: "metric-label" }, "RATE"), h("span", { key: '7f9e9e49c68da719fe43391518514af3cdab004d', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: 'c6546f8ec722c56fa369da6d5d732f29d3afc65f', class: "watermark" }, h("img", { key: 'd195a395051a4c436dec33d7835c565e748cf60a', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
1486
1558
|
}
|
|
1487
1559
|
// Utility methods
|
|
1488
1560
|
updateDetectionBoxes(boxes) {
|
|
@@ -1555,19 +1627,37 @@ const JaakStamps = class {
|
|
|
1555
1627
|
cardOutline?.classList.add('perfect-match');
|
|
1556
1628
|
corners?.forEach(corner => corner.classList.add('perfect-match'));
|
|
1557
1629
|
if (!this.hasScreenshotTaken) {
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1630
|
+
const currentTime = Date.now();
|
|
1631
|
+
// Initialize alignment start time if not set
|
|
1632
|
+
if (!this.alignmentStartTime) {
|
|
1633
|
+
this.alignmentStartTime = currentTime;
|
|
1634
|
+
}
|
|
1635
|
+
// Check if document has been aligned for 1 second
|
|
1636
|
+
const alignmentDuration = currentTime - this.alignmentStartTime;
|
|
1637
|
+
if (alignmentDuration >= 1000) {
|
|
1638
|
+
this.lastDetectedBox = bestBox;
|
|
1639
|
+
this.takeScreenshot().catch(error => {
|
|
1640
|
+
this.logger.error('Error al tomar captura de pantalla:', error);
|
|
1641
|
+
});
|
|
1642
|
+
this.hasScreenshotTaken = true;
|
|
1643
|
+
this.alignmentStartTime = undefined;
|
|
1644
|
+
setTimeout(() => {
|
|
1645
|
+
this.hasScreenshotTaken = false;
|
|
1646
|
+
}, 2000);
|
|
1647
|
+
}
|
|
1566
1648
|
}
|
|
1567
1649
|
}
|
|
1568
1650
|
else {
|
|
1569
1651
|
cardOutline?.classList.remove('perfect-match');
|
|
1570
1652
|
corners?.forEach(corner => corner.classList.remove('perfect-match'));
|
|
1653
|
+
// Reset alignment timer when document moves out of position
|
|
1654
|
+
if (this.alignmentStartTime) {
|
|
1655
|
+
this.alignmentStartTime = undefined;
|
|
1656
|
+
}
|
|
1657
|
+
if (this.alignmentTimer) {
|
|
1658
|
+
clearTimeout(this.alignmentTimer);
|
|
1659
|
+
this.alignmentTimer = undefined;
|
|
1660
|
+
}
|
|
1571
1661
|
}
|
|
1572
1662
|
}
|
|
1573
1663
|
async takeScreenshot() {
|
|
@@ -1684,8 +1774,52 @@ const JaakStamps = class {
|
|
|
1684
1774
|
this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
|
|
1685
1775
|
}
|
|
1686
1776
|
toggleCameraSelector() {
|
|
1777
|
+
if (this.isSwitchingCamera)
|
|
1778
|
+
return; // Don't toggle if switching camera
|
|
1687
1779
|
this.showCameraSelector = !this.showCameraSelector;
|
|
1688
1780
|
}
|
|
1781
|
+
async handleCameraSwitch(cameraId) {
|
|
1782
|
+
if (this.isSwitchingCamera)
|
|
1783
|
+
return; // Prevent multiple simultaneous switches
|
|
1784
|
+
try {
|
|
1785
|
+
// Close the selector immediately when user selects a camera
|
|
1786
|
+
this.showCameraSelector = false;
|
|
1787
|
+
this.isSwitchingCamera = true;
|
|
1788
|
+
this.logger.state('INICIANDO_CAMBIO_CAMARA', {
|
|
1789
|
+
from: this.cameraService.getSelectedCameraId(),
|
|
1790
|
+
to: cameraId
|
|
1791
|
+
});
|
|
1792
|
+
// Stop current video stream
|
|
1793
|
+
if (this.videoStream) {
|
|
1794
|
+
this.videoStream.getTracks().forEach(track => track.stop());
|
|
1795
|
+
}
|
|
1796
|
+
// Switch camera in service
|
|
1797
|
+
await this.cameraService.switchCamera(cameraId);
|
|
1798
|
+
// Setup new camera stream
|
|
1799
|
+
const newStream = await this.cameraService.setupCamera();
|
|
1800
|
+
// Update video element
|
|
1801
|
+
await this.initializeVideoStream(newStream);
|
|
1802
|
+
this.logger.state('CAMBIO_CAMARA_EXITOSO', {
|
|
1803
|
+
newCameraId: cameraId,
|
|
1804
|
+
isRearCamera: this.cameraService.isRearCamera(newStream)
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
catch (error) {
|
|
1808
|
+
this.logger.error('Error al cambiar cámara:', error);
|
|
1809
|
+
// Try to restore previous camera if switch failed
|
|
1810
|
+
try {
|
|
1811
|
+
const fallbackStream = await this.cameraService.setupCamera();
|
|
1812
|
+
await this.initializeVideoStream(fallbackStream);
|
|
1813
|
+
}
|
|
1814
|
+
catch (fallbackError) {
|
|
1815
|
+
this.logger.error('Error al restaurar cámara anterior:', fallbackError);
|
|
1816
|
+
this.updateStatus('Error al cambiar cámara', 'No se pudo completar el cambio de dispositivo', 'error');
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
finally {
|
|
1820
|
+
this.isSwitchingCamera = false;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1689
1823
|
resetDetection() {
|
|
1690
1824
|
this.stateManager.reset();
|
|
1691
1825
|
this.hasScreenshotTaken = false;
|
|
@@ -1694,6 +1828,11 @@ const JaakStamps = class {
|
|
|
1694
1828
|
this.consecutiveFailures = 0;
|
|
1695
1829
|
this.lastInferenceTime = 0;
|
|
1696
1830
|
this.detectionBoxes = [];
|
|
1831
|
+
this.alignmentStartTime = undefined;
|
|
1832
|
+
if (this.alignmentTimer) {
|
|
1833
|
+
clearTimeout(this.alignmentTimer);
|
|
1834
|
+
this.alignmentTimer = undefined;
|
|
1835
|
+
}
|
|
1697
1836
|
const captureState = this.stateManager.getCaptureState();
|
|
1698
1837
|
if (captureState.isVideoActive && this.detectionService.isModelLoaded()) {
|
|
1699
1838
|
this.updateStatus('Captura reiniciada', 'Buscando documento en el marco de captura', 'active');
|
|
@@ -1713,6 +1852,60 @@ const JaakStamps = class {
|
|
|
1713
1852
|
this.detectionBoxes = [];
|
|
1714
1853
|
this.cleanup();
|
|
1715
1854
|
}
|
|
1855
|
+
// PERFORMANCE MONITORING METHODS
|
|
1856
|
+
initializePerformanceMonitor() {
|
|
1857
|
+
this.performanceMetrics.lastUpdateTime = performance.now();
|
|
1858
|
+
// Update performance metrics every 500ms
|
|
1859
|
+
this.performanceUpdateInterval = window.setInterval(() => {
|
|
1860
|
+
this.updatePerformanceMetrics();
|
|
1861
|
+
}, 500);
|
|
1862
|
+
this.logger.debug('Monitor de performance inicializado');
|
|
1863
|
+
}
|
|
1864
|
+
updatePerformanceMetrics() {
|
|
1865
|
+
const currentTime = performance.now();
|
|
1866
|
+
const deltaTime = currentTime - this.performanceMetrics.lastUpdateTime;
|
|
1867
|
+
// Calculate FPS
|
|
1868
|
+
if (deltaTime > 0) {
|
|
1869
|
+
this.performanceMetrics.fps = Math.round(1000 / (deltaTime / this.frameSkipCounter || 1));
|
|
1870
|
+
}
|
|
1871
|
+
// Get memory usage if available
|
|
1872
|
+
if ('memory' in performance) {
|
|
1873
|
+
const memInfo = performance.memory;
|
|
1874
|
+
this.performanceMetrics.memoryUsage = Math.round(memInfo.usedJSHeapSize / 1048576); // MB
|
|
1875
|
+
}
|
|
1876
|
+
// Calculate detection success rate
|
|
1877
|
+
if (this.performanceMetrics.totalDetections > 0) {
|
|
1878
|
+
this.performanceMetrics.successfulDetections = this.performanceMetrics.successfulDetections;
|
|
1879
|
+
const detectionRate = (this.performanceMetrics.successfulDetections / this.performanceMetrics.totalDetections) * 100;
|
|
1880
|
+
this.performanceMetrics.detectionRate = Math.round(detectionRate);
|
|
1881
|
+
}
|
|
1882
|
+
// Update state for rendering
|
|
1883
|
+
this.performanceData = {
|
|
1884
|
+
fps: this.performanceMetrics.fps,
|
|
1885
|
+
inferenceTime: this.performanceMetrics.inferenceTime,
|
|
1886
|
+
memoryUsage: this.performanceMetrics.memoryUsage,
|
|
1887
|
+
onnxLoadTime: this.performanceMetrics.onnxLoadTime,
|
|
1888
|
+
frameProcessingTime: this.performanceMetrics.frameProcessingTime,
|
|
1889
|
+
totalDetections: this.performanceMetrics.totalDetections,
|
|
1890
|
+
successfulDetections: this.performanceMetrics.successfulDetections,
|
|
1891
|
+
detectionRate: this.performanceMetrics.detectionRate
|
|
1892
|
+
};
|
|
1893
|
+
this.performanceMetrics.lastUpdateTime = currentTime;
|
|
1894
|
+
}
|
|
1895
|
+
recordOnnxPerformance(loadTime, inferenceTime) {
|
|
1896
|
+
this.performanceMetrics.onnxLoadTime = Math.round(loadTime);
|
|
1897
|
+
this.performanceMetrics.inferenceTime = Math.round(inferenceTime);
|
|
1898
|
+
}
|
|
1899
|
+
recordFrameProcessing(processingTime, detectionsFound) {
|
|
1900
|
+
this.performanceMetrics.frameProcessingTime = Math.round(processingTime);
|
|
1901
|
+
this.performanceMetrics.totalDetections++;
|
|
1902
|
+
if (detectionsFound > 0) {
|
|
1903
|
+
this.performanceMetrics.successfulDetections++;
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
togglePerformanceMonitor() {
|
|
1907
|
+
this.isPerformanceMonitorMinimized = !this.isPerformanceMonitorMinimized;
|
|
1908
|
+
}
|
|
1716
1909
|
};
|
|
1717
1910
|
JaakStamps.style = myComponentCss;
|
|
1718
1911
|
|