@jaak.ai/stamps 2.1.0-dev.9 → 2.2.0-beta.1
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/README.md +227 -14
- package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
- package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
- package/dist/cjs/{index-BfhtOB0D.js → index-D6NBn_qu.js} +203 -121
- package/dist/cjs/index-D6NBn_qu.js.map +1 -0
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js +5 -4
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js.map +1 -1
- package/dist/cjs/jaak-stamps.cjs.entry.js +17780 -442
- 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 +4 -3
- package/dist/cjs/loader.cjs.js.map +1 -1
- package/dist/collection/collection-manifest.json +1 -1
- package/dist/collection/components/my-component/my-component.css +106 -5
- package/dist/collection/components/my-component/my-component.js +558 -313
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/collection/services/CameraService.js +125 -11
- package/dist/collection/services/CameraService.js.map +1 -1
- package/dist/collection/services/DetectionService.js +7 -148
- package/dist/collection/services/DetectionService.js.map +1 -1
- package/dist/collection/services/LicenseValidationService.js +111 -0
- package/dist/collection/services/LicenseValidationService.js.map +1 -0
- package/dist/collection/services/MetricsService.js +350 -0
- package/dist/collection/services/MetricsService.js.map +1 -0
- package/dist/collection/services/ServiceContainer.js +66 -1
- package/dist/collection/services/ServiceContainer.js.map +1 -1
- package/dist/collection/services/TracingService.js +494 -0
- package/dist/collection/services/TracingService.js.map +1 -0
- package/dist/collection/services/interfaces/IDetectionService.js.map +1 -1
- package/dist/collection/services/interfaces/ILicenseValidationService.js +2 -0
- package/dist/collection/services/interfaces/ILicenseValidationService.js.map +1 -0
- package/dist/collection/services/interfaces/IMetricsService.js +2 -0
- package/dist/collection/services/interfaces/IMetricsService.js.map +1 -0
- package/dist/collection/services/interfaces/ITracingService.js +2 -0
- package/dist/collection/services/interfaces/ITracingService.js.map +1 -0
- package/dist/components/index.js +192 -115
- package/dist/components/index.js.map +1 -1
- package/dist/components/jaak-stamps.js +17796 -445
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/app-globals-DQuL1Twl.js +6 -0
- package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
- package/dist/esm/{index-BP1Q4KOg.js → index-BCfAsrzL.js} +204 -121
- package/dist/esm/index-BCfAsrzL.js.map +1 -0
- package/dist/esm/jaak-stamps-webcomponent.js +5 -4
- package/dist/esm/jaak-stamps-webcomponent.js.map +1 -1
- package/dist/esm/jaak-stamps.entry.js +17780 -442
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/esm/loader.js +4 -3
- package/dist/esm/loader.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/loader.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/p-34bcebb1.entry.js +7 -0
- package/dist/jaak-stamps-webcomponent/p-34bcebb1.entry.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js +3 -0
- package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +25 -27
- package/dist/types/components.d.ts +77 -3
- package/dist/types/services/CameraService.d.ts +1 -0
- package/dist/types/services/DetectionService.d.ts +1 -9
- package/dist/types/services/LicenseValidationService.d.ts +59 -0
- package/dist/types/services/MetricsService.d.ts +74 -0
- package/dist/types/services/ServiceContainer.d.ts +14 -1
- package/dist/types/services/TracingService.d.ts +72 -0
- package/dist/types/services/interfaces/IDetectionService.d.ts +0 -6
- package/dist/types/services/interfaces/ILicenseValidationService.d.ts +4 -0
- package/dist/types/services/interfaces/IMetricsService.d.ts +70 -0
- package/dist/types/services/interfaces/ITracingService.d.ts +64 -0
- package/dist/types/stencil-public-runtime.d.ts +12 -5
- package/package.json +20 -2
- package/dist/cjs/index-BfhtOB0D.js.map +0 -1
- package/dist/esm/index-BP1Q4KOg.js.map +0 -1
- package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js +0 -3
- package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js.map +0 -1
- package/dist/jaak-stamps-webcomponent/p-c115e01a.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-c115e01a.entry.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
2
|
import { ServiceContainer } from "../../services/ServiceContainer";
|
|
3
|
+
import { LicenseValidationService } from "../../services/LicenseValidationService";
|
|
3
4
|
export class JaakStamps {
|
|
4
5
|
el;
|
|
5
6
|
debug = false;
|
|
@@ -12,8 +13,22 @@ export class JaakStamps {
|
|
|
12
13
|
captureDelay = 1500;
|
|
13
14
|
enableBackDocumentTimer = false;
|
|
14
15
|
backDocumentTimerDuration = 20;
|
|
16
|
+
telemetryCollectorUrl = 'https://collector.jaak.ai/v1/traces';
|
|
17
|
+
metricsCollectorUrl = 'https://collector.jaak.ai/v1/metrics';
|
|
18
|
+
enableTelemetry = true;
|
|
19
|
+
enableMetrics = true;
|
|
20
|
+
customerId;
|
|
21
|
+
tenantId;
|
|
22
|
+
environment = 'production';
|
|
23
|
+
propagateTraceHeaderCorsUrls; // Comma-separated URLs or regex patterns
|
|
24
|
+
metricsExportIntervalMillis = 60000; // Export metrics every 60 seconds
|
|
25
|
+
license; // License key for validation
|
|
26
|
+
licenseEnvironment = 'prod'; // Environment for license validation
|
|
27
|
+
traceId; // Optional trace ID for tracking
|
|
28
|
+
appId = 'jaak-stamps-web'; // Application ID for license validation
|
|
15
29
|
captureCompleted;
|
|
16
30
|
isReady;
|
|
31
|
+
traceIdGenerated;
|
|
17
32
|
// State derived from services
|
|
18
33
|
detectionBoxes = [];
|
|
19
34
|
sideAlignment = {
|
|
@@ -53,12 +68,17 @@ export class JaakStamps {
|
|
|
53
68
|
showPerformanceMessage = false; // Show performance message temporarily
|
|
54
69
|
captureStateVersion = 0; // Triggers re-render when StateManager changes
|
|
55
70
|
processingButton = null; // Track which button is processing
|
|
71
|
+
licenseValid = true; // License validation status
|
|
72
|
+
licenseError = null; // License validation error message
|
|
56
73
|
// Services
|
|
74
|
+
licenseValidationService = null;
|
|
57
75
|
serviceContainer;
|
|
58
76
|
eventBus;
|
|
59
77
|
stateManager;
|
|
60
78
|
cameraService;
|
|
61
79
|
detectionService;
|
|
80
|
+
tracingService;
|
|
81
|
+
metricsService;
|
|
62
82
|
// UI References
|
|
63
83
|
videoRef;
|
|
64
84
|
detectionContainer;
|
|
@@ -71,6 +91,7 @@ export class JaakStamps {
|
|
|
71
91
|
alignmentStartTime;
|
|
72
92
|
alignmentTimer;
|
|
73
93
|
backDocumentTimer;
|
|
94
|
+
orientationTimer;
|
|
74
95
|
// Performance monitoring
|
|
75
96
|
performanceMetrics = {
|
|
76
97
|
fps: 0,
|
|
@@ -92,6 +113,7 @@ export class JaakStamps {
|
|
|
92
113
|
MAX_FAILURES = 30;
|
|
93
114
|
lastInferenceTime = 0;
|
|
94
115
|
MIN_INFERENCE_INTERVAL = 50;
|
|
116
|
+
MOBILE_MIN_INFERENCE_INTERVAL = 100; // Higher interval for mobile to prevent slow motion
|
|
95
117
|
performanceHistory = [];
|
|
96
118
|
PERFORMANCE_HISTORY_SIZE = 10;
|
|
97
119
|
// Sistema simplificado de monitoreo de rendimiento
|
|
@@ -103,8 +125,23 @@ export class JaakStamps {
|
|
|
103
125
|
// Canvas pool for optimized screenshot capture
|
|
104
126
|
canvasPool = [];
|
|
105
127
|
MAX_CANVAS_POOL_SIZE = 3;
|
|
128
|
+
async componentWillLoad() {
|
|
129
|
+
// License is required - always validate
|
|
130
|
+
// Wait a bit to ensure props are set from attributes
|
|
131
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
132
|
+
this.updateStatus('Validando licencia...', 'Verificando autorización de uso', 'initializing');
|
|
133
|
+
await this.validateLicense();
|
|
134
|
+
// If license validation failed, stop initialization
|
|
135
|
+
if (!this.licenseValid) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
106
139
|
async componentDidLoad() {
|
|
107
140
|
try {
|
|
141
|
+
// If license validation failed, stop initialization
|
|
142
|
+
if (!this.licenseValid) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
108
145
|
this.updateStatus('Preparando capturador...', 'Configurando herramientas de captura', 'initializing');
|
|
109
146
|
await this.initializeServices();
|
|
110
147
|
this.updateStatus('Preparando funciones...', 'Configurando herramientas de trabajo', 'initializing');
|
|
@@ -120,6 +157,10 @@ export class JaakStamps {
|
|
|
120
157
|
}
|
|
121
158
|
}
|
|
122
159
|
async initializeServices() {
|
|
160
|
+
// Parse propagateTraceHeaderCorsUrls from comma-separated string
|
|
161
|
+
const propagateUrls = this.propagateTraceHeaderCorsUrls
|
|
162
|
+
? this.propagateTraceHeaderCorsUrls.split(',').map(url => url.trim())
|
|
163
|
+
: [];
|
|
123
164
|
const config = {
|
|
124
165
|
debug: this.debug,
|
|
125
166
|
alignmentTolerance: this.alignmentTolerance,
|
|
@@ -128,13 +169,76 @@ export class JaakStamps {
|
|
|
128
169
|
useDocumentClassification: this.useDocumentClassification,
|
|
129
170
|
useDocumentDetector: this.useDocumentDetector,
|
|
130
171
|
preferredCamera: this.preferredCamera,
|
|
131
|
-
captureDelay: this.captureDelay
|
|
172
|
+
captureDelay: this.captureDelay,
|
|
173
|
+
telemetryCollectorUrl: this.telemetryCollectorUrl,
|
|
174
|
+
metricsCollectorUrl: this.metricsCollectorUrl,
|
|
175
|
+
enableTelemetry: this.enableTelemetry,
|
|
176
|
+
enableMetrics: this.enableMetrics,
|
|
177
|
+
customerId: this.customerId,
|
|
178
|
+
tenantId: this.tenantId,
|
|
179
|
+
environment: this.environment,
|
|
180
|
+
propagateTraceHeaderCorsUrls: propagateUrls,
|
|
181
|
+
metricsExportIntervalMillis: this.metricsExportIntervalMillis
|
|
132
182
|
};
|
|
133
183
|
this.serviceContainer = new ServiceContainer(config);
|
|
134
184
|
this.eventBus = this.serviceContainer.getEventBus();
|
|
135
185
|
this.stateManager = this.serviceContainer.getStateManager();
|
|
136
186
|
this.cameraService = this.serviceContainer.getCameraService();
|
|
137
187
|
this.detectionService = this.serviceContainer.getDetectionService();
|
|
188
|
+
this.tracingService = this.serviceContainer.getTracingService();
|
|
189
|
+
this.metricsService = this.serviceContainer.getMetricsService();
|
|
190
|
+
// Set the custom trace ID if provided via prop
|
|
191
|
+
if (this.tracingService && this.traceId) {
|
|
192
|
+
this.tracingService.setSessionTraceId(this.traceId);
|
|
193
|
+
}
|
|
194
|
+
// Record component initialization
|
|
195
|
+
if (this.tracingService) {
|
|
196
|
+
const span = this.tracingService.startSpan('component.initialize', {
|
|
197
|
+
'component.debug': this.debug,
|
|
198
|
+
'component.useDocumentDetector': this.useDocumentDetector,
|
|
199
|
+
'component.useDocumentClassification': this.useDocumentClassification,
|
|
200
|
+
});
|
|
201
|
+
this.tracingService.endSpan(span);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async validateLicense() {
|
|
205
|
+
if (!this.license) {
|
|
206
|
+
console.error('❌ No license provided for JAAK Stamps component');
|
|
207
|
+
this.licenseError = 'Este componente requiere una licencia válida. Por favor, proporcione una licencia usando el atributo "license".';
|
|
208
|
+
this.licenseValid = false;
|
|
209
|
+
this.updateStatus('Error de licencia', 'Licencia no proporcionada', 'error');
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
console.log('🔑 Validating license for JAAK Stamps...');
|
|
214
|
+
// Initialize license validation service
|
|
215
|
+
this.licenseValidationService = new LicenseValidationService(this.licenseEnvironment);
|
|
216
|
+
// Validate the license, passing traceId and appId if provided
|
|
217
|
+
const response = await this.licenseValidationService.validateLicense(this.license, this.traceId, this.appId);
|
|
218
|
+
if (response && response.access_token) {
|
|
219
|
+
this.licenseValid = true;
|
|
220
|
+
this.licenseError = null;
|
|
221
|
+
console.log('✅ License validated successfully for JAAK Stamps');
|
|
222
|
+
// Emit the traceId (either provided or generated)
|
|
223
|
+
if (response.traceId) {
|
|
224
|
+
this.traceIdGenerated.emit({ traceId: response.traceId });
|
|
225
|
+
console.log('📋 TraceId:', response.traceId);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
this.licenseValid = false;
|
|
230
|
+
this.licenseError = 'La licencia proporcionada no es válida. Por favor, verifique su licencia e intente nuevamente.';
|
|
231
|
+
this.updateStatus('Error de licencia', 'Licencia inválida', 'error');
|
|
232
|
+
console.error('❌ Invalid license for JAAK Stamps');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
this.licenseValid = false;
|
|
237
|
+
const licenseError = error;
|
|
238
|
+
this.licenseError = licenseError.error_description || 'Error al validar la licencia. Por favor, verifique su conexión e intente nuevamente.';
|
|
239
|
+
this.updateStatus('Error de licencia', 'Fallo en la validación', 'error');
|
|
240
|
+
console.error('❌ License validation failed for JAAK Stamps:', error);
|
|
241
|
+
}
|
|
138
242
|
}
|
|
139
243
|
async setupEventListeners() {
|
|
140
244
|
this.eventBus.on('state-changed', () => {
|
|
@@ -174,7 +278,7 @@ export class JaakStamps {
|
|
|
174
278
|
if (!window.ort) {
|
|
175
279
|
this.updateStatus('Preparando herramientas...', 'Configurando funciones de captura', 'initializing');
|
|
176
280
|
const script = document.createElement('script');
|
|
177
|
-
script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js';
|
|
281
|
+
script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.min.js';
|
|
178
282
|
document.head.appendChild(script);
|
|
179
283
|
await new Promise((resolve) => {
|
|
180
284
|
script.onload = () => {
|
|
@@ -255,6 +359,18 @@ export class JaakStamps {
|
|
|
255
359
|
});
|
|
256
360
|
resizeObserver.observe(this.detectionContainer.parentElement);
|
|
257
361
|
}
|
|
362
|
+
// Handle mobile device orientation changes
|
|
363
|
+
window.addEventListener('orientationchange', () => {
|
|
364
|
+
// Clear any existing orientation timer
|
|
365
|
+
if (this.orientationTimer) {
|
|
366
|
+
clearTimeout(this.orientationTimer);
|
|
367
|
+
}
|
|
368
|
+
// Add delay to ensure video dimensions are updated after rotation
|
|
369
|
+
this.orientationTimer = window.setTimeout(() => {
|
|
370
|
+
this.handleResize();
|
|
371
|
+
this.orientationTimer = undefined;
|
|
372
|
+
}, 300);
|
|
373
|
+
});
|
|
258
374
|
}
|
|
259
375
|
handleResize() {
|
|
260
376
|
if (this.detectionContainer) {
|
|
@@ -390,17 +506,31 @@ export class JaakStamps {
|
|
|
390
506
|
return this.stateManager.isProcessCompleted();
|
|
391
507
|
}
|
|
392
508
|
async startCapture() {
|
|
509
|
+
const span = this.tracingService?.startSpan('capture.start');
|
|
393
510
|
const readyCheck = this.isComponentReady();
|
|
394
511
|
if (!readyCheck.ready) {
|
|
395
512
|
this.updateStatus(readyCheck.message, 'Espere a que termine la inicialización', readyCheck.status);
|
|
513
|
+
if (span) {
|
|
514
|
+
this.tracingService?.setSpanAttribute(span, 'error', true);
|
|
515
|
+
this.tracingService?.setSpanAttribute(span, 'error.message', readyCheck.message);
|
|
516
|
+
this.tracingService?.endSpan(span);
|
|
517
|
+
}
|
|
396
518
|
return { success: false, error: readyCheck.message };
|
|
397
519
|
}
|
|
398
520
|
try {
|
|
399
521
|
await this.startDetection();
|
|
522
|
+
if (span) {
|
|
523
|
+
this.tracingService?.setSpanAttribute(span, 'success', true);
|
|
524
|
+
this.tracingService?.endSpan(span);
|
|
525
|
+
}
|
|
400
526
|
return { success: true };
|
|
401
527
|
}
|
|
402
528
|
catch (error) {
|
|
403
529
|
this.updateStatus('Error al iniciar captura', error.message, 'error');
|
|
530
|
+
if (span) {
|
|
531
|
+
this.tracingService?.recordException(span, error);
|
|
532
|
+
this.tracingService?.endSpan(span);
|
|
533
|
+
}
|
|
404
534
|
return { success: false, error: error.message };
|
|
405
535
|
}
|
|
406
536
|
}
|
|
@@ -411,13 +541,7 @@ export class JaakStamps {
|
|
|
411
541
|
}
|
|
412
542
|
try {
|
|
413
543
|
this.exitSession();
|
|
414
|
-
|
|
415
|
-
const cleanupResult = await this.aggressiveResourceCleanup();
|
|
416
|
-
return {
|
|
417
|
-
success: true,
|
|
418
|
-
resourcesFreed: cleanupResult.freed,
|
|
419
|
-
cleanupErrors: cleanupResult.errors
|
|
420
|
-
};
|
|
544
|
+
return { success: true };
|
|
421
545
|
}
|
|
422
546
|
catch (error) {
|
|
423
547
|
return { success: false, error: error.message };
|
|
@@ -504,13 +628,22 @@ export class JaakStamps {
|
|
|
504
628
|
}
|
|
505
629
|
}
|
|
506
630
|
async preloadModel() {
|
|
631
|
+
const span = this.tracingService?.startSpan('model.preload');
|
|
507
632
|
const readyCheck = this.isComponentReady();
|
|
508
633
|
if (!readyCheck.ready) {
|
|
509
634
|
this.updateStatus(readyCheck.message, 'Espere a que termine la inicialización', readyCheck.status);
|
|
635
|
+
if (span) {
|
|
636
|
+
this.tracingService?.setSpanAttribute(span, 'error', true);
|
|
637
|
+
this.tracingService?.endSpan(span);
|
|
638
|
+
}
|
|
510
639
|
return { success: false, error: readyCheck.message };
|
|
511
640
|
}
|
|
512
641
|
if (this.detectionService.isModelLoaded()) {
|
|
513
642
|
this.updateStatus('Reconocimiento listo', '', 'ready');
|
|
643
|
+
if (span) {
|
|
644
|
+
this.tracingService?.setSpanAttribute(span, 'cached', true);
|
|
645
|
+
this.tracingService?.endSpan(span);
|
|
646
|
+
}
|
|
514
647
|
return { success: true, message: 'Model already loaded' };
|
|
515
648
|
}
|
|
516
649
|
try {
|
|
@@ -520,17 +653,31 @@ export class JaakStamps {
|
|
|
520
653
|
this.stateManager.updateCaptureState({ isLoading: true });
|
|
521
654
|
}
|
|
522
655
|
try {
|
|
656
|
+
const detectionStartTime = performance.now();
|
|
657
|
+
const modelSpan = this.tracingService?.startSpan('model.detection.load');
|
|
523
658
|
await this.detectionService.loadModel();
|
|
659
|
+
if (modelSpan)
|
|
660
|
+
this.tracingService?.endSpan(modelSpan);
|
|
661
|
+
const detectionLoadTime = performance.now() - detectionStartTime;
|
|
662
|
+
this.metricsService?.recordModelLoad('detection', detectionLoadTime, false);
|
|
524
663
|
}
|
|
525
664
|
catch (modelError) {
|
|
665
|
+
this.metricsService?.recordError('model_load_failed', 'detection');
|
|
526
666
|
this.switchToManualModeWithError('Error al cargar modelo de detección');
|
|
527
667
|
throw modelError;
|
|
528
668
|
}
|
|
529
669
|
this.updateStatus('Optimizando detección...', 'Configurando reconocimiento de documentos', 'loading');
|
|
530
670
|
try {
|
|
671
|
+
const classificationStartTime = performance.now();
|
|
672
|
+
const classSpan = this.tracingService?.startSpan('model.classification.load');
|
|
531
673
|
await this.detectionService.loadClassificationModel();
|
|
674
|
+
if (classSpan)
|
|
675
|
+
this.tracingService?.endSpan(classSpan);
|
|
676
|
+
const classificationLoadTime = performance.now() - classificationStartTime;
|
|
677
|
+
this.metricsService?.recordModelLoad('classification', classificationLoadTime, false);
|
|
532
678
|
}
|
|
533
679
|
catch (classificationError) {
|
|
680
|
+
this.metricsService?.recordError('model_load_failed', 'classification');
|
|
534
681
|
this.switchToManualModeWithError('Error al cargar modelo de clasificación');
|
|
535
682
|
throw classificationError;
|
|
536
683
|
}
|
|
@@ -540,6 +687,9 @@ export class JaakStamps {
|
|
|
540
687
|
if (this.debug) {
|
|
541
688
|
this.recordOnnxPerformance(loadTime, 0);
|
|
542
689
|
}
|
|
690
|
+
if (span) {
|
|
691
|
+
this.tracingService?.setSpanAttribute(span, 'loadTime', loadTime);
|
|
692
|
+
}
|
|
543
693
|
this.updateStatus('Finalizando configuración...', 'Preparando herramientas para captura', 'loading');
|
|
544
694
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
545
695
|
this.updateStatus('Reconocimiento preparado', '', 'ready');
|
|
@@ -547,6 +697,10 @@ export class JaakStamps {
|
|
|
547
697
|
this.stateManager.updateCaptureState({ isLoading: false });
|
|
548
698
|
}
|
|
549
699
|
this.emitReadyEvent();
|
|
700
|
+
if (span) {
|
|
701
|
+
this.tracingService?.setSpanAttribute(span, 'success', true);
|
|
702
|
+
this.tracingService?.endSpan(span);
|
|
703
|
+
}
|
|
550
704
|
return { success: true, message: 'Models preloaded successfully' };
|
|
551
705
|
}
|
|
552
706
|
catch (error) {
|
|
@@ -554,6 +708,10 @@ export class JaakStamps {
|
|
|
554
708
|
if (this.stateManager) {
|
|
555
709
|
this.stateManager.updateCaptureState({ isLoading: false });
|
|
556
710
|
}
|
|
711
|
+
if (span) {
|
|
712
|
+
this.tracingService?.recordException(span, error);
|
|
713
|
+
this.tracingService?.endSpan(span);
|
|
714
|
+
}
|
|
557
715
|
return { success: false, error: error.message };
|
|
558
716
|
}
|
|
559
717
|
}
|
|
@@ -642,65 +800,11 @@ export class JaakStamps {
|
|
|
642
800
|
// Always allow getting capture delay, even during initialization
|
|
643
801
|
return this.captureDelay;
|
|
644
802
|
}
|
|
645
|
-
async getResourceReport() {
|
|
646
|
-
// Public method to get resource usage report
|
|
647
|
-
return this.getResourceReportInternal();
|
|
648
|
-
}
|
|
649
|
-
async forceResourceCleanup() {
|
|
650
|
-
// Public method to force aggressive resource cleanup
|
|
651
|
-
const readyCheck = this.isComponentReady();
|
|
652
|
-
if (!readyCheck.ready) {
|
|
653
|
-
return { success: false, error: readyCheck.message };
|
|
654
|
-
}
|
|
655
|
-
try {
|
|
656
|
-
const cleanupResult = await this.aggressiveResourceCleanup();
|
|
657
|
-
return {
|
|
658
|
-
success: true,
|
|
659
|
-
resourcesFreed: cleanupResult.freed,
|
|
660
|
-
errors: cleanupResult.errors,
|
|
661
|
-
timestamp: new Date().toISOString()
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
|
-
catch (error) {
|
|
665
|
-
return { success: false, error: error.message };
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
803
|
// Memory and device capability detection
|
|
669
804
|
checkDeviceCapabilities() {
|
|
670
805
|
const deviceMemory = navigator.deviceMemory;
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
674
|
-
const isSafari = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
|
|
675
|
-
// Si tenemos info de memoria del dispositivo
|
|
676
|
-
if (deviceMemory && deviceMemory < 4) {
|
|
677
|
-
return {
|
|
678
|
-
canUseML: false,
|
|
679
|
-
reason: `Memoria del dispositivo (${deviceMemory}GB) insuficiente para detección automática. Modo manual activado para mejor rendimiento.`,
|
|
680
|
-
memoryMB: deviceMemory * 1024
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
// Dispositivos móviles de gama baja
|
|
684
|
-
if (isMobile && isLowEndDevice) {
|
|
685
|
-
return {
|
|
686
|
-
canUseML: false,
|
|
687
|
-
reason: 'Dispositivo móvil optimizado detectado. Modo manual activado para mejor rendimiento y duración de batería.',
|
|
688
|
-
memoryMB: null
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
// Safari moderno soporta WASM, solo bloquearlo en versiones muy antiguas
|
|
692
|
-
if (isSafari) {
|
|
693
|
-
const safariMatch = navigator.userAgent.match(/Version\/(\d+)/);
|
|
694
|
-
const safariVersion = safariMatch ? parseInt(safariMatch[1]) : 0;
|
|
695
|
-
// Solo bloquear Safari muy antiguo (< version 14)
|
|
696
|
-
if (safariVersion > 0 && safariVersion < 14) {
|
|
697
|
-
return {
|
|
698
|
-
canUseML: false,
|
|
699
|
-
reason: 'Safari antiguo detectado. Modo manual activado por compatibilidad.',
|
|
700
|
-
memoryMB: null
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
}
|
|
806
|
+
// Siempre intentar usar ML, independientemente del dispositivo
|
|
807
|
+
// Las restricciones anteriores no eran confiables
|
|
704
808
|
return {
|
|
705
809
|
canUseML: true,
|
|
706
810
|
reason: 'Dispositivo compatible con detección automática.',
|
|
@@ -826,6 +930,12 @@ export class JaakStamps {
|
|
|
826
930
|
this.videoRef.onloadedmetadata = async () => {
|
|
827
931
|
await this.videoRef.play();
|
|
828
932
|
this.stateManager.updateCaptureState({ isVideoActive: true });
|
|
933
|
+
// Recalculate mask dimensions when new camera stream loads
|
|
934
|
+
if (this.detectionContainer) {
|
|
935
|
+
const container = this.detectionContainer.parentElement;
|
|
936
|
+
const rect = container.getBoundingClientRect();
|
|
937
|
+
this.updateMaskDimensions(rect);
|
|
938
|
+
}
|
|
829
939
|
resolve();
|
|
830
940
|
};
|
|
831
941
|
});
|
|
@@ -868,9 +978,14 @@ export class JaakStamps {
|
|
|
868
978
|
return;
|
|
869
979
|
}
|
|
870
980
|
this.frameSkipCounter = 0;
|
|
871
|
-
// Throttle inference
|
|
981
|
+
// Throttle inference - use higher interval for mobile devices to prevent slow motion effect
|
|
872
982
|
const currentTime = Date.now();
|
|
873
|
-
|
|
983
|
+
const isMobileDevice = this.cameraInfoWithAutofocus.deviceType === 'mobile' ||
|
|
984
|
+
/Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
985
|
+
const isTablet = this.cameraInfoWithAutofocus.deviceType === 'tablet' ||
|
|
986
|
+
(/iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768);
|
|
987
|
+
const minInterval = (isMobileDevice && !isTablet) ? this.MOBILE_MIN_INFERENCE_INTERVAL : this.MIN_INFERENCE_INTERVAL;
|
|
988
|
+
if (currentTime - this.lastInferenceTime < minInterval) {
|
|
874
989
|
if (captureState.step !== 'completed') {
|
|
875
990
|
this.animationId = requestAnimationFrame(() => this.detectFrame());
|
|
876
991
|
}
|
|
@@ -997,6 +1112,10 @@ export class JaakStamps {
|
|
|
997
1112
|
clearTimeout(this.alignmentTimer);
|
|
998
1113
|
this.alignmentTimer = undefined;
|
|
999
1114
|
}
|
|
1115
|
+
if (this.orientationTimer) {
|
|
1116
|
+
clearTimeout(this.orientationTimer);
|
|
1117
|
+
this.orientationTimer = undefined;
|
|
1118
|
+
}
|
|
1000
1119
|
// Liberar recursos de ONNX al limpiar el componente
|
|
1001
1120
|
this.releaseOnnxResources();
|
|
1002
1121
|
if (this.performanceUpdateInterval) {
|
|
@@ -1005,182 +1124,11 @@ export class JaakStamps {
|
|
|
1005
1124
|
}
|
|
1006
1125
|
// Clear canvas pool
|
|
1007
1126
|
this.canvasPool = [];
|
|
1008
|
-
// Clean DOM references and memory leaks
|
|
1009
|
-
this.cleanupDOMReferences();
|
|
1010
1127
|
this.detectionBoxes = [];
|
|
1011
1128
|
this.alignmentStartTime = undefined;
|
|
1012
1129
|
this.hasDocumentDetected = false;
|
|
1013
1130
|
this.serviceContainer?.cleanup();
|
|
1014
1131
|
}
|
|
1015
|
-
// AGGRESSIVE RESOURCE CLEANUP METHODS
|
|
1016
|
-
// Clean DOM references and memory leaks
|
|
1017
|
-
cleanupDOMReferences() {
|
|
1018
|
-
// Remove event listeners that could maintain references
|
|
1019
|
-
if (this.videoRef) {
|
|
1020
|
-
// Remove common event listeners (if any were added)
|
|
1021
|
-
this.videoRef.srcObject = null;
|
|
1022
|
-
this.videoRef = undefined;
|
|
1023
|
-
}
|
|
1024
|
-
// Clean detection container
|
|
1025
|
-
if (this.detectionContainer) {
|
|
1026
|
-
this.detectionContainer = undefined;
|
|
1027
|
-
}
|
|
1028
|
-
// Clean references to images in the DOM and revoke blob URLs
|
|
1029
|
-
const images = this.el.shadowRoot?.querySelectorAll('img');
|
|
1030
|
-
images?.forEach(img => {
|
|
1031
|
-
if (img.src.startsWith('blob:')) {
|
|
1032
|
-
URL.revokeObjectURL(img.src);
|
|
1033
|
-
}
|
|
1034
|
-
img.src = '';
|
|
1035
|
-
});
|
|
1036
|
-
}
|
|
1037
|
-
// Clear browser cache and storage
|
|
1038
|
-
async clearBrowserCache() {
|
|
1039
|
-
try {
|
|
1040
|
-
// 1. Clear Service Worker cache if exists
|
|
1041
|
-
if ('serviceWorker' in navigator) {
|
|
1042
|
-
const registrations = await navigator.serviceWorker.getRegistrations();
|
|
1043
|
-
await Promise.all(registrations.map(registration => registration.unregister()));
|
|
1044
|
-
}
|
|
1045
|
-
// 2. Clear Cache API specific to the component
|
|
1046
|
-
const cacheNames = await caches.keys();
|
|
1047
|
-
const componentCaches = cacheNames.filter(name => name.includes('jaak') || name.includes('stamps'));
|
|
1048
|
-
await Promise.all(componentCaches.map(cacheName => caches.delete(cacheName)));
|
|
1049
|
-
// 3. Force garbage collection if available (only in dev)
|
|
1050
|
-
if (this.debug && window.gc) {
|
|
1051
|
-
window.gc();
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
catch (error) {
|
|
1055
|
-
console.warn('Error clearing browser cache:', error);
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
// Clear local storage specific to the component
|
|
1059
|
-
async clearLocalStorage() {
|
|
1060
|
-
try {
|
|
1061
|
-
// Clear localStorage specific to the component
|
|
1062
|
-
const keysToRemove = [];
|
|
1063
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
1064
|
-
const key = localStorage.key(i);
|
|
1065
|
-
if (key && (key.includes('jaak') || key.includes('onnx') || key.includes('stamps'))) {
|
|
1066
|
-
keysToRemove.push(key);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
keysToRemove.forEach(key => localStorage.removeItem(key));
|
|
1070
|
-
// Clear sessionStorage
|
|
1071
|
-
const sessionKeysToRemove = [];
|
|
1072
|
-
for (let i = 0; i < sessionStorage.length; i++) {
|
|
1073
|
-
const key = sessionStorage.key(i);
|
|
1074
|
-
if (key && (key.includes('jaak') || key.includes('onnx'))) {
|
|
1075
|
-
sessionKeysToRemove.push(key);
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
sessionKeysToRemove.forEach(key => sessionStorage.removeItem(key));
|
|
1079
|
-
}
|
|
1080
|
-
catch (error) {
|
|
1081
|
-
console.warn('Error clearing local storage:', error);
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
// Aggressive resource cleanup combining all strategies
|
|
1085
|
-
async aggressiveResourceCleanup() {
|
|
1086
|
-
const freed = [];
|
|
1087
|
-
const errors = [];
|
|
1088
|
-
try {
|
|
1089
|
-
// 1. Release ONNX resources
|
|
1090
|
-
this.releaseOnnxResources();
|
|
1091
|
-
freed.push('ONNX models');
|
|
1092
|
-
// 2. Clear model cache in detection service
|
|
1093
|
-
if (this.detectionService) {
|
|
1094
|
-
await this.detectionService.clearModelCache();
|
|
1095
|
-
freed.push('Model cache');
|
|
1096
|
-
}
|
|
1097
|
-
// 3. Clear browser cache
|
|
1098
|
-
await this.clearBrowserCache();
|
|
1099
|
-
freed.push('Browser cache');
|
|
1100
|
-
// 4. Clear local storage
|
|
1101
|
-
await this.clearLocalStorage();
|
|
1102
|
-
freed.push('Local storage');
|
|
1103
|
-
// 5. Clean DOM references
|
|
1104
|
-
this.cleanupDOMReferences();
|
|
1105
|
-
freed.push('DOM references');
|
|
1106
|
-
// 6. Optimize canvas pools
|
|
1107
|
-
if (this.detectionService) {
|
|
1108
|
-
this.detectionService.optimizeCanvasPool(0);
|
|
1109
|
-
freed.push('Canvas pools');
|
|
1110
|
-
}
|
|
1111
|
-
// 7. Clear component canvas pool
|
|
1112
|
-
this.canvasPool = [];
|
|
1113
|
-
freed.push('Component canvas pool');
|
|
1114
|
-
// 8. Force garbage collection (if available)
|
|
1115
|
-
if (this.debug && window.gc) {
|
|
1116
|
-
window.gc();
|
|
1117
|
-
freed.push('Garbage collection');
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
catch (error) {
|
|
1121
|
-
errors.push(error.message);
|
|
1122
|
-
}
|
|
1123
|
-
return { freed, errors };
|
|
1124
|
-
}
|
|
1125
|
-
// Progressive resource release after front capture
|
|
1126
|
-
async onFrontCaptureComplete() {
|
|
1127
|
-
try {
|
|
1128
|
-
// Release classification model if not needed for back
|
|
1129
|
-
if (this.detectionService && !this.useDocumentClassification) {
|
|
1130
|
-
await this.detectionService.releaseMobileNetResources();
|
|
1131
|
-
}
|
|
1132
|
-
// Optimize canvas pool to minimum needed for back capture
|
|
1133
|
-
if (this.detectionService) {
|
|
1134
|
-
this.detectionService.optimizeCanvasPool(1);
|
|
1135
|
-
}
|
|
1136
|
-
// Reduce component canvas pool
|
|
1137
|
-
while (this.canvasPool.length > 1) {
|
|
1138
|
-
const canvas = this.canvasPool.pop();
|
|
1139
|
-
if (canvas) {
|
|
1140
|
-
const ctx = canvas.getContext('2d');
|
|
1141
|
-
if (ctx) {
|
|
1142
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
if (this.debug) {
|
|
1147
|
-
console.log('🧹 Progressive cleanup after front capture completed');
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
catch (error) {
|
|
1151
|
-
console.warn('Error in progressive cleanup:', error);
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
// Resource reporting for debugging
|
|
1155
|
-
getResourceReportInternal() {
|
|
1156
|
-
const report = {
|
|
1157
|
-
timestamp: new Date().toISOString(),
|
|
1158
|
-
component: {
|
|
1159
|
-
hasVideoStream: !!this.videoStream,
|
|
1160
|
-
hasAnimationFrame: !!this.animationId,
|
|
1161
|
-
canvasPoolSize: this.canvasPool.length,
|
|
1162
|
-
detectionBoxesCount: this.detectionBoxes.length,
|
|
1163
|
-
performanceMonitorActive: !!this.performanceUpdateInterval
|
|
1164
|
-
}
|
|
1165
|
-
};
|
|
1166
|
-
// Add detection service stats if available
|
|
1167
|
-
if (this.detectionService) {
|
|
1168
|
-
report.detectionService = {
|
|
1169
|
-
isModelLoaded: this.detectionService.isModelLoaded(),
|
|
1170
|
-
canvasPoolStats: this.detectionService.getPoolStats()
|
|
1171
|
-
};
|
|
1172
|
-
}
|
|
1173
|
-
// Add memory info if available
|
|
1174
|
-
if ('memory' in performance) {
|
|
1175
|
-
const memInfo = performance.memory;
|
|
1176
|
-
report.memory = {
|
|
1177
|
-
usedJSHeapSize: Math.round(memInfo.usedJSHeapSize / 1048576), // MB
|
|
1178
|
-
totalJSHeapSize: Math.round(memInfo.totalJSHeapSize / 1048576), // MB
|
|
1179
|
-
jsHeapSizeLimit: Math.round(memInfo.jsHeapSizeLimit / 1048576) // MB
|
|
1180
|
-
};
|
|
1181
|
-
}
|
|
1182
|
-
return report;
|
|
1183
|
-
}
|
|
1184
1132
|
render() {
|
|
1185
1133
|
const captureState = this.stateManager?.getCaptureState() || {
|
|
1186
1134
|
isVideoActive: false,
|
|
@@ -1191,7 +1139,7 @@ export class JaakStamps {
|
|
|
1191
1139
|
isCapturing: false
|
|
1192
1140
|
};
|
|
1193
1141
|
const cameraInfo = this.cameraInfoWithAutofocus;
|
|
1194
|
-
return (h("div", { key: '
|
|
1142
|
+
return (h("div", { key: 'df70f4fa13b2997a19312125c8b236651cb2b81e', class: "detector-container" }, !this.licenseValid && this.licenseError && (h("div", { key: 'c4f7b51515843177bc3063dd7cf9383e3a4c6c73', class: "license-error-container" }, h("div", { key: 'a4a7e95a23690f9f59c971dd2af9bd096ae13ef0', class: "license-error-card" }, h("svg", { key: '6489a82c60fc9c1a7d89c2b3a537c04c1766cbd4', 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: 'b90b16b0ee155c8baeee321237470de7b6fa1ff5', 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: 'c90ec519befb073208dbc5e30e1237dda7f0a18f', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("circle", { key: 'b926e97a83e19c7ca9b66472fedd53b12d22b7d8', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), h("h2", { key: '1f1fce48179331b0150e0c55a6d5efcd0bf95762', class: "license-error-title" }, "Licencia Requerida"), h("p", { key: '1f28787cea92c5160664bd8e445fb514ac55eff4', class: "license-error-message" }, this.licenseError), h("p", { key: '552aecf92fd34fbdd802fc80cdba46596edb115b', class: "license-error-help" }, "Contacte a soporte: ", h("a", { key: '8c44e1e33fbd22a2319acd6c6b27766bec4355f0', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), h("div", { key: 'c2e139fdedcb8e8922f37e915caa7ae3a1b09cb9', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (h("div", { key: 'c7876bbe35cd28b52433aab6e97de4a0282e25d5', class: "video-container" }, h("video", { key: 'a5fa99c086eb3730ceee7750ece0842539defa3d', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '2c7923dfa706f65cfc3fe71a6ec626cb2ccce7d4', 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: {
|
|
1195
1143
|
position: 'absolute',
|
|
1196
1144
|
left: `${box.x}px`,
|
|
1197
1145
|
top: `${box.y}px`,
|
|
@@ -1200,9 +1148,9 @@ export class JaakStamps {
|
|
|
1200
1148
|
border: '2px solid #32406C',
|
|
1201
1149
|
pointerEvents: 'none',
|
|
1202
1150
|
boxSizing: 'border-box'
|
|
1203
|
-
} })))), this.isMaskReady && (h("div", { key: '
|
|
1151
|
+
} })))), this.isMaskReady && (h("div", { key: '3e1f77d89a00e4ad1519875cacd5c541c9b16f91', class: "overlay-mask" }, h("div", { key: '3c717afa809ef2fa102fdaab3418915602516d39', class: "card-outline" }, h("div", { key: 'd3dcd1a85290f3fb2216b1182dce9a4b62cc59c6', class: "side side-top" }), h("div", { key: '4280c1e0f0900ec69b905a6226c1afe9a0a993ad', class: "side side-right" }), h("div", { key: '9b88c21f5eb28d74872409335cd6ca83a284bd9b', class: "side side-bottom" }), h("div", { key: '46b4ef3fca60fcf807da8f574a43cba7f148165b', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '2222975293bebfd04fa2d4ac4878bce48fd35880', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '836fbeadb849cb9df66e03ef0cb791dd0e179df8', class: "back-capture-section" }, h("div", { key: 'f0e8119b79f30ffd40ae206783a83869196757ac', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: 'e245e800e2378989bfa011524cca66026ace52d9', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: 'd98a692f9ff883d05e24122b54c4e36f5f96e82f', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: 'c32b7784e2bbb89947219f0d458d0a4d62b5352a', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: 'bb935e91f07c4c1052576c52aa2a82a726877217', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
|
|
1204
1152
|
? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
|
|
1205
|
-
: 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: '
|
|
1153
|
+
: 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: '471a1292e9d093cce0a0d3fa7f96f3665de749fb', class: "camera-controls" }, h("button", { key: '406911235a06723310ff577c27e3858912e522c4', 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: 'b8fd729b78a3c5cb52b7f17d031bb12b894aaf41', class: "camera-selector-dropdown" }, h("div", { key: '2b9b451440d6b6be4103419694ff6a53c92e68ad', class: "camera-selector-header" }, h("span", { key: '2271f4694aa6c0b32ab23a02a7a8d6d4c1bd4144' }, "Seleccionar C\u00E1mara"), h("button", { key: 'ccfc02eb031da17a4907cd835642785bc2ef5e77', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '073d6e9e09cde8523e926850dfa73704b579c899', 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: '8f914f855727a6ab02a2941fee91283bf3882df2', class: "device-info" }, h("small", { key: '295433a43a539034992f04a29355deed12082092' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'cc780583a636e7d4910851789710837c9e188d40', class: "manual-capture-section" }, h("button", { key: '40c5e212a3a4eab4d2edf44e29e6b4fe0e4c5e37', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: '1245a13523250b5959a1c303ca20662c2d6750c7', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: '10a0a26b346ecf0945688f82292720871f8dc0b7', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '68dc7effe82d2f043d778239e2aecb847d159818', class: "flip-animation" }, h("div", { key: '153e0c2229c39c5b9402b9610eaee586d98f84c1', class: "id-card-icon" }), h("div", { key: 'b60b249c43ac5f8417c15b8ce46f60d2cb3134d5', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'fefa7bf80546a463a54a275e425241545ace5c77', class: "success-animation" }, h("div", { key: 'cda9d64b3b30cc636d976c2c644a927a8ebe341e', class: "check-icon" }), h("div", { key: 'fd00554df841cdb6e1a167b7e6cc4a6b9b60957a', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: 'cd5fa1fbfa5e3a4e362281553dde2c37601b1078', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: 'cb0d76938d8ccab99632920ffc9d73a1fa7dec79', class: "status-spinner" })), h("div", { key: 'bcfdc2a24e12dc0bcc19ae0d647be5ce810994d5', class: "status-content" }, h("div", { key: 'a4b6dad22b40aed65a9c81e9581e61a9ca064e40', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '236084444d4d156b672f823349f95b462a8a9bba', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '7423d6c8c7e37b7baffc27fc243536e2659475cc', class: "performance-monitor" }, h("div", { key: '892736f4be3d1cd563ec919c5a504ca8e0d55db0', class: "performance-expanded" }, h("div", { key: 'aa0464f739f838ac4c9e553c79f4c7815f7f65cf', class: "metrics-row" }, h("div", { key: '5dca0c5fe0f91ecfaa25c5775c18a99d53eb8f73', class: "metric-compact" }, h("span", { key: '8e498b185cdefb97286356b56e45dc7b514f667e', class: "metric-label" }, "FPS"), h("span", { key: '3a90611c84b338314ae1503aef6208c67d1282ff', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: '568e492ef7dad971f1613132028999a81f38f457', class: "metric-compact" }, h("span", { key: '222fd2b522dd9f7172ad9adb442b10c1ce4c6455', class: "metric-label" }, "MEM"), h("span", { key: '8cbe2cf9fd7dd9e22e9a0df6f214165a09e03045', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'e5d946afd1cc80a15a52c9ba1cb252e6e146e929', class: "metrics-row" }, h("div", { key: '65aaaa92e3ce7b5567560d94f98e16226ecf9fd5', class: "metric-compact" }, h("span", { key: '80c6ad0923e729912274a05fffca039e88aa5719', class: "metric-label" }, "INF"), h("span", { key: '4a87270ebdad3be718b86d1382b2a54092e53a16', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '41ddc923cdfab0012a2f5d3e19aee33dad6116fe', class: "metric-compact" }, h("span", { key: '84e9f4fb3d5bf60235d71d61dc1d6a8ad429293c', class: "metric-label" }, "FRAME"), h("span", { key: '88fd6964307399ac1547c7086f489af90a92a925', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '22409e8dfb349e66ac54c20c6043b414b7ddba34', class: "metrics-row" }, h("div", { key: 'bbe72cb477f4bc313e7978d98c217a4789765df1', class: "metric-compact" }, h("span", { key: '56df43d72df8d3549fa42b2bc32fa5491c3cdb41', class: "metric-label" }, "DET"), h("span", { key: '7ceedb73086eccaed0e25177d76218e9bae1262d', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: '9407541b4f975b20843c19e7081d1c26bb3f4fd4', class: "metric-compact" }, h("span", { key: '511ffc66436ffe2f14300122213de11f50fbbc30', class: "metric-label" }, "RATE"), h("span", { key: '6a0c864b46314937043831be7646fbfa3d994c86', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '72f26e4248c87e428a10bbd7b67bd77a9a32f321', class: "watermark" }, h("img", { key: '32e3f23ca1ff81699dd2a4922f8f7d4aeaa3cc2b', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" }))))));
|
|
1206
1154
|
}
|
|
1207
1155
|
// Utility methods
|
|
1208
1156
|
updateDetectionBoxes(boxes) {
|
|
@@ -1319,24 +1267,44 @@ export class JaakStamps {
|
|
|
1319
1267
|
}
|
|
1320
1268
|
async takeManualScreenshot() {
|
|
1321
1269
|
console.log('🔵 Botón clicked: Capturar (Frente/Reverso)');
|
|
1270
|
+
const captureStartTime = performance.now();
|
|
1271
|
+
const span = this.tracingService?.startSpan('capture.screenshot.manual');
|
|
1322
1272
|
// Set processing state immediately
|
|
1323
1273
|
const captureState = this.stateManager?.getCaptureState();
|
|
1274
|
+
const side = captureState?.step === 'front' ? 'front' : 'back';
|
|
1324
1275
|
if (captureState?.step === 'front') {
|
|
1325
1276
|
this.processingButton = 'capture-front';
|
|
1277
|
+
if (span)
|
|
1278
|
+
this.tracingService?.setSpanAttribute(span, 'side', 'front');
|
|
1326
1279
|
}
|
|
1327
1280
|
else if (captureState?.step === 'back') {
|
|
1328
1281
|
this.processingButton = 'capture-back';
|
|
1282
|
+
if (span)
|
|
1283
|
+
this.tracingService?.setSpanAttribute(span, 'side', 'back');
|
|
1329
1284
|
}
|
|
1285
|
+
// Record user interaction
|
|
1286
|
+
this.metricsService?.recordUserInteraction('manual_capture_button');
|
|
1330
1287
|
console.log('🔵 processingButton set to:', this.processingButton);
|
|
1331
1288
|
// Add small delay to show spinner
|
|
1332
1289
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
1333
1290
|
if (!this.videoRef) {
|
|
1334
1291
|
this.processingButton = null;
|
|
1292
|
+
if (span) {
|
|
1293
|
+
this.tracingService?.setSpanAttribute(span, 'error', 'no_video_ref');
|
|
1294
|
+
this.tracingService?.endSpan(span);
|
|
1295
|
+
}
|
|
1335
1296
|
return;
|
|
1336
1297
|
}
|
|
1337
1298
|
// When using manual capture, use mask coordinates for cropping
|
|
1338
1299
|
// Note: processingButton will be cleared inside takeScreenshotWithMaskCoordinates
|
|
1339
1300
|
await this.takeScreenshotWithMaskCoordinates();
|
|
1301
|
+
// Record metrics
|
|
1302
|
+
const captureDuration = performance.now() - captureStartTime;
|
|
1303
|
+
this.metricsService?.recordCapture(side, 'manual', captureDuration);
|
|
1304
|
+
if (span) {
|
|
1305
|
+
this.tracingService?.setSpanAttribute(span, 'success', true);
|
|
1306
|
+
this.tracingService?.endSpan(span);
|
|
1307
|
+
}
|
|
1340
1308
|
}
|
|
1341
1309
|
async takeScreenshotWithMaskCoordinates() {
|
|
1342
1310
|
if (!this.videoRef || !this.detectionContainer)
|
|
@@ -1399,8 +1367,8 @@ export class JaakStamps {
|
|
|
1399
1367
|
if (captureState.step === 'front') {
|
|
1400
1368
|
this.stateManager.setCapturedImages({
|
|
1401
1369
|
front: {
|
|
1402
|
-
fullFrame: captureCanvas.toDataURL('image/
|
|
1403
|
-
cropped: croppedCanvas.toDataURL('image/
|
|
1370
|
+
fullFrame: captureCanvas.toDataURL('image/jpeg'),
|
|
1371
|
+
cropped: croppedCanvas.toDataURL('image/jpeg')
|
|
1404
1372
|
}
|
|
1405
1373
|
});
|
|
1406
1374
|
// Check if document classification is enabled (independent of detector)
|
|
@@ -1426,8 +1394,6 @@ export class JaakStamps {
|
|
|
1426
1394
|
showFlipAnimation: true
|
|
1427
1395
|
});
|
|
1428
1396
|
this.triggerRerender();
|
|
1429
|
-
// Progressive resource cleanup after front capture
|
|
1430
|
-
await this.onFrontCaptureComplete();
|
|
1431
1397
|
setTimeout(() => {
|
|
1432
1398
|
this.stateManager.updateCaptureState({
|
|
1433
1399
|
showFlipAnimation: false,
|
|
@@ -1442,8 +1408,8 @@ export class JaakStamps {
|
|
|
1442
1408
|
else if (captureState.step === 'back') {
|
|
1443
1409
|
this.stateManager.setCapturedImages({
|
|
1444
1410
|
back: {
|
|
1445
|
-
fullFrame: captureCanvas.toDataURL('image/
|
|
1446
|
-
cropped: croppedCanvas.toDataURL('image/
|
|
1411
|
+
fullFrame: captureCanvas.toDataURL('image/jpeg'),
|
|
1412
|
+
cropped: croppedCanvas.toDataURL('image/jpeg')
|
|
1447
1413
|
}
|
|
1448
1414
|
});
|
|
1449
1415
|
this.completeProcess(false);
|
|
@@ -1457,6 +1423,8 @@ export class JaakStamps {
|
|
|
1457
1423
|
async takeScreenshot() {
|
|
1458
1424
|
if (!this.videoRef || !this.lastDetectedBox)
|
|
1459
1425
|
return;
|
|
1426
|
+
const captureStartTime = performance.now();
|
|
1427
|
+
const span = this.tracingService?.startSpan('capture.screenshot.auto');
|
|
1460
1428
|
this.stateManager.updateCaptureState({ isCapturing: true });
|
|
1461
1429
|
this.triggerCaptureAnimation();
|
|
1462
1430
|
// Use pooled canvas for optimization
|
|
@@ -1479,17 +1447,30 @@ export class JaakStamps {
|
|
|
1479
1447
|
croppedCtx.drawImage(this.videoRef, cropX, cropY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);
|
|
1480
1448
|
const captureState = this.stateManager.getCaptureState();
|
|
1481
1449
|
if (captureState.step === 'front') {
|
|
1450
|
+
const frontImageData = captureCanvas.toDataURL('image/jpeg');
|
|
1451
|
+
const croppedImageData = croppedCanvas.toDataURL('image/jpeg');
|
|
1482
1452
|
this.stateManager.setCapturedImages({
|
|
1483
1453
|
front: {
|
|
1484
|
-
fullFrame:
|
|
1485
|
-
cropped:
|
|
1454
|
+
fullFrame: frontImageData,
|
|
1455
|
+
cropped: croppedImageData
|
|
1486
1456
|
}
|
|
1487
1457
|
});
|
|
1458
|
+
// Record metrics
|
|
1459
|
+
const captureDuration = performance.now() - captureStartTime;
|
|
1460
|
+
this.metricsService?.recordCapture('front', 'auto', captureDuration);
|
|
1461
|
+
this.metricsService?.recordImageSize('front', frontImageData.length);
|
|
1462
|
+
if (span) {
|
|
1463
|
+
this.tracingService?.setSpanAttribute(span, 'side', 'front');
|
|
1464
|
+
}
|
|
1488
1465
|
// Check if document classification is enabled
|
|
1489
1466
|
if (this.useDocumentClassification) {
|
|
1490
1467
|
try {
|
|
1491
1468
|
const classification = await this.detectionService.classifyDocument(croppedCanvas);
|
|
1492
1469
|
if (classification && classification.class === 'passport') {
|
|
1470
|
+
if (span) {
|
|
1471
|
+
this.tracingService?.setSpanAttribute(span, 'document.type', 'passport');
|
|
1472
|
+
this.tracingService?.endSpan(span);
|
|
1473
|
+
}
|
|
1493
1474
|
this.completeProcess(true);
|
|
1494
1475
|
return;
|
|
1495
1476
|
}
|
|
@@ -1503,8 +1484,9 @@ export class JaakStamps {
|
|
|
1503
1484
|
isDetectionPaused: true,
|
|
1504
1485
|
showFlipAnimation: true
|
|
1505
1486
|
});
|
|
1506
|
-
|
|
1507
|
-
|
|
1487
|
+
if (span) {
|
|
1488
|
+
this.tracingService?.endSpan(span);
|
|
1489
|
+
}
|
|
1508
1490
|
setTimeout(() => {
|
|
1509
1491
|
this.stateManager.updateCaptureState({
|
|
1510
1492
|
showFlipAnimation: false,
|
|
@@ -1514,12 +1496,22 @@ export class JaakStamps {
|
|
|
1514
1496
|
}, 3000);
|
|
1515
1497
|
}
|
|
1516
1498
|
else if (captureState.step === 'back') {
|
|
1499
|
+
const backImageData = captureCanvas.toDataURL('image/jpeg');
|
|
1500
|
+
const croppedBackImageData = croppedCanvas.toDataURL('image/jpeg');
|
|
1517
1501
|
this.stateManager.setCapturedImages({
|
|
1518
1502
|
back: {
|
|
1519
|
-
fullFrame:
|
|
1520
|
-
cropped:
|
|
1503
|
+
fullFrame: backImageData,
|
|
1504
|
+
cropped: croppedBackImageData
|
|
1521
1505
|
}
|
|
1522
1506
|
});
|
|
1507
|
+
// Record metrics
|
|
1508
|
+
const captureDuration = performance.now() - captureStartTime;
|
|
1509
|
+
this.metricsService?.recordCapture('back', 'auto', captureDuration);
|
|
1510
|
+
this.metricsService?.recordImageSize('back', backImageData.length);
|
|
1511
|
+
if (span) {
|
|
1512
|
+
this.tracingService?.setSpanAttribute(span, 'side', 'back');
|
|
1513
|
+
this.tracingService?.endSpan(span);
|
|
1514
|
+
}
|
|
1523
1515
|
this.completeProcess(false);
|
|
1524
1516
|
}
|
|
1525
1517
|
// Return canvases to pool after use
|
|
@@ -1643,10 +1635,13 @@ export class JaakStamps {
|
|
|
1643
1635
|
this.useDocumentDetector = false; // Desactivar detector automático
|
|
1644
1636
|
// Actualizar el estado con mensaje de error
|
|
1645
1637
|
this.updateStatus('Modo manual activado', errorMessage, 'error');
|
|
1646
|
-
//
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1638
|
+
// Continuar con la configuración de cámara para mostrar el video
|
|
1639
|
+
this.continueWithCameraSetup().catch(() => {
|
|
1640
|
+
// Si falla la configuración de cámara, mantener el mensaje de error pero cambiar el estado
|
|
1641
|
+
setTimeout(() => {
|
|
1642
|
+
this.updateStatus('Captura manual', 'Use el botón para capturar', 'ready');
|
|
1643
|
+
}, 5000);
|
|
1644
|
+
});
|
|
1650
1645
|
}
|
|
1651
1646
|
stopPerformanceMonitoring() {
|
|
1652
1647
|
// Nota: No necesitamos limpiar más variables porque ya no se usarán
|
|
@@ -1663,7 +1658,7 @@ export class JaakStamps {
|
|
|
1663
1658
|
catch (error) {
|
|
1664
1659
|
}
|
|
1665
1660
|
}
|
|
1666
|
-
completeProcess(skippedBack = false) {
|
|
1661
|
+
async completeProcess(skippedBack = false) {
|
|
1667
1662
|
this.stateManager.updateCaptureState({
|
|
1668
1663
|
step: 'completed',
|
|
1669
1664
|
showSuccessAnimation: true
|
|
@@ -1678,20 +1673,19 @@ export class JaakStamps {
|
|
|
1678
1673
|
...capturedImages,
|
|
1679
1674
|
timestamp: new Date().toISOString()
|
|
1680
1675
|
};
|
|
1676
|
+
// Flush all traces to collector before emitting capture completed
|
|
1677
|
+
if (this.tracingService) {
|
|
1678
|
+
try {
|
|
1679
|
+
await this.tracingService.flush();
|
|
1680
|
+
}
|
|
1681
|
+
catch (error) {
|
|
1682
|
+
console.error('[my-component] Failed to flush traces:', error);
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1681
1685
|
this.captureCompleted.emit(finalImages);
|
|
1682
1686
|
setTimeout(() => {
|
|
1683
1687
|
this.stateManager.updateCaptureState({ showSuccessAnimation: false });
|
|
1684
1688
|
}, 3000);
|
|
1685
|
-
// Aggressive cleanup after process completion with delay
|
|
1686
|
-
setTimeout(async () => {
|
|
1687
|
-
const cleanupResult = await this.aggressiveResourceCleanup();
|
|
1688
|
-
if (this.debug) {
|
|
1689
|
-
console.log('🧹 Post-completion cleanup:', cleanupResult.freed);
|
|
1690
|
-
if (cleanupResult.errors.length > 0) {
|
|
1691
|
-
console.warn('⚠️ Cleanup errors:', cleanupResult.errors);
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
}, 1000); // Wait 1 second after completion
|
|
1695
1689
|
}
|
|
1696
1690
|
stopDetection() {
|
|
1697
1691
|
if (this.animationId) {
|
|
@@ -1743,6 +1737,12 @@ export class JaakStamps {
|
|
|
1743
1737
|
try {
|
|
1744
1738
|
// Close the selector immediately when user selects a camera
|
|
1745
1739
|
this.showCameraSelector = false;
|
|
1740
|
+
// Check if user selected the same camera that's already active
|
|
1741
|
+
const currentCameraId = this.cameraService.getSelectedCameraId();
|
|
1742
|
+
if (currentCameraId === cameraId) {
|
|
1743
|
+
// Same camera selected, just close the selector without switching
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
1746
|
this.isSwitchingCamera = true;
|
|
1747
1747
|
// Stop current video stream
|
|
1748
1748
|
if (this.videoStream) {
|
|
@@ -1873,28 +1873,35 @@ export class JaakStamps {
|
|
|
1873
1873
|
}
|
|
1874
1874
|
// Adaptive frame skipping based on performance
|
|
1875
1875
|
getAdaptiveFrameSkip() {
|
|
1876
|
+
// Check if running on mobile device for more aggressive frame skipping
|
|
1877
|
+
const isMobileDevice = this.cameraInfoWithAutofocus.deviceType === 'mobile' ||
|
|
1878
|
+
/Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
1879
|
+
const isTablet = this.cameraInfoWithAutofocus.deviceType === 'tablet' ||
|
|
1880
|
+
(/iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768);
|
|
1881
|
+
// Mobile-specific base frame skip (more aggressive to prevent slow motion effect)
|
|
1882
|
+
const mobileBaseSkip = isMobileDevice && !isTablet ? 4 : this.BASE_FRAME_SKIP;
|
|
1876
1883
|
// Base conditions for high frame skip
|
|
1877
1884
|
if (this.consecutiveFailures > 20)
|
|
1878
1885
|
return this.MAX_FRAME_SKIP;
|
|
1879
1886
|
if (this.performanceMetrics.inferenceTime > 200)
|
|
1880
|
-
return 6;
|
|
1887
|
+
return Math.max(6, mobileBaseSkip);
|
|
1881
1888
|
if (this.performanceMetrics.memoryUsage > 200)
|
|
1882
|
-
return 5;
|
|
1889
|
+
return Math.max(5, mobileBaseSkip);
|
|
1883
1890
|
// Calculate average processing time
|
|
1884
1891
|
if (this.performanceHistory.length > 0) {
|
|
1885
1892
|
const avgProcessingTime = this.performanceHistory.reduce((a, b) => a + b, 0) / this.performanceHistory.length;
|
|
1886
1893
|
if (avgProcessingTime > 100)
|
|
1887
|
-
return 4;
|
|
1894
|
+
return Math.max(4, mobileBaseSkip);
|
|
1888
1895
|
if (avgProcessingTime > 80)
|
|
1889
|
-
return 3;
|
|
1896
|
+
return Math.max(3, mobileBaseSkip);
|
|
1890
1897
|
if (avgProcessingTime > 60)
|
|
1891
|
-
return this.BASE_FRAME_SKIP + 1;
|
|
1898
|
+
return Math.max(this.BASE_FRAME_SKIP + 1, mobileBaseSkip);
|
|
1892
1899
|
}
|
|
1893
1900
|
// Low memory devices get higher frame skip
|
|
1894
1901
|
if (this.performanceMetrics.memoryUsage > 150)
|
|
1895
|
-
return 4;
|
|
1896
|
-
//
|
|
1897
|
-
return
|
|
1902
|
+
return Math.max(4, mobileBaseSkip);
|
|
1903
|
+
// Mobile devices use higher base frame skip for smoother video
|
|
1904
|
+
return mobileBaseSkip;
|
|
1898
1905
|
}
|
|
1899
1906
|
// Método para resetear la máscara a color blanco
|
|
1900
1907
|
resetMaskToWhite() {
|
|
@@ -2157,6 +2164,261 @@ export class JaakStamps {
|
|
|
2157
2164
|
"setter": false,
|
|
2158
2165
|
"reflect": false,
|
|
2159
2166
|
"defaultValue": "20"
|
|
2167
|
+
},
|
|
2168
|
+
"telemetryCollectorUrl": {
|
|
2169
|
+
"type": "string",
|
|
2170
|
+
"attribute": "telemetry-collector-url",
|
|
2171
|
+
"mutable": false,
|
|
2172
|
+
"complexType": {
|
|
2173
|
+
"original": "string",
|
|
2174
|
+
"resolved": "string",
|
|
2175
|
+
"references": {}
|
|
2176
|
+
},
|
|
2177
|
+
"required": false,
|
|
2178
|
+
"optional": true,
|
|
2179
|
+
"docs": {
|
|
2180
|
+
"tags": [],
|
|
2181
|
+
"text": ""
|
|
2182
|
+
},
|
|
2183
|
+
"getter": false,
|
|
2184
|
+
"setter": false,
|
|
2185
|
+
"reflect": false,
|
|
2186
|
+
"defaultValue": "'https://collector.jaak.ai/v1/traces'"
|
|
2187
|
+
},
|
|
2188
|
+
"metricsCollectorUrl": {
|
|
2189
|
+
"type": "string",
|
|
2190
|
+
"attribute": "metrics-collector-url",
|
|
2191
|
+
"mutable": false,
|
|
2192
|
+
"complexType": {
|
|
2193
|
+
"original": "string",
|
|
2194
|
+
"resolved": "string",
|
|
2195
|
+
"references": {}
|
|
2196
|
+
},
|
|
2197
|
+
"required": false,
|
|
2198
|
+
"optional": true,
|
|
2199
|
+
"docs": {
|
|
2200
|
+
"tags": [],
|
|
2201
|
+
"text": ""
|
|
2202
|
+
},
|
|
2203
|
+
"getter": false,
|
|
2204
|
+
"setter": false,
|
|
2205
|
+
"reflect": false,
|
|
2206
|
+
"defaultValue": "'https://collector.jaak.ai/v1/metrics'"
|
|
2207
|
+
},
|
|
2208
|
+
"enableTelemetry": {
|
|
2209
|
+
"type": "boolean",
|
|
2210
|
+
"attribute": "enable-telemetry",
|
|
2211
|
+
"mutable": false,
|
|
2212
|
+
"complexType": {
|
|
2213
|
+
"original": "boolean",
|
|
2214
|
+
"resolved": "boolean",
|
|
2215
|
+
"references": {}
|
|
2216
|
+
},
|
|
2217
|
+
"required": false,
|
|
2218
|
+
"optional": false,
|
|
2219
|
+
"docs": {
|
|
2220
|
+
"tags": [],
|
|
2221
|
+
"text": ""
|
|
2222
|
+
},
|
|
2223
|
+
"getter": false,
|
|
2224
|
+
"setter": false,
|
|
2225
|
+
"reflect": false,
|
|
2226
|
+
"defaultValue": "true"
|
|
2227
|
+
},
|
|
2228
|
+
"enableMetrics": {
|
|
2229
|
+
"type": "boolean",
|
|
2230
|
+
"attribute": "enable-metrics",
|
|
2231
|
+
"mutable": false,
|
|
2232
|
+
"complexType": {
|
|
2233
|
+
"original": "boolean",
|
|
2234
|
+
"resolved": "boolean",
|
|
2235
|
+
"references": {}
|
|
2236
|
+
},
|
|
2237
|
+
"required": false,
|
|
2238
|
+
"optional": false,
|
|
2239
|
+
"docs": {
|
|
2240
|
+
"tags": [],
|
|
2241
|
+
"text": ""
|
|
2242
|
+
},
|
|
2243
|
+
"getter": false,
|
|
2244
|
+
"setter": false,
|
|
2245
|
+
"reflect": false,
|
|
2246
|
+
"defaultValue": "true"
|
|
2247
|
+
},
|
|
2248
|
+
"customerId": {
|
|
2249
|
+
"type": "string",
|
|
2250
|
+
"attribute": "customer-id",
|
|
2251
|
+
"mutable": false,
|
|
2252
|
+
"complexType": {
|
|
2253
|
+
"original": "string",
|
|
2254
|
+
"resolved": "string",
|
|
2255
|
+
"references": {}
|
|
2256
|
+
},
|
|
2257
|
+
"required": false,
|
|
2258
|
+
"optional": true,
|
|
2259
|
+
"docs": {
|
|
2260
|
+
"tags": [],
|
|
2261
|
+
"text": ""
|
|
2262
|
+
},
|
|
2263
|
+
"getter": false,
|
|
2264
|
+
"setter": false,
|
|
2265
|
+
"reflect": false
|
|
2266
|
+
},
|
|
2267
|
+
"tenantId": {
|
|
2268
|
+
"type": "string",
|
|
2269
|
+
"attribute": "tenant-id",
|
|
2270
|
+
"mutable": false,
|
|
2271
|
+
"complexType": {
|
|
2272
|
+
"original": "string",
|
|
2273
|
+
"resolved": "string",
|
|
2274
|
+
"references": {}
|
|
2275
|
+
},
|
|
2276
|
+
"required": false,
|
|
2277
|
+
"optional": true,
|
|
2278
|
+
"docs": {
|
|
2279
|
+
"tags": [],
|
|
2280
|
+
"text": ""
|
|
2281
|
+
},
|
|
2282
|
+
"getter": false,
|
|
2283
|
+
"setter": false,
|
|
2284
|
+
"reflect": false
|
|
2285
|
+
},
|
|
2286
|
+
"environment": {
|
|
2287
|
+
"type": "string",
|
|
2288
|
+
"attribute": "environment",
|
|
2289
|
+
"mutable": false,
|
|
2290
|
+
"complexType": {
|
|
2291
|
+
"original": "string",
|
|
2292
|
+
"resolved": "string",
|
|
2293
|
+
"references": {}
|
|
2294
|
+
},
|
|
2295
|
+
"required": false,
|
|
2296
|
+
"optional": true,
|
|
2297
|
+
"docs": {
|
|
2298
|
+
"tags": [],
|
|
2299
|
+
"text": ""
|
|
2300
|
+
},
|
|
2301
|
+
"getter": false,
|
|
2302
|
+
"setter": false,
|
|
2303
|
+
"reflect": false,
|
|
2304
|
+
"defaultValue": "'production'"
|
|
2305
|
+
},
|
|
2306
|
+
"propagateTraceHeaderCorsUrls": {
|
|
2307
|
+
"type": "string",
|
|
2308
|
+
"attribute": "propagate-trace-header-cors-urls",
|
|
2309
|
+
"mutable": false,
|
|
2310
|
+
"complexType": {
|
|
2311
|
+
"original": "string",
|
|
2312
|
+
"resolved": "string",
|
|
2313
|
+
"references": {}
|
|
2314
|
+
},
|
|
2315
|
+
"required": false,
|
|
2316
|
+
"optional": true,
|
|
2317
|
+
"docs": {
|
|
2318
|
+
"tags": [],
|
|
2319
|
+
"text": ""
|
|
2320
|
+
},
|
|
2321
|
+
"getter": false,
|
|
2322
|
+
"setter": false,
|
|
2323
|
+
"reflect": false
|
|
2324
|
+
},
|
|
2325
|
+
"metricsExportIntervalMillis": {
|
|
2326
|
+
"type": "number",
|
|
2327
|
+
"attribute": "metrics-export-interval-millis",
|
|
2328
|
+
"mutable": false,
|
|
2329
|
+
"complexType": {
|
|
2330
|
+
"original": "number",
|
|
2331
|
+
"resolved": "number",
|
|
2332
|
+
"references": {}
|
|
2333
|
+
},
|
|
2334
|
+
"required": false,
|
|
2335
|
+
"optional": true,
|
|
2336
|
+
"docs": {
|
|
2337
|
+
"tags": [],
|
|
2338
|
+
"text": ""
|
|
2339
|
+
},
|
|
2340
|
+
"getter": false,
|
|
2341
|
+
"setter": false,
|
|
2342
|
+
"reflect": false,
|
|
2343
|
+
"defaultValue": "60000"
|
|
2344
|
+
},
|
|
2345
|
+
"license": {
|
|
2346
|
+
"type": "string",
|
|
2347
|
+
"attribute": "license",
|
|
2348
|
+
"mutable": false,
|
|
2349
|
+
"complexType": {
|
|
2350
|
+
"original": "string",
|
|
2351
|
+
"resolved": "string",
|
|
2352
|
+
"references": {}
|
|
2353
|
+
},
|
|
2354
|
+
"required": false,
|
|
2355
|
+
"optional": true,
|
|
2356
|
+
"docs": {
|
|
2357
|
+
"tags": [],
|
|
2358
|
+
"text": ""
|
|
2359
|
+
},
|
|
2360
|
+
"getter": false,
|
|
2361
|
+
"setter": false,
|
|
2362
|
+
"reflect": false
|
|
2363
|
+
},
|
|
2364
|
+
"licenseEnvironment": {
|
|
2365
|
+
"type": "string",
|
|
2366
|
+
"attribute": "license-environment",
|
|
2367
|
+
"mutable": false,
|
|
2368
|
+
"complexType": {
|
|
2369
|
+
"original": "'dev' | 'qa' | 'sandbox' | 'prod'",
|
|
2370
|
+
"resolved": "\"dev\" | \"prod\" | \"qa\" | \"sandbox\"",
|
|
2371
|
+
"references": {}
|
|
2372
|
+
},
|
|
2373
|
+
"required": false,
|
|
2374
|
+
"optional": true,
|
|
2375
|
+
"docs": {
|
|
2376
|
+
"tags": [],
|
|
2377
|
+
"text": ""
|
|
2378
|
+
},
|
|
2379
|
+
"getter": false,
|
|
2380
|
+
"setter": false,
|
|
2381
|
+
"reflect": false,
|
|
2382
|
+
"defaultValue": "'prod'"
|
|
2383
|
+
},
|
|
2384
|
+
"traceId": {
|
|
2385
|
+
"type": "string",
|
|
2386
|
+
"attribute": "trace-id",
|
|
2387
|
+
"mutable": false,
|
|
2388
|
+
"complexType": {
|
|
2389
|
+
"original": "string",
|
|
2390
|
+
"resolved": "string",
|
|
2391
|
+
"references": {}
|
|
2392
|
+
},
|
|
2393
|
+
"required": false,
|
|
2394
|
+
"optional": true,
|
|
2395
|
+
"docs": {
|
|
2396
|
+
"tags": [],
|
|
2397
|
+
"text": ""
|
|
2398
|
+
},
|
|
2399
|
+
"getter": false,
|
|
2400
|
+
"setter": false,
|
|
2401
|
+
"reflect": false
|
|
2402
|
+
},
|
|
2403
|
+
"appId": {
|
|
2404
|
+
"type": "string",
|
|
2405
|
+
"attribute": "app-id",
|
|
2406
|
+
"mutable": false,
|
|
2407
|
+
"complexType": {
|
|
2408
|
+
"original": "string",
|
|
2409
|
+
"resolved": "string",
|
|
2410
|
+
"references": {}
|
|
2411
|
+
},
|
|
2412
|
+
"required": false,
|
|
2413
|
+
"optional": true,
|
|
2414
|
+
"docs": {
|
|
2415
|
+
"tags": [],
|
|
2416
|
+
"text": ""
|
|
2417
|
+
},
|
|
2418
|
+
"getter": false,
|
|
2419
|
+
"setter": false,
|
|
2420
|
+
"reflect": false,
|
|
2421
|
+
"defaultValue": "'jaak-stamps-web'"
|
|
2160
2422
|
}
|
|
2161
2423
|
};
|
|
2162
2424
|
}
|
|
@@ -2177,7 +2439,9 @@ export class JaakStamps {
|
|
|
2177
2439
|
"performanceDegradedMode": {},
|
|
2178
2440
|
"showPerformanceMessage": {},
|
|
2179
2441
|
"captureStateVersion": {},
|
|
2180
|
-
"processingButton": {}
|
|
2442
|
+
"processingButton": {},
|
|
2443
|
+
"licenseValid": {},
|
|
2444
|
+
"licenseError": {}
|
|
2181
2445
|
};
|
|
2182
2446
|
}
|
|
2183
2447
|
static get events() {
|
|
@@ -2211,6 +2475,21 @@ export class JaakStamps {
|
|
|
2211
2475
|
"resolved": "boolean",
|
|
2212
2476
|
"references": {}
|
|
2213
2477
|
}
|
|
2478
|
+
}, {
|
|
2479
|
+
"method": "traceIdGenerated",
|
|
2480
|
+
"name": "traceIdGenerated",
|
|
2481
|
+
"bubbles": true,
|
|
2482
|
+
"cancelable": true,
|
|
2483
|
+
"composed": true,
|
|
2484
|
+
"docs": {
|
|
2485
|
+
"tags": [],
|
|
2486
|
+
"text": ""
|
|
2487
|
+
},
|
|
2488
|
+
"complexType": {
|
|
2489
|
+
"original": "{traceId: string}",
|
|
2490
|
+
"resolved": "{ traceId: string; }",
|
|
2491
|
+
"references": {}
|
|
2492
|
+
}
|
|
2214
2493
|
}];
|
|
2215
2494
|
}
|
|
2216
2495
|
static get methods() {
|
|
@@ -2273,7 +2552,7 @@ export class JaakStamps {
|
|
|
2273
2552
|
},
|
|
2274
2553
|
"stopCapture": {
|
|
2275
2554
|
"complexType": {
|
|
2276
|
-
"signature": "() => Promise<{ success: boolean;
|
|
2555
|
+
"signature": "() => Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>",
|
|
2277
2556
|
"parameters": [],
|
|
2278
2557
|
"references": {
|
|
2279
2558
|
"Promise": {
|
|
@@ -2281,7 +2560,7 @@ export class JaakStamps {
|
|
|
2281
2560
|
"id": "global::Promise"
|
|
2282
2561
|
}
|
|
2283
2562
|
},
|
|
2284
|
-
"return": "Promise<{ success: boolean;
|
|
2563
|
+
"return": "Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>"
|
|
2285
2564
|
},
|
|
2286
2565
|
"docs": {
|
|
2287
2566
|
"text": "",
|
|
@@ -2441,40 +2720,6 @@ export class JaakStamps {
|
|
|
2441
2720
|
"text": "",
|
|
2442
2721
|
"tags": []
|
|
2443
2722
|
}
|
|
2444
|
-
},
|
|
2445
|
-
"getResourceReport": {
|
|
2446
|
-
"complexType": {
|
|
2447
|
-
"signature": "() => Promise<any>",
|
|
2448
|
-
"parameters": [],
|
|
2449
|
-
"references": {
|
|
2450
|
-
"Promise": {
|
|
2451
|
-
"location": "global",
|
|
2452
|
-
"id": "global::Promise"
|
|
2453
|
-
}
|
|
2454
|
-
},
|
|
2455
|
-
"return": "Promise<any>"
|
|
2456
|
-
},
|
|
2457
|
-
"docs": {
|
|
2458
|
-
"text": "",
|
|
2459
|
-
"tags": []
|
|
2460
|
-
}
|
|
2461
|
-
},
|
|
2462
|
-
"forceResourceCleanup": {
|
|
2463
|
-
"complexType": {
|
|
2464
|
-
"signature": "() => Promise<{ success: boolean; resourcesFreed: string[]; errors: string[]; timestamp: string; error?: undefined; } | { success: boolean; error: any; resourcesFreed?: undefined; errors?: undefined; timestamp?: undefined; }>",
|
|
2465
|
-
"parameters": [],
|
|
2466
|
-
"references": {
|
|
2467
|
-
"Promise": {
|
|
2468
|
-
"location": "global",
|
|
2469
|
-
"id": "global::Promise"
|
|
2470
|
-
}
|
|
2471
|
-
},
|
|
2472
|
-
"return": "Promise<{ success: boolean; resourcesFreed: string[]; errors: string[]; timestamp: string; error?: undefined; } | { success: boolean; error: any; resourcesFreed?: undefined; errors?: undefined; timestamp?: undefined; }>"
|
|
2473
|
-
},
|
|
2474
|
-
"docs": {
|
|
2475
|
-
"text": "",
|
|
2476
|
-
"tags": []
|
|
2477
|
-
}
|
|
2478
2723
|
}
|
|
2479
2724
|
};
|
|
2480
2725
|
}
|