@jaak.ai/stamps 2.5.8-dev.1 → 2.5.8-dev.2
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.cjs.entry.js +73 -5
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/collection/components/jaak-stamps/jaak-stamps.js +73 -5
- package/dist/collection/components/jaak-stamps/jaak-stamps.js.map +1 -1
- package/dist/components/jaak-stamps.js +73 -5
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/jaak-stamps.entry.js +73 -5
- package/dist/esm/jaak-stamps.entry.js.map +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-474f6bec.entry.js → p-b4834625.entry.js} +2 -2
- package/dist/jaak-stamps-webcomponent/p-b4834625.entry.js.map +1 -0
- package/dist/types/components/jaak-stamps/jaak-stamps.d.ts +5 -0
- package/package.json +1 -1
- package/dist/jaak-stamps-webcomponent/p-474f6bec.entry.js.map +0 -1
|
@@ -144,6 +144,18 @@ export class JaakStamps {
|
|
|
144
144
|
// Canvas pool for optimized screenshot capture
|
|
145
145
|
canvasPool = [];
|
|
146
146
|
MAX_CANVAS_POOL_SIZE = 3;
|
|
147
|
+
// Readiness gate for startCapture(). The host may call startCapture() before the
|
|
148
|
+
// component finishes loading its resources (ONNX Runtime + WASM/models from the CDN).
|
|
149
|
+
// On slow devices/networks this race made startCapture() abort with "El componente
|
|
150
|
+
// está cargando recursos", leaving the screen black (TO-807). Instead of aborting we
|
|
151
|
+
// wait for initialization to settle and retry. `initializationSettled` flips once
|
|
152
|
+
// finalizeInitialization() has run; pending waiters are released via these callbacks.
|
|
153
|
+
initializationSettled = false;
|
|
154
|
+
initializationWaiters = [];
|
|
155
|
+
// Max time startCapture() waits for a still-initializing component before giving up.
|
|
156
|
+
// Sized for slow Android/network asset downloads; if resources never load (CDN down,
|
|
157
|
+
// 404, CORS) the timeout fires and startCapture() returns the original error.
|
|
158
|
+
START_CAPTURE_READY_TIMEOUT_MS = 15000;
|
|
147
159
|
async componentWillLoad() {
|
|
148
160
|
// @Watch handlers fire synchronously when Angular sets properties, which happens
|
|
149
161
|
// BEFORE componentWillLoad (Stencil schedules componentWillLoad as a microtask after
|
|
@@ -283,6 +295,13 @@ export class JaakStamps {
|
|
|
283
295
|
else {
|
|
284
296
|
this._pendingEnvironmentRetry = false;
|
|
285
297
|
}
|
|
298
|
+
// Release any startCapture() calls waiting on readiness. On success this is a
|
|
299
|
+
// no-op (finalizeInitialization already settled); on a terminal failure (invalid
|
|
300
|
+
// license / init error) it lets startCapture() return its error without waiting
|
|
301
|
+
// out the full timeout. Idempotent, so a completed retry above stays settled.
|
|
302
|
+
if (!this._initializing) {
|
|
303
|
+
this.settleInitialization();
|
|
304
|
+
}
|
|
286
305
|
}
|
|
287
306
|
}
|
|
288
307
|
async initializeServices() {
|
|
@@ -473,6 +492,42 @@ export class JaakStamps {
|
|
|
473
492
|
};
|
|
474
493
|
}
|
|
475
494
|
this.emitReadyEvent();
|
|
495
|
+
this.settleInitialization();
|
|
496
|
+
}
|
|
497
|
+
// Releases any startCapture() calls that arrived while the component was still
|
|
498
|
+
// initializing. Idempotent: safe to call more than once.
|
|
499
|
+
settleInitialization() {
|
|
500
|
+
if (this.initializationSettled) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
this.initializationSettled = true;
|
|
504
|
+
const waiters = this.initializationWaiters;
|
|
505
|
+
this.initializationWaiters = [];
|
|
506
|
+
waiters.forEach(resolve => resolve());
|
|
507
|
+
}
|
|
508
|
+
// Waits until initialization settles (finalizeInitialization ran) or the timeout
|
|
509
|
+
// elapses, whichever comes first. Resolves regardless of outcome; the caller
|
|
510
|
+
// re-checks isComponentReady() afterwards to decide success/failure.
|
|
511
|
+
waitForInitialization(timeoutMs) {
|
|
512
|
+
if (this.initializationSettled) {
|
|
513
|
+
return Promise.resolve();
|
|
514
|
+
}
|
|
515
|
+
return new Promise(resolve => {
|
|
516
|
+
let settled = false;
|
|
517
|
+
const done = () => {
|
|
518
|
+
if (settled) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
settled = true;
|
|
522
|
+
clearTimeout(timer);
|
|
523
|
+
resolve();
|
|
524
|
+
};
|
|
525
|
+
const timer = setTimeout(() => {
|
|
526
|
+
this.initializationWaiters = this.initializationWaiters.filter(w => w !== done);
|
|
527
|
+
done();
|
|
528
|
+
}, timeoutMs);
|
|
529
|
+
this.initializationWaiters.push(done);
|
|
530
|
+
});
|
|
476
531
|
}
|
|
477
532
|
updateStatus(message, description, type = 'loading') {
|
|
478
533
|
this.currentStatus = {
|
|
@@ -664,7 +719,20 @@ export class JaakStamps {
|
|
|
664
719
|
}
|
|
665
720
|
async startCapture() {
|
|
666
721
|
const span = this.tracingService?.startSpan('capture.start');
|
|
667
|
-
|
|
722
|
+
let readyCheck = this.isComponentReady();
|
|
723
|
+
// TO-807: absorb the start-before-ready race instead of aborting. When the
|
|
724
|
+
// component is still loading its resources (transient initializing/loading
|
|
725
|
+
// state) we wait for initialization to settle and re-check, rather than
|
|
726
|
+
// returning an error immediately (which left the host with a black screen).
|
|
727
|
+
// A terminal state ('error' / missing services) is not waited on.
|
|
728
|
+
if (!readyCheck.ready && (readyCheck.status === 'initializing' || readyCheck.status === 'loading')) {
|
|
729
|
+
this.updateStatus('El componente está cargando recursos', 'Espere a que termine la inicialización', 'loading');
|
|
730
|
+
if (span) {
|
|
731
|
+
this.tracingService?.setSpanAttribute(span, 'startCapture.waitedForReady', true);
|
|
732
|
+
}
|
|
733
|
+
await this.waitForInitialization(this.START_CAPTURE_READY_TIMEOUT_MS);
|
|
734
|
+
readyCheck = this.isComponentReady();
|
|
735
|
+
}
|
|
668
736
|
if (!readyCheck.ready) {
|
|
669
737
|
this.updateStatus(readyCheck.message, 'Espere a que termine la inicialización', readyCheck.status);
|
|
670
738
|
if (span) {
|
|
@@ -1657,7 +1725,7 @@ export class JaakStamps {
|
|
|
1657
1725
|
isCapturing: false
|
|
1658
1726
|
};
|
|
1659
1727
|
const cameraInfo = this.cameraInfoWithAutofocus;
|
|
1660
|
-
return (h("div", { key: '
|
|
1728
|
+
return (h("div", { key: 'ed400c7cc247fb12e5915e270207d3fa916362fd', class: "detector-container" }, !this.licenseValid && this.licenseError && (h("div", { key: 'd2f7507026d01d2fd381d365c9954067eb37c3f4', class: "license-error-container" }, h("div", { key: 'fc4ae7ae434a038a3730057a99a7d96d851dba43', class: "license-error-card" }, h("svg", { key: '7361da72e3fda0147044873bc770460098a4b4f1', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { key: '57a3dce14d47d4b91af6ff84ab39cde58814f573', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("path", { key: '8c96a1638602eface0ae8c7377cdda04dffde5c7', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("circle", { key: '7455af58b1827570713d778a4ef01bb0ffcfb553', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), h("h2", { key: '5779f8a2c4468ea185df620edecb3f79b7ae8bfb', class: "license-error-title" }, "Licencia Requerida"), h("p", { key: '8180147597c077798ff4ea4eb9309a3bec69c77f', class: "license-error-message" }, this.licenseError), h("p", { key: '2103af42045a8ee8385de273da8f98e23395469b', class: "license-error-help" }, "Contacte a soporte: ", h("a", { key: '8a7fe987b24600b123216c952c5b69f2c2afc0a0', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), h("div", { key: 'fd00ef42e259669b7b7cc512478c9c925bd03415', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (h("div", { key: '44a92ba0a4cc066bb4497f4f548fce0bd5dbc121', class: "video-container" }, h("video", { key: '9ef40fb28c0fea1b59657ae50134b4dc3df4cf24', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: {
|
|
1661
1729
|
// Keep the element rendered (display: block) so the browser
|
|
1662
1730
|
// loads stream metadata and fires 'loadedmetadata'. Hiding it
|
|
1663
1731
|
// with display:none prevents metadata loading in Chrome and
|
|
@@ -1666,7 +1734,7 @@ export class JaakStamps {
|
|
|
1666
1734
|
// render context alive.
|
|
1667
1735
|
opacity: captureState.isVideoActive ? '1' : '0',
|
|
1668
1736
|
visibility: captureState.isVideoActive ? 'visible' : 'hidden',
|
|
1669
|
-
} }), h("div", { key: '
|
|
1737
|
+
} }), h("div", { key: 'f3d6e544bb8b13214894f71216badf092d2516dd', 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: {
|
|
1670
1738
|
position: 'absolute',
|
|
1671
1739
|
left: `${box.x}px`,
|
|
1672
1740
|
top: `${box.y}px`,
|
|
@@ -1675,9 +1743,9 @@ export class JaakStamps {
|
|
|
1675
1743
|
border: '2px solid #32406C',
|
|
1676
1744
|
pointerEvents: 'none',
|
|
1677
1745
|
boxSizing: 'border-box'
|
|
1678
|
-
} })))), this.isMaskReady && (h("div", { key: '
|
|
1746
|
+
} })))), this.isMaskReady && (h("div", { key: '312b9d7733e550a444e84d699c0e14834fc41057', class: "overlay-mask" }, h("div", { key: '2af1c83efb4d360ecada3301f4479bbf8845f032', class: "card-outline" }, h("div", { key: 'b6f57f153953e059056fae6d9f8a8220bfff4357', class: "side side-top" }), h("div", { key: 'e465f72b8834a04174dc88897b813517afa372fb', class: "side side-right" }), h("div", { key: '32e2785c7570f2002b6bc68b491007925d9fcad5', class: "side side-bottom" }), h("div", { key: 'bf2133811df7f516d9e3b37ae6019c90c0a68d0b', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'de00829ac42fe7f3645cb515fb46cfabe415190b', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'ae09d9c23635d87d31110781dc0ab3acb8ec4667', class: "back-capture-section" }, h("div", { key: 'a30a50ee0272140d16e32f582dd93f8de87d2a44', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: 'fb104cf6feaeca2f9542a2d5933bbf4f15c6771f', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: '7a1bff56bae244c5b8d1d4c3fd523e7a20b4b5ce', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: '59125b29ad55122e5ee9e8c2aaf9689a1fef588e', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: '4d0b8184b4eb82824d5d864fb1b196f22302506d', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
|
|
1679
1747
|
? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
|
|
1680
|
-
: 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: '
|
|
1748
|
+
: 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: '1febf678f87e32916d3990677b41345ce034db4e', class: "camera-controls" }, h("button", { key: '79f00bac9d56347de1fc08b2e06be1c0e996a855', 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: '4f6d101ce789b7fff227a6a2ce2479cb6255fd58', class: "camera-selector-dropdown" }, h("div", { key: 'f82222bb25162d2717d84c098c2a6540caa821f3', class: "camera-selector-header" }, h("span", { key: '0b1648857467c5749fe5d1d846d1786fa2e394c3' }, "Seleccionar C\u00E1mara"), h("button", { key: 'f406f08ad9dc2dcaced7e95aed013665c5fcfb4e', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'a051beeab1c8447730d41e963cd3b95027922cab', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'c9c0702a57c105b02062f325cd413b531c7f802c', class: "device-info" }, h("small", { key: '584f4c1ce525b8ab03107329c92797737d5afad5' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'e3e2a270d3c4e7accdd9bc8b37861af4fceaad5d', class: "manual-capture-section" }, h("button", { key: '1283629ce59fc82d7b3fc08d5573bc69238f7aab', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: '5de009e4d2ff0de43355e95e1d69f12d7f2e65f8', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: '975142144bb104d3ed532ac80fca19a7f237bb2b', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '5d54b9130ed4d1e13b95cfeee8f9d694b5de68d3', class: "flip-animation" }, h("div", { key: 'c8b955180065d2b99f8e5f405b1ff92bc050af77', class: "id-card-icon" }), h("div", { key: 'f103b1871266886455d5bba094a0e119aa484595', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '5845c045d37099cf906f7c56d3c91568dd198bdf', class: "success-animation" }, h("div", { key: '430496db95f10834a43842e9ac97bdf0f025eb3b', class: "check-icon" }), h("div", { key: '0815cf6feffe8bd4ba84712c14d8f29c1a945577', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: 'f8a8a529850fc93e93f12810b7928e4700bac880', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '929ab612be046e97bb02ebe366b531864b90cc7a', class: "status-spinner" })), h("div", { key: 'defaf70aa54f2ccc222ddbe392cc47f7c143fc06', class: "status-content" }, h("div", { key: '685cca31f70e26d062f2d01b9ffd8c5a4a6b6f86', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '21bce9f6de9e5a50763ef83a25787225319dc5bf', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '6e43560821e469e397b78ab44d1679a3ff8e330f', class: "performance-monitor" }, h("div", { key: 'afcde6083be4a1b4a76d5523e0a239926b76ff9a', class: "performance-expanded" }, h("div", { key: '0706e93c06bcaf2e573c0c2ac414c3ca7d3605ba', class: "metrics-row" }, h("div", { key: '32b755f0f81ae758d9ab0b2e75dd9d55ef52eef0', class: "metric-compact" }, h("span", { key: 'b1d8e773fdd1e333cd55bb5bbed2878a7e106474', class: "metric-label" }, "FPS"), h("span", { key: 'a6c53d389e7424f6696b6279bef267b28e112201', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'a8c4157b696ae53e8ae5cee14f9e8b37be34a0a6', class: "metric-compact" }, h("span", { key: '0fa82dd84f6e0a9c16c1894021932e8ba355991a', class: "metric-label" }, "MEM"), h("span", { key: 'fc7f19be4e3fbbc82da538703ef9049e26571496', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: '84bd7b6da8e91004ef6c554264b97b89fa6123e1', class: "metrics-row" }, h("div", { key: 'a2bc7af57fe87f5ef53ee00f76aa27675736c404', class: "metric-compact" }, h("span", { key: '59e9114f50cf4d69bfc447162001e8ab3214906a', class: "metric-label" }, "INF"), h("span", { key: 'c92e1f7e92127d85e0cdd647af44f1da4c46da57', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '5751e9dee9d55ddc559d1c60e68c4be7da2eb7a2', class: "metric-compact" }, h("span", { key: 'a34e394ab188e74a39eb77af4cf0108c8a2be1c3', class: "metric-label" }, "FRAME"), h("span", { key: '19165e851fc7f348e6cee93deccff0159c3bb982', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'dde9e547b8c9e200624e525d15baaa4a18a27417', class: "metrics-row" }, h("div", { key: '770301e51025a446e29638d38e8e8a8dfb911882', class: "metric-compact" }, h("span", { key: '96750b7a455ef1f3353b870467afdff402fa605b', class: "metric-label" }, "DET"), h("span", { key: 'a7951b69998e1d13beee40b6677d55091a413a4c', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'a82589fbccc749ef904a68933c6b850c3b69018c', class: "metric-compact" }, h("span", { key: 'ced7d42d2ebf2c4f20671c696b845263f4de4f4a', class: "metric-label" }, "RATE"), h("span", { key: '693c9735796ec276ca1d7e559aea250dafb0e5cf', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '3ff1698eae36352f9268839b86cef29144de297c', class: "watermark" }, h("img", { key: 'efa9735216e7caafdb67e10a5fc9363b503307b5', src: "https://static.jaak.ai/commons/powered-by-jaak.png", alt: "Powered by Jaak", onError: (e) => {
|
|
1681
1749
|
const img = e.target;
|
|
1682
1750
|
img.onerror = null;
|
|
1683
1751
|
img.src = POWERED_BY_JAAK_FALLBACK;
|