@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
|
@@ -68,34 +68,65 @@ export class JaakStamps {
|
|
|
68
68
|
CONFIDENCE_THRESHOLD = 0.6;
|
|
69
69
|
// ISO/IEC 7810 ID-1 standard dimensions (85.60mm x 53.98mm)
|
|
70
70
|
ID1_ASPECT_RATIO = 85.60 / 53.98; // 1.5863320574...
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
logger = {
|
|
72
|
+
info: (...args) => {
|
|
73
|
+
if (this.debug) {
|
|
74
|
+
console.log(`[JAAK-STAMPS] [INFO] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
warn: (...args) => {
|
|
78
|
+
if (this.debug) {
|
|
79
|
+
console.warn(`[JAAK-STAMPS] [WARN] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
error: (...args) => {
|
|
83
|
+
if (this.debug) {
|
|
84
|
+
console.error(`[JAAK-STAMPS] [ERROR] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
debug: (...args) => {
|
|
88
|
+
if (this.debug) {
|
|
89
|
+
console.debug(`[JAAK-STAMPS] [DEBUG] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
state: (state, data) => {
|
|
93
|
+
if (this.debug) {
|
|
94
|
+
console.log(`[JAAK-STAMPS] [STATE] [${new Date().toLocaleTimeString()}] ${state}`, data || '');
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
performance: (operation, duration) => {
|
|
98
|
+
if (this.debug) {
|
|
99
|
+
console.log(`[JAAK-STAMPS] [PERF] [${new Date().toLocaleTimeString()}] ${operation}: ${duration}ms`);
|
|
100
|
+
}
|
|
74
101
|
}
|
|
75
|
-
}
|
|
102
|
+
};
|
|
76
103
|
validateMaskSize() {
|
|
77
104
|
if (this.maskSize < 50 || this.maskSize > 100) {
|
|
78
|
-
|
|
105
|
+
this.logger.warn(`Propiedad maskSize inválida. Valor: ${this.maskSize}, esperado: 50-100. Usando valor por defecto: 90`);
|
|
79
106
|
this.maskSize = 90;
|
|
80
107
|
}
|
|
81
108
|
}
|
|
82
109
|
validateCropMargin() {
|
|
83
110
|
if (this.cropMargin < 0 || this.cropMargin > 100) {
|
|
84
|
-
|
|
111
|
+
this.logger.warn(`Propiedad cropMargin inválida. Valor: ${this.cropMargin}, esperado: 0-100. Usando valor por defecto: 0`);
|
|
85
112
|
this.cropMargin = 0;
|
|
86
113
|
}
|
|
87
114
|
}
|
|
88
115
|
validatePreferredCamera() {
|
|
89
116
|
const validOptions = ['auto', 'front', 'back'];
|
|
90
117
|
if (!validOptions.includes(this.preferredCamera)) {
|
|
91
|
-
|
|
118
|
+
this.logger.warn(`Propiedad preferredCamera inválida. Valor: ${this.preferredCamera}, esperado: ${validOptions.join(', ')}. Usando valor por defecto: 'auto'`);
|
|
92
119
|
this.preferredCamera = 'auto';
|
|
93
120
|
}
|
|
94
121
|
}
|
|
95
122
|
emitReadyEvent() {
|
|
96
123
|
const isDocumentReady = !!window.ort && this.isModelPreloaded;
|
|
97
124
|
this.isReady.emit(isDocumentReady);
|
|
98
|
-
this.
|
|
125
|
+
this.logger.state('COMPONENTE_LISTO', {
|
|
126
|
+
ortLibraryLoaded: !!window.ort,
|
|
127
|
+
modelPreloaded: this.isModelPreloaded,
|
|
128
|
+
isReady: isDocumentReady
|
|
129
|
+
});
|
|
99
130
|
}
|
|
100
131
|
isRearCamera(stream) {
|
|
101
132
|
const videoTrack = stream.getVideoTracks()[0];
|
|
@@ -118,7 +149,11 @@ export class JaakStamps {
|
|
|
118
149
|
else {
|
|
119
150
|
this.deviceType = 'desktop';
|
|
120
151
|
}
|
|
121
|
-
this.
|
|
152
|
+
this.logger.state('DISPOSITIVO_DETECTADO', {
|
|
153
|
+
deviceType: this.deviceType,
|
|
154
|
+
userAgent: navigator.userAgent,
|
|
155
|
+
screenDimensions: { width: window.innerWidth, height: window.innerHeight }
|
|
156
|
+
});
|
|
122
157
|
// Enumerate available cameras
|
|
123
158
|
await this.enumerateAndDetectCameras();
|
|
124
159
|
// Load user preference
|
|
@@ -129,7 +164,7 @@ export class JaakStamps {
|
|
|
129
164
|
// First, check if we have permission to enumerate devices
|
|
130
165
|
const permissionStatus = await this.checkCameraPermission();
|
|
131
166
|
if (permissionStatus === 'denied') {
|
|
132
|
-
this.
|
|
167
|
+
this.logger.error('Permiso de cámara denegado por el usuario');
|
|
133
168
|
this.statusMessage = "Permiso de cámara denegado";
|
|
134
169
|
this.statusColor = "#ff6b6b";
|
|
135
170
|
return;
|
|
@@ -143,7 +178,7 @@ export class JaakStamps {
|
|
|
143
178
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
144
179
|
this.availableCameras = devices.filter(device => device.kind === 'videoinput');
|
|
145
180
|
this.isMultipleCamerasAvailable = this.availableCameras.length > 1;
|
|
146
|
-
this.
|
|
181
|
+
this.logger.state('CAMARAS_DETECTADAS', {
|
|
147
182
|
count: this.availableCameras.length,
|
|
148
183
|
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
149
184
|
cameras: this.availableCameras.map(cam => ({
|
|
@@ -155,7 +190,7 @@ export class JaakStamps {
|
|
|
155
190
|
this.setInitialCameraPreference();
|
|
156
191
|
}
|
|
157
192
|
catch (error) {
|
|
158
|
-
this.
|
|
193
|
+
this.logger.error('Error al enumerar cámaras disponibles:', error);
|
|
159
194
|
this.handleCameraPermissionError(error);
|
|
160
195
|
}
|
|
161
196
|
}
|
|
@@ -168,7 +203,7 @@ export class JaakStamps {
|
|
|
168
203
|
return permission.state;
|
|
169
204
|
}
|
|
170
205
|
catch (error) {
|
|
171
|
-
this.
|
|
206
|
+
this.logger.warn('No se pudo verificar permisos de cámara:', error);
|
|
172
207
|
return 'prompt';
|
|
173
208
|
}
|
|
174
209
|
}
|
|
@@ -211,11 +246,11 @@ export class JaakStamps {
|
|
|
211
246
|
!camera.label.toLowerCase().includes('back') && !camera.label.toLowerCase().includes('rear'));
|
|
212
247
|
if (frontCamera) {
|
|
213
248
|
this.selectedCameraId = frontCamera.deviceId;
|
|
214
|
-
this.
|
|
249
|
+
this.logger.state('CAMARA_FRONTAL_SELECCIONADA', { label: frontCamera.label, deviceId: frontCamera.deviceId });
|
|
215
250
|
}
|
|
216
251
|
else {
|
|
217
252
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
218
|
-
this.
|
|
253
|
+
this.logger.warn('Cámara frontal no encontrada, usando primera disponible:', this.availableCameras[0].label);
|
|
219
254
|
}
|
|
220
255
|
}
|
|
221
256
|
else if (this.preferredCamera === 'back') {
|
|
@@ -226,11 +261,11 @@ export class JaakStamps {
|
|
|
226
261
|
camera.label.toLowerCase().includes('environment'));
|
|
227
262
|
if (backCamera) {
|
|
228
263
|
this.selectedCameraId = backCamera.deviceId;
|
|
229
|
-
this.
|
|
264
|
+
this.logger.state('CAMARA_TRASERA_SELECCIONADA', { label: backCamera.label, deviceId: backCamera.deviceId });
|
|
230
265
|
}
|
|
231
266
|
else {
|
|
232
267
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
233
|
-
this.
|
|
268
|
+
this.logger.warn('Cámara trasera no encontrada, usando primera disponible:', this.availableCameras[0].label);
|
|
234
269
|
}
|
|
235
270
|
}
|
|
236
271
|
else {
|
|
@@ -243,17 +278,17 @@ export class JaakStamps {
|
|
|
243
278
|
camera.label.toLowerCase().includes('environment'));
|
|
244
279
|
if (rearCamera) {
|
|
245
280
|
this.selectedCameraId = rearCamera.deviceId;
|
|
246
|
-
this.
|
|
281
|
+
this.logger.state('CAMARA_AUTO_SELECCIONADA_MOBILE', { type: 'rear', label: rearCamera.label, deviceId: rearCamera.deviceId });
|
|
247
282
|
}
|
|
248
283
|
else {
|
|
249
284
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
250
|
-
this.
|
|
285
|
+
this.logger.warn('Cámara trasera no encontrada en mobile, usando primera disponible:', this.availableCameras[0].label);
|
|
251
286
|
}
|
|
252
287
|
}
|
|
253
288
|
else {
|
|
254
289
|
// For desktop, use first available camera (usually the only one)
|
|
255
290
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
256
|
-
this.
|
|
291
|
+
this.logger.state('CAMARA_AUTO_SELECCIONADA_DESKTOP', { label: this.availableCameras[0].label, deviceId: this.availableCameras[0].deviceId });
|
|
257
292
|
}
|
|
258
293
|
}
|
|
259
294
|
}
|
|
@@ -267,12 +302,12 @@ export class JaakStamps {
|
|
|
267
302
|
if (isStillAvailable) {
|
|
268
303
|
this.selectedCameraId = preference.cameraId;
|
|
269
304
|
this.preferredCameraFacing = preference.facing;
|
|
270
|
-
this.
|
|
305
|
+
this.logger.state('PREFERENCIA_CAMARA_CARGADA', preference);
|
|
271
306
|
}
|
|
272
307
|
}
|
|
273
308
|
}
|
|
274
309
|
catch (error) {
|
|
275
|
-
this.
|
|
310
|
+
this.logger.warn('Error al cargar preferencia de cámara:', error);
|
|
276
311
|
}
|
|
277
312
|
}
|
|
278
313
|
saveCameraPreference() {
|
|
@@ -283,10 +318,10 @@ export class JaakStamps {
|
|
|
283
318
|
timestamp: Date.now()
|
|
284
319
|
};
|
|
285
320
|
localStorage.setItem('jaak-stamps-camera-preference', JSON.stringify(preference));
|
|
286
|
-
this.
|
|
321
|
+
this.logger.state('PREFERENCIA_CAMARA_GUARDADA', preference);
|
|
287
322
|
}
|
|
288
323
|
catch (error) {
|
|
289
|
-
this.
|
|
324
|
+
this.logger.warn('Error al guardar preferencia de cámara:', error);
|
|
290
325
|
}
|
|
291
326
|
}
|
|
292
327
|
async switchCamera(cameraId) {
|
|
@@ -296,7 +331,7 @@ export class JaakStamps {
|
|
|
296
331
|
// Check if the selected camera is still available
|
|
297
332
|
const selectedCamera = this.availableCameras.find(cam => cam.deviceId === cameraId);
|
|
298
333
|
if (!selectedCamera) {
|
|
299
|
-
this.
|
|
334
|
+
this.logger.warn('Cámara seleccionada no encontrada, re-enumerando dispositivos...');
|
|
300
335
|
await this.enumerateAndDetectCameras();
|
|
301
336
|
return;
|
|
302
337
|
}
|
|
@@ -320,10 +355,10 @@ export class JaakStamps {
|
|
|
320
355
|
this.saveCameraPreference();
|
|
321
356
|
// Setup new camera with error handling
|
|
322
357
|
await this.setupCameraWithRetry();
|
|
323
|
-
this.
|
|
358
|
+
this.logger.state('CAMARA_CAMBIADA', { label: selectedCamera.label, deviceId: selectedCamera.deviceId });
|
|
324
359
|
}
|
|
325
360
|
catch (error) {
|
|
326
|
-
this.
|
|
361
|
+
this.logger.error('Error al cambiar de cámara:', error);
|
|
327
362
|
this.handleCameraPermissionError(error);
|
|
328
363
|
}
|
|
329
364
|
}
|
|
@@ -338,7 +373,7 @@ export class JaakStamps {
|
|
|
338
373
|
return; // Success
|
|
339
374
|
}
|
|
340
375
|
catch (error) {
|
|
341
|
-
this.
|
|
376
|
+
this.logger.error(`Intento ${attempt} de configuración de cámara fallido:`, error);
|
|
342
377
|
if (attempt === maxRetries) {
|
|
343
378
|
// Last attempt failed, handle the error
|
|
344
379
|
this.statusMessage = "Error al configurar la cámara";
|
|
@@ -358,7 +393,7 @@ export class JaakStamps {
|
|
|
358
393
|
}
|
|
359
394
|
toggleCameraSelector() {
|
|
360
395
|
this.showCameraSelector = !this.showCameraSelector;
|
|
361
|
-
this.
|
|
396
|
+
this.logger.state('SELECTOR_CAMARA_TOGGLE', {
|
|
362
397
|
showCameraSelector: this.showCameraSelector,
|
|
363
398
|
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
364
399
|
availableCameras: this.availableCameras.length,
|
|
@@ -374,6 +409,13 @@ export class JaakStamps {
|
|
|
374
409
|
await this.switchCamera(nextCamera.deviceId);
|
|
375
410
|
}
|
|
376
411
|
async componentDidLoad() {
|
|
412
|
+
this.logger.state('COMPONENTE_INICIALIZANDO', {
|
|
413
|
+
debug: this.debug,
|
|
414
|
+
maskSize: this.maskSize,
|
|
415
|
+
cropMargin: this.cropMargin,
|
|
416
|
+
useDocumentClassification: this.useDocumentClassification,
|
|
417
|
+
preferredCamera: this.preferredCamera
|
|
418
|
+
});
|
|
377
419
|
if (this.debug) {
|
|
378
420
|
// Show detailed initialization loading state only in debug mode
|
|
379
421
|
this.isLoading = true;
|
|
@@ -438,7 +480,7 @@ export class JaakStamps {
|
|
|
438
480
|
this.canvasRef.height = rect.height;
|
|
439
481
|
// Update mask positioning based on container and video dimensions
|
|
440
482
|
this.updateMaskDimensions(rect);
|
|
441
|
-
this.
|
|
483
|
+
this.logger.debug('Canvas redimensionado:', { width: rect.width, height: rect.height });
|
|
442
484
|
}
|
|
443
485
|
}
|
|
444
486
|
updateMaskDimensions(containerRect) {
|
|
@@ -498,7 +540,7 @@ export class JaakStamps {
|
|
|
498
540
|
this.el.style.setProperty('--mask-center-y', `${videoCenterYPercent}%`);
|
|
499
541
|
// Mark mask as ready now that dimensions are calculated
|
|
500
542
|
this.isMaskReady = true;
|
|
501
|
-
this.
|
|
543
|
+
this.logger.state('DIMENSIONES_MASCARA_ACTUALIZADAS', {
|
|
502
544
|
video: { width: videoWidth, height: videoHeight },
|
|
503
545
|
displayed: { width: displayedVideoWidth, height: displayedVideoHeight },
|
|
504
546
|
mask: { widthPercent: maskWidthPercent, heightPercent: maskHeightPercent },
|
|
@@ -520,7 +562,7 @@ export class JaakStamps {
|
|
|
520
562
|
this.captureCtx = this.captureCanvas.getContext('2d', {
|
|
521
563
|
alpha: false
|
|
522
564
|
});
|
|
523
|
-
this.
|
|
565
|
+
this.logger.state('CANVAS_POOL_INICIALIZADO', { preprocessCanvasSize: this.INPUT_SIZE });
|
|
524
566
|
}
|
|
525
567
|
disconnectedCallback() {
|
|
526
568
|
this.cleanup();
|
|
@@ -568,7 +610,7 @@ export class JaakStamps {
|
|
|
568
610
|
}
|
|
569
611
|
async preloadModel() {
|
|
570
612
|
if (this.isModelPreloaded || this.session) {
|
|
571
|
-
this.
|
|
613
|
+
this.logger.state('MODELO_YA_PRECARGADO', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
|
|
572
614
|
return { success: true, message: 'Model already loaded' };
|
|
573
615
|
}
|
|
574
616
|
try {
|
|
@@ -576,12 +618,39 @@ export class JaakStamps {
|
|
|
576
618
|
this.statusMessage = "Precargando modelos...";
|
|
577
619
|
this.statusColor = "#007bff";
|
|
578
620
|
const modelPath = this.MODEL_PATH;
|
|
579
|
-
this.
|
|
621
|
+
this.logger.state('PRECARGANDO_MODELO_DETECCION', { modelPath });
|
|
580
622
|
// Configure ONNX Runtime with device-specific optimizations
|
|
581
623
|
const sessionOptions = this.getSessionOptions();
|
|
582
|
-
|
|
624
|
+
const deviceInfo = this.getDeviceMemoryInfo();
|
|
625
|
+
try {
|
|
626
|
+
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
627
|
+
}
|
|
628
|
+
catch (error) {
|
|
629
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
630
|
+
this.logger.warn('Fallo en asignación de buffer durante precarga, intentando con configuración mínima');
|
|
631
|
+
const fallbackOptions = {
|
|
632
|
+
executionProviders: ['wasm'],
|
|
633
|
+
graphOptimizationLevel: 'disabled',
|
|
634
|
+
logSeverityLevel: 4,
|
|
635
|
+
enableCpuMemArena: false,
|
|
636
|
+
enableMemPattern: false,
|
|
637
|
+
executionMode: 'sequential',
|
|
638
|
+
interOpNumThreads: 1,
|
|
639
|
+
intraOpNumThreads: 1,
|
|
640
|
+
};
|
|
641
|
+
this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
throw error;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
583
647
|
// Preload MobileNet model and classes only if classification is enabled
|
|
648
|
+
// For low memory devices, load sequentially to avoid memory pressure
|
|
584
649
|
if (this.useDocumentClassification) {
|
|
650
|
+
if (deviceInfo.isLowMemory) {
|
|
651
|
+
this.logger.state('CARGA_SECUENCIAL_MODELOS', { reason: 'low memory device' });
|
|
652
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
653
|
+
}
|
|
585
654
|
await this.loadMobileNetModel();
|
|
586
655
|
}
|
|
587
656
|
this.isModelPreloaded = true;
|
|
@@ -589,11 +658,15 @@ export class JaakStamps {
|
|
|
589
658
|
this.statusMessage = "Modelos precargados. Listo para comenzar detección";
|
|
590
659
|
this.statusColor = "#28a745";
|
|
591
660
|
this.emitReadyEvent();
|
|
592
|
-
this.
|
|
661
|
+
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE', {
|
|
662
|
+
detectionModel: !!this.session,
|
|
663
|
+
classificationModel: !!this.mobileNetSession,
|
|
664
|
+
useClassification: this.useDocumentClassification
|
|
665
|
+
});
|
|
593
666
|
return { success: true, message: 'Models preloaded successfully' };
|
|
594
667
|
}
|
|
595
668
|
catch (error) {
|
|
596
|
-
this.
|
|
669
|
+
this.logger.error('Error al precargar modelos:', error);
|
|
597
670
|
this.isLoading = false;
|
|
598
671
|
this.statusMessage = "Error al precargar los modelos";
|
|
599
672
|
this.statusColor = "#ff6b6b";
|
|
@@ -621,7 +694,7 @@ export class JaakStamps {
|
|
|
621
694
|
}
|
|
622
695
|
async setPreferredCamera(camera) {
|
|
623
696
|
this.preferredCamera = camera;
|
|
624
|
-
this.
|
|
697
|
+
this.logger.state('PREFERENCIA_CAMARA_CAMBIADA', { newPreference: camera });
|
|
625
698
|
// Re-detect and apply new camera preference
|
|
626
699
|
await this.enumerateAndDetectCameras();
|
|
627
700
|
// If video is active, switch to the new preferred camera
|
|
@@ -636,21 +709,42 @@ export class JaakStamps {
|
|
|
636
709
|
}
|
|
637
710
|
async loadMobileNetModel() {
|
|
638
711
|
try {
|
|
639
|
-
this.
|
|
712
|
+
this.logger.state('CARGANDO_MODELO_MOBILENET', { path: this.MOBILENET_MODEL_PATH });
|
|
640
713
|
// Load class map
|
|
641
714
|
const classResponse = await fetch(this.MOBILENET_CLASSES_PATH);
|
|
642
715
|
if (!classResponse.ok) {
|
|
643
716
|
throw new Error(`Failed to load class map: ${this.MOBILENET_CLASSES_PATH}`);
|
|
644
717
|
}
|
|
645
718
|
this.mobileNetClassMap = await classResponse.json();
|
|
646
|
-
this.
|
|
719
|
+
this.logger.state('CLASES_MOBILENET_CARGADAS', { classCount: Object.keys(this.mobileNetClassMap).length });
|
|
647
720
|
// Load model
|
|
648
721
|
const sessionOptions = this.getSessionOptions();
|
|
649
|
-
|
|
650
|
-
|
|
722
|
+
try {
|
|
723
|
+
this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, sessionOptions);
|
|
724
|
+
}
|
|
725
|
+
catch (error) {
|
|
726
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
727
|
+
this.logger.warn('Fallo en asignación de buffer de MobileNet, intentando con configuración mínima');
|
|
728
|
+
const fallbackOptions = {
|
|
729
|
+
executionProviders: ['wasm'],
|
|
730
|
+
graphOptimizationLevel: 'disabled',
|
|
731
|
+
logSeverityLevel: 4,
|
|
732
|
+
enableCpuMemArena: false,
|
|
733
|
+
enableMemPattern: false,
|
|
734
|
+
executionMode: 'sequential',
|
|
735
|
+
interOpNumThreads: 1,
|
|
736
|
+
intraOpNumThreads: 1,
|
|
737
|
+
};
|
|
738
|
+
this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, fallbackOptions);
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
throw error;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
this.logger.state('MODELO_MOBILENET_CARGADO_EXITOSAMENTE', { sessionCreated: !!this.mobileNetSession });
|
|
651
745
|
}
|
|
652
746
|
catch (error) {
|
|
653
|
-
this.
|
|
747
|
+
this.logger.error('Error al cargar modelo MobileNet:', error);
|
|
654
748
|
throw error;
|
|
655
749
|
}
|
|
656
750
|
}
|
|
@@ -677,11 +771,11 @@ export class JaakStamps {
|
|
|
677
771
|
}
|
|
678
772
|
async classifyDocument(canvas) {
|
|
679
773
|
if (!this.mobileNetSession || !this.mobileNetClassMap) {
|
|
680
|
-
this.
|
|
774
|
+
this.logger.warn('Modelo MobileNet no está cargado, saltando clasificación');
|
|
681
775
|
return null;
|
|
682
776
|
}
|
|
683
777
|
try {
|
|
684
|
-
this.
|
|
778
|
+
this.logger.state('CLASIFICANDO_DOCUMENTO', { timestamp: Date.now() });
|
|
685
779
|
// Preprocess image for MobileNet
|
|
686
780
|
const inputTensor = this.preprocessMobileNet(canvas);
|
|
687
781
|
// Run inference
|
|
@@ -692,10 +786,11 @@ export class JaakStamps {
|
|
|
692
786
|
const maxIdx = output.reduce((bestIdx, val, idx, arr) => val > arr[bestIdx] ? idx : bestIdx, 0);
|
|
693
787
|
const confidence = output[maxIdx];
|
|
694
788
|
const className = this.mobileNetClassMap[maxIdx.toString()] || "unknown";
|
|
695
|
-
this.
|
|
789
|
+
this.logger.state('DOCUMENTO_CLASIFICADO', {
|
|
696
790
|
class: className,
|
|
697
791
|
confidence: confidence.toFixed(3),
|
|
698
|
-
classIndex: maxIdx
|
|
792
|
+
classIndex: maxIdx,
|
|
793
|
+
timestamp: Date.now()
|
|
699
794
|
});
|
|
700
795
|
return {
|
|
701
796
|
class: className,
|
|
@@ -704,7 +799,7 @@ export class JaakStamps {
|
|
|
704
799
|
};
|
|
705
800
|
}
|
|
706
801
|
catch (error) {
|
|
707
|
-
this.
|
|
802
|
+
this.logger.error('Error al clasificar documento:', error);
|
|
708
803
|
return null;
|
|
709
804
|
}
|
|
710
805
|
}
|
|
@@ -746,7 +841,7 @@ export class JaakStamps {
|
|
|
746
841
|
}
|
|
747
842
|
this.mobileNetClassMap = undefined;
|
|
748
843
|
this.isModelPreloaded = false;
|
|
749
|
-
this.
|
|
844
|
+
this.logger.state('CANVAS_POOL_LIMPIADO', { timestamp: Date.now() });
|
|
750
845
|
}
|
|
751
846
|
async getMaxResolution() {
|
|
752
847
|
try {
|
|
@@ -796,18 +891,19 @@ export class JaakStamps {
|
|
|
796
891
|
constraints.width = { ideal: maxWidth };
|
|
797
892
|
constraints.height = { ideal: maxHeight };
|
|
798
893
|
}
|
|
799
|
-
this.
|
|
894
|
+
this.logger.state('CAPACIDADES_RESOLUCION_DETECTADAS', {
|
|
800
895
|
maxWidth: capabilities.width.max,
|
|
801
896
|
maxHeight: capabilities.height.max,
|
|
802
897
|
selectedWidth: constraints.width.ideal,
|
|
803
898
|
selectedHeight: constraints.height.ideal,
|
|
804
|
-
isTablet
|
|
899
|
+
isTablet,
|
|
900
|
+
deviceType: this.deviceType
|
|
805
901
|
});
|
|
806
902
|
}
|
|
807
903
|
return constraints;
|
|
808
904
|
}
|
|
809
905
|
catch (err) {
|
|
810
|
-
this.
|
|
906
|
+
this.logger.warn('No se pudieron obtener capacidades de cámara, usando configuración de respaldo');
|
|
811
907
|
// Optimized fallback for tablets
|
|
812
908
|
const isTablet = /iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768;
|
|
813
909
|
const fallbackConstraints = {
|
|
@@ -840,8 +936,11 @@ export class JaakStamps {
|
|
|
840
936
|
// Determine if video should be mirrored
|
|
841
937
|
const isRear = this.isRearCamera(stream);
|
|
842
938
|
this.shouldMirrorVideo = !isRear;
|
|
843
|
-
this.
|
|
844
|
-
|
|
939
|
+
this.logger.state('CAMARA_CONFIGURADA', {
|
|
940
|
+
isRearCamera: isRear,
|
|
941
|
+
shouldMirrorVideo: this.shouldMirrorVideo,
|
|
942
|
+
videoActive: this.isVideoActive
|
|
943
|
+
});
|
|
845
944
|
return new Promise((resolve) => {
|
|
846
945
|
this.videoRef.onloadedmetadata = async () => {
|
|
847
946
|
await this.videoRef.play();
|
|
@@ -858,7 +957,7 @@ export class JaakStamps {
|
|
|
858
957
|
}
|
|
859
958
|
}
|
|
860
959
|
catch (err) {
|
|
861
|
-
this.
|
|
960
|
+
this.logger.error('No se pudo acceder a la cámara:', err);
|
|
862
961
|
this.handleCameraPermissionError(err);
|
|
863
962
|
}
|
|
864
963
|
}
|
|
@@ -882,15 +981,39 @@ export class JaakStamps {
|
|
|
882
981
|
const transposedData = new Float32Array(R.concat(G, B));
|
|
883
982
|
return new window.ort.Tensor("float32", transposedData, [1, 3, this.INPUT_SIZE, this.INPUT_SIZE]);
|
|
884
983
|
}
|
|
984
|
+
getDeviceMemoryInfo() {
|
|
985
|
+
const nav = navigator;
|
|
986
|
+
const memory = nav.deviceMemory || nav.hardwareConcurrency || 4;
|
|
987
|
+
const connection = nav.connection || nav.mozConnection || nav.webkitConnection;
|
|
988
|
+
const isSlowConnection = connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g');
|
|
989
|
+
return {
|
|
990
|
+
estimatedRAM: memory,
|
|
991
|
+
isLowMemory: memory <= 4,
|
|
992
|
+
isSlowConnection: isSlowConnection
|
|
993
|
+
};
|
|
994
|
+
}
|
|
885
995
|
getSessionOptions() {
|
|
996
|
+
const deviceInfo = this.getDeviceMemoryInfo();
|
|
997
|
+
if (deviceInfo.isLowMemory) {
|
|
998
|
+
return {
|
|
999
|
+
executionProviders: ['wasm'],
|
|
1000
|
+
graphOptimizationLevel: 'basic',
|
|
1001
|
+
logSeverityLevel: 4,
|
|
1002
|
+
logVerbosityLevel: 0,
|
|
1003
|
+
enableCpuMemArena: false,
|
|
1004
|
+
enableMemPattern: false,
|
|
1005
|
+
executionMode: 'sequential',
|
|
1006
|
+
interOpNumThreads: 1,
|
|
1007
|
+
intraOpNumThreads: 1,
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
886
1010
|
return {
|
|
887
1011
|
executionProviders: [
|
|
888
|
-
// Try WebGL first for GPU acceleration, fallback to WASM
|
|
889
1012
|
'webgl',
|
|
890
1013
|
'wasm'
|
|
891
1014
|
],
|
|
892
|
-
graphOptimizationLevel: 'all',
|
|
893
|
-
logSeverityLevel: this.debug ? 2 : 4,
|
|
1015
|
+
graphOptimizationLevel: 'all',
|
|
1016
|
+
logSeverityLevel: this.debug ? 2 : 4,
|
|
894
1017
|
logVerbosityLevel: 0,
|
|
895
1018
|
enableCpuMemArena: true,
|
|
896
1019
|
enableMemPattern: true,
|
|
@@ -900,6 +1023,12 @@ export class JaakStamps {
|
|
|
900
1023
|
};
|
|
901
1024
|
}
|
|
902
1025
|
async startDetection() {
|
|
1026
|
+
this.logger.state('INICIANDO_DETECCION', {
|
|
1027
|
+
sessionExists: !!this.session,
|
|
1028
|
+
modelPreloaded: this.isModelPreloaded,
|
|
1029
|
+
videoActive: this.isVideoActive,
|
|
1030
|
+
captureStep: this.captureStep
|
|
1031
|
+
});
|
|
903
1032
|
try {
|
|
904
1033
|
// Check if model is already preloaded
|
|
905
1034
|
if (!this.session) {
|
|
@@ -913,9 +1042,30 @@ export class JaakStamps {
|
|
|
913
1042
|
this.statusColor = "#007bff";
|
|
914
1043
|
}
|
|
915
1044
|
const modelPath = this.MODEL_PATH;
|
|
916
|
-
this.
|
|
1045
|
+
this.logger.state('CARGANDO_MODELO_DETECCION', { modelPath });
|
|
917
1046
|
const sessionOptions = this.getSessionOptions();
|
|
918
|
-
|
|
1047
|
+
try {
|
|
1048
|
+
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
1049
|
+
}
|
|
1050
|
+
catch (error) {
|
|
1051
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
1052
|
+
this.logger.warn('Fallo en asignación de buffer, intentando con configuración mínima');
|
|
1053
|
+
const fallbackOptions = {
|
|
1054
|
+
executionProviders: ['wasm'],
|
|
1055
|
+
graphOptimizationLevel: 'disabled',
|
|
1056
|
+
logSeverityLevel: 4,
|
|
1057
|
+
enableCpuMemArena: false,
|
|
1058
|
+
enableMemPattern: false,
|
|
1059
|
+
executionMode: 'sequential',
|
|
1060
|
+
interOpNumThreads: 1,
|
|
1061
|
+
intraOpNumThreads: 1,
|
|
1062
|
+
};
|
|
1063
|
+
this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
throw error;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
919
1069
|
// Load MobileNet model if classification is enabled and not already loaded
|
|
920
1070
|
if (this.useDocumentClassification && !this.mobileNetSession) {
|
|
921
1071
|
if (this.debug) {
|
|
@@ -930,7 +1080,7 @@ export class JaakStamps {
|
|
|
930
1080
|
this.emitReadyEvent();
|
|
931
1081
|
}
|
|
932
1082
|
else {
|
|
933
|
-
this.
|
|
1083
|
+
this.logger.state('USANDO_MODELOS_PRECARGADOS', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
|
|
934
1084
|
if (this.debug) {
|
|
935
1085
|
this.statusMessage = "Usando modelos precargados...";
|
|
936
1086
|
this.statusColor = "#007bff";
|
|
@@ -949,7 +1099,7 @@ export class JaakStamps {
|
|
|
949
1099
|
this.detectFrame();
|
|
950
1100
|
}
|
|
951
1101
|
catch (err) {
|
|
952
|
-
this.
|
|
1102
|
+
this.logger.error('Error al inicializar detección:', err);
|
|
953
1103
|
this.statusMessage = "Error al inicializar el detector";
|
|
954
1104
|
this.statusColor = "#ff6b6b";
|
|
955
1105
|
this.isLoading = false;
|
|
@@ -1031,7 +1181,7 @@ export class JaakStamps {
|
|
|
1031
1181
|
}
|
|
1032
1182
|
}
|
|
1033
1183
|
catch (e) {
|
|
1034
|
-
this.
|
|
1184
|
+
this.logger.error('Error en inferencia de modelo:', e);
|
|
1035
1185
|
// Solo continuar si no hemos completado el proceso
|
|
1036
1186
|
if (this.captureStep !== 'completed') {
|
|
1037
1187
|
// On error, wait longer before retrying
|
|
@@ -1159,7 +1309,7 @@ export class JaakStamps {
|
|
|
1159
1309
|
if (!this.hasScreenshotTaken) {
|
|
1160
1310
|
this.lastDetectedBox = bestBox;
|
|
1161
1311
|
this.takeScreenshot().catch(error => {
|
|
1162
|
-
this.
|
|
1312
|
+
this.logger.error('Error al tomar captura de pantalla:', error);
|
|
1163
1313
|
});
|
|
1164
1314
|
this.hasScreenshotTaken = true;
|
|
1165
1315
|
// Reset para permitir segunda captura
|
|
@@ -1177,6 +1327,7 @@ export class JaakStamps {
|
|
|
1177
1327
|
if (boxes.length === 0) {
|
|
1178
1328
|
this.statusMessage = "Posicione la identificación dentro del marco";
|
|
1179
1329
|
this.statusColor = "#ff6b6b";
|
|
1330
|
+
this.logger.debug('Sin detección de documento en el frame');
|
|
1180
1331
|
}
|
|
1181
1332
|
else {
|
|
1182
1333
|
const bestBox = boxes.reduce((best, current) => current.score > best.score ? current : best);
|
|
@@ -1186,6 +1337,11 @@ export class JaakStamps {
|
|
|
1186
1337
|
if (allSidesAligned) {
|
|
1187
1338
|
this.statusMessage = "Identificación perfectamente alineada. Mantenga inmóvil";
|
|
1188
1339
|
this.statusColor = "#00ff00";
|
|
1340
|
+
this.logger.state('DOCUMENTO_PERFECTAMENTE_ALINEADO', {
|
|
1341
|
+
score: bestBox.score,
|
|
1342
|
+
boxDimensions: { width: bestBox.w, height: bestBox.h },
|
|
1343
|
+
alignedSides: 4
|
|
1344
|
+
});
|
|
1189
1345
|
}
|
|
1190
1346
|
else if (alignedSides > 0) {
|
|
1191
1347
|
this.statusMessage = `Alinee los lados restantes (${alignedSides}/4 lados correctos)`;
|
|
@@ -1246,6 +1402,14 @@ export class JaakStamps {
|
|
|
1246
1402
|
async takeScreenshot() {
|
|
1247
1403
|
if (!this.videoRef || !this.lastDetectedBox)
|
|
1248
1404
|
return;
|
|
1405
|
+
this.logger.state('INICIANDO_CAPTURA', {
|
|
1406
|
+
captureStep: this.captureStep,
|
|
1407
|
+
detectedBox: this.lastDetectedBox,
|
|
1408
|
+
videoResolution: {
|
|
1409
|
+
width: this.videoRef.videoWidth,
|
|
1410
|
+
height: this.videoRef.videoHeight
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1249
1413
|
// Activar animación
|
|
1250
1414
|
this.triggerCaptureAnimation();
|
|
1251
1415
|
// OPTIMIZATION: Reuse capture canvas for full frame
|
|
@@ -1285,7 +1449,7 @@ export class JaakStamps {
|
|
|
1285
1449
|
await this.loadMobileNetModel();
|
|
1286
1450
|
}
|
|
1287
1451
|
catch (error) {
|
|
1288
|
-
this.
|
|
1452
|
+
this.logger.warn('Fallo al cargar modelo de clasificación, continuando sin clasificación:', error);
|
|
1289
1453
|
}
|
|
1290
1454
|
}
|
|
1291
1455
|
// Classify the cropped document if model is available
|
|
@@ -1293,7 +1457,7 @@ export class JaakStamps {
|
|
|
1293
1457
|
const classification = await this.classifyDocument(croppedCanvas);
|
|
1294
1458
|
if (classification && classification.class === 'passport') {
|
|
1295
1459
|
// If it's a passport, skip back capture since passports don't have a back side
|
|
1296
|
-
this.
|
|
1460
|
+
this.logger.state('PASAPORTE_DETECTADO_SALTANDO_REVERSO', { classification: classification?.class });
|
|
1297
1461
|
this.completeProcess(true);
|
|
1298
1462
|
return;
|
|
1299
1463
|
}
|
|
@@ -1314,14 +1478,23 @@ export class JaakStamps {
|
|
|
1314
1478
|
this.isDetectionPaused = false;
|
|
1315
1479
|
}, 3000);
|
|
1316
1480
|
}, 800);
|
|
1317
|
-
this.
|
|
1481
|
+
this.logger.state('CAPTURA_FRENTE_COMPLETADA', {
|
|
1482
|
+
captureStep: this.captureStep,
|
|
1483
|
+
hasFullFrame: !!this.capturedFullFrame,
|
|
1484
|
+
hasCroppedId: !!this.capturedCroppedId
|
|
1485
|
+
});
|
|
1318
1486
|
}
|
|
1319
1487
|
else if (this.captureStep === 'back') {
|
|
1320
1488
|
// Captura de la trasera usando canvas reutilizado
|
|
1321
1489
|
this.capturedBackFullFrame = this.captureCanvas.toDataURL('image/png');
|
|
1322
1490
|
this.capturedBackCroppedId = croppedCanvas.toDataURL('image/png');
|
|
1323
1491
|
this.completeProcess(false);
|
|
1324
|
-
this.
|
|
1492
|
+
this.logger.state('CAPTURA_TRASERA_COMPLETADA', {
|
|
1493
|
+
captureStep: this.captureStep,
|
|
1494
|
+
hasBackFullFrame: !!this.capturedBackFullFrame,
|
|
1495
|
+
hasBackCroppedId: !!this.capturedBackCroppedId,
|
|
1496
|
+
processCompleted: true
|
|
1497
|
+
});
|
|
1325
1498
|
}
|
|
1326
1499
|
}
|
|
1327
1500
|
triggerCaptureAnimation() {
|
|
@@ -1345,7 +1518,7 @@ export class JaakStamps {
|
|
|
1345
1518
|
const ctx = this.canvasRef.getContext("2d");
|
|
1346
1519
|
ctx.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
|
|
1347
1520
|
}
|
|
1348
|
-
this.
|
|
1521
|
+
this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
|
|
1349
1522
|
}
|
|
1350
1523
|
resetDetection() {
|
|
1351
1524
|
this.bestScore = 0;
|
|
@@ -1384,6 +1557,13 @@ export class JaakStamps {
|
|
|
1384
1557
|
"Proceso completado (solo frente capturado)" :
|
|
1385
1558
|
"Proceso de captura completado exitosamente";
|
|
1386
1559
|
this.statusColor = "#28a745";
|
|
1560
|
+
this.logger.state('PROCESO_COMPLETADO', {
|
|
1561
|
+
skippedBack,
|
|
1562
|
+
hasFrontImages: !!(this.capturedFullFrame && this.capturedCroppedId),
|
|
1563
|
+
hasBackImages: !!(this.capturedBackFullFrame && this.capturedBackCroppedId),
|
|
1564
|
+
totalImages: skippedBack ? 2 : 4,
|
|
1565
|
+
timestamp: new Date().toISOString()
|
|
1566
|
+
});
|
|
1387
1567
|
// Detener el detector
|
|
1388
1568
|
this.stopDetection();
|
|
1389
1569
|
// Emitir evento con las imágenes capturadas
|
|
@@ -1435,7 +1615,7 @@ export class JaakStamps {
|
|
|
1435
1615
|
this.cleanup();
|
|
1436
1616
|
}
|
|
1437
1617
|
render() {
|
|
1438
|
-
return (h("div", { key: '
|
|
1618
|
+
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: {
|
|
1439
1619
|
position: 'absolute',
|
|
1440
1620
|
top: '50px',
|
|
1441
1621
|
right: '0',
|
|
@@ -1445,10 +1625,10 @@ export class JaakStamps {
|
|
|
1445
1625
|
fontSize: '10px',
|
|
1446
1626
|
borderRadius: '4px',
|
|
1447
1627
|
whiteSpace: 'nowrap'
|
|
1448
|
-
} }, "C\u00E1maras: ", this.availableCameras.length, h("br", { key: '
|
|
1628
|
+
} }, "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: () => {
|
|
1449
1629
|
this.switchCamera(camera.deviceId);
|
|
1450
1630
|
this.toggleCameraSelector();
|
|
1451
|
-
}, 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: '
|
|
1631
|
+
}, 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" })))));
|
|
1452
1632
|
}
|
|
1453
1633
|
static get is() { return "jaak-stamps"; }
|
|
1454
1634
|
static get encapsulation() { return "shadow"; }
|