@jaak.ai/stamps 2.0.0-dev.27 → 2.0.0-dev.29
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 +252 -72
- 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/my-component/my-component.js +252 -72
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/components/jaak-stamps.js +252 -72
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/jaak-stamps.entry.js +252 -72
- 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-28adb830.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-28adb830.entry.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +2 -1
- package/package.json +1 -1
- package/dist/jaak-stamps-webcomponent/p-eb318f43.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-eb318f43.entry.js.map +0 -1
|
@@ -76,34 +76,65 @@ const JaakStamps = class {
|
|
|
76
76
|
CONFIDENCE_THRESHOLD = 0.6;
|
|
77
77
|
// ISO/IEC 7810 ID-1 standard dimensions (85.60mm x 53.98mm)
|
|
78
78
|
ID1_ASPECT_RATIO = 85.60 / 53.98; // 1.5863320574...
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
logger = {
|
|
80
|
+
info: (...args) => {
|
|
81
|
+
if (this.debug) {
|
|
82
|
+
console.log(`[JAAK-STAMPS] [INFO] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
warn: (...args) => {
|
|
86
|
+
if (this.debug) {
|
|
87
|
+
console.warn(`[JAAK-STAMPS] [WARN] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
error: (...args) => {
|
|
91
|
+
if (this.debug) {
|
|
92
|
+
console.error(`[JAAK-STAMPS] [ERROR] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
debug: (...args) => {
|
|
96
|
+
if (this.debug) {
|
|
97
|
+
console.debug(`[JAAK-STAMPS] [DEBUG] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
state: (state, data) => {
|
|
101
|
+
if (this.debug) {
|
|
102
|
+
console.log(`[JAAK-STAMPS] [STATE] [${new Date().toLocaleTimeString()}] ${state}`, data || '');
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
performance: (operation, duration) => {
|
|
106
|
+
if (this.debug) {
|
|
107
|
+
console.log(`[JAAK-STAMPS] [PERF] [${new Date().toLocaleTimeString()}] ${operation}: ${duration}ms`);
|
|
108
|
+
}
|
|
82
109
|
}
|
|
83
|
-
}
|
|
110
|
+
};
|
|
84
111
|
validateMaskSize() {
|
|
85
112
|
if (this.maskSize < 50 || this.maskSize > 100) {
|
|
86
|
-
|
|
113
|
+
this.logger.warn(`Propiedad maskSize inválida. Valor: ${this.maskSize}, esperado: 50-100. Usando valor por defecto: 90`);
|
|
87
114
|
this.maskSize = 90;
|
|
88
115
|
}
|
|
89
116
|
}
|
|
90
117
|
validateCropMargin() {
|
|
91
118
|
if (this.cropMargin < 0 || this.cropMargin > 100) {
|
|
92
|
-
|
|
119
|
+
this.logger.warn(`Propiedad cropMargin inválida. Valor: ${this.cropMargin}, esperado: 0-100. Usando valor por defecto: 0`);
|
|
93
120
|
this.cropMargin = 0;
|
|
94
121
|
}
|
|
95
122
|
}
|
|
96
123
|
validatePreferredCamera() {
|
|
97
124
|
const validOptions = ['auto', 'front', 'back'];
|
|
98
125
|
if (!validOptions.includes(this.preferredCamera)) {
|
|
99
|
-
|
|
126
|
+
this.logger.warn(`Propiedad preferredCamera inválida. Valor: ${this.preferredCamera}, esperado: ${validOptions.join(', ')}. Usando valor por defecto: 'auto'`);
|
|
100
127
|
this.preferredCamera = 'auto';
|
|
101
128
|
}
|
|
102
129
|
}
|
|
103
130
|
emitReadyEvent() {
|
|
104
131
|
const isDocumentReady = !!window.ort && this.isModelPreloaded;
|
|
105
132
|
this.isReady.emit(isDocumentReady);
|
|
106
|
-
this.
|
|
133
|
+
this.logger.state('COMPONENTE_LISTO', {
|
|
134
|
+
ortLibraryLoaded: !!window.ort,
|
|
135
|
+
modelPreloaded: this.isModelPreloaded,
|
|
136
|
+
isReady: isDocumentReady
|
|
137
|
+
});
|
|
107
138
|
}
|
|
108
139
|
isRearCamera(stream) {
|
|
109
140
|
const videoTrack = stream.getVideoTracks()[0];
|
|
@@ -126,7 +157,11 @@ const JaakStamps = class {
|
|
|
126
157
|
else {
|
|
127
158
|
this.deviceType = 'desktop';
|
|
128
159
|
}
|
|
129
|
-
this.
|
|
160
|
+
this.logger.state('DISPOSITIVO_DETECTADO', {
|
|
161
|
+
deviceType: this.deviceType,
|
|
162
|
+
userAgent: navigator.userAgent,
|
|
163
|
+
screenDimensions: { width: window.innerWidth, height: window.innerHeight }
|
|
164
|
+
});
|
|
130
165
|
// Enumerate available cameras
|
|
131
166
|
await this.enumerateAndDetectCameras();
|
|
132
167
|
// Load user preference
|
|
@@ -137,7 +172,7 @@ const JaakStamps = class {
|
|
|
137
172
|
// First, check if we have permission to enumerate devices
|
|
138
173
|
const permissionStatus = await this.checkCameraPermission();
|
|
139
174
|
if (permissionStatus === 'denied') {
|
|
140
|
-
this.
|
|
175
|
+
this.logger.error('Permiso de cámara denegado por el usuario');
|
|
141
176
|
this.statusMessage = "Permiso de cámara denegado";
|
|
142
177
|
this.statusColor = "#ff6b6b";
|
|
143
178
|
return;
|
|
@@ -151,7 +186,7 @@ const JaakStamps = class {
|
|
|
151
186
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
152
187
|
this.availableCameras = devices.filter(device => device.kind === 'videoinput');
|
|
153
188
|
this.isMultipleCamerasAvailable = this.availableCameras.length > 1;
|
|
154
|
-
this.
|
|
189
|
+
this.logger.state('CAMARAS_DETECTADAS', {
|
|
155
190
|
count: this.availableCameras.length,
|
|
156
191
|
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
157
192
|
cameras: this.availableCameras.map(cam => ({
|
|
@@ -163,7 +198,7 @@ const JaakStamps = class {
|
|
|
163
198
|
this.setInitialCameraPreference();
|
|
164
199
|
}
|
|
165
200
|
catch (error) {
|
|
166
|
-
this.
|
|
201
|
+
this.logger.error('Error al enumerar cámaras disponibles:', error);
|
|
167
202
|
this.handleCameraPermissionError(error);
|
|
168
203
|
}
|
|
169
204
|
}
|
|
@@ -176,7 +211,7 @@ const JaakStamps = class {
|
|
|
176
211
|
return permission.state;
|
|
177
212
|
}
|
|
178
213
|
catch (error) {
|
|
179
|
-
this.
|
|
214
|
+
this.logger.warn('No se pudo verificar permisos de cámara:', error);
|
|
180
215
|
return 'prompt';
|
|
181
216
|
}
|
|
182
217
|
}
|
|
@@ -219,11 +254,11 @@ const JaakStamps = class {
|
|
|
219
254
|
!camera.label.toLowerCase().includes('back') && !camera.label.toLowerCase().includes('rear'));
|
|
220
255
|
if (frontCamera) {
|
|
221
256
|
this.selectedCameraId = frontCamera.deviceId;
|
|
222
|
-
this.
|
|
257
|
+
this.logger.state('CAMARA_FRONTAL_SELECCIONADA', { label: frontCamera.label, deviceId: frontCamera.deviceId });
|
|
223
258
|
}
|
|
224
259
|
else {
|
|
225
260
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
226
|
-
this.
|
|
261
|
+
this.logger.warn('Cámara frontal no encontrada, usando primera disponible:', this.availableCameras[0].label);
|
|
227
262
|
}
|
|
228
263
|
}
|
|
229
264
|
else if (this.preferredCamera === 'back') {
|
|
@@ -234,11 +269,11 @@ const JaakStamps = class {
|
|
|
234
269
|
camera.label.toLowerCase().includes('environment'));
|
|
235
270
|
if (backCamera) {
|
|
236
271
|
this.selectedCameraId = backCamera.deviceId;
|
|
237
|
-
this.
|
|
272
|
+
this.logger.state('CAMARA_TRASERA_SELECCIONADA', { label: backCamera.label, deviceId: backCamera.deviceId });
|
|
238
273
|
}
|
|
239
274
|
else {
|
|
240
275
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
241
|
-
this.
|
|
276
|
+
this.logger.warn('Cámara trasera no encontrada, usando primera disponible:', this.availableCameras[0].label);
|
|
242
277
|
}
|
|
243
278
|
}
|
|
244
279
|
else {
|
|
@@ -251,17 +286,17 @@ const JaakStamps = class {
|
|
|
251
286
|
camera.label.toLowerCase().includes('environment'));
|
|
252
287
|
if (rearCamera) {
|
|
253
288
|
this.selectedCameraId = rearCamera.deviceId;
|
|
254
|
-
this.
|
|
289
|
+
this.logger.state('CAMARA_AUTO_SELECCIONADA_MOBILE', { type: 'rear', label: rearCamera.label, deviceId: rearCamera.deviceId });
|
|
255
290
|
}
|
|
256
291
|
else {
|
|
257
292
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
258
|
-
this.
|
|
293
|
+
this.logger.warn('Cámara trasera no encontrada en mobile, usando primera disponible:', this.availableCameras[0].label);
|
|
259
294
|
}
|
|
260
295
|
}
|
|
261
296
|
else {
|
|
262
297
|
// For desktop, use first available camera (usually the only one)
|
|
263
298
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
264
|
-
this.
|
|
299
|
+
this.logger.state('CAMARA_AUTO_SELECCIONADA_DESKTOP', { label: this.availableCameras[0].label, deviceId: this.availableCameras[0].deviceId });
|
|
265
300
|
}
|
|
266
301
|
}
|
|
267
302
|
}
|
|
@@ -275,12 +310,12 @@ const JaakStamps = class {
|
|
|
275
310
|
if (isStillAvailable) {
|
|
276
311
|
this.selectedCameraId = preference.cameraId;
|
|
277
312
|
this.preferredCameraFacing = preference.facing;
|
|
278
|
-
this.
|
|
313
|
+
this.logger.state('PREFERENCIA_CAMARA_CARGADA', preference);
|
|
279
314
|
}
|
|
280
315
|
}
|
|
281
316
|
}
|
|
282
317
|
catch (error) {
|
|
283
|
-
this.
|
|
318
|
+
this.logger.warn('Error al cargar preferencia de cámara:', error);
|
|
284
319
|
}
|
|
285
320
|
}
|
|
286
321
|
saveCameraPreference() {
|
|
@@ -291,10 +326,10 @@ const JaakStamps = class {
|
|
|
291
326
|
timestamp: Date.now()
|
|
292
327
|
};
|
|
293
328
|
localStorage.setItem('jaak-stamps-camera-preference', JSON.stringify(preference));
|
|
294
|
-
this.
|
|
329
|
+
this.logger.state('PREFERENCIA_CAMARA_GUARDADA', preference);
|
|
295
330
|
}
|
|
296
331
|
catch (error) {
|
|
297
|
-
this.
|
|
332
|
+
this.logger.warn('Error al guardar preferencia de cámara:', error);
|
|
298
333
|
}
|
|
299
334
|
}
|
|
300
335
|
async switchCamera(cameraId) {
|
|
@@ -304,7 +339,7 @@ const JaakStamps = class {
|
|
|
304
339
|
// Check if the selected camera is still available
|
|
305
340
|
const selectedCamera = this.availableCameras.find(cam => cam.deviceId === cameraId);
|
|
306
341
|
if (!selectedCamera) {
|
|
307
|
-
this.
|
|
342
|
+
this.logger.warn('Cámara seleccionada no encontrada, re-enumerando dispositivos...');
|
|
308
343
|
await this.enumerateAndDetectCameras();
|
|
309
344
|
return;
|
|
310
345
|
}
|
|
@@ -328,10 +363,10 @@ const JaakStamps = class {
|
|
|
328
363
|
this.saveCameraPreference();
|
|
329
364
|
// Setup new camera with error handling
|
|
330
365
|
await this.setupCameraWithRetry();
|
|
331
|
-
this.
|
|
366
|
+
this.logger.state('CAMARA_CAMBIADA', { label: selectedCamera.label, deviceId: selectedCamera.deviceId });
|
|
332
367
|
}
|
|
333
368
|
catch (error) {
|
|
334
|
-
this.
|
|
369
|
+
this.logger.error('Error al cambiar de cámara:', error);
|
|
335
370
|
this.handleCameraPermissionError(error);
|
|
336
371
|
}
|
|
337
372
|
}
|
|
@@ -346,7 +381,7 @@ const JaakStamps = class {
|
|
|
346
381
|
return; // Success
|
|
347
382
|
}
|
|
348
383
|
catch (error) {
|
|
349
|
-
this.
|
|
384
|
+
this.logger.error(`Intento ${attempt} de configuración de cámara fallido:`, error);
|
|
350
385
|
if (attempt === maxRetries) {
|
|
351
386
|
// Last attempt failed, handle the error
|
|
352
387
|
this.statusMessage = "Error al configurar la cámara";
|
|
@@ -366,7 +401,7 @@ const JaakStamps = class {
|
|
|
366
401
|
}
|
|
367
402
|
toggleCameraSelector() {
|
|
368
403
|
this.showCameraSelector = !this.showCameraSelector;
|
|
369
|
-
this.
|
|
404
|
+
this.logger.state('SELECTOR_CAMARA_TOGGLE', {
|
|
370
405
|
showCameraSelector: this.showCameraSelector,
|
|
371
406
|
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
372
407
|
availableCameras: this.availableCameras.length,
|
|
@@ -382,6 +417,13 @@ const JaakStamps = class {
|
|
|
382
417
|
await this.switchCamera(nextCamera.deviceId);
|
|
383
418
|
}
|
|
384
419
|
async componentDidLoad() {
|
|
420
|
+
this.logger.state('COMPONENTE_INICIALIZANDO', {
|
|
421
|
+
debug: this.debug,
|
|
422
|
+
maskSize: this.maskSize,
|
|
423
|
+
cropMargin: this.cropMargin,
|
|
424
|
+
useDocumentClassification: this.useDocumentClassification,
|
|
425
|
+
preferredCamera: this.preferredCamera
|
|
426
|
+
});
|
|
385
427
|
if (this.debug) {
|
|
386
428
|
// Show detailed initialization loading state only in debug mode
|
|
387
429
|
this.isLoading = true;
|
|
@@ -446,7 +488,7 @@ const JaakStamps = class {
|
|
|
446
488
|
this.canvasRef.height = rect.height;
|
|
447
489
|
// Update mask positioning based on container and video dimensions
|
|
448
490
|
this.updateMaskDimensions(rect);
|
|
449
|
-
this.
|
|
491
|
+
this.logger.debug('Canvas redimensionado:', { width: rect.width, height: rect.height });
|
|
450
492
|
}
|
|
451
493
|
}
|
|
452
494
|
updateMaskDimensions(containerRect) {
|
|
@@ -506,7 +548,7 @@ const JaakStamps = class {
|
|
|
506
548
|
this.el.style.setProperty('--mask-center-y', `${videoCenterYPercent}%`);
|
|
507
549
|
// Mark mask as ready now that dimensions are calculated
|
|
508
550
|
this.isMaskReady = true;
|
|
509
|
-
this.
|
|
551
|
+
this.logger.state('DIMENSIONES_MASCARA_ACTUALIZADAS', {
|
|
510
552
|
video: { width: videoWidth, height: videoHeight },
|
|
511
553
|
displayed: { width: displayedVideoWidth, height: displayedVideoHeight },
|
|
512
554
|
mask: { widthPercent: maskWidthPercent, heightPercent: maskHeightPercent },
|
|
@@ -528,7 +570,7 @@ const JaakStamps = class {
|
|
|
528
570
|
this.captureCtx = this.captureCanvas.getContext('2d', {
|
|
529
571
|
alpha: false
|
|
530
572
|
});
|
|
531
|
-
this.
|
|
573
|
+
this.logger.state('CANVAS_POOL_INICIALIZADO', { preprocessCanvasSize: this.INPUT_SIZE });
|
|
532
574
|
}
|
|
533
575
|
disconnectedCallback() {
|
|
534
576
|
this.cleanup();
|
|
@@ -576,7 +618,7 @@ const JaakStamps = class {
|
|
|
576
618
|
}
|
|
577
619
|
async preloadModel() {
|
|
578
620
|
if (this.isModelPreloaded || this.session) {
|
|
579
|
-
this.
|
|
621
|
+
this.logger.state('MODELO_YA_PRECARGADO', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
|
|
580
622
|
return { success: true, message: 'Model already loaded' };
|
|
581
623
|
}
|
|
582
624
|
try {
|
|
@@ -584,12 +626,39 @@ const JaakStamps = class {
|
|
|
584
626
|
this.statusMessage = "Precargando modelos...";
|
|
585
627
|
this.statusColor = "#007bff";
|
|
586
628
|
const modelPath = this.MODEL_PATH;
|
|
587
|
-
this.
|
|
629
|
+
this.logger.state('PRECARGANDO_MODELO_DETECCION', { modelPath });
|
|
588
630
|
// Configure ONNX Runtime with device-specific optimizations
|
|
589
631
|
const sessionOptions = this.getSessionOptions();
|
|
590
|
-
|
|
632
|
+
const deviceInfo = this.getDeviceMemoryInfo();
|
|
633
|
+
try {
|
|
634
|
+
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
638
|
+
this.logger.warn('Fallo en asignación de buffer durante precarga, intentando con configuración mínima');
|
|
639
|
+
const fallbackOptions = {
|
|
640
|
+
executionProviders: ['wasm'],
|
|
641
|
+
graphOptimizationLevel: 'disabled',
|
|
642
|
+
logSeverityLevel: 4,
|
|
643
|
+
enableCpuMemArena: false,
|
|
644
|
+
enableMemPattern: false,
|
|
645
|
+
executionMode: 'sequential',
|
|
646
|
+
interOpNumThreads: 1,
|
|
647
|
+
intraOpNumThreads: 1,
|
|
648
|
+
};
|
|
649
|
+
this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
throw error;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
591
655
|
// Preload MobileNet model and classes only if classification is enabled
|
|
656
|
+
// For low memory devices, load sequentially to avoid memory pressure
|
|
592
657
|
if (this.useDocumentClassification) {
|
|
658
|
+
if (deviceInfo.isLowMemory) {
|
|
659
|
+
this.logger.state('CARGA_SECUENCIAL_MODELOS', { reason: 'low memory device' });
|
|
660
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
661
|
+
}
|
|
593
662
|
await this.loadMobileNetModel();
|
|
594
663
|
}
|
|
595
664
|
this.isModelPreloaded = true;
|
|
@@ -597,11 +666,15 @@ const JaakStamps = class {
|
|
|
597
666
|
this.statusMessage = "Modelos precargados. Listo para comenzar detección";
|
|
598
667
|
this.statusColor = "#28a745";
|
|
599
668
|
this.emitReadyEvent();
|
|
600
|
-
this.
|
|
669
|
+
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE', {
|
|
670
|
+
detectionModel: !!this.session,
|
|
671
|
+
classificationModel: !!this.mobileNetSession,
|
|
672
|
+
useClassification: this.useDocumentClassification
|
|
673
|
+
});
|
|
601
674
|
return { success: true, message: 'Models preloaded successfully' };
|
|
602
675
|
}
|
|
603
676
|
catch (error) {
|
|
604
|
-
this.
|
|
677
|
+
this.logger.error('Error al precargar modelos:', error);
|
|
605
678
|
this.isLoading = false;
|
|
606
679
|
this.statusMessage = "Error al precargar los modelos";
|
|
607
680
|
this.statusColor = "#ff6b6b";
|
|
@@ -629,7 +702,7 @@ const JaakStamps = class {
|
|
|
629
702
|
}
|
|
630
703
|
async setPreferredCamera(camera) {
|
|
631
704
|
this.preferredCamera = camera;
|
|
632
|
-
this.
|
|
705
|
+
this.logger.state('PREFERENCIA_CAMARA_CAMBIADA', { newPreference: camera });
|
|
633
706
|
// Re-detect and apply new camera preference
|
|
634
707
|
await this.enumerateAndDetectCameras();
|
|
635
708
|
// If video is active, switch to the new preferred camera
|
|
@@ -644,21 +717,42 @@ const JaakStamps = class {
|
|
|
644
717
|
}
|
|
645
718
|
async loadMobileNetModel() {
|
|
646
719
|
try {
|
|
647
|
-
this.
|
|
720
|
+
this.logger.state('CARGANDO_MODELO_MOBILENET', { path: this.MOBILENET_MODEL_PATH });
|
|
648
721
|
// Load class map
|
|
649
722
|
const classResponse = await fetch(this.MOBILENET_CLASSES_PATH);
|
|
650
723
|
if (!classResponse.ok) {
|
|
651
724
|
throw new Error(`Failed to load class map: ${this.MOBILENET_CLASSES_PATH}`);
|
|
652
725
|
}
|
|
653
726
|
this.mobileNetClassMap = await classResponse.json();
|
|
654
|
-
this.
|
|
727
|
+
this.logger.state('CLASES_MOBILENET_CARGADAS', { classCount: Object.keys(this.mobileNetClassMap).length });
|
|
655
728
|
// Load model
|
|
656
729
|
const sessionOptions = this.getSessionOptions();
|
|
657
|
-
|
|
658
|
-
|
|
730
|
+
try {
|
|
731
|
+
this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, sessionOptions);
|
|
732
|
+
}
|
|
733
|
+
catch (error) {
|
|
734
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
735
|
+
this.logger.warn('Fallo en asignación de buffer de MobileNet, intentando con configuración mínima');
|
|
736
|
+
const fallbackOptions = {
|
|
737
|
+
executionProviders: ['wasm'],
|
|
738
|
+
graphOptimizationLevel: 'disabled',
|
|
739
|
+
logSeverityLevel: 4,
|
|
740
|
+
enableCpuMemArena: false,
|
|
741
|
+
enableMemPattern: false,
|
|
742
|
+
executionMode: 'sequential',
|
|
743
|
+
interOpNumThreads: 1,
|
|
744
|
+
intraOpNumThreads: 1,
|
|
745
|
+
};
|
|
746
|
+
this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, fallbackOptions);
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
throw error;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
this.logger.state('MODELO_MOBILENET_CARGADO_EXITOSAMENTE', { sessionCreated: !!this.mobileNetSession });
|
|
659
753
|
}
|
|
660
754
|
catch (error) {
|
|
661
|
-
this.
|
|
755
|
+
this.logger.error('Error al cargar modelo MobileNet:', error);
|
|
662
756
|
throw error;
|
|
663
757
|
}
|
|
664
758
|
}
|
|
@@ -685,11 +779,11 @@ const JaakStamps = class {
|
|
|
685
779
|
}
|
|
686
780
|
async classifyDocument(canvas) {
|
|
687
781
|
if (!this.mobileNetSession || !this.mobileNetClassMap) {
|
|
688
|
-
this.
|
|
782
|
+
this.logger.warn('Modelo MobileNet no está cargado, saltando clasificación');
|
|
689
783
|
return null;
|
|
690
784
|
}
|
|
691
785
|
try {
|
|
692
|
-
this.
|
|
786
|
+
this.logger.state('CLASIFICANDO_DOCUMENTO', { timestamp: Date.now() });
|
|
693
787
|
// Preprocess image for MobileNet
|
|
694
788
|
const inputTensor = this.preprocessMobileNet(canvas);
|
|
695
789
|
// Run inference
|
|
@@ -700,10 +794,11 @@ const JaakStamps = class {
|
|
|
700
794
|
const maxIdx = output.reduce((bestIdx, val, idx, arr) => val > arr[bestIdx] ? idx : bestIdx, 0);
|
|
701
795
|
const confidence = output[maxIdx];
|
|
702
796
|
const className = this.mobileNetClassMap[maxIdx.toString()] || "unknown";
|
|
703
|
-
this.
|
|
797
|
+
this.logger.state('DOCUMENTO_CLASIFICADO', {
|
|
704
798
|
class: className,
|
|
705
799
|
confidence: confidence.toFixed(3),
|
|
706
|
-
classIndex: maxIdx
|
|
800
|
+
classIndex: maxIdx,
|
|
801
|
+
timestamp: Date.now()
|
|
707
802
|
});
|
|
708
803
|
return {
|
|
709
804
|
class: className,
|
|
@@ -712,7 +807,7 @@ const JaakStamps = class {
|
|
|
712
807
|
};
|
|
713
808
|
}
|
|
714
809
|
catch (error) {
|
|
715
|
-
this.
|
|
810
|
+
this.logger.error('Error al clasificar documento:', error);
|
|
716
811
|
return null;
|
|
717
812
|
}
|
|
718
813
|
}
|
|
@@ -754,7 +849,7 @@ const JaakStamps = class {
|
|
|
754
849
|
}
|
|
755
850
|
this.mobileNetClassMap = undefined;
|
|
756
851
|
this.isModelPreloaded = false;
|
|
757
|
-
this.
|
|
852
|
+
this.logger.state('CANVAS_POOL_LIMPIADO', { timestamp: Date.now() });
|
|
758
853
|
}
|
|
759
854
|
async getMaxResolution() {
|
|
760
855
|
try {
|
|
@@ -803,18 +898,19 @@ const JaakStamps = class {
|
|
|
803
898
|
constraints.width = { ideal: maxWidth };
|
|
804
899
|
constraints.height = { ideal: maxHeight };
|
|
805
900
|
}
|
|
806
|
-
this.
|
|
901
|
+
this.logger.state('CAPACIDADES_RESOLUCION_DETECTADAS', {
|
|
807
902
|
maxWidth: capabilities.width.max,
|
|
808
903
|
maxHeight: capabilities.height.max,
|
|
809
904
|
selectedWidth: constraints.width.ideal,
|
|
810
905
|
selectedHeight: constraints.height.ideal,
|
|
811
|
-
isTablet
|
|
906
|
+
isTablet,
|
|
907
|
+
deviceType: this.deviceType
|
|
812
908
|
});
|
|
813
909
|
}
|
|
814
910
|
return constraints;
|
|
815
911
|
}
|
|
816
912
|
catch (err) {
|
|
817
|
-
this.
|
|
913
|
+
this.logger.warn('No se pudieron obtener capacidades de cámara, usando configuración de respaldo');
|
|
818
914
|
// Optimized fallback for tablets
|
|
819
915
|
const isTablet = /iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768;
|
|
820
916
|
const fallbackConstraints = {
|
|
@@ -847,8 +943,11 @@ const JaakStamps = class {
|
|
|
847
943
|
// Determine if video should be mirrored
|
|
848
944
|
const isRear = this.isRearCamera(stream);
|
|
849
945
|
this.shouldMirrorVideo = !isRear;
|
|
850
|
-
this.
|
|
851
|
-
|
|
946
|
+
this.logger.state('CAMARA_CONFIGURADA', {
|
|
947
|
+
isRearCamera: isRear,
|
|
948
|
+
shouldMirrorVideo: this.shouldMirrorVideo,
|
|
949
|
+
videoActive: this.isVideoActive
|
|
950
|
+
});
|
|
852
951
|
return new Promise((resolve) => {
|
|
853
952
|
this.videoRef.onloadedmetadata = async () => {
|
|
854
953
|
await this.videoRef.play();
|
|
@@ -865,7 +964,7 @@ const JaakStamps = class {
|
|
|
865
964
|
}
|
|
866
965
|
}
|
|
867
966
|
catch (err) {
|
|
868
|
-
this.
|
|
967
|
+
this.logger.error('No se pudo acceder a la cámara:', err);
|
|
869
968
|
this.handleCameraPermissionError(err);
|
|
870
969
|
}
|
|
871
970
|
}
|
|
@@ -889,15 +988,39 @@ const JaakStamps = class {
|
|
|
889
988
|
const transposedData = new Float32Array(R.concat(G, B));
|
|
890
989
|
return new window.ort.Tensor("float32", transposedData, [1, 3, this.INPUT_SIZE, this.INPUT_SIZE]);
|
|
891
990
|
}
|
|
991
|
+
getDeviceMemoryInfo() {
|
|
992
|
+
const nav = navigator;
|
|
993
|
+
const memory = nav.deviceMemory || nav.hardwareConcurrency || 4;
|
|
994
|
+
const connection = nav.connection || nav.mozConnection || nav.webkitConnection;
|
|
995
|
+
const isSlowConnection = connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g');
|
|
996
|
+
return {
|
|
997
|
+
estimatedRAM: memory,
|
|
998
|
+
isLowMemory: memory <= 4,
|
|
999
|
+
isSlowConnection: isSlowConnection
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
892
1002
|
getSessionOptions() {
|
|
1003
|
+
const deviceInfo = this.getDeviceMemoryInfo();
|
|
1004
|
+
if (deviceInfo.isLowMemory) {
|
|
1005
|
+
return {
|
|
1006
|
+
executionProviders: ['wasm'],
|
|
1007
|
+
graphOptimizationLevel: 'basic',
|
|
1008
|
+
logSeverityLevel: 4,
|
|
1009
|
+
logVerbosityLevel: 0,
|
|
1010
|
+
enableCpuMemArena: false,
|
|
1011
|
+
enableMemPattern: false,
|
|
1012
|
+
executionMode: 'sequential',
|
|
1013
|
+
interOpNumThreads: 1,
|
|
1014
|
+
intraOpNumThreads: 1,
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
893
1017
|
return {
|
|
894
1018
|
executionProviders: [
|
|
895
|
-
// Try WebGL first for GPU acceleration, fallback to WASM
|
|
896
1019
|
'webgl',
|
|
897
1020
|
'wasm'
|
|
898
1021
|
],
|
|
899
|
-
graphOptimizationLevel: 'all',
|
|
900
|
-
logSeverityLevel: this.debug ? 2 : 4,
|
|
1022
|
+
graphOptimizationLevel: 'all',
|
|
1023
|
+
logSeverityLevel: this.debug ? 2 : 4,
|
|
901
1024
|
logVerbosityLevel: 0,
|
|
902
1025
|
enableCpuMemArena: true,
|
|
903
1026
|
enableMemPattern: true,
|
|
@@ -907,6 +1030,12 @@ const JaakStamps = class {
|
|
|
907
1030
|
};
|
|
908
1031
|
}
|
|
909
1032
|
async startDetection() {
|
|
1033
|
+
this.logger.state('INICIANDO_DETECCION', {
|
|
1034
|
+
sessionExists: !!this.session,
|
|
1035
|
+
modelPreloaded: this.isModelPreloaded,
|
|
1036
|
+
videoActive: this.isVideoActive,
|
|
1037
|
+
captureStep: this.captureStep
|
|
1038
|
+
});
|
|
910
1039
|
try {
|
|
911
1040
|
// Check if model is already preloaded
|
|
912
1041
|
if (!this.session) {
|
|
@@ -920,9 +1049,30 @@ const JaakStamps = class {
|
|
|
920
1049
|
this.statusColor = "#007bff";
|
|
921
1050
|
}
|
|
922
1051
|
const modelPath = this.MODEL_PATH;
|
|
923
|
-
this.
|
|
1052
|
+
this.logger.state('CARGANDO_MODELO_DETECCION', { modelPath });
|
|
924
1053
|
const sessionOptions = this.getSessionOptions();
|
|
925
|
-
|
|
1054
|
+
try {
|
|
1055
|
+
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
1056
|
+
}
|
|
1057
|
+
catch (error) {
|
|
1058
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
1059
|
+
this.logger.warn('Fallo en asignación de buffer, intentando con configuración mínima');
|
|
1060
|
+
const fallbackOptions = {
|
|
1061
|
+
executionProviders: ['wasm'],
|
|
1062
|
+
graphOptimizationLevel: 'disabled',
|
|
1063
|
+
logSeverityLevel: 4,
|
|
1064
|
+
enableCpuMemArena: false,
|
|
1065
|
+
enableMemPattern: false,
|
|
1066
|
+
executionMode: 'sequential',
|
|
1067
|
+
interOpNumThreads: 1,
|
|
1068
|
+
intraOpNumThreads: 1,
|
|
1069
|
+
};
|
|
1070
|
+
this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
throw error;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
926
1076
|
// Load MobileNet model if classification is enabled and not already loaded
|
|
927
1077
|
if (this.useDocumentClassification && !this.mobileNetSession) {
|
|
928
1078
|
if (this.debug) {
|
|
@@ -937,7 +1087,7 @@ const JaakStamps = class {
|
|
|
937
1087
|
this.emitReadyEvent();
|
|
938
1088
|
}
|
|
939
1089
|
else {
|
|
940
|
-
this.
|
|
1090
|
+
this.logger.state('USANDO_MODELOS_PRECARGADOS', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
|
|
941
1091
|
if (this.debug) {
|
|
942
1092
|
this.statusMessage = "Usando modelos precargados...";
|
|
943
1093
|
this.statusColor = "#007bff";
|
|
@@ -956,7 +1106,7 @@ const JaakStamps = class {
|
|
|
956
1106
|
this.detectFrame();
|
|
957
1107
|
}
|
|
958
1108
|
catch (err) {
|
|
959
|
-
this.
|
|
1109
|
+
this.logger.error('Error al inicializar detección:', err);
|
|
960
1110
|
this.statusMessage = "Error al inicializar el detector";
|
|
961
1111
|
this.statusColor = "#ff6b6b";
|
|
962
1112
|
this.isLoading = false;
|
|
@@ -1038,7 +1188,7 @@ const JaakStamps = class {
|
|
|
1038
1188
|
}
|
|
1039
1189
|
}
|
|
1040
1190
|
catch (e) {
|
|
1041
|
-
this.
|
|
1191
|
+
this.logger.error('Error en inferencia de modelo:', e);
|
|
1042
1192
|
// Solo continuar si no hemos completado el proceso
|
|
1043
1193
|
if (this.captureStep !== 'completed') {
|
|
1044
1194
|
// On error, wait longer before retrying
|
|
@@ -1166,7 +1316,7 @@ const JaakStamps = class {
|
|
|
1166
1316
|
if (!this.hasScreenshotTaken) {
|
|
1167
1317
|
this.lastDetectedBox = bestBox;
|
|
1168
1318
|
this.takeScreenshot().catch(error => {
|
|
1169
|
-
this.
|
|
1319
|
+
this.logger.error('Error al tomar captura de pantalla:', error);
|
|
1170
1320
|
});
|
|
1171
1321
|
this.hasScreenshotTaken = true;
|
|
1172
1322
|
// Reset para permitir segunda captura
|
|
@@ -1184,6 +1334,7 @@ const JaakStamps = class {
|
|
|
1184
1334
|
if (boxes.length === 0) {
|
|
1185
1335
|
this.statusMessage = "Posicione la identificación dentro del marco";
|
|
1186
1336
|
this.statusColor = "#ff6b6b";
|
|
1337
|
+
this.logger.debug('Sin detección de documento en el frame');
|
|
1187
1338
|
}
|
|
1188
1339
|
else {
|
|
1189
1340
|
const bestBox = boxes.reduce((best, current) => current.score > best.score ? current : best);
|
|
@@ -1193,6 +1344,11 @@ const JaakStamps = class {
|
|
|
1193
1344
|
if (allSidesAligned) {
|
|
1194
1345
|
this.statusMessage = "Identificación perfectamente alineada. Mantenga inmóvil";
|
|
1195
1346
|
this.statusColor = "#00ff00";
|
|
1347
|
+
this.logger.state('DOCUMENTO_PERFECTAMENTE_ALINEADO', {
|
|
1348
|
+
score: bestBox.score,
|
|
1349
|
+
boxDimensions: { width: bestBox.w, height: bestBox.h },
|
|
1350
|
+
alignedSides: 4
|
|
1351
|
+
});
|
|
1196
1352
|
}
|
|
1197
1353
|
else if (alignedSides > 0) {
|
|
1198
1354
|
this.statusMessage = `Alinee los lados restantes (${alignedSides}/4 lados correctos)`;
|
|
@@ -1253,6 +1409,14 @@ const JaakStamps = class {
|
|
|
1253
1409
|
async takeScreenshot() {
|
|
1254
1410
|
if (!this.videoRef || !this.lastDetectedBox)
|
|
1255
1411
|
return;
|
|
1412
|
+
this.logger.state('INICIANDO_CAPTURA', {
|
|
1413
|
+
captureStep: this.captureStep,
|
|
1414
|
+
detectedBox: this.lastDetectedBox,
|
|
1415
|
+
videoResolution: {
|
|
1416
|
+
width: this.videoRef.videoWidth,
|
|
1417
|
+
height: this.videoRef.videoHeight
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
1256
1420
|
// Activar animación
|
|
1257
1421
|
this.triggerCaptureAnimation();
|
|
1258
1422
|
// OPTIMIZATION: Reuse capture canvas for full frame
|
|
@@ -1292,7 +1456,7 @@ const JaakStamps = class {
|
|
|
1292
1456
|
await this.loadMobileNetModel();
|
|
1293
1457
|
}
|
|
1294
1458
|
catch (error) {
|
|
1295
|
-
this.
|
|
1459
|
+
this.logger.warn('Fallo al cargar modelo de clasificación, continuando sin clasificación:', error);
|
|
1296
1460
|
}
|
|
1297
1461
|
}
|
|
1298
1462
|
// Classify the cropped document if model is available
|
|
@@ -1300,7 +1464,7 @@ const JaakStamps = class {
|
|
|
1300
1464
|
const classification = await this.classifyDocument(croppedCanvas);
|
|
1301
1465
|
if (classification && classification.class === 'passport') {
|
|
1302
1466
|
// If it's a passport, skip back capture since passports don't have a back side
|
|
1303
|
-
this.
|
|
1467
|
+
this.logger.state('PASAPORTE_DETECTADO_SALTANDO_REVERSO', { classification: classification?.class });
|
|
1304
1468
|
this.completeProcess(true);
|
|
1305
1469
|
return;
|
|
1306
1470
|
}
|
|
@@ -1321,14 +1485,23 @@ const JaakStamps = class {
|
|
|
1321
1485
|
this.isDetectionPaused = false;
|
|
1322
1486
|
}, 3000);
|
|
1323
1487
|
}, 800);
|
|
1324
|
-
this.
|
|
1488
|
+
this.logger.state('CAPTURA_FRENTE_COMPLETADA', {
|
|
1489
|
+
captureStep: this.captureStep,
|
|
1490
|
+
hasFullFrame: !!this.capturedFullFrame,
|
|
1491
|
+
hasCroppedId: !!this.capturedCroppedId
|
|
1492
|
+
});
|
|
1325
1493
|
}
|
|
1326
1494
|
else if (this.captureStep === 'back') {
|
|
1327
1495
|
// Captura de la trasera usando canvas reutilizado
|
|
1328
1496
|
this.capturedBackFullFrame = this.captureCanvas.toDataURL('image/png');
|
|
1329
1497
|
this.capturedBackCroppedId = croppedCanvas.toDataURL('image/png');
|
|
1330
1498
|
this.completeProcess(false);
|
|
1331
|
-
this.
|
|
1499
|
+
this.logger.state('CAPTURA_TRASERA_COMPLETADA', {
|
|
1500
|
+
captureStep: this.captureStep,
|
|
1501
|
+
hasBackFullFrame: !!this.capturedBackFullFrame,
|
|
1502
|
+
hasBackCroppedId: !!this.capturedBackCroppedId,
|
|
1503
|
+
processCompleted: true
|
|
1504
|
+
});
|
|
1332
1505
|
}
|
|
1333
1506
|
}
|
|
1334
1507
|
triggerCaptureAnimation() {
|
|
@@ -1352,7 +1525,7 @@ const JaakStamps = class {
|
|
|
1352
1525
|
const ctx = this.canvasRef.getContext("2d");
|
|
1353
1526
|
ctx.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
|
|
1354
1527
|
}
|
|
1355
|
-
this.
|
|
1528
|
+
this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
|
|
1356
1529
|
}
|
|
1357
1530
|
resetDetection() {
|
|
1358
1531
|
this.bestScore = 0;
|
|
@@ -1391,6 +1564,13 @@ const JaakStamps = class {
|
|
|
1391
1564
|
"Proceso completado (solo frente capturado)" :
|
|
1392
1565
|
"Proceso de captura completado exitosamente";
|
|
1393
1566
|
this.statusColor = "#28a745";
|
|
1567
|
+
this.logger.state('PROCESO_COMPLETADO', {
|
|
1568
|
+
skippedBack,
|
|
1569
|
+
hasFrontImages: !!(this.capturedFullFrame && this.capturedCroppedId),
|
|
1570
|
+
hasBackImages: !!(this.capturedBackFullFrame && this.capturedBackCroppedId),
|
|
1571
|
+
totalImages: skippedBack ? 2 : 4,
|
|
1572
|
+
timestamp: new Date().toISOString()
|
|
1573
|
+
});
|
|
1394
1574
|
// Detener el detector
|
|
1395
1575
|
this.stopDetection();
|
|
1396
1576
|
// Emitir evento con las imágenes capturadas
|
|
@@ -1442,7 +1622,7 @@ const JaakStamps = class {
|
|
|
1442
1622
|
this.cleanup();
|
|
1443
1623
|
}
|
|
1444
1624
|
render() {
|
|
1445
|
-
return (h("div", { key: '
|
|
1625
|
+
return (h("div", { key: '87e2e2065012b5792b52b18349490492b5bdc80c', class: "detector-container" }, h("div", { key: '04b8bba38297d39c84ddc01f5a9bf72c65b9bef4', class: "video-container" }, h("video", { key: '905b99e1670fccb2ff5555818f91d0b0241fa29d', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: this.isVideoActive ? 'block' : 'none' } }), h("canvas", { key: '3f219b649b8d4f961b15256b8586451c2a737eb8', ref: el => this.canvasRef = el, class: this.shouldMirrorVideo ? 'mirror' : '' }), this.isMaskReady && (h("div", { key: 'f8d6742689d4446897ca48c2407cb3d3fab643e9', class: "overlay-mask" }, h("div", { key: '630a06c530f168cc0b71286adbf48fd922eb710d', class: "card-outline" }, h("div", { key: 'ce8c043ad41d5574cd0c4d737dec08b9f7fee927', class: "side side-top" }), h("div", { key: 'e90ead592f84e5df98143bc88714e70f32684204', class: "side side-right" }), h("div", { key: '31d6778c5036e42a3addb26c732149abc5a18ef7', class: "side side-bottom" }), h("div", { key: 'f85c31e77f024f9070c706b06b91d62a7fdbc357', class: "side side-left" }), h("div", { key: '27b362711bc53019483c0d36742d97e10ae9b9ce', class: "corner corner-tl" }), h("div", { key: '03b55893610684d690987c2eacf3c4e5d0c3bbe5', class: "corner corner-tr" }), h("div", { key: 'b6bf31327925c45a7fa8e1fd5ab2f25b824a03a2', class: "corner corner-bl" }), h("div", { key: '0737e0c82f8ad9703ce2546f3e594db6d50cafde', class: "corner corner-br" }), !this.showFlipAnimation && !this.showSuccessAnimation && (h("div", { key: '145f8383c496e151bd6ef4f5841292adeba083c4', class: "guide-text" }, this.statusMessage))), this.captureStep === 'back' && !this.showFlipAnimation && !this.showSuccessAnimation && (h("button", { key: 'fcdedebc31eddd21b978dd63e93c348d324b47da', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), this.isVideoActive && (h("div", { key: 'dc9157bf7bed3b6439db742055201e2c4eddec84', class: "camera-controls" }, this.isMultipleCamerasAvailable && (h("button", { key: '6b052562ccb203dbf3cc8b627f31ed2435559f80', class: "flip-camera-button", onClick: () => this.flipCamera(), type: "button", title: "Cambiar c\u00E1mara" }, "Girar c\u00E1mara")), h("button", { key: 'f9fad1757d01f0cb45f65bb2088bd1f0bc0e4e8d', class: "camera-selector-button", onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara" }, "C\u00E1maras"), this.debug && (h("div", { key: '5362fb33508c7f903b09f65fdb449b608804260d', style: {
|
|
1446
1626
|
position: 'absolute',
|
|
1447
1627
|
top: '50px',
|
|
1448
1628
|
right: '0',
|
|
@@ -1452,10 +1632,10 @@ const JaakStamps = class {
|
|
|
1452
1632
|
fontSize: '10px',
|
|
1453
1633
|
borderRadius: '4px',
|
|
1454
1634
|
whiteSpace: 'nowrap'
|
|
1455
|
-
} }, "C\u00E1maras: ", this.availableCameras.length, h("br", { key: '
|
|
1635
|
+
} }, "C\u00E1maras: ", this.availableCameras.length, h("br", { key: '5ead451a54a59c885f62740d0a0ce43ba8b674e4' }), "M\u00FAltiples: ", this.isMultipleCamerasAvailable ? 'Sí' : 'No', h("br", { key: '9a92514d07576ed7052eaa3a418c00013ef7c479' }), "Selector: ", this.showCameraSelector ? 'Visible' : 'Oculto', h("br", { key: 'd06abebad3b2e3c19aa22e511e0c4cfd4425b8b2' }), "Video: ", this.isVideoActive ? 'Activo' : 'Inactivo')))), this.showCameraSelector && this.availableCameras.length > 0 && (h("div", { key: '93a09ce3bb108175b55944a71c21e86e58de55be', class: "camera-selector-dropdown" }, h("div", { key: '7ceb4c8826945ab2a9da106a88a44cbb5490e92a', class: "camera-selector-header" }, h("span", { key: 'fa98621700584d8021ff57eca6f804b6eb792c5b' }, "Seleccionar C\u00E1mara"), h("button", { key: 'ce6477a1494f58fb5974dd7c9e62bd7d041572c5', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'eff226b006c95fafce2566947155e13ee68f9a02', class: "camera-list" }, this.availableCameras.map((camera) => (h("button", { key: camera.deviceId, class: `camera-option ${this.selectedCameraId === camera.deviceId ? 'selected' : ''}`, onClick: () => {
|
|
1456
1636
|
this.switchCamera(camera.deviceId);
|
|
1457
1637
|
this.toggleCameraSelector();
|
|
1458
|
-
}, type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${this.availableCameras.indexOf(camera) + 1}`), this.selectedCameraId === camera.deviceId && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '
|
|
1638
|
+
}, type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${this.availableCameras.indexOf(camera) + 1}`), this.selectedCameraId === camera.deviceId && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '617d33caa5d3b3e6dca56d479b27c0ac7ed19c2c', class: "device-info" }, h("small", { key: 'fba56ac1238c33864f8dba1d8bd9a5661e11d770' }, "Dispositivo: ", this.deviceType)))))), this.isCapturing && (h("div", { key: 'b46982a0b949ee9d50d0a819c59b24dceec9d7b2', class: "capture-animation" })), this.showFlipAnimation && (h("div", { key: 'c82773fffca8ec53949197a105e1e11bf0f9b294', class: "flip-animation" }, h("div", { key: 'ad52c9ec91132bf5ed94e36f621489a66b0bf680', class: "id-card-icon" }), h("div", { key: '2be407ee84beddc5ce968a9a94d9014f416cde54', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), this.showSuccessAnimation && (h("div", { key: 'f20b6be925178a123de99e535e893b7c09391dee', class: "success-animation" }, h("div", { key: 'd3ae65d40943f73bc92e9529764ded454adc5dbf', class: "check-icon" }), h("div", { key: 'f2b03082a106c69f09d384ba3b1cb4a636d3a189', class: "success-text" }, "\u00A1Proceso completado!"))), this.isLoading && (h("div", { key: '65736e303d9eb1c3f6f2dccb5cc0d27c571ac9c8', class: "loading-overlay" }, h("div", { key: '5863d855d1caea9202a9f3d0a29919985ddbb926', class: "loading-spinner" }), h("div", { key: 'aa5a16c96ac6bfa43846ba06346fad6dce39dfbb', class: "loading-text" }, this.statusMessage))), this.debug && (h("div", { key: '308c664b07d2c2427c38f766fc9eb78d27843f67', class: "status-bar" }, h("div", { key: '3884b311710d7f373a508eb492771e503e68f648', class: "status-message", style: { 'color': this.statusColor } }, this.statusMessage))), h("div", { key: '3125cfecda03d3ab9e80e0d9d5674f1cc167e2f8', class: "watermark" }, h("img", { key: '5ef43a18aea74f570db0d61f4fd86c3becf1d23e', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
1459
1639
|
}
|
|
1460
1640
|
};
|
|
1461
1641
|
JaakStamps.style = myComponentCss;
|