@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
|
@@ -18,7 +18,7 @@ var patchBrowser = () => {
|
|
|
18
18
|
|
|
19
19
|
patchBrowser().then(async (options) => {
|
|
20
20
|
await index.globalScripts();
|
|
21
|
-
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"],"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);
|
|
21
|
+
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"],"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);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
exports.setNonce = index.setNonce;
|
|
@@ -820,11 +820,17 @@ class DetectionService {
|
|
|
820
820
|
}
|
|
821
821
|
// Tolerancia para considerar que un lado está alineado (en píxeles)
|
|
822
822
|
const tolerance = alignmentTolerance;
|
|
823
|
+
// Verificar alineación de esquinas más estricta
|
|
824
|
+
// Una esquina está alineada solo si AMBOS bordes que la forman están alineados
|
|
825
|
+
const topAligned = Math.abs(docTop - maskTop) <= tolerance;
|
|
826
|
+
const rightAligned = Math.abs(docRight - maskRight) <= tolerance;
|
|
827
|
+
const bottomAligned = Math.abs(docBottom - maskBottom) <= tolerance;
|
|
828
|
+
const leftAligned = Math.abs(docLeft - maskLeft) <= tolerance;
|
|
823
829
|
return {
|
|
824
|
-
top:
|
|
825
|
-
right:
|
|
826
|
-
bottom:
|
|
827
|
-
left:
|
|
830
|
+
top: topAligned && leftAligned, // Esquina superior izquierda: borde top Y left alineados
|
|
831
|
+
right: topAligned && rightAligned, // Esquina superior derecha: borde top Y right alineados
|
|
832
|
+
bottom: bottomAligned && leftAligned, // Esquina inferior izquierda: borde bottom Y left alineados
|
|
833
|
+
left: bottomAligned && rightAligned // Esquina inferior derecha: borde bottom Y right alineados
|
|
828
834
|
};
|
|
829
835
|
}
|
|
830
836
|
isCardInFrame(box) {
|
|
@@ -976,7 +982,7 @@ class ServiceContainer {
|
|
|
976
982
|
}
|
|
977
983
|
}
|
|
978
984
|
|
|
979
|
-
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)}}";
|
|
985
|
+
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}";
|
|
980
986
|
|
|
981
987
|
const JaakStamps = class {
|
|
982
988
|
constructor(hostRef) {
|
|
@@ -1001,12 +1007,24 @@ const JaakStamps = class {
|
|
|
1001
1007
|
isMaskReady = false;
|
|
1002
1008
|
shouldMirrorVideo = true;
|
|
1003
1009
|
showCameraSelector = false;
|
|
1010
|
+
isSwitchingCamera = false;
|
|
1004
1011
|
currentStatus = {
|
|
1005
1012
|
message: 'Inicializando componente...',
|
|
1006
1013
|
description: 'Configurando servicios y cargando recursos',
|
|
1007
1014
|
type: 'initializing',
|
|
1008
1015
|
isInitialized: false
|
|
1009
1016
|
};
|
|
1017
|
+
performanceData = {
|
|
1018
|
+
fps: 0,
|
|
1019
|
+
inferenceTime: 0,
|
|
1020
|
+
memoryUsage: 0,
|
|
1021
|
+
onnxLoadTime: 0,
|
|
1022
|
+
frameProcessingTime: 0,
|
|
1023
|
+
totalDetections: 0,
|
|
1024
|
+
successfulDetections: 0,
|
|
1025
|
+
detectionRate: 0
|
|
1026
|
+
};
|
|
1027
|
+
isPerformanceMonitorMinimized = false;
|
|
1010
1028
|
// Services
|
|
1011
1029
|
serviceContainer;
|
|
1012
1030
|
logger;
|
|
@@ -1023,6 +1041,22 @@ const JaakStamps = class {
|
|
|
1023
1041
|
lastDetectedBox;
|
|
1024
1042
|
startTime;
|
|
1025
1043
|
hasScreenshotTaken = false;
|
|
1044
|
+
alignmentStartTime;
|
|
1045
|
+
alignmentTimer;
|
|
1046
|
+
// Performance monitoring
|
|
1047
|
+
performanceMetrics = {
|
|
1048
|
+
fps: 0,
|
|
1049
|
+
inferenceTime: 0,
|
|
1050
|
+
memoryUsage: 0,
|
|
1051
|
+
cpuUsage: 0,
|
|
1052
|
+
onnxLoadTime: 0,
|
|
1053
|
+
frameProcessingTime: 0,
|
|
1054
|
+
totalDetections: 0,
|
|
1055
|
+
successfulDetections: 0,
|
|
1056
|
+
detectionRate: 0,
|
|
1057
|
+
lastUpdateTime: 0
|
|
1058
|
+
};
|
|
1059
|
+
performanceUpdateInterval;
|
|
1026
1060
|
// Performance optimization
|
|
1027
1061
|
frameSkipCounter = 0;
|
|
1028
1062
|
FRAME_SKIP = 2;
|
|
@@ -1037,6 +1071,9 @@ const JaakStamps = class {
|
|
|
1037
1071
|
await this.setupEventListeners();
|
|
1038
1072
|
this.updateStatus('Inicializando cámara...', 'Detectando dispositivos disponibles', 'initializing');
|
|
1039
1073
|
await this.initializeComponent();
|
|
1074
|
+
if (this.debug) {
|
|
1075
|
+
this.initializePerformanceMonitor();
|
|
1076
|
+
}
|
|
1040
1077
|
}
|
|
1041
1078
|
async initializeServices() {
|
|
1042
1079
|
const config = {
|
|
@@ -1271,17 +1308,24 @@ const JaakStamps = class {
|
|
|
1271
1308
|
return { success: true, message: 'Model already loaded' };
|
|
1272
1309
|
}
|
|
1273
1310
|
try {
|
|
1311
|
+
const loadStartTime = performance.now();
|
|
1274
1312
|
this.updateStatus('Descargando modelo de detección...', 'Obteniendo red neuronal para reconocimiento de documentos', 'loading');
|
|
1275
1313
|
this.stateManager.updateCaptureState({ isLoading: true });
|
|
1276
1314
|
await this.detectionService.loadModel();
|
|
1277
1315
|
this.updateStatus('Cargando clasificador...', 'Preparando modelo de clasificación de tipos de documento', 'loading');
|
|
1278
1316
|
await this.detectionService.loadClassificationModel();
|
|
1317
|
+
const loadEndTime = performance.now();
|
|
1318
|
+
const loadTime = loadEndTime - loadStartTime;
|
|
1319
|
+
// Record ONNX load time
|
|
1320
|
+
if (this.debug) {
|
|
1321
|
+
this.recordOnnxPerformance(loadTime, 0);
|
|
1322
|
+
}
|
|
1279
1323
|
this.updateStatus('Optimizando modelos...', 'Configurando parámetros de rendimiento', 'loading');
|
|
1280
1324
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
1281
1325
|
this.updateStatus('Modelos precargados', '', 'ready');
|
|
1282
1326
|
this.stateManager.updateCaptureState({ isLoading: false });
|
|
1283
1327
|
this.emitReadyEvent();
|
|
1284
|
-
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE');
|
|
1328
|
+
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE', { loadTime: Math.round(loadTime) });
|
|
1285
1329
|
return { success: true, message: 'Models preloaded successfully' };
|
|
1286
1330
|
}
|
|
1287
1331
|
catch (error) {
|
|
@@ -1317,11 +1361,19 @@ const JaakStamps = class {
|
|
|
1317
1361
|
try {
|
|
1318
1362
|
// Paso 1: Verificar y cargar modelos si es necesario
|
|
1319
1363
|
if (!this.detectionService.isModelLoaded()) {
|
|
1364
|
+
const loadStartTime = performance.now();
|
|
1320
1365
|
this.updateStatus('Cargando modelo de detección...', 'Descargando red neuronal para reconocimiento', 'loading');
|
|
1321
1366
|
this.stateManager.updateCaptureState({ isLoading: true });
|
|
1322
1367
|
await this.detectionService.loadModel();
|
|
1323
1368
|
this.updateStatus('Cargando clasificador...', 'Preparando modelo de clasificación de documentos', 'loading');
|
|
1324
1369
|
await this.detectionService.loadClassificationModel();
|
|
1370
|
+
const loadEndTime = performance.now();
|
|
1371
|
+
const loadTime = loadEndTime - loadStartTime;
|
|
1372
|
+
// Record ONNX load time
|
|
1373
|
+
if (this.debug) {
|
|
1374
|
+
this.recordOnnxPerformance(loadTime, 0);
|
|
1375
|
+
}
|
|
1376
|
+
this.logger.state('MODELOS_CARGADOS_EN_DETECCION', { loadTime: Math.round(loadTime) });
|
|
1325
1377
|
}
|
|
1326
1378
|
// Paso 2: Detectar y configurar dispositivos
|
|
1327
1379
|
this.updateStatus('Detectando cámaras...', 'Buscando dispositivos de captura disponibles', 'loading');
|
|
@@ -1373,6 +1425,7 @@ const JaakStamps = class {
|
|
|
1373
1425
|
}
|
|
1374
1426
|
async detectFrame() {
|
|
1375
1427
|
try {
|
|
1428
|
+
const frameStartTime = performance.now();
|
|
1376
1429
|
const captureState = this.stateManager.getCaptureState();
|
|
1377
1430
|
if (!this.videoRef || !this.detectionContainer || !this.detectionService.isModelLoaded())
|
|
1378
1431
|
return;
|
|
@@ -1400,8 +1453,15 @@ const JaakStamps = class {
|
|
|
1400
1453
|
return;
|
|
1401
1454
|
}
|
|
1402
1455
|
this.lastInferenceTime = currentTime;
|
|
1456
|
+
// Measure preprocessing and inference time
|
|
1457
|
+
const inferenceStartTime = performance.now();
|
|
1403
1458
|
const inputTensor = this.detectionService.preprocess(this.videoRef);
|
|
1404
1459
|
const detections = await this.detectionService.runInference(inputTensor);
|
|
1460
|
+
const inferenceTime = performance.now() - inferenceStartTime;
|
|
1461
|
+
// Record ONNX performance metrics
|
|
1462
|
+
if (this.debug) {
|
|
1463
|
+
this.recordOnnxPerformance(0, inferenceTime);
|
|
1464
|
+
}
|
|
1405
1465
|
// Update best score logic
|
|
1406
1466
|
if (this.startTime && Date.now() - this.startTime < 5000) {
|
|
1407
1467
|
detections.forEach(detection => {
|
|
@@ -1427,6 +1487,12 @@ const JaakStamps = class {
|
|
|
1427
1487
|
this.detectionBoxes = [];
|
|
1428
1488
|
}
|
|
1429
1489
|
this.updateMaskColor(detections);
|
|
1490
|
+
// Record frame processing metrics
|
|
1491
|
+
if (this.debug) {
|
|
1492
|
+
const frameEndTime = performance.now();
|
|
1493
|
+
const totalFrameTime = frameEndTime - frameStartTime;
|
|
1494
|
+
this.recordFrameProcessing(totalFrameTime, detections.length);
|
|
1495
|
+
}
|
|
1430
1496
|
// Continue detection loop
|
|
1431
1497
|
if (captureState.step !== 'completed') {
|
|
1432
1498
|
if (this.consecutiveFailures > this.MAX_FAILURES) {
|
|
@@ -1457,7 +1523,16 @@ const JaakStamps = class {
|
|
|
1457
1523
|
if (this.videoStream) {
|
|
1458
1524
|
this.videoStream.getTracks().forEach(track => track.stop());
|
|
1459
1525
|
}
|
|
1526
|
+
if (this.alignmentTimer) {
|
|
1527
|
+
clearTimeout(this.alignmentTimer);
|
|
1528
|
+
this.alignmentTimer = undefined;
|
|
1529
|
+
}
|
|
1530
|
+
if (this.performanceUpdateInterval) {
|
|
1531
|
+
clearInterval(this.performanceUpdateInterval);
|
|
1532
|
+
this.performanceUpdateInterval = undefined;
|
|
1533
|
+
}
|
|
1460
1534
|
this.detectionBoxes = [];
|
|
1535
|
+
this.alignmentStartTime = undefined;
|
|
1461
1536
|
this.serviceContainer?.cleanup();
|
|
1462
1537
|
}
|
|
1463
1538
|
render() {
|
|
@@ -1472,7 +1547,7 @@ const JaakStamps = class {
|
|
|
1472
1547
|
availableCameras: [],
|
|
1473
1548
|
selectedCameraId: null,
|
|
1474
1549
|
deviceType: 'desktop'};
|
|
1475
|
-
return (index.h("div", { key: '
|
|
1550
|
+
return (index.h("div", { key: '6d83055c7dcfc6c6f77e99d8439866aaca31f323', class: "detector-container" }, index.h("div", { key: '89d95da0fbee2bf03a455da911103d13f2d55a64', class: "video-container" }, index.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' } }), index.h("div", { key: 'a11ae04dd825208d069a02368708811a718a5b68', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index$1) => (index.h("div", { key: index$1, class: "detection-box", style: {
|
|
1476
1551
|
position: 'absolute',
|
|
1477
1552
|
left: `${box.x}px`,
|
|
1478
1553
|
top: `${box.y}px`,
|
|
@@ -1481,10 +1556,7 @@ const JaakStamps = class {
|
|
|
1481
1556
|
border: '2px solid #32406C',
|
|
1482
1557
|
pointerEvents: 'none',
|
|
1483
1558
|
boxSizing: 'border-box'
|
|
1484
|
-
} })))), this.isMaskReady && (index.h("div", { key: '
|
|
1485
|
-
this.cameraService.switchCamera(camera.id);
|
|
1486
|
-
this.toggleCameraSelector();
|
|
1487
|
-
}, type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: 'afd0e161367e9dcf9105bef6fa3510a8fa25d221', class: "device-info" }, index.h("small", { key: 'fd57d4bfaba32b77d441d163491655468b0263d2' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (index.h("div", { key: 'dcb69cad03369a87e2834e1cd04cbab5dc052866', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: '899ef764d10497b023140b296c3fc72a7e762607', class: "flip-animation" }, index.h("div", { key: 'ec7449b92e28dcbd40d956e435c3a0ebc65d16ff', class: "id-card-icon" }), index.h("div", { key: 'f086a238ecc3b3fa91fc1010380676e9b3bc7429', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: '4d6f0030db7a14c403b4b6fd00714aa04fd5abed', class: "success-animation" }, index.h("div", { key: 'c08babe375bbc94c9403ef264739016bbfac13ae', class: "check-icon" }), index.h("div", { key: '24393d75b67dd27da6520dd2b7a223dc9dfa73e4', class: "success-text" }, "\u00A1Proceso completado!"))), this.currentStatus.type !== 'active' && (index.h("div", { key: '20820f96090471728b9ed654e0b92f0a503e2052', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: '0709abb333b47085e4c48ff162e58226e2204978', class: "status-spinner" })), index.h("div", { key: '5eb17314e376a5e0db32a6f00023d2f502c55fe4', class: "status-content" }, index.h("div", { key: 'fd98ef9b6889de7ca5cce0befd05285d7247795c', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: '3aa93673546a06137f407aafd2933bf09d6814b0', class: "status-description" }, this.currentStatus.description))))), index.h("div", { key: '2247b9245bc8ecf265cb03c6c518583ae49a3e6d', class: "watermark" }, index.h("img", { key: '7a50ec51fe6c08a6d7907f5d4bda85b3d9a5b48b', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
1559
|
+
} })))), this.isMaskReady && (index.h("div", { key: '58c0a0bdd8088835c677c9b455e01ffd8a28bcc0', class: "overlay-mask" }, index.h("div", { key: '52f87e8837f82a4ab6fd75bd22f8c178ff5670c4', class: "card-outline" }, index.h("div", { key: '0f503ec7ab610342e01d2b976fff0a5ff1b01845', class: "side side-top" }), index.h("div", { key: '305c980c5d638270c348ce2fc7bf762515557ea1', class: "side side-right" }), index.h("div", { key: '201531d41aa8fab1782bc3045bda313bfac14929', class: "side side-bottom" }), index.h("div", { key: 'acaa082133217e2b4aa807571d6f7f8e5f225530', class: "side side-left" }), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '17246f4264074dfae7fdef963120a2d3756b0f64', class: "guide-text" }, "Alinee su identificaci\u00F3n con el marco"))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("button", { key: '9f21b022b3601f2b8f9898f72683e33b86f433a6', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), captureState.isVideoActive && (index.h("div", { key: '3c9d8e3b2135dd14414463a6ada636b425385583', class: "camera-controls" }, index.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 ? (index.h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (index.h("div", { key: 'd8dca3049cbdf827d03cd432ac183a1651f77ab6', class: "camera-selector-dropdown" }, index.h("div", { key: '3a4200b5624f5d96de4ae8acb821a47d31a34c93', class: "camera-selector-header" }, index.h("span", { key: '14f8e8618d9404cdfd3f9cc150e54b510507c977' }, "Seleccionar C\u00E1mara"), index.h("button", { key: '98367e182d227093742e0fc9118f81db32352bdd', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: '172471ef3c0d55cb619a061eafe37205c3a0bee4', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (index.h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: 'e08ced0c02b5662be31c60b2ba35c83fac46bb80', class: "device-info" }, index.h("small", { key: '8489f10c13a0a528abc878cc66d71dc769890b90' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (index.h("div", { key: '89f6c5a9bc1efb9bd8af190ae0821dabe992a2be', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: 'ead4d0cf0751097220572a4946bf4dcb3d7f4f33', class: "flip-animation" }, index.h("div", { key: '357e981fd9b2f616e9b1b90c8454555dceac6fbd', class: "id-card-icon" }), index.h("div", { key: '4abfecbb5ee0165b720d6ad8398984b25ecec7a1', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: 'cdeedd36903c8467e7ebb406e3414ecd92abf47c', class: "success-animation" }, index.h("div", { key: '8731f318d490ff67fa7f68edf264acb762632604', class: "check-icon" }), index.h("div", { key: '2e21ce0921fedfaa0b90c56ec44d289426ea7708', class: "success-text" }, "\u00A1Proceso completado!"))), index.h("div", { key: '6cf678c79f8e57fde12202a932fe855905ae770f', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: 'f9e888616736c26624bd3de7c2f1eee297d0a2f5', class: "status-spinner" })), index.h("div", { key: 'b849c5187ed8e66b4cf62113d2f93c006cf9f836', class: "status-content" }, index.h("div", { key: '64a2dac4cb5e4c17fc2aa161c8faa389c64a0458', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: '64e85a98129f791d6784a98129f2411607360fff', class: "status-description" }, this.currentStatus.description)))), this.debug && (index.h("div", { key: '1d41d3139d7d486bdf9225f584d6de250faeddf7', class: "performance-monitor" }, index.h("div", { key: '75bf3d45d869c4b0365f994444292de2245d391c', class: "performance-expanded" }, index.h("div", { key: '762c977e7125202103aba84c568c0fefee43d6b2', class: "metrics-row" }, index.h("div", { key: '51b03d882f84e835664af11d409fc01a5363c0ce', class: "metric-compact" }, index.h("span", { key: '21767c803c2fda9fe8653881cb8dfdcaa992fe3b', class: "metric-label" }, "FPS"), index.h("span", { key: '5467ba22adb75668a0acadd4ffcbaa25117fd8ae', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), index.h("div", { key: 'a6c020d500a72f330a7cbb01cfdddc1fff63f1bb', class: "metric-compact" }, index.h("span", { key: '5034e33c12ad454368e4fa32567c307bce6ffe0e', class: "metric-label" }, "MEM"), index.h("span", { key: '19f691984f9e6aac29067fc983561b701b9080de', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), index.h("div", { key: 'c2a11b8dc156b90a4ba18020e5a62ff87c29f624', class: "metrics-row" }, index.h("div", { key: '7af9c2c1286bb32d6c166d3487c8ea4a02f14490', class: "metric-compact" }, index.h("span", { key: 'b34e54ac6b4e387ee8155176f999dd2b721a8617', class: "metric-label" }, "INF"), index.h("span", { key: 'ada2f913ac6c97661a054f9bf596f4ac52eb918e', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), index.h("div", { key: 'cc2d819a7e75af4e03d2521756c23110785076ad', class: "metric-compact" }, index.h("span", { key: 'b2f7e528be88eafcc66d801e8f547b4d274e0cf8', class: "metric-label" }, "FRAME"), index.h("span", { key: '1bcddf221b960018fb5505553e9f8cfd3717c349', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), index.h("div", { key: 'cb80b6198f621fab68b13c4992578ef2e548ae99', class: "metrics-row" }, index.h("div", { key: 'b752b65906c92eff86cad2d0ffdc1420f03a8932', class: "metric-compact" }, index.h("span", { key: '96af746b42a101c6bfe4c197b652837ecc66fc06', class: "metric-label" }, "DET"), index.h("span", { key: 'f2038ae4943ebd9ae2ec1d8b907ae23f04c8fd90', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), index.h("div", { key: 'c2e6b9380928b30b1a879a6abc43eb7053da9ac1', class: "metric-compact" }, index.h("span", { key: '096268d19a7ac7471c5dafd5adc3103d30433a55', class: "metric-label" }, "RATE"), index.h("span", { key: '7f9e9e49c68da719fe43391518514af3cdab004d', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), index.h("div", { key: 'c6546f8ec722c56fa369da6d5d732f29d3afc65f', class: "watermark" }, index.h("img", { key: 'd195a395051a4c436dec33d7835c565e748cf60a', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
1488
1560
|
}
|
|
1489
1561
|
// Utility methods
|
|
1490
1562
|
updateDetectionBoxes(boxes) {
|
|
@@ -1557,19 +1629,37 @@ const JaakStamps = class {
|
|
|
1557
1629
|
cardOutline?.classList.add('perfect-match');
|
|
1558
1630
|
corners?.forEach(corner => corner.classList.add('perfect-match'));
|
|
1559
1631
|
if (!this.hasScreenshotTaken) {
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1632
|
+
const currentTime = Date.now();
|
|
1633
|
+
// Initialize alignment start time if not set
|
|
1634
|
+
if (!this.alignmentStartTime) {
|
|
1635
|
+
this.alignmentStartTime = currentTime;
|
|
1636
|
+
}
|
|
1637
|
+
// Check if document has been aligned for 1 second
|
|
1638
|
+
const alignmentDuration = currentTime - this.alignmentStartTime;
|
|
1639
|
+
if (alignmentDuration >= 1000) {
|
|
1640
|
+
this.lastDetectedBox = bestBox;
|
|
1641
|
+
this.takeScreenshot().catch(error => {
|
|
1642
|
+
this.logger.error('Error al tomar captura de pantalla:', error);
|
|
1643
|
+
});
|
|
1644
|
+
this.hasScreenshotTaken = true;
|
|
1645
|
+
this.alignmentStartTime = undefined;
|
|
1646
|
+
setTimeout(() => {
|
|
1647
|
+
this.hasScreenshotTaken = false;
|
|
1648
|
+
}, 2000);
|
|
1649
|
+
}
|
|
1568
1650
|
}
|
|
1569
1651
|
}
|
|
1570
1652
|
else {
|
|
1571
1653
|
cardOutline?.classList.remove('perfect-match');
|
|
1572
1654
|
corners?.forEach(corner => corner.classList.remove('perfect-match'));
|
|
1655
|
+
// Reset alignment timer when document moves out of position
|
|
1656
|
+
if (this.alignmentStartTime) {
|
|
1657
|
+
this.alignmentStartTime = undefined;
|
|
1658
|
+
}
|
|
1659
|
+
if (this.alignmentTimer) {
|
|
1660
|
+
clearTimeout(this.alignmentTimer);
|
|
1661
|
+
this.alignmentTimer = undefined;
|
|
1662
|
+
}
|
|
1573
1663
|
}
|
|
1574
1664
|
}
|
|
1575
1665
|
async takeScreenshot() {
|
|
@@ -1686,8 +1776,52 @@ const JaakStamps = class {
|
|
|
1686
1776
|
this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
|
|
1687
1777
|
}
|
|
1688
1778
|
toggleCameraSelector() {
|
|
1779
|
+
if (this.isSwitchingCamera)
|
|
1780
|
+
return; // Don't toggle if switching camera
|
|
1689
1781
|
this.showCameraSelector = !this.showCameraSelector;
|
|
1690
1782
|
}
|
|
1783
|
+
async handleCameraSwitch(cameraId) {
|
|
1784
|
+
if (this.isSwitchingCamera)
|
|
1785
|
+
return; // Prevent multiple simultaneous switches
|
|
1786
|
+
try {
|
|
1787
|
+
// Close the selector immediately when user selects a camera
|
|
1788
|
+
this.showCameraSelector = false;
|
|
1789
|
+
this.isSwitchingCamera = true;
|
|
1790
|
+
this.logger.state('INICIANDO_CAMBIO_CAMARA', {
|
|
1791
|
+
from: this.cameraService.getSelectedCameraId(),
|
|
1792
|
+
to: cameraId
|
|
1793
|
+
});
|
|
1794
|
+
// Stop current video stream
|
|
1795
|
+
if (this.videoStream) {
|
|
1796
|
+
this.videoStream.getTracks().forEach(track => track.stop());
|
|
1797
|
+
}
|
|
1798
|
+
// Switch camera in service
|
|
1799
|
+
await this.cameraService.switchCamera(cameraId);
|
|
1800
|
+
// Setup new camera stream
|
|
1801
|
+
const newStream = await this.cameraService.setupCamera();
|
|
1802
|
+
// Update video element
|
|
1803
|
+
await this.initializeVideoStream(newStream);
|
|
1804
|
+
this.logger.state('CAMBIO_CAMARA_EXITOSO', {
|
|
1805
|
+
newCameraId: cameraId,
|
|
1806
|
+
isRearCamera: this.cameraService.isRearCamera(newStream)
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
catch (error) {
|
|
1810
|
+
this.logger.error('Error al cambiar cámara:', error);
|
|
1811
|
+
// Try to restore previous camera if switch failed
|
|
1812
|
+
try {
|
|
1813
|
+
const fallbackStream = await this.cameraService.setupCamera();
|
|
1814
|
+
await this.initializeVideoStream(fallbackStream);
|
|
1815
|
+
}
|
|
1816
|
+
catch (fallbackError) {
|
|
1817
|
+
this.logger.error('Error al restaurar cámara anterior:', fallbackError);
|
|
1818
|
+
this.updateStatus('Error al cambiar cámara', 'No se pudo completar el cambio de dispositivo', 'error');
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
finally {
|
|
1822
|
+
this.isSwitchingCamera = false;
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1691
1825
|
resetDetection() {
|
|
1692
1826
|
this.stateManager.reset();
|
|
1693
1827
|
this.hasScreenshotTaken = false;
|
|
@@ -1696,6 +1830,11 @@ const JaakStamps = class {
|
|
|
1696
1830
|
this.consecutiveFailures = 0;
|
|
1697
1831
|
this.lastInferenceTime = 0;
|
|
1698
1832
|
this.detectionBoxes = [];
|
|
1833
|
+
this.alignmentStartTime = undefined;
|
|
1834
|
+
if (this.alignmentTimer) {
|
|
1835
|
+
clearTimeout(this.alignmentTimer);
|
|
1836
|
+
this.alignmentTimer = undefined;
|
|
1837
|
+
}
|
|
1699
1838
|
const captureState = this.stateManager.getCaptureState();
|
|
1700
1839
|
if (captureState.isVideoActive && this.detectionService.isModelLoaded()) {
|
|
1701
1840
|
this.updateStatus('Captura reiniciada', 'Buscando documento en el marco de captura', 'active');
|
|
@@ -1715,6 +1854,60 @@ const JaakStamps = class {
|
|
|
1715
1854
|
this.detectionBoxes = [];
|
|
1716
1855
|
this.cleanup();
|
|
1717
1856
|
}
|
|
1857
|
+
// PERFORMANCE MONITORING METHODS
|
|
1858
|
+
initializePerformanceMonitor() {
|
|
1859
|
+
this.performanceMetrics.lastUpdateTime = performance.now();
|
|
1860
|
+
// Update performance metrics every 500ms
|
|
1861
|
+
this.performanceUpdateInterval = window.setInterval(() => {
|
|
1862
|
+
this.updatePerformanceMetrics();
|
|
1863
|
+
}, 500);
|
|
1864
|
+
this.logger.debug('Monitor de performance inicializado');
|
|
1865
|
+
}
|
|
1866
|
+
updatePerformanceMetrics() {
|
|
1867
|
+
const currentTime = performance.now();
|
|
1868
|
+
const deltaTime = currentTime - this.performanceMetrics.lastUpdateTime;
|
|
1869
|
+
// Calculate FPS
|
|
1870
|
+
if (deltaTime > 0) {
|
|
1871
|
+
this.performanceMetrics.fps = Math.round(1000 / (deltaTime / this.frameSkipCounter || 1));
|
|
1872
|
+
}
|
|
1873
|
+
// Get memory usage if available
|
|
1874
|
+
if ('memory' in performance) {
|
|
1875
|
+
const memInfo = performance.memory;
|
|
1876
|
+
this.performanceMetrics.memoryUsage = Math.round(memInfo.usedJSHeapSize / 1048576); // MB
|
|
1877
|
+
}
|
|
1878
|
+
// Calculate detection success rate
|
|
1879
|
+
if (this.performanceMetrics.totalDetections > 0) {
|
|
1880
|
+
this.performanceMetrics.successfulDetections = this.performanceMetrics.successfulDetections;
|
|
1881
|
+
const detectionRate = (this.performanceMetrics.successfulDetections / this.performanceMetrics.totalDetections) * 100;
|
|
1882
|
+
this.performanceMetrics.detectionRate = Math.round(detectionRate);
|
|
1883
|
+
}
|
|
1884
|
+
// Update state for rendering
|
|
1885
|
+
this.performanceData = {
|
|
1886
|
+
fps: this.performanceMetrics.fps,
|
|
1887
|
+
inferenceTime: this.performanceMetrics.inferenceTime,
|
|
1888
|
+
memoryUsage: this.performanceMetrics.memoryUsage,
|
|
1889
|
+
onnxLoadTime: this.performanceMetrics.onnxLoadTime,
|
|
1890
|
+
frameProcessingTime: this.performanceMetrics.frameProcessingTime,
|
|
1891
|
+
totalDetections: this.performanceMetrics.totalDetections,
|
|
1892
|
+
successfulDetections: this.performanceMetrics.successfulDetections,
|
|
1893
|
+
detectionRate: this.performanceMetrics.detectionRate
|
|
1894
|
+
};
|
|
1895
|
+
this.performanceMetrics.lastUpdateTime = currentTime;
|
|
1896
|
+
}
|
|
1897
|
+
recordOnnxPerformance(loadTime, inferenceTime) {
|
|
1898
|
+
this.performanceMetrics.onnxLoadTime = Math.round(loadTime);
|
|
1899
|
+
this.performanceMetrics.inferenceTime = Math.round(inferenceTime);
|
|
1900
|
+
}
|
|
1901
|
+
recordFrameProcessing(processingTime, detectionsFound) {
|
|
1902
|
+
this.performanceMetrics.frameProcessingTime = Math.round(processingTime);
|
|
1903
|
+
this.performanceMetrics.totalDetections++;
|
|
1904
|
+
if (detectionsFound > 0) {
|
|
1905
|
+
this.performanceMetrics.successfulDetections++;
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
togglePerformanceMonitor() {
|
|
1909
|
+
this.isPerformanceMonitorMinimized = !this.isPerformanceMonitorMinimized;
|
|
1910
|
+
}
|
|
1718
1911
|
};
|
|
1719
1912
|
JaakStamps.style = myComponentCss;
|
|
1720
1913
|
|