metag-verify 0.1.0 → 0.1.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/esm2022/lib/screens/selfie/selfie.component.mjs +81 -9
- package/esm2022/lib/services/camera.mjs +120 -0
- package/esm2022/lib/version.mjs +2 -2
- package/fesm2022/metag-verify.mjs +200 -9
- package/fesm2022/metag-verify.mjs.map +1 -1
- package/lib/screens/selfie/selfie.component.d.ts +22 -0
- package/lib/services/camera.d.ts +15 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/metag-verify-0.1.0.tgz +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metag-verify.mjs","sources":["../../../projects/metag-verify/src/lib/services/crypto.ts","../../../projects/metag-verify/src/lib/services/metag-api.service.ts","../../../projects/metag-verify/src/lib/services/virtual-camera.ts","../../../projects/metag-verify/src/lib/version.ts","../../../projects/metag-verify/src/lib/theme/brand.ts","../../../projects/metag-verify/src/lib/screens/loading/loading.component.ts","../../../projects/metag-verify/src/lib/screens/dialog/dialog.component.ts","../../../projects/metag-verify/src/lib/services/screen-brightness.ts","../../../projects/metag-verify/src/lib/screens/selfie/selfie.component.ts","../../../projects/metag-verify/src/lib/screens/selfie/selfie.component.html","../../../projects/metag-verify/src/lib/screens/blocked/blocked.component.ts","../../../projects/metag-verify/src/lib/metag-verify.component.ts","../../../projects/metag-verify/src/public-api.ts","../../../projects/metag-verify/src/metag-verify.ts"],"sourcesContent":["import AES from 'crypto-js/aes';\nimport Utf8 from 'crypto-js/enc-utf8';\n\n// Mismo esquema que el SDK actual: AES de crypto-js en modo frase (formato OpenSSL \"Salted__\", base64).\n// El backend espera exactamente este formato, por eso no se cambia.\n\nexport function encrypt(data: unknown, key: string): string {\n return AES.encrypt(JSON.stringify(data), key).toString();\n}\n\nexport function decrypt<T = any>(cipherText: string, key: string): T {\n const text = AES.decrypt(cipherText, key).toString(Utf8);\n if (!text) {\n throw new Error('Lo sentimos, respuesta inválida.');\n }\n return JSON.parse(text) as T;\n}\n","import { Injectable } from '@angular/core';\nimport { decrypt, encrypt } from './crypto';\n\n// Contrato del backend de MetaG, igual al del SDK actual (metag-sdk-ionic).\n// Los nombres con errores tipográficos (enviroment, versionSDk, initProces) son del contrato y no se corrigen.\n\nconst ENV_HUB_URL = 'https://innova.genesisempresarial.com/metaGEnvHub/api/url';\nconst ENV_HUB_KEY = 'A9fB3xTzWqP8LmYd';\nconst CONNECTION_KEY = 'Zm6QqN48qDwn8XBl12MqwPV2';\nconst INIT_KEY_SUFFIX = 'initProccessNew';\nconst PHOTO_SELFIE_KEY_SUFFIX = '5';\n\n/** Mensaje para cualquier falla de red. */\nexport const NO_CONNECTION_MESSAGE = 'No pudimos cargar la página. Verifica tu internet y prueba de nuevo.';\n\nexport interface MetagEnvironment {\n env_name?: string;\n env_endpoint: string;\n show_label?: boolean;\n}\n\nexport interface MetagStep {\n id: number;\n type: number;\n order: number;\n}\n\nexport interface MetagConnectionConfig {\n typeProccess: string;\n steps: MetagStep[];\n}\n\nexport interface MetagInitProcess {\n codigo: string;\n completed: boolean;\n continuation: boolean;\n}\n\n/** Error con un mensaje apto para mostrar al usuario. */\nexport class MetagApiError extends Error {\n constructor(message: string, readonly network = false) {\n super(message);\n this.name = 'MetagApiError';\n }\n}\n\n@Injectable({ providedIn: 'root' })\nexport class MetagApiService {\n\n async getEnvironment(env: string): Promise<MetagEnvironment> {\n const res = await this.request<{ env_endpoint?: string; env_name?: string; show_label?: boolean; error?: boolean }>(ENV_HUB_URL, {\n method: 'POST',\n headers: { 'x-api-key': ENV_HUB_KEY, 'Content-Type': 'application/json', Accept: 'application/json' },\n body: JSON.stringify({ enviroment: env }),\n });\n if (res.error || !res.env_endpoint) {\n throw new MetagApiError('No se pudo obtener la configuración del ambiente.');\n }\n return { env_endpoint: res.env_endpoint, env_name: res.env_name, show_label: res.show_label };\n }\n\n async getConnectionConfig(endpoint: string, connection: string): Promise<MetagConnectionConfig> {\n const raw = await this.request<any>(`${endpoint}connection/api/getConnectionXIDSecure/${connection}`, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json', 'api-key': CONNECTION_KEY, 'connection-mg': connection },\n });\n const res = raw?.data ? this.safeDecrypt<any>(raw.data, CONNECTION_KEY) : raw;\n const config = res?.details?.config;\n if (!Array.isArray(config)) {\n throw new MetagApiError('Configuración inválida');\n }\n const steps: MetagStep[] = config\n .map((c: any) => ({ id: c.id, type: Number(c.type), order: Number(c.order) }))\n .sort((a: MetagStep, b: MetagStep) => a.order - b.order);\n return { typeProccess: res.details.typeProccess || 'lifeValidation', steps };\n }\n\n async initProcess(endpoint: string, params: { dpi: string; connection: string; apiKey: string; version: string }): Promise<MetagInitProcess> {\n const { dpi, connection, apiKey, version } = params;\n const key = connection + INIT_KEY_SUFFIX;\n const data = encrypt({ identificador: dpi + '', connection, apikey: apiKey, versionSDk: version }, key);\n const raw = await this.request<{ data?: string }>(`${endpoint}initProces/api/initProccessNewEncrypted`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'connection-mg': connection, 'api-key': apiKey, 'sdk-version': version },\n body: JSON.stringify({ data }),\n });\n const res = this.safeDecrypt<any>(raw?.data ?? '', key);\n if (res.error) {\n throw new MetagApiError(res.message || 'No se pudo iniciar el proceso.');\n }\n return { codigo: res.details, completed: !!res.completed, continuation: !!res.continuation };\n }\n\n /** Envía la foto como data URL (data:image/jpeg;base64,...), igual que el SDK actual. */\n async sendPhotoSelfie(endpoint: string, params: { codigo: string; connection: string; apiKey: string; fileBase64: string }): Promise<void> {\n const { codigo, connection, apiKey, fileBase64 } = params;\n const key = codigo + PHOTO_SELFIE_KEY_SUFFIX;\n const data = encrypt({ codigo, fileBase64 }, key);\n const raw = await this.request<{ data?: string }>(`${endpoint}selfieAuth/api/validatebase64Encrypted`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'connection-mg': connection, 'api-key': apiKey, 'x-code-mg': codigo },\n body: JSON.stringify({ data }),\n });\n const res = this.safeDecrypt<any>(raw?.data ?? '', key);\n if (res.error) {\n throw new MetagApiError(res.message || 'No se pudo realizar el proceso.');\n }\n }\n\n private async request<T>(url: string, init: RequestInit): Promise<T> {\n let response: Response;\n try {\n response = await fetch(url, init);\n } catch {\n throw new MetagApiError(NO_CONNECTION_MESSAGE, true);\n }\n const text = await response.text();\n let body: any = null;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n body = null;\n }\n if (!response.ok) {\n throw new MetagApiError(body?.message || 'No se pudo realizar el proceso.');\n }\n return body as T;\n }\n\n private safeDecrypt<T>(cipher: string, key: string): T {\n try {\n return decrypt<T>(cipher, key);\n } catch {\n throw new MetagApiError('Lo sentimos, respuesta inválida.');\n }\n }\n}\n","// Detección de cámaras virtuales, con la misma lista y regla que el SDK actual:\n// se bloquea si cualquier cámara del dispositivo tiene un nombre sospechoso.\n// Se ejecuta después de obtener el permiso de cámara, cuando los nombres ya están disponibles.\n\nconst BLOCKED_LABELS = ['obs', 'virtual', 'droidcam', 'snap camera', 'ndi', 'manycam', 'xsplit', 'camo', 'epoccam', 'v4l2loopback', 'vdo.ninja'];\n\nexport const VIRTUAL_CAMERA_REASON = 'No puedes continuar con el proceso de validación, hemos detectado actividad sospechosa.';\n\nexport async function isVirtualCamera(stream: MediaStream): Promise<boolean> {\n const labels = stream.getVideoTracks().map(t => t.label);\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n labels.push(...devices.filter(d => d.kind === 'videoinput').map(d => d.label));\n } catch {\n // Si no se pueden enumerar, se revisa solo la cámara activa.\n }\n return labels.some(label => BLOCKED_LABELS.some(word => label.toLowerCase().includes(word)));\n}\n","/** Versión que se envía en el header sdk-version (el backend no la valida). */\nexport const METAG_VERIFY_VERSION = '0.1.0';\n","// ARCHIVO GENERADO por scripts/brand.mjs (npm run brand). No editar a mano.\n// Recursos de marca incrustados para que el SDK no dependa de archivos externos.\n\n/** Logo \"MetaG\" completo (theme/meta-g.svg): \"Meta\" en Montserrat 800 + logo g. */\nexport const METAG_LOGO_DATA_URI = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjE1MjQiIGhlaWdodD0iNDUwIiB2aWV3Qm94PSIwIDAgMTUyNCA0NTAiPjxwYXRoIGQ9Ik01My43IDM2NC4wVjg3LjBIMTE4LjIwMUwyMzIuOTU4IDI3NS4zNkgxOTguOTI3TDMxMC41MTggODcuMEgzNzUuMDIwTDM3NS44MTEgMzY0LjBIMzAzLjc5MUwzMDMuMCAxOTYuNjEySDMxNS4yNjdMMjMxLjc3MSAzMzYuNjk1SDE5Ni45NDhMMTExLjA3OCAxOTYuNjEySDEyNi4xMTVWMzY0LjBaIE01NDAuMDMyIDM2Ny41NjFRNTAyLjA0NCAzNjcuNTYxIDQ3My43NTAgMzUzLjExN1E0NDUuNDU3IDMzOC42NzQgNDI5LjgyNiAzMTMuNTQ2UTQxNC4xOTUgMjg4LjQxOCA0MTQuMTk1IDI1Ni4zNjVRNDE0LjE5NSAyMjQuMzEyIDQyOS40MzAgMTk5LjE4NVE0NDQuNjY1IDE3NC4wNTcgNDcxLjU3NCAxNjAuMDA5UTQ5OC40ODIgMTQ1Ljk2MSA1MzIuMTE4IDE0NS45NjFRNTYzLjc3NSAxNDUuOTYxIDU4OS44OTIgMTU4LjgyMlE2MTYuMDEgMTcxLjY4MiA2MzEuNDQyIDE5Ni42MTJRNjQ2Ljg3NSAyMjEuNTQyIDY0Ni44NzUgMjU3LjE1N1E2NDYuODc1IDI2MS4xMTQgNjQ2LjQ4IDI2Ni4yNThRNjQ2LjA4NCAyNzEuNDAyIDY0NS42ODggMjc1Ljc1NUg0NzUuOTI3VjIzNi4xODRINjA1LjcyMUw1NzcuMjMgMjQ3LjI2NFE1NzcuNjI1IDIzMi42MjIgNTcxLjg4NyAyMjEuOTM4UTU2Ni4xNTAgMjExLjI1NCA1NTYuMDU5IDIwNS4zMThRNTQ1Ljk2OCAxOTkuMzgyIDUzMi41MTQgMTk5LjM4MlE1MTkuMDYwIDE5OS4zODIgNTA4Ljk2OSAyMDUuMzE4UTQ5OC44NzggMjExLjI1NCA0OTMuMzM4IDIyMi4xMzZRNDg3Ljc5OCAyMzMuMDE4IDQ4Ny43OTggMjQ3LjY2VjI1OS4xMzVRNDg3Ljc5OCAyNzQuOTY0IDQ5NC4zMjcgMjg2LjQ0UTUwMC44NTcgMjk3LjkxNSA1MTMuMTI0IDMwNC4wNDlRNTI1LjM5MSAzMTAuMTgyIDU0Mi40MDcgMzEwLjE4MlE1NTguMjM1IDMxMC4xODIgNTY5LjUxMyAzMDUuNjMyUTU4MC43OTEgMzAxLjA4MSA1OTEuODcxIDI5MS41ODRMNjMxLjQ0MiAzMzIuNzM4UTYxNi4wMSAzNDkuNzU0IDU5My40NTQgMzU4LjY1N1E1NzAuODk4IDM2Ny41NjEgNTQwLjAzMiAzNjcuNTYxWiBNNzc3LjQ2MSAzNjcuNTYxUTczNi4zMDcgMzY3LjU2MSA3MTMuMzU1IDM0Ny4xODJRNjkwLjQwNCAzMjYuODAyIDY5MC40MDQgMjg1LjY0OFYxMDEuNjQxSDc2NS41OVYyODQuODU3UTc2NS41OSAyOTYuMzMyIDc3MS45MjEgMzAyLjg2MlE3NzguMjUyIDMwOS4zOTEgNzg4LjE0NSAzMDkuMzkxUTgwMS42MDAgMzA5LjM5MSA4MTEuMDk3IDMwMi42NjRMODI5LjY5NSAzNTUuMjk0UTgyMC4xOTggMzYxLjYyNSA4MDYuMzQ4IDM2NC41OTNRNzkyLjQ5OCAzNjcuNTYxIDc3Ny40NjEgMzY3LjU2MVpNNjU5LjE0MiAyMDUuMzE4VjE0OS41MjJIODE0LjY1OFYyMDUuMzE4WiBNOTgyLjgzNyAzNjQuMFYzMjQuMDMyTDk3Ny42OTIgMzE0LjE0VjI0MC41MzdROTc3LjY5MiAyMjIuNzMgOTY2LjgxMCAyMTMuMDM1UTk1NS45MjggMjAzLjM0IDkzMi4xODUgMjAzLjM0UTkxNi43NTIgMjAzLjM0IDkwMC45MjQgMjA4LjI4NlE4ODUuMDk1IDIxMy4yMzIgODc0LjAxNSAyMjEuOTM4TDg0OC42OSAxNzAuODkxUTg2Ni44OTIgMTU5LjAxOSA4OTIuNDE2IDE1Mi40OTBROTE3Ljk0IDE0NS45NjEgOTQzLjI2NSAxNDUuOTYxUTk5NS41IDE0NS45NjEgMTAyNC4xODkgMTY5LjkwMlExMDUyLjg3OCAxOTMuODQyIDEwNTIuODc4IDI0NC44OVYzNjQuMFpNOTE5LjUyMiAzNjcuNTYxUTg5My44MDEgMzY3LjU2MSA4NzUuOTk0IDM1OC44NTVRODU4LjE4NyAzNTAuMTUgODQ4Ljg4NyAzMzUuMTEyUTgzOS41ODggMzIwLjA3NSA4MzkuNTg4IDMwMS40NzdRODM5LjU4OCAyODEuNjkxIDg0OS42NzkgMjY3LjI0N1E4NTkuNzcwIDI1Mi44MDQgODgwLjc0MiAyNDUuMDg3UTkwMS43MTUgMjM3LjM3MSA5MzQuOTU1IDIzNy4zNzFIOTg1LjYwN1YyNzYuNTQ3SDk0NS4yNDRROTI3LjA0MSAyNzYuNTQ3IDkxOS43MjAgMjgyLjQ4MlE5MTIuNDAwIDI4OC40MTggOTEyLjQwMCAyOTguMzExUTkxMi40MDAgMzA4LjIwNCA5MTkuOTE4IDMxNC4xNFE5MjcuNDM3IDMyMC4wNzUgOTQwLjQ5NSAzMjAuMDc1UTk1Mi43NjIgMzIwLjA3NSA5NjIuODUzIDMxMy45NDJROTcyLjk0NCAzMDcuODA4IDk3Ny42OTIgMjk1LjE0NUw5ODcuOTgxIDMyMi44NDVROTgyLjA0NSAzNDUuMDA1IDk2NC44MzIgMzU2LjI4M1E5NDcuNjE4IDM2Ny41NjEgOTE5LjUyMiAzNjcuNTYxWiIgZmlsbD0iIzA1NDVBQiIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01Ljc3LDApIj48cGF0aCBkPSJNMCAwIEMwLjYxIDAuMzIgMS4yMSAwLjY0IDEuODQgMC45OCBDMTguMTggOS43NSAzMi42MiAyMS4wMyA0Ni4yNSAzMy41NiBDNDYuODIgMzQuMDggNDcuMzggMzQuNiA0Ny45NyAzNS4xMyBDODcuMDcgNzEuNTYgMTA3LjgyIDEyNS43NiAxMDkuODYgMTc4LjM4IEMxMTAuOTMgMjE0LjU0IDEwMi4wMSAyNTAuMTggODUgMjgyIEM4NC42OCAyODIuNjEgODQuMzYgMjgzLjIxIDg0LjAyIDI4My44NCBDNzUuMjUgMzAwLjE4IDYzLjk3IDMxNC42MiA1MS40NCAzMjguMjUgQzUwLjkyIDMyOC44MiA1MC40IDMyOS4zOCA0OS44NyAzMjkuOTcgQzEzLjQ0IDM2OS4wNyAtNDAuNzYgMzg5LjgyIC05My4zOCAzOTEuODYgQy0xMjkuNTQgMzkyLjkzIC0xNjUuMTggMzg0LjAxIC0xOTcgMzY3IEMtMTk3LjYxIDM2Ni42OCAtMTk4LjIxIDM2Ni4zNiAtMTk4Ljg0IDM2Ni4wMiBDLTIxNS4xOCAzNTcuMjUgLTIyOS42MiAzNDUuOTcgLTI0My4yNSAzMzMuNDQgQy0yNDMuODIgMzMyLjkyIC0yNDQuMzggMzMyLjQgLTI0NC45NyAzMzEuODcgQy0yODQuMDcgMjk1LjQ0IC0zMDQuODIgMjQxLjI0IC0zMDYuODYgMTg4LjYyIEMtMzA3LjkzIDE1Mi40NiAtMjk5LjAxIDExNi44MiAtMjgyIDg1IEMtMjgxLjY4IDg0LjM5IC0yODEuMzYgODMuNzkgLTI4MS4wMiA4My4xNiBDLTI3Mi4yNSA2Ni44MiAtMjYwLjk3IDUyLjM4IC0yNDguNDQgMzguNzUgQy0yNDguMTggMzguNDcgLTI0OC4xOCAzOC40NyAtMjQ2Ljg3IDM3LjAzIEMtMjEwLjcxIC0xLjc4IC0xNTYuNzMgLTIyLjczIC0xMDQuNDcgLTI0Ljg2IEMtNjcuOTkgLTI1Ljk4IC0zMi4xIC0xNy4xNyAwIDAgWiAiIGZpbGw9IiNFRDAwMUIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE0MDMsNDIpIiAvPjxwYXRoIGQ9Ik0wIDAgQzIuOCAyLjY0IDUuMjUgNS40OSA3LjYzIDguNTEgQzguMDkgOC45OCA4LjU2IDkuNDQgOS4wNCA5LjkyIEM5LjM3IDkuNzUgOS4zNyA5Ljc1IDExLjA0IDguOTIgQzExLjM3IDIuOTggMTEuNyAtMi45NiAxMi4wNCAtOS4wOCBDMzcuNDUgLTkuMDggNjIuODYgLTkuMDggODkuMDQgLTkuMDggQzg5LjA4IDE0LjM3IDg5LjEyIDM3LjgyIDg5LjE0IDYxLjI4IEM4OS4xNSA3Mi4xNyA4OS4xNyA4My4wNiA4OS4xOSA5My45NSBDODkuMjEgMTAzLjQ1IDg5LjIyIDExMi45NSA4OS4yMyAxMjIuNDUgQzg5LjIzIDEyNy40NyA4OS4yNCAxMzIuNSA4OS4yNSAxMzcuNTIgQzg5LjI2IDE0Mi4yNiA4OS4yNyAxNDcgODkuMjcgMTUxLjc0IEM4OS4yNyAxNTMuNDcgODkuMjcgMTU1LjIgODkuMjggMTU2LjkzIEM4OS4zNCAxNzAuNTkgODguOTUgMTg0LjQ1IDg0Ljg1IDE5Ny42MSBDODQuNjQgMTk4LjMxIDg0LjQyIDE5OS4wMSA4NC4yIDE5OS43MyBDNzcuOTQgMjE5LjI0IDY0LjA2IDIzNS41OSA0NS45IDI0NS4xIEMxMi4wOCAyNjEuNjQgLTM1LjY2IDI2MS45OCAtNzEuMDkgMjUwLjYxIEMtOTEuODggMjQyLjk1IC0xMDcuNjcgMjMxLjMgLTExNy4xIDIxMS4wMSBDLTExOS41OSAyMDQuOTcgLTEyMS45NiAxOTcuNDggLTEyMS45NiAxOTAuOTIgQy0xMTIuMDMgMTkwLjY5IC0xMDIuMDkgMTkwLjUxIC05Mi4xNSAxOTAuNCBDLTg3LjU0IDE5MC4zNSAtODIuOTMgMTkwLjI4IC03OC4zMSAxOTAuMTYgQy03My44NiAxOTAuMDUgLTY5LjQgMTkwIC02NC45NSAxODkuOTcgQy02My4yNSAxODkuOTUgLTYxLjU1IDE4OS45MSAtNTkuODYgMTg5Ljg2IEMtNTQuNzMgMTg5LjcgLTQ5Ljk2IDE4OS42NyAtNDQuOTYgMTkwLjkyIEMtNDIuNDYgMTkzLjI5IC00MS4yOSAxOTUuMjYgLTM5Ljk5IDE5OC40MyBDLTM3Ljg1IDIwMy42MSAtMzMuMTUgMjA2LjYxIC0yOC4xNSAyMDguNzkgQy0yMS40OCAyMTAuOTYgLTE0LjM0IDIxMC44MyAtNy45IDIwOCBDMC4zMiAyMDMuNCA0LjkxIDE5Ni43MyA4LjA0IDE4Ny45MiBDOS45NyAxODAuMTggMTAuMyAxNzIuNjggMTAuMTYgMTY0LjczIEMxMC4xNiAxNjMuNjggMTAuMTUgMTYyLjY0IDEwLjE0IDE2MS41NiBDMTAuMTEgMTU5LjAxIDEwLjA4IDE1Ni40NiAxMC4wNCAxNTMuOTIgQzcuMDQgMTUzLjkyIDcuMDQgMTUzLjkyIDUuMjcgMTU1LjYxIEM0LjYgMTU2LjM3IDMuOTIgMTU3LjEzIDMuMjMgMTU3LjkyIEMtOS4wOCAxNzAuNTcgLTI2LjIzIDE3NS45MSAtNDMuNiAxNzYuMTYgQy02My45MiAxNzYuMjIgLTgyIDE3Mi4xNCAtOTcuOTYgMTU4LjkyIEMtOTguMzkgMTU4LjU4IC05OC4zOSAxNTguNTggLTEwMC41NCAxNTYuOSBDLTExOC45NSAxNDEuNjYgLTEyNi40MiAxMTcuMTkgLTEyOC43OCA5NC4yMiBDLTEzMC45MyA2Ny4yNyAtMTI2LjU1IDM4LjcxIC0xMDguOTkgMTcuMjMgQy05My42NiAtMC4yOCAtNzQuNTkgLTEwLjY1IC01MS4xNSAtMTIuOTUgQy0zMy4wNiAtMTQuMDIgLTE0LjQ3IC0xMS45MSAwIDAgWiAiIGZpbGw9IiNGRkZGRkYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMTkuOTYwOTM3NSwxMTAuMDgyMDMxMjUpIiAvPjxwYXRoIGQ9Ik0wIDAgQzguMjggNi43NyAxMi4zNCAxNC45IDEzLjcxIDI1LjQ2IEMxNC43MyA0MS4xNyAxNC41NyA1NS45MSA1LjcxIDY5LjQ2IEM1LjQyIDY5LjkxIDUuNDIgNjkuOTEgMy45NiA3Mi4yMSBDLTIuODcgNzkuMDQgLTEwLjc4IDgwLjc2IC0yMC4xIDgwLjc3IEMtMjUuOTMgODAuNjYgLTMwLjM4IDc5Ljc1IC0zNS4yOSA3Ni40NiBDLTM1Ljk4IDc1Ljk5IC0zNi42OCA3NS41MyAtMzcuMzkgNzUuMDUgQy00Ni4xMyA2OC4zNSAtNTAuMTMgNTcuNzIgLTUxLjYyIDQ3LjEgQy01MS45MiA0NC41NSAtNTIuMTIgNDIuMDIgLTUyLjI5IDM5LjQ2IEMtNTIuMzQgMzguNjggLTUyLjQgMzcuODkgLTUyLjQ1IDM3LjA5IEMtNTIuODggMjUuMTggLTQ5Ljg4IDEzLjk2IC00My4wNCA0LjI3IEMtMzEuNTEgLTcuNTIgLTEzLjc1IC05LjI3IDAgMCBaICIgZmlsbD0iI0VEMDAxQiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMxOS4yODkwNjI1LDE1Ni41NDI5Njg3NSkiIC8+PC9nPjwvc3ZnPg==';\n\n/** Logo \"g\" de Fundación Génesis (theme/g.svg, 440x440). */\nexport const G_LOGO_DATA_URI = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ0MCIgaGVpZ2h0PSI0NDAiIHZpZXdCb3g9IjEwODQgNSA0NDAgNDQwIj48cGF0aCBkPSJNMCAwIEMwLjYxIDAuMzIgMS4yMSAwLjY0IDEuODQgMC45OCBDMTguMTggOS43NSAzMi42MiAyMS4wMyA0Ni4yNSAzMy41NiBDNDYuODIgMzQuMDggNDcuMzggMzQuNiA0Ny45NyAzNS4xMyBDODcuMDcgNzEuNTYgMTA3LjgyIDEyNS43NiAxMDkuODYgMTc4LjM4IEMxMTAuOTMgMjE0LjU0IDEwMi4wMSAyNTAuMTggODUgMjgyIEM4NC42OCAyODIuNjEgODQuMzYgMjgzLjIxIDg0LjAyIDI4My44NCBDNzUuMjUgMzAwLjE4IDYzLjk3IDMxNC42MiA1MS40NCAzMjguMjUgQzUwLjkyIDMyOC44MiA1MC40IDMyOS4zOCA0OS44NyAzMjkuOTcgQzEzLjQ0IDM2OS4wNyAtNDAuNzYgMzg5LjgyIC05My4zOCAzOTEuODYgQy0xMjkuNTQgMzkyLjkzIC0xNjUuMTggMzg0LjAxIC0xOTcgMzY3IEMtMTk3LjYxIDM2Ni42OCAtMTk4LjIxIDM2Ni4zNiAtMTk4Ljg0IDM2Ni4wMiBDLTIxNS4xOCAzNTcuMjUgLTIyOS42MiAzNDUuOTcgLTI0My4yNSAzMzMuNDQgQy0yNDMuODIgMzMyLjkyIC0yNDQuMzggMzMyLjQgLTI0NC45NyAzMzEuODcgQy0yODQuMDcgMjk1LjQ0IC0zMDQuODIgMjQxLjI0IC0zMDYuODYgMTg4LjYyIEMtMzA3LjkzIDE1Mi40NiAtMjk5LjAxIDExNi44MiAtMjgyIDg1IEMtMjgxLjY4IDg0LjM5IC0yODEuMzYgODMuNzkgLTI4MS4wMiA4My4xNiBDLTI3Mi4yNSA2Ni44MiAtMjYwLjk3IDUyLjM4IC0yNDguNDQgMzguNzUgQy0yNDguMTggMzguNDcgLTI0OC4xOCAzOC40NyAtMjQ2Ljg3IDM3LjAzIEMtMjEwLjcxIC0xLjc4IC0xNTYuNzMgLTIyLjczIC0xMDQuNDcgLTI0Ljg2IEMtNjcuOTkgLTI1Ljk4IC0zMi4xIC0xNy4xNyAwIDAgWiAiIGZpbGw9IiNFRDAwMUIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE0MDMsNDIpIiAvPjxwYXRoIGQ9Ik0wIDAgQzIuOCAyLjY0IDUuMjUgNS40OSA3LjYzIDguNTEgQzguMDkgOC45OCA4LjU2IDkuNDQgOS4wNCA5LjkyIEM5LjM3IDkuNzUgOS4zNyA5Ljc1IDExLjA0IDguOTIgQzExLjM3IDIuOTggMTEuNyAtMi45NiAxMi4wNCAtOS4wOCBDMzcuNDUgLTkuMDggNjIuODYgLTkuMDggODkuMDQgLTkuMDggQzg5LjA4IDE0LjM3IDg5LjEyIDM3LjgyIDg5LjE0IDYxLjI4IEM4OS4xNSA3Mi4xNyA4OS4xNyA4My4wNiA4OS4xOSA5My45NSBDODkuMjEgMTAzLjQ1IDg5LjIyIDExMi45NSA4OS4yMyAxMjIuNDUgQzg5LjIzIDEyNy40NyA4OS4yNCAxMzIuNSA4OS4yNSAxMzcuNTIgQzg5LjI2IDE0Mi4yNiA4OS4yNyAxNDcgODkuMjcgMTUxLjc0IEM4OS4yNyAxNTMuNDcgODkuMjcgMTU1LjIgODkuMjggMTU2LjkzIEM4OS4zNCAxNzAuNTkgODguOTUgMTg0LjQ1IDg0Ljg1IDE5Ny42MSBDODQuNjQgMTk4LjMxIDg0LjQyIDE5OS4wMSA4NC4yIDE5OS43MyBDNzcuOTQgMjE5LjI0IDY0LjA2IDIzNS41OSA0NS45IDI0NS4xIEMxMi4wOCAyNjEuNjQgLTM1LjY2IDI2MS45OCAtNzEuMDkgMjUwLjYxIEMtOTEuODggMjQyLjk1IC0xMDcuNjcgMjMxLjMgLTExNy4xIDIxMS4wMSBDLTExOS41OSAyMDQuOTcgLTEyMS45NiAxOTcuNDggLTEyMS45NiAxOTAuOTIgQy0xMTIuMDMgMTkwLjY5IC0xMDIuMDkgMTkwLjUxIC05Mi4xNSAxOTAuNCBDLTg3LjU0IDE5MC4zNSAtODIuOTMgMTkwLjI4IC03OC4zMSAxOTAuMTYgQy03My44NiAxOTAuMDUgLTY5LjQgMTkwIC02NC45NSAxODkuOTcgQy02My4yNSAxODkuOTUgLTYxLjU1IDE4OS45MSAtNTkuODYgMTg5Ljg2IEMtNTQuNzMgMTg5LjcgLTQ5Ljk2IDE4OS42NyAtNDQuOTYgMTkwLjkyIEMtNDIuNDYgMTkzLjI5IC00MS4yOSAxOTUuMjYgLTM5Ljk5IDE5OC40MyBDLTM3Ljg1IDIwMy42MSAtMzMuMTUgMjA2LjYxIC0yOC4xNSAyMDguNzkgQy0yMS40OCAyMTAuOTYgLTE0LjM0IDIxMC44MyAtNy45IDIwOCBDMC4zMiAyMDMuNCA0LjkxIDE5Ni43MyA4LjA0IDE4Ny45MiBDOS45NyAxODAuMTggMTAuMyAxNzIuNjggMTAuMTYgMTY0LjczIEMxMC4xNiAxNjMuNjggMTAuMTUgMTYyLjY0IDEwLjE0IDE2MS41NiBDMTAuMTEgMTU5LjAxIDEwLjA4IDE1Ni40NiAxMC4wNCAxNTMuOTIgQzcuMDQgMTUzLjkyIDcuMDQgMTUzLjkyIDUuMjcgMTU1LjYxIEM0LjYgMTU2LjM3IDMuOTIgMTU3LjEzIDMuMjMgMTU3LjkyIEMtOS4wOCAxNzAuNTcgLTI2LjIzIDE3NS45MSAtNDMuNiAxNzYuMTYgQy02My45MiAxNzYuMjIgLTgyIDE3Mi4xNCAtOTcuOTYgMTU4LjkyIEMtOTguMzkgMTU4LjU4IC05OC4zOSAxNTguNTggLTEwMC41NCAxNTYuOSBDLTExOC45NSAxNDEuNjYgLTEyNi40MiAxMTcuMTkgLTEyOC43OCA5NC4yMiBDLTEzMC45MyA2Ny4yNyAtMTI2LjU1IDM4LjcxIC0xMDguOTkgMTcuMjMgQy05My42NiAtMC4yOCAtNzQuNTkgLTEwLjY1IC01MS4xNSAtMTIuOTUgQy0zMy4wNiAtMTQuMDIgLTE0LjQ3IC0xMS45MSAwIDAgWiAiIGZpbGw9IiNGRkZGRkYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMTkuOTYwOTM3NSwxMTAuMDgyMDMxMjUpIiAvPjxwYXRoIGQ9Ik0wIDAgQzguMjggNi43NyAxMi4zNCAxNC45IDEzLjcxIDI1LjQ2IEMxNC43MyA0MS4xNyAxNC41NyA1NS45MSA1LjcxIDY5LjQ2IEM1LjQyIDY5LjkxIDUuNDIgNjkuOTEgMy45NiA3Mi4yMSBDLTIuODcgNzkuMDQgLTEwLjc4IDgwLjc2IC0yMC4xIDgwLjc3IEMtMjUuOTMgODAuNjYgLTMwLjM4IDc5Ljc1IC0zNS4yOSA3Ni40NiBDLTM1Ljk4IDc1Ljk5IC0zNi42OCA3NS41MyAtMzcuMzkgNzUuMDUgQy00Ni4xMyA2OC4zNSAtNTAuMTMgNTcuNzIgLTUxLjYyIDQ3LjEgQy01MS45MiA0NC41NSAtNTIuMTIgNDIuMDIgLTUyLjI5IDM5LjQ2IEMtNTIuMzQgMzguNjggLTUyLjQgMzcuODkgLTUyLjQ1IDM3LjA5IEMtNTIuODggMjUuMTggLTQ5Ljg4IDEzLjk2IC00My4wNCA0LjI3IEMtMzEuNTEgLTcuNTIgLTEzLjc1IC05LjI3IDAgMCBaICIgZmlsbD0iI0VEMDAxQiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMxOS4yODkwNjI1LDE1Ni41NDI5Njg3NSkiIC8+PC9zdmc+';\n","import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { METAG_LOGO_DATA_URI } from '../../theme/brand';\n\n/**\n * Pantalla inicial mientras se consulta la configuración e inicia el proceso.\n * Muestra el logo \"MetaG\" (SVG) con una animación de entrada.\n */\n@Component({\n selector: 'mv-loading',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mv-brand\" role=\"status\" aria-live=\"polite\">\n <span class=\"mv-sr-only\">Comencemos...</span>\n <img class=\"mv-brand-logo\" [src]=\"logo\" alt=\"\" aria-hidden=\"true\" />\n </div>\n <p class=\"mv-signature\">Fundación Génesis Empresarial</p>\n `,\n styles: `\n :host {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n background: var(--mv-surface);\n }\n\n /* Firma sutil al pie de la pantalla. */\n .mv-signature {\n position: absolute;\n left: 16px;\n right: 16px;\n bottom: max(24px, env(safe-area-inset-bottom));\n margin: 0;\n font-family: var(--mv-font);\n font-size: 18px; /* mismo tamaño que el botón \"Tomar Fotografía\" */\n font-weight: 400;\n letter-spacing: 0.01em;\n color: #a1a1aa;\n text-align: center;\n animation: mv-brand-in 0.5s ease-out 0.25s both;\n }\n\n .mv-brand {\n animation: mv-brand-in 0.5s ease-out both;\n }\n\n .mv-brand-logo {\n display: block;\n height: 44px;\n width: auto;\n }\n\n .mv-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n }\n\n @keyframes mv-brand-in {\n from { opacity: 0; transform: translateY(6px); }\n to { opacity: 1; transform: none; }\n }\n\n @media (min-width: 768px) {\n .mv-brand-logo { height: 52px; }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .mv-brand, .mv-signature { animation: none; }\n }\n `,\n})\nexport class LoadingComponent {\n readonly logo = METAG_LOGO_DATA_URI;\n}\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\n\n/** Modal de mensaje (errores). Sin bordes, botón \"De acuerdo\". */\n@Component({\n selector: 'mv-dialog',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mv-dialog-backdrop\">\n <div class=\"mv-dialog\" role=\"alertdialog\" aria-modal=\"true\" aria-labelledby=\"mv-dialog-title\" aria-describedby=\"mv-dialog-message\">\n <span class=\"mv-dialog-icon\" aria-hidden=\"true\">!</span>\n <h2 id=\"mv-dialog-title\" class=\"mv-dialog-title\">{{ title }}</h2>\n <p id=\"mv-dialog-message\" class=\"mv-dialog-message\">{{ message }}</p>\n <button type=\"button\" class=\"mv-dialog-button\" (click)=\"closed.emit()\">{{ buttonLabel }}</button>\n </div>\n </div>\n `,\n styles: `\n @use '../../theme/tokens' as mv;\n\n :host {\n position: absolute;\n inset: 0;\n z-index: 20;\n }\n\n .mv-dialog-backdrop {\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 22px;\n background: rgba(9, 9, 11, 0.55);\n animation: mv-fade 0.2s ease-out both;\n }\n\n .mv-dialog {\n width: 100%;\n max-width: 380px;\n padding: 32px 24px 24px;\n border-radius: 24px;\n background: #ffffff;\n box-shadow: 0 24px 60px -12px rgba(0, 0, 0, 0.4);\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n animation: mv-pop 0.2s ease-out both;\n }\n\n .mv-dialog-icon {\n width: 56px;\n height: 56px;\n margin-bottom: 16px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fdecec;\n color: var(--mv-accent);\n font-family: var(--mv-font);\n font-size: 24px;\n font-weight: 700;\n }\n\n .mv-dialog-title {\n @include mv.title;\n margin-bottom: 8px;\n color: var(--mv-text);\n }\n\n .mv-dialog-message {\n @include mv.text;\n margin-bottom: 20px;\n color: var(--mv-muted);\n }\n\n .mv-dialog-button {\n @include mv.primary-button;\n }\n\n @keyframes mv-fade { from { opacity: 0; } to { opacity: 1; } }\n @keyframes mv-pop { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }\n\n @media (prefers-reduced-motion: reduce) {\n .mv-dialog-backdrop, .mv-dialog { animation: none; }\n }\n `,\n})\nexport class DialogComponent {\n @Input() title = '¡Lo sentimos!';\n @Input() message = 'No se pudo realizar el proceso.';\n @Input() buttonLabel = 'De acuerdo';\n @Output() closed = new EventEmitter<void>();\n}\n","// Brillo de pantalla al máximo mientras la cámara está abierta (mejora la foto con poca luz).\n// Usa el plugin nativo @capacitor-community/screen-brightness a través del objeto global de Capacitor,\n// sin importar el paquete: si la app no lo instaló, o se ejecuta en el navegador, no hace nada.\n\ninterface ScreenBrightnessPlugin {\n getBrightness(): Promise<{ brightness: number }>;\n setBrightness(options: { brightness: number }): Promise<void>;\n}\n\nconst PLUGIN_NAME = 'ScreenBrightness';\n/** En Android, -1 devuelve el brillo que el usuario tenía configurado. */\nconst SYSTEM_DEFAULT = -1;\n\nlet cachedPlugin: ScreenBrightnessPlugin | null | undefined;\n\nfunction getPlugin(): ScreenBrightnessPlugin | null {\n if (cachedPlugin !== undefined) return cachedPlugin;\n const capacitor = (globalThis as any).Capacitor;\n const available =\n capacitor?.isNativePlatform?.() &&\n (typeof capacitor.isPluginAvailable !== 'function' || capacitor.isPluginAvailable(PLUGIN_NAME));\n const plugin: ScreenBrightnessPlugin | null = available\n ? (capacitor.registerPlugin?.(PLUGIN_NAME) ?? capacitor.Plugins?.[PLUGIN_NAME] ?? null)\n : null;\n cachedPlugin = plugin;\n return plugin;\n}\n\n/** Sube el brillo al máximo y lo restaura después. Seguro de llamar varias veces. */\nexport class BrightnessBoost {\n private previous: number | null = null;\n private active = false;\n\n async raise(): Promise<void> {\n const plugin = getPlugin();\n if (!plugin || this.active) return;\n this.active = true;\n try {\n const { brightness } = await plugin.getBrightness();\n this.previous = brightness;\n await plugin.setBrightness({ brightness: 1 });\n } catch {\n this.active = false;\n }\n }\n\n async restore(): Promise<void> {\n if (!this.active) return;\n this.active = false;\n const plugin = getPlugin();\n try {\n await plugin?.setBrightness({ brightness: this.previous ?? SYSTEM_DEFAULT });\n } catch {\n // Si no se puede restaurar, el sistema lo hará al salir de la app.\n }\n }\n}\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnDestroy,\n Output,\n ViewChild,\n signal,\n} from '@angular/core';\nimport { DialogComponent } from '../dialog/dialog.component';\nimport { NO_CONNECTION_MESSAGE } from '../../services/metag-api.service';\nimport { isVirtualCamera } from '../../services/virtual-camera';\nimport { G_LOGO_DATA_URI } from '../../theme/brand';\nimport { BrightnessBoost } from '../../services/screen-brightness';\n\nconst JPEG_QUALITY = 0.75;\n/** Cuenta regresiva antes de tomar la foto: 3, 2, 1. */\nconst COUNTDOWN_FROM = 3;\n/** Tiempo que se muestra cada tip y duración de su salida. */\nconst TIP_INTERVAL_MS = 3000;\nconst TIP_LEAVE_MS = 250;\n\n/** Tips que rotan mientras la persona se prepara (orden fijo: el más importante primero). */\nconst TIPS: ReadonlyArray<{ text: string; icon: string }> = [\n { text: 'Permanece quieto', icon: 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18 M9 10h.01 M15 10h.01 M8.5 14.5c1 1.2 2.2 1.8 3.5 1.8s2.5-.6 3.5-1.8' },\n { text: 'Solo una persona', icon: 'M12 4a4 4 0 1 0 0 8a4 4 0 1 0 0-8 M4 20c1.5-3.5 4.4-5.5 8-5.5s6.5 2 8 5.5' },\n { text: 'Busca buena iluminación', icon: 'M12 8a4 4 0 1 0 0 8a4 4 0 1 0 0-8 M12 2v2 M12 20v2 M4.9 4.9l1.4 1.4 M17.7 17.7l1.4 1.4 M2 12h2 M20 12h2 M4.9 19.1l1.4-1.4 M17.7 6.3l1.4-1.4' },\n { text: 'Sin lentes ni gorra', icon: 'M7 11a3 3 0 1 0 0 6a3 3 0 1 0 0-6 M17 11a3 3 0 1 0 0 6a3 3 0 1 0 0-6 M10 14h4 M3 4l18 16' }\n];\n/** GIF transparente de 1x1 para el poster del video. */\nconst EMPTY_POSTER = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n/** Tiempo que se muestra \"Verificación completada\" antes de cerrar. */\nconst SUCCESS_HOLD_MS = 1200;\nconst CAMERA_ERROR_MESSAGE = 'No pudimos acceder a la cámara. Revisa los permisos e intenta de nuevo.';\n\ntype DialogState = { message: string; fatal: boolean } | null;\n\n/**\n * Foto Selfie, diseño A: cámara al 100% de la pantalla y botón rectangular \"Tomar Fotografía\".\n * La foto se toma al instante; mientras se valida, la barra roja inferior indica el envío.\n */\n@Component({\n selector: 'mv-selfie',\n standalone: true,\n imports: [DialogComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './selfie.component.html',\n styleUrl: './selfie.component.scss',\n})\nexport class SelfieComponent implements AfterViewInit, OnDestroy {\n /** Envía la foto (data URL JPEG). Si lanza error, se muestra el mensaje y se permite reintentar. */\n @Input({ required: true }) submit!: (fileBase64: string) => Promise<void>;\n /** La foto fue aceptada y ya se mostró la confirmación. */\n @Output() completed = new EventEmitter<void>();\n @Output() closed = new EventEmitter<void>();\n @Output() blocked = new EventEmitter<void>();\n @Output() failed = new EventEmitter<string>();\n\n @ViewChild('video', { static: true }) private videoRef!: ElementRef<HTMLVideoElement>;\n\n readonly gLogo = G_LOGO_DATA_URI;\n readonly emptyPoster = EMPTY_POSTER;\n /** La cámara ya está transmitiendo imagen. */\n readonly cameraReady = signal(false);\n readonly tips = TIPS;\n readonly tipIndex = signal(0);\n readonly tipLeaving = signal(false);\n readonly sending = signal(false);\n readonly success = signal(false);\n readonly countdown = signal<number | null>(null);\n readonly dialog = signal<DialogState>(null);\n\n private stream: MediaStream | null = null;\n private readonly brightness = new BrightnessBoost();\n private countdownTimer: ReturnType<typeof setInterval> | null = null;\n private tipTimer: ReturnType<typeof setInterval> | null = null;\n private tipLeaveTimer: ReturnType<typeof setTimeout> | null = null;\n private successTimer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n\n async ngAfterViewInit(): Promise<void> {\n this.startTips();\n await this.startCamera();\n }\n\n ngOnDestroy(): void {\n this.destroyed = true;\n this.stopTips();\n if (this.successTimer) clearTimeout(this.successTimer);\n this.stopCountdown();\n this.stopCamera();\n }\n\n takePhoto(): void {\n if (this.sending() || this.success() || this.countdown() !== null || !this.stream) return;\n this.stopTips();\n this.countdown.set(COUNTDOWN_FROM);\n this.countdownTimer = setInterval(() => {\n const next = (this.countdown() ?? 1) - 1;\n if (next > 0) {\n this.countdown.set(next);\n return;\n }\n this.stopCountdown();\n void this.captureAndSend();\n }, 1000);\n }\n\n close(): void {\n if (this.sending() || this.success()) return;\n this.stopCountdown();\n this.stopCamera();\n this.closed.emit();\n }\n\n onDialogClosed(): void {\n const state = this.dialog();\n this.dialog.set(null);\n if (state?.fatal) {\n this.failed.emit(state.message);\n return;\n }\n // Reintento: se reanuda la cámara y los tips empiezan de nuevo.\n this.startTips();\n void this.videoRef.nativeElement.play().catch(() => undefined);\n }\n\n private async startCamera(): Promise<void> {\n try {\n this.stream = await navigator.mediaDevices.getUserMedia({\n video: { width: { ideal: 1920 }, height: { ideal: 1080 }, facingMode: 'user' },\n audio: false,\n });\n } catch {\n this.dialog.set({ message: CAMERA_ERROR_MESSAGE, fatal: true });\n return;\n }\n\n if (this.destroyed) {\n this.stopCamera();\n return;\n }\n\n if (await isVirtualCamera(this.stream)) {\n this.stopCamera();\n this.blocked.emit();\n return;\n }\n\n const video = this.videoRef.nativeElement;\n video.srcObject = this.stream;\n void this.brightness.raise();\n await video.play().catch(() => undefined);\n }\n\n private async captureAndSend(): Promise<void> {\n const video = this.videoRef.nativeElement;\n const fileBase64 = this.grabFrame(video);\n video.pause();\n\n if (!fileBase64) {\n this.dialog.set({ message: 'No se pudo realizar el proceso.', fatal: false });\n return;\n }\n\n if (typeof navigator !== 'undefined' && navigator.onLine === false) {\n this.dialog.set({ message: NO_CONNECTION_MESSAGE, fatal: false });\n return;\n }\n\n this.sending.set(true);\n try {\n await this.submit(fileBase64);\n } catch (error) {\n const message = error instanceof Error && error.message ? error.message : 'No se pudo realizar el proceso.';\n this.sending.set(false);\n this.dialog.set({ message, fatal: false });\n return;\n }\n\n // Éxito en la misma pantalla: barra completa en verde, texto de confirmación y la foto congelada.\n this.sending.set(false);\n this.success.set(true);\n this.stopCamera();\n this.vibrate();\n this.successTimer = setTimeout(() => this.completed.emit(), SUCCESS_HOLD_MS);\n }\n\n /** Toma el cuadro completo del video (sin espejo) como JPEG. */\n private grabFrame(video: HTMLVideoElement): string | null {\n const width = video.videoWidth || 1920;\n const height = video.videoHeight || 1080;\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) return null;\n ctx.drawImage(video, 0, 0, width, height);\n return canvas.toDataURL('image/jpeg', JPEG_QUALITY);\n }\n\n /** Vibración corta de confirmación (Android; iOS no lo permite desde el navegador). */\n private vibrate(): void {\n try {\n navigator.vibrate?.(60);\n } catch {\n // Sin soporte: no pasa nada.\n }\n }\n\n /** Rota los tips: el actual sale y luego entra el siguiente. */\n private startTips(): void {\n this.stopTips();\n this.tipIndex.set(0);\n this.tipLeaving.set(false);\n this.tipTimer = setInterval(() => {\n this.tipLeaving.set(true);\n this.tipLeaveTimer = setTimeout(() => {\n this.tipIndex.update(i => (i + 1) % TIPS.length);\n this.tipLeaving.set(false);\n }, TIP_LEAVE_MS);\n }, TIP_INTERVAL_MS);\n }\n\n private stopTips(): void {\n if (this.tipTimer) clearInterval(this.tipTimer);\n if (this.tipLeaveTimer) clearTimeout(this.tipLeaveTimer);\n this.tipTimer = null;\n this.tipLeaveTimer = null;\n this.tipLeaving.set(false);\n }\n\n private stopCountdown(): void {\n if (this.countdownTimer) {\n clearInterval(this.countdownTimer);\n this.countdownTimer = null;\n }\n this.countdown.set(null);\n }\n\n private stopCamera(): void {\n this.stream?.getTracks().forEach(track => track.stop());\n this.stream = null;\n void this.brightness.restore();\n }\n}\n","<div class=\"mv-camera\">\n <!-- poster transparente: evita el ícono gris de \"play\" que Android WebView muestra mientras arranca la cámara -->\n <video #video class=\"mv-video\" [class.mv-video--ready]=\"cameraReady()\" [poster]=\"emptyPoster\"\n muted autoplay playsinline (playing)=\"cameraReady.set(true)\"></video>\n <div class=\"mv-scrim\" aria-hidden=\"true\"></div>\n\n <div class=\"mv-ui\">\n <header class=\"mv-head\">\n <div class=\"mv-title-group\">\n <img class=\"mv-title-logo\" [src]=\"gLogo\" alt=\"\" aria-hidden=\"true\" />\n <h2 class=\"mv-title\">Foto Selfie</h2>\n </div>\n <button type=\"button\" class=\"mv-close\" aria-label=\"Cerrar\" [disabled]=\"sending() || success()\" (click)=\"close()\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\" /></svg>\n </button>\n </header>\n\n <div class=\"mv-spacer\"></div>\n\n <footer class=\"mv-foot\">\n @if (countdown() !== null) {\n <!-- @for recrea el elemento en cada número para repetir la animación -->\n @for (n of [countdown()]; track n) {\n <p class=\"mv-hint mv-countdown\" aria-live=\"assertive\">{{ n }}</p>\n }\n } @else if (success()) {\n <p class=\"mv-hint mv-success-text\" role=\"status\" aria-live=\"polite\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M5 12.5l4.5 4.5L19 7.5\" /></svg>\n Verificación completada\n </p>\n } @else {\n @if (sending()) {\n <p class=\"mv-hint\" aria-live=\"polite\">Validando foto...</p>\n } @else {\n <!-- Tips rotativos: el recuadro se queda fijo y solo cambia el contenido -->\n <div class=\"mv-hint mv-tips\">\n <span class=\"mv-sr-only\">{{ tips[0].text }}</span>\n @for (i of [tipIndex()]; track i) {\n <span class=\"mv-tip\" [class.mv-tip--leaving]=\"tipLeaving()\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\"><path [attr.d]=\"tips[i].icon\" /></svg>\n {{ tips[i].text }}\n </span>\n }\n </div>\n }\n }\n @if (sending()) {\n <span class=\"mv-sending-bar\" aria-hidden=\"true\"></span>\n } @else if (success()) {\n <span class=\"mv-success-bar\" aria-hidden=\"true\"></span>\n }\n <!-- Oculto mientras se envía y al confirmar el éxito; vuelve a aparecer si hay error para reintentar -->\n @if (!sending() && !success()) {\n <button type=\"button\" class=\"mv-button\" [disabled]=\"!cameraReady() || countdown() !== null\" (click)=\"takePhoto()\">\n Tomar Fotografía\n </button>\n }\n </footer>\n </div>\n\n @if (dialog(); as d) {\n <mv-dialog [message]=\"d.message\" (closed)=\"onDialogClosed()\"></mv-dialog>\n }\n</div>\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\n\n/** Pantalla de bloqueo cuando se detecta una cámara virtual o no permitida. */\n@Component({\n selector: 'mv-blocked',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <section class=\"mv-step\">\n <h2 class=\"mv-title\">Bloqueo por seguridad</h2>\n <div class=\"mv-content\">\n <span class=\"mv-icon\" aria-hidden=\"true\">!</span>\n <p class=\"mv-text\">Detectamos una cámara virtual o no permitida durante la inicialización del SDK.</p>\n @if (reason) {\n <p class=\"mv-text\">{{ reason }}</p>\n }\n </div>\n <button type=\"button\" class=\"mv-button\" (click)=\"exit.emit()\">Entiendo</button>\n </section>\n `,\n styles: `\n @use '../../theme/tokens' as mv;\n\n :host {\n display: block;\n height: 100%;\n background: var(--mv-surface);\n }\n\n .mv-step {\n height: 100%;\n max-width: 420px;\n margin: 0 auto;\n padding: max(24px, env(safe-area-inset-top)) 22px max(22px, env(safe-area-inset-bottom));\n display: flex;\n flex-direction: column;\n }\n\n .mv-title {\n @include mv.title;\n color: var(--mv-accent);\n }\n\n .mv-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n text-align: center;\n }\n\n .mv-icon {\n width: 72px;\n height: 72px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fdecec;\n color: var(--mv-accent);\n font-family: var(--mv-font);\n font-size: 32px;\n font-weight: 700;\n }\n\n .mv-text {\n @include mv.text;\n max-width: 300px;\n color: var(--mv-muted);\n }\n\n .mv-button {\n @include mv.primary-button;\n flex-shrink: 0;\n }\n `,\n})\nexport class BlockedComponent {\n @Input() reason = '';\n @Output() exit = new EventEmitter<void>();\n}\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output, inject, signal } from '@angular/core';\nimport { MetagVerifyReason, MetagVerifyResult } from './models';\nimport { MetagApiError, MetagApiService } from './services/metag-api.service';\nimport { VIRTUAL_CAMERA_REASON } from './services/virtual-camera';\nimport { METAG_VERIFY_VERSION } from './version';\nimport { LoadingComponent } from './screens/loading/loading.component';\nimport { SelfieComponent } from './screens/selfie/selfie.component';\nimport { BlockedComponent } from './screens/blocked/blocked.component';\n\nconst DEFAULT_ENV = 'PROD_IT_01';\nconst PHOTO_SELFIE_STEP = 5;\n\ntype Screen = 'loading' | 'selfie' | 'blocked';\n\n/**\n * Componente de entrada de metag-verify. Versión 1: flujo Simple Auth con Foto Selfie.\n *\n * Uso:\n * <metag-verify [connection]=\"...\" [apiKey]=\"...\" [env]=\"'QA_IT_01'\" [dpi]=\"...\" (finished)=\"onResult($event)\">\n *\n * Se muestra a pantalla completa sobre la app. Cuando emite (finished), la app debe quitarlo de la vista.\n */\n@Component({\n selector: 'metag-verify',\n standalone: true,\n imports: [LoadingComponent, SelfieComponent, BlockedComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @switch (screen()) {\n @case ('loading') { <mv-loading /> }\n @case ('selfie') {\n <mv-selfie\n [submit]=\"submitSelfie\"\n (completed)=\"finish(true, 'completed')\"\n (closed)=\"finish(false, 'cancelled')\"\n (blocked)=\"screen.set('blocked')\"\n (failed)=\"finish(false, 'error', $event)\" />\n }\n @case ('blocked') {\n <mv-blocked [reason]=\"blockedReason\" (exit)=\"finish(false, 'blocked', blockedReason)\" />\n }\n }\n `,\n styleUrl: './metag-verify.component.scss',\n})\nexport class MetagVerifyComponent implements OnInit {\n /** Identificador de la conexión (connectionString). */\n @Input({ required: true }) connection!: string;\n /** API key del cliente para esa conexión. */\n @Input({ required: true }) apiKey!: string;\n /** Ambiente de MetaG, por ejemplo 'QA_IT_01'. Por defecto 'PROD_IT_01'. */\n @Input() env = DEFAULT_ENV;\n /** Número de DPI de la persona. */\n @Input() dpi = '';\n\n @Output() finished = new EventEmitter<MetagVerifyResult>();\n\n private readonly api = inject(MetagApiService);\n\n readonly screen = signal<Screen>('loading');\n readonly blockedReason = VIRTUAL_CAMERA_REASON;\n\n private endpoint = '';\n private codigo = '';\n private done = false;\n\n /** Se pasa a la pantalla de selfie; si lanza error, la selfie muestra el mensaje y permite reintentar.\n * Si sale bien, la selfie muestra la confirmación y luego emite (completed). */\n readonly submitSelfie = async (fileBase64: string): Promise<void> => {\n await this.api.sendPhotoSelfie(this.endpoint, {\n codigo: this.codigo,\n connection: this.connection,\n apiKey: this.apiKey,\n fileBase64,\n });\n };\n\n ngOnInit(): void {\n void this.start();\n }\n\n finish(success: boolean, reason: MetagVerifyReason, message?: string): void {\n if (this.done) return;\n this.done = true;\n this.finished.emit({ success, reason, ...(message ? { message } : {}) });\n }\n\n private async start(): Promise<void> {\n if (!this.connection || !this.apiKey) {\n this.finish(false, 'error', 'Faltan los datos de conexión (connection y apiKey).');\n return;\n }\n\n try {\n const environment = await this.api.getEnvironment(this.env || DEFAULT_ENV);\n this.endpoint = environment.env_endpoint;\n\n const config = await this.api.getConnectionConfig(this.endpoint, this.connection);\n const firstStep = config.steps[0];\n if (!firstStep || firstStep.type !== PHOTO_SELFIE_STEP) {\n this.finish(false, 'unsupported', 'Esta versión de metag-verify solo soporta el flujo de Foto Selfie.');\n return;\n }\n\n const process = await this.api.initProcess(this.endpoint, {\n dpi: this.dpi,\n connection: this.connection,\n apiKey: this.apiKey,\n version: METAG_VERIFY_VERSION,\n });\n this.codigo = process.codigo;\n\n // Si el proceso ya estaba completo, no hay nada que capturar.\n if (process.completed) {\n this.finish(true, 'completed');\n return;\n }\n\n this.screen.set('selfie');\n } catch (error) {\n const message = error instanceof MetagApiError ? error.message : 'No se pudo realizar el proceso.';\n this.finish(false, 'error', message);\n }\n }\n}\n","/*\n * API pública de metag-verify\n */\n\nexport * from './lib/metag-verify.component';\nexport * from './lib/models';\nexport { METAG_VERIFY_VERSION } from './lib/version';\nexport { METAG_LOGO_DATA_URI, G_LOGO_DATA_URI } from './lib/theme/brand';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"metag-verify.mjs","sources":["../../../projects/metag-verify/src/lib/services/crypto.ts","../../../projects/metag-verify/src/lib/services/metag-api.service.ts","../../../projects/metag-verify/src/lib/services/virtual-camera.ts","../../../projects/metag-verify/src/lib/version.ts","../../../projects/metag-verify/src/lib/theme/brand.ts","../../../projects/metag-verify/src/lib/screens/loading/loading.component.ts","../../../projects/metag-verify/src/lib/screens/dialog/dialog.component.ts","../../../projects/metag-verify/src/lib/services/screen-brightness.ts","../../../projects/metag-verify/src/lib/services/camera.ts","../../../projects/metag-verify/src/lib/screens/selfie/selfie.component.ts","../../../projects/metag-verify/src/lib/screens/selfie/selfie.component.html","../../../projects/metag-verify/src/lib/screens/blocked/blocked.component.ts","../../../projects/metag-verify/src/lib/metag-verify.component.ts","../../../projects/metag-verify/src/public-api.ts","../../../projects/metag-verify/src/metag-verify.ts"],"sourcesContent":["import AES from 'crypto-js/aes';\nimport Utf8 from 'crypto-js/enc-utf8';\n\n// Mismo esquema que el SDK actual: AES de crypto-js en modo frase (formato OpenSSL \"Salted__\", base64).\n// El backend espera exactamente este formato, por eso no se cambia.\n\nexport function encrypt(data: unknown, key: string): string {\n return AES.encrypt(JSON.stringify(data), key).toString();\n}\n\nexport function decrypt<T = any>(cipherText: string, key: string): T {\n const text = AES.decrypt(cipherText, key).toString(Utf8);\n if (!text) {\n throw new Error('Lo sentimos, respuesta inválida.');\n }\n return JSON.parse(text) as T;\n}\n","import { Injectable } from '@angular/core';\nimport { decrypt, encrypt } from './crypto';\n\n// Contrato del backend de MetaG, igual al del SDK actual (metag-sdk-ionic).\n// Los nombres con errores tipográficos (enviroment, versionSDk, initProces) son del contrato y no se corrigen.\n\nconst ENV_HUB_URL = 'https://innova.genesisempresarial.com/metaGEnvHub/api/url';\nconst ENV_HUB_KEY = 'A9fB3xTzWqP8LmYd';\nconst CONNECTION_KEY = 'Zm6QqN48qDwn8XBl12MqwPV2';\nconst INIT_KEY_SUFFIX = 'initProccessNew';\nconst PHOTO_SELFIE_KEY_SUFFIX = '5';\n\n/** Mensaje para cualquier falla de red. */\nexport const NO_CONNECTION_MESSAGE = 'No pudimos cargar la página. Verifica tu internet y prueba de nuevo.';\n\nexport interface MetagEnvironment {\n env_name?: string;\n env_endpoint: string;\n show_label?: boolean;\n}\n\nexport interface MetagStep {\n id: number;\n type: number;\n order: number;\n}\n\nexport interface MetagConnectionConfig {\n typeProccess: string;\n steps: MetagStep[];\n}\n\nexport interface MetagInitProcess {\n codigo: string;\n completed: boolean;\n continuation: boolean;\n}\n\n/** Error con un mensaje apto para mostrar al usuario. */\nexport class MetagApiError extends Error {\n constructor(message: string, readonly network = false) {\n super(message);\n this.name = 'MetagApiError';\n }\n}\n\n@Injectable({ providedIn: 'root' })\nexport class MetagApiService {\n\n async getEnvironment(env: string): Promise<MetagEnvironment> {\n const res = await this.request<{ env_endpoint?: string; env_name?: string; show_label?: boolean; error?: boolean }>(ENV_HUB_URL, {\n method: 'POST',\n headers: { 'x-api-key': ENV_HUB_KEY, 'Content-Type': 'application/json', Accept: 'application/json' },\n body: JSON.stringify({ enviroment: env }),\n });\n if (res.error || !res.env_endpoint) {\n throw new MetagApiError('No se pudo obtener la configuración del ambiente.');\n }\n return { env_endpoint: res.env_endpoint, env_name: res.env_name, show_label: res.show_label };\n }\n\n async getConnectionConfig(endpoint: string, connection: string): Promise<MetagConnectionConfig> {\n const raw = await this.request<any>(`${endpoint}connection/api/getConnectionXIDSecure/${connection}`, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json', 'api-key': CONNECTION_KEY, 'connection-mg': connection },\n });\n const res = raw?.data ? this.safeDecrypt<any>(raw.data, CONNECTION_KEY) : raw;\n const config = res?.details?.config;\n if (!Array.isArray(config)) {\n throw new MetagApiError('Configuración inválida');\n }\n const steps: MetagStep[] = config\n .map((c: any) => ({ id: c.id, type: Number(c.type), order: Number(c.order) }))\n .sort((a: MetagStep, b: MetagStep) => a.order - b.order);\n return { typeProccess: res.details.typeProccess || 'lifeValidation', steps };\n }\n\n async initProcess(endpoint: string, params: { dpi: string; connection: string; apiKey: string; version: string }): Promise<MetagInitProcess> {\n const { dpi, connection, apiKey, version } = params;\n const key = connection + INIT_KEY_SUFFIX;\n const data = encrypt({ identificador: dpi + '', connection, apikey: apiKey, versionSDk: version }, key);\n const raw = await this.request<{ data?: string }>(`${endpoint}initProces/api/initProccessNewEncrypted`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'connection-mg': connection, 'api-key': apiKey, 'sdk-version': version },\n body: JSON.stringify({ data }),\n });\n const res = this.safeDecrypt<any>(raw?.data ?? '', key);\n if (res.error) {\n throw new MetagApiError(res.message || 'No se pudo iniciar el proceso.');\n }\n return { codigo: res.details, completed: !!res.completed, continuation: !!res.continuation };\n }\n\n /** Envía la foto como data URL (data:image/jpeg;base64,...), igual que el SDK actual. */\n async sendPhotoSelfie(endpoint: string, params: { codigo: string; connection: string; apiKey: string; fileBase64: string }): Promise<void> {\n const { codigo, connection, apiKey, fileBase64 } = params;\n const key = codigo + PHOTO_SELFIE_KEY_SUFFIX;\n const data = encrypt({ codigo, fileBase64 }, key);\n const raw = await this.request<{ data?: string }>(`${endpoint}selfieAuth/api/validatebase64Encrypted`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'connection-mg': connection, 'api-key': apiKey, 'x-code-mg': codigo },\n body: JSON.stringify({ data }),\n });\n const res = this.safeDecrypt<any>(raw?.data ?? '', key);\n if (res.error) {\n throw new MetagApiError(res.message || 'No se pudo realizar el proceso.');\n }\n }\n\n private async request<T>(url: string, init: RequestInit): Promise<T> {\n let response: Response;\n try {\n response = await fetch(url, init);\n } catch {\n throw new MetagApiError(NO_CONNECTION_MESSAGE, true);\n }\n const text = await response.text();\n let body: any = null;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n body = null;\n }\n if (!response.ok) {\n throw new MetagApiError(body?.message || 'No se pudo realizar el proceso.');\n }\n return body as T;\n }\n\n private safeDecrypt<T>(cipher: string, key: string): T {\n try {\n return decrypt<T>(cipher, key);\n } catch {\n throw new MetagApiError('Lo sentimos, respuesta inválida.');\n }\n }\n}\n","// Detección de cámaras virtuales, con la misma lista y regla que el SDK actual:\n// se bloquea si cualquier cámara del dispositivo tiene un nombre sospechoso.\n// Se ejecuta después de obtener el permiso de cámara, cuando los nombres ya están disponibles.\n\nconst BLOCKED_LABELS = ['obs', 'virtual', 'droidcam', 'snap camera', 'ndi', 'manycam', 'xsplit', 'camo', 'epoccam', 'v4l2loopback', 'vdo.ninja'];\n\nexport const VIRTUAL_CAMERA_REASON = 'No puedes continuar con el proceso de validación, hemos detectado actividad sospechosa.';\n\nexport async function isVirtualCamera(stream: MediaStream): Promise<boolean> {\n const labels = stream.getVideoTracks().map(t => t.label);\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n labels.push(...devices.filter(d => d.kind === 'videoinput').map(d => d.label));\n } catch {\n // Si no se pueden enumerar, se revisa solo la cámara activa.\n }\n return labels.some(label => BLOCKED_LABELS.some(word => label.toLowerCase().includes(word)));\n}\n","/** Versión que se envía en el header sdk-version (el backend no la valida). */\nexport const METAG_VERIFY_VERSION = '0.1.1';\n","// ARCHIVO GENERADO por scripts/brand.mjs (npm run brand). No editar a mano.\n// Recursos de marca incrustados para que el SDK no dependa de archivos externos.\n\n/** Logo \"MetaG\" completo (theme/meta-g.svg): \"Meta\" en Montserrat 800 + logo g. */\nexport const METAG_LOGO_DATA_URI = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjE1MjQiIGhlaWdodD0iNDUwIiB2aWV3Qm94PSIwIDAgMTUyNCA0NTAiPjxwYXRoIGQ9Ik01My43IDM2NC4wVjg3LjBIMTE4LjIwMUwyMzIuOTU4IDI3NS4zNkgxOTguOTI3TDMxMC41MTggODcuMEgzNzUuMDIwTDM3NS44MTEgMzY0LjBIMzAzLjc5MUwzMDMuMCAxOTYuNjEySDMxNS4yNjdMMjMxLjc3MSAzMzYuNjk1SDE5Ni45NDhMMTExLjA3OCAxOTYuNjEySDEyNi4xMTVWMzY0LjBaIE01NDAuMDMyIDM2Ny41NjFRNTAyLjA0NCAzNjcuNTYxIDQ3My43NTAgMzUzLjExN1E0NDUuNDU3IDMzOC42NzQgNDI5LjgyNiAzMTMuNTQ2UTQxNC4xOTUgMjg4LjQxOCA0MTQuMTk1IDI1Ni4zNjVRNDE0LjE5NSAyMjQuMzEyIDQyOS40MzAgMTk5LjE4NVE0NDQuNjY1IDE3NC4wNTcgNDcxLjU3NCAxNjAuMDA5UTQ5OC40ODIgMTQ1Ljk2MSA1MzIuMTE4IDE0NS45NjFRNTYzLjc3NSAxNDUuOTYxIDU4OS44OTIgMTU4LjgyMlE2MTYuMDEgMTcxLjY4MiA2MzEuNDQyIDE5Ni42MTJRNjQ2Ljg3NSAyMjEuNTQyIDY0Ni44NzUgMjU3LjE1N1E2NDYuODc1IDI2MS4xMTQgNjQ2LjQ4IDI2Ni4yNThRNjQ2LjA4NCAyNzEuNDAyIDY0NS42ODggMjc1Ljc1NUg0NzUuOTI3VjIzNi4xODRINjA1LjcyMUw1NzcuMjMgMjQ3LjI2NFE1NzcuNjI1IDIzMi42MjIgNTcxLjg4NyAyMjEuOTM4UTU2Ni4xNTAgMjExLjI1NCA1NTYuMDU5IDIwNS4zMThRNTQ1Ljk2OCAxOTkuMzgyIDUzMi41MTQgMTk5LjM4MlE1MTkuMDYwIDE5OS4zODIgNTA4Ljk2OSAyMDUuMzE4UTQ5OC44NzggMjExLjI1NCA0OTMuMzM4IDIyMi4xMzZRNDg3Ljc5OCAyMzMuMDE4IDQ4Ny43OTggMjQ3LjY2VjI1OS4xMzVRNDg3Ljc5OCAyNzQuOTY0IDQ5NC4zMjcgMjg2LjQ0UTUwMC44NTcgMjk3LjkxNSA1MTMuMTI0IDMwNC4wNDlRNTI1LjM5MSAzMTAuMTgyIDU0Mi40MDcgMzEwLjE4MlE1NTguMjM1IDMxMC4xODIgNTY5LjUxMyAzMDUuNjMyUTU4MC43OTEgMzAxLjA4MSA1OTEuODcxIDI5MS41ODRMNjMxLjQ0MiAzMzIuNzM4UTYxNi4wMSAzNDkuNzU0IDU5My40NTQgMzU4LjY1N1E1NzAuODk4IDM2Ny41NjEgNTQwLjAzMiAzNjcuNTYxWiBNNzc3LjQ2MSAzNjcuNTYxUTczNi4zMDcgMzY3LjU2MSA3MTMuMzU1IDM0Ny4xODJRNjkwLjQwNCAzMjYuODAyIDY5MC40MDQgMjg1LjY0OFYxMDEuNjQxSDc2NS41OVYyODQuODU3UTc2NS41OSAyOTYuMzMyIDc3MS45MjEgMzAyLjg2MlE3NzguMjUyIDMwOS4zOTEgNzg4LjE0NSAzMDkuMzkxUTgwMS42MDAgMzA5LjM5MSA4MTEuMDk3IDMwMi42NjRMODI5LjY5NSAzNTUuMjk0UTgyMC4xOTggMzYxLjYyNSA4MDYuMzQ4IDM2NC41OTNRNzkyLjQ5OCAzNjcuNTYxIDc3Ny40NjEgMzY3LjU2MVpNNjU5LjE0MiAyMDUuMzE4VjE0OS41MjJIODE0LjY1OFYyMDUuMzE4WiBNOTgyLjgzNyAzNjQuMFYzMjQuMDMyTDk3Ny42OTIgMzE0LjE0VjI0MC41MzdROTc3LjY5MiAyMjIuNzMgOTY2LjgxMCAyMTMuMDM1UTk1NS45MjggMjAzLjM0IDkzMi4xODUgMjAzLjM0UTkxNi43NTIgMjAzLjM0IDkwMC45MjQgMjA4LjI4NlE4ODUuMDk1IDIxMy4yMzIgODc0LjAxNSAyMjEuOTM4TDg0OC42OSAxNzAuODkxUTg2Ni44OTIgMTU5LjAxOSA4OTIuNDE2IDE1Mi40OTBROTE3Ljk0IDE0NS45NjEgOTQzLjI2NSAxNDUuOTYxUTk5NS41IDE0NS45NjEgMTAyNC4xODkgMTY5LjkwMlExMDUyLjg3OCAxOTMuODQyIDEwNTIuODc4IDI0NC44OVYzNjQuMFpNOTE5LjUyMiAzNjcuNTYxUTg5My44MDEgMzY3LjU2MSA4NzUuOTk0IDM1OC44NTVRODU4LjE4NyAzNTAuMTUgODQ4Ljg4NyAzMzUuMTEyUTgzOS41ODggMzIwLjA3NSA4MzkuNTg4IDMwMS40NzdRODM5LjU4OCAyODEuNjkxIDg0OS42NzkgMjY3LjI0N1E4NTkuNzcwIDI1Mi44MDQgODgwLjc0MiAyNDUuMDg3UTkwMS43MTUgMjM3LjM3MSA5MzQuOTU1IDIzNy4zNzFIOTg1LjYwN1YyNzYuNTQ3SDk0NS4yNDRROTI3LjA0MSAyNzYuNTQ3IDkxOS43MjAgMjgyLjQ4MlE5MTIuNDAwIDI4OC40MTggOTEyLjQwMCAyOTguMzExUTkxMi40MDAgMzA4LjIwNCA5MTkuOTE4IDMxNC4xNFE5MjcuNDM3IDMyMC4wNzUgOTQwLjQ5NSAzMjAuMDc1UTk1Mi43NjIgMzIwLjA3NSA5NjIuODUzIDMxMy45NDJROTcyLjk0NCAzMDcuODA4IDk3Ny42OTIgMjk1LjE0NUw5ODcuOTgxIDMyMi44NDVROTgyLjA0NSAzNDUuMDA1IDk2NC44MzIgMzU2LjI4M1E5NDcuNjE4IDM2Ny41NjEgOTE5LjUyMiAzNjcuNTYxWiIgZmlsbD0iIzA1NDVBQiIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01Ljc3LDApIj48cGF0aCBkPSJNMCAwIEMwLjYxIDAuMzIgMS4yMSAwLjY0IDEuODQgMC45OCBDMTguMTggOS43NSAzMi42MiAyMS4wMyA0Ni4yNSAzMy41NiBDNDYuODIgMzQuMDggNDcuMzggMzQuNiA0Ny45NyAzNS4xMyBDODcuMDcgNzEuNTYgMTA3LjgyIDEyNS43NiAxMDkuODYgMTc4LjM4IEMxMTAuOTMgMjE0LjU0IDEwMi4wMSAyNTAuMTggODUgMjgyIEM4NC42OCAyODIuNjEgODQuMzYgMjgzLjIxIDg0LjAyIDI4My44NCBDNzUuMjUgMzAwLjE4IDYzLjk3IDMxNC42MiA1MS40NCAzMjguMjUgQzUwLjkyIDMyOC44MiA1MC40IDMyOS4zOCA0OS44NyAzMjkuOTcgQzEzLjQ0IDM2OS4wNyAtNDAuNzYgMzg5LjgyIC05My4zOCAzOTEuODYgQy0xMjkuNTQgMzkyLjkzIC0xNjUuMTggMzg0LjAxIC0xOTcgMzY3IEMtMTk3LjYxIDM2Ni42OCAtMTk4LjIxIDM2Ni4zNiAtMTk4Ljg0IDM2Ni4wMiBDLTIxNS4xOCAzNTcuMjUgLTIyOS42MiAzNDUuOTcgLTI0My4yNSAzMzMuNDQgQy0yNDMuODIgMzMyLjkyIC0yNDQuMzggMzMyLjQgLTI0NC45NyAzMzEuODcgQy0yODQuMDcgMjk1LjQ0IC0zMDQuODIgMjQxLjI0IC0zMDYuODYgMTg4LjYyIEMtMzA3LjkzIDE1Mi40NiAtMjk5LjAxIDExNi44MiAtMjgyIDg1IEMtMjgxLjY4IDg0LjM5IC0yODEuMzYgODMuNzkgLTI4MS4wMiA4My4xNiBDLTI3Mi4yNSA2Ni44MiAtMjYwLjk3IDUyLjM4IC0yNDguNDQgMzguNzUgQy0yNDguMTggMzguNDcgLTI0OC4xOCAzOC40NyAtMjQ2Ljg3IDM3LjAzIEMtMjEwLjcxIC0xLjc4IC0xNTYuNzMgLTIyLjczIC0xMDQuNDcgLTI0Ljg2IEMtNjcuOTkgLTI1Ljk4IC0zMi4xIC0xNy4xNyAwIDAgWiAiIGZpbGw9IiNFRDAwMUIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE0MDMsNDIpIiAvPjxwYXRoIGQ9Ik0wIDAgQzIuOCAyLjY0IDUuMjUgNS40OSA3LjYzIDguNTEgQzguMDkgOC45OCA4LjU2IDkuNDQgOS4wNCA5LjkyIEM5LjM3IDkuNzUgOS4zNyA5Ljc1IDExLjA0IDguOTIgQzExLjM3IDIuOTggMTEuNyAtMi45NiAxMi4wNCAtOS4wOCBDMzcuNDUgLTkuMDggNjIuODYgLTkuMDggODkuMDQgLTkuMDggQzg5LjA4IDE0LjM3IDg5LjEyIDM3LjgyIDg5LjE0IDYxLjI4IEM4OS4xNSA3Mi4xNyA4OS4xNyA4My4wNiA4OS4xOSA5My45NSBDODkuMjEgMTAzLjQ1IDg5LjIyIDExMi45NSA4OS4yMyAxMjIuNDUgQzg5LjIzIDEyNy40NyA4OS4yNCAxMzIuNSA4OS4yNSAxMzcuNTIgQzg5LjI2IDE0Mi4yNiA4OS4yNyAxNDcgODkuMjcgMTUxLjc0IEM4OS4yNyAxNTMuNDcgODkuMjcgMTU1LjIgODkuMjggMTU2LjkzIEM4OS4zNCAxNzAuNTkgODguOTUgMTg0LjQ1IDg0Ljg1IDE5Ny42MSBDODQuNjQgMTk4LjMxIDg0LjQyIDE5OS4wMSA4NC4yIDE5OS43MyBDNzcuOTQgMjE5LjI0IDY0LjA2IDIzNS41OSA0NS45IDI0NS4xIEMxMi4wOCAyNjEuNjQgLTM1LjY2IDI2MS45OCAtNzEuMDkgMjUwLjYxIEMtOTEuODggMjQyLjk1IC0xMDcuNjcgMjMxLjMgLTExNy4xIDIxMS4wMSBDLTExOS41OSAyMDQuOTcgLTEyMS45NiAxOTcuNDggLTEyMS45NiAxOTAuOTIgQy0xMTIuMDMgMTkwLjY5IC0xMDIuMDkgMTkwLjUxIC05Mi4xNSAxOTAuNCBDLTg3LjU0IDE5MC4zNSAtODIuOTMgMTkwLjI4IC03OC4zMSAxOTAuMTYgQy03My44NiAxOTAuMDUgLTY5LjQgMTkwIC02NC45NSAxODkuOTcgQy02My4yNSAxODkuOTUgLTYxLjU1IDE4OS45MSAtNTkuODYgMTg5Ljg2IEMtNTQuNzMgMTg5LjcgLTQ5Ljk2IDE4OS42NyAtNDQuOTYgMTkwLjkyIEMtNDIuNDYgMTkzLjI5IC00MS4yOSAxOTUuMjYgLTM5Ljk5IDE5OC40MyBDLTM3Ljg1IDIwMy42MSAtMzMuMTUgMjA2LjYxIC0yOC4xNSAyMDguNzkgQy0yMS40OCAyMTAuOTYgLTE0LjM0IDIxMC44MyAtNy45IDIwOCBDMC4zMiAyMDMuNCA0LjkxIDE5Ni43MyA4LjA0IDE4Ny45MiBDOS45NyAxODAuMTggMTAuMyAxNzIuNjggMTAuMTYgMTY0LjczIEMxMC4xNiAxNjMuNjggMTAuMTUgMTYyLjY0IDEwLjE0IDE2MS41NiBDMTAuMTEgMTU5LjAxIDEwLjA4IDE1Ni40NiAxMC4wNCAxNTMuOTIgQzcuMDQgMTUzLjkyIDcuMDQgMTUzLjkyIDUuMjcgMTU1LjYxIEM0LjYgMTU2LjM3IDMuOTIgMTU3LjEzIDMuMjMgMTU3LjkyIEMtOS4wOCAxNzAuNTcgLTI2LjIzIDE3NS45MSAtNDMuNiAxNzYuMTYgQy02My45MiAxNzYuMjIgLTgyIDE3Mi4xNCAtOTcuOTYgMTU4LjkyIEMtOTguMzkgMTU4LjU4IC05OC4zOSAxNTguNTggLTEwMC41NCAxNTYuOSBDLTExOC45NSAxNDEuNjYgLTEyNi40MiAxMTcuMTkgLTEyOC43OCA5NC4yMiBDLTEzMC45MyA2Ny4yNyAtMTI2LjU1IDM4LjcxIC0xMDguOTkgMTcuMjMgQy05My42NiAtMC4yOCAtNzQuNTkgLTEwLjY1IC01MS4xNSAtMTIuOTUgQy0zMy4wNiAtMTQuMDIgLTE0LjQ3IC0xMS45MSAwIDAgWiAiIGZpbGw9IiNGRkZGRkYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMTkuOTYwOTM3NSwxMTAuMDgyMDMxMjUpIiAvPjxwYXRoIGQ9Ik0wIDAgQzguMjggNi43NyAxMi4zNCAxNC45IDEzLjcxIDI1LjQ2IEMxNC43MyA0MS4xNyAxNC41NyA1NS45MSA1LjcxIDY5LjQ2IEM1LjQyIDY5LjkxIDUuNDIgNjkuOTEgMy45NiA3Mi4yMSBDLTIuODcgNzkuMDQgLTEwLjc4IDgwLjc2IC0yMC4xIDgwLjc3IEMtMjUuOTMgODAuNjYgLTMwLjM4IDc5Ljc1IC0zNS4yOSA3Ni40NiBDLTM1Ljk4IDc1Ljk5IC0zNi42OCA3NS41MyAtMzcuMzkgNzUuMDUgQy00Ni4xMyA2OC4zNSAtNTAuMTMgNTcuNzIgLTUxLjYyIDQ3LjEgQy01MS45MiA0NC41NSAtNTIuMTIgNDIuMDIgLTUyLjI5IDM5LjQ2IEMtNTIuMzQgMzguNjggLTUyLjQgMzcuODkgLTUyLjQ1IDM3LjA5IEMtNTIuODggMjUuMTggLTQ5Ljg4IDEzLjk2IC00My4wNCA0LjI3IEMtMzEuNTEgLTcuNTIgLTEzLjc1IC05LjI3IDAgMCBaICIgZmlsbD0iI0VEMDAxQiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMxOS4yODkwNjI1LDE1Ni41NDI5Njg3NSkiIC8+PC9nPjwvc3ZnPg==';\n\n/** Logo \"g\" de Fundación Génesis (theme/g.svg, 440x440). */\nexport const G_LOGO_DATA_URI = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjQ0MCIgaGVpZ2h0PSI0NDAiIHZpZXdCb3g9IjEwODQgNSA0NDAgNDQwIj48cGF0aCBkPSJNMCAwIEMwLjYxIDAuMzIgMS4yMSAwLjY0IDEuODQgMC45OCBDMTguMTggOS43NSAzMi42MiAyMS4wMyA0Ni4yNSAzMy41NiBDNDYuODIgMzQuMDggNDcuMzggMzQuNiA0Ny45NyAzNS4xMyBDODcuMDcgNzEuNTYgMTA3LjgyIDEyNS43NiAxMDkuODYgMTc4LjM4IEMxMTAuOTMgMjE0LjU0IDEwMi4wMSAyNTAuMTggODUgMjgyIEM4NC42OCAyODIuNjEgODQuMzYgMjgzLjIxIDg0LjAyIDI4My44NCBDNzUuMjUgMzAwLjE4IDYzLjk3IDMxNC42MiA1MS40NCAzMjguMjUgQzUwLjkyIDMyOC44MiA1MC40IDMyOS4zOCA0OS44NyAzMjkuOTcgQzEzLjQ0IDM2OS4wNyAtNDAuNzYgMzg5LjgyIC05My4zOCAzOTEuODYgQy0xMjkuNTQgMzkyLjkzIC0xNjUuMTggMzg0LjAxIC0xOTcgMzY3IEMtMTk3LjYxIDM2Ni42OCAtMTk4LjIxIDM2Ni4zNiAtMTk4Ljg0IDM2Ni4wMiBDLTIxNS4xOCAzNTcuMjUgLTIyOS42MiAzNDUuOTcgLTI0My4yNSAzMzMuNDQgQy0yNDMuODIgMzMyLjkyIC0yNDQuMzggMzMyLjQgLTI0NC45NyAzMzEuODcgQy0yODQuMDcgMjk1LjQ0IC0zMDQuODIgMjQxLjI0IC0zMDYuODYgMTg4LjYyIEMtMzA3LjkzIDE1Mi40NiAtMjk5LjAxIDExNi44MiAtMjgyIDg1IEMtMjgxLjY4IDg0LjM5IC0yODEuMzYgODMuNzkgLTI4MS4wMiA4My4xNiBDLTI3Mi4yNSA2Ni44MiAtMjYwLjk3IDUyLjM4IC0yNDguNDQgMzguNzUgQy0yNDguMTggMzguNDcgLTI0OC4xOCAzOC40NyAtMjQ2Ljg3IDM3LjAzIEMtMjEwLjcxIC0xLjc4IC0xNTYuNzMgLTIyLjczIC0xMDQuNDcgLTI0Ljg2IEMtNjcuOTkgLTI1Ljk4IC0zMi4xIC0xNy4xNyAwIDAgWiAiIGZpbGw9IiNFRDAwMUIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE0MDMsNDIpIiAvPjxwYXRoIGQ9Ik0wIDAgQzIuOCAyLjY0IDUuMjUgNS40OSA3LjYzIDguNTEgQzguMDkgOC45OCA4LjU2IDkuNDQgOS4wNCA5LjkyIEM5LjM3IDkuNzUgOS4zNyA5Ljc1IDExLjA0IDguOTIgQzExLjM3IDIuOTggMTEuNyAtMi45NiAxMi4wNCAtOS4wOCBDMzcuNDUgLTkuMDggNjIuODYgLTkuMDggODkuMDQgLTkuMDggQzg5LjA4IDE0LjM3IDg5LjEyIDM3LjgyIDg5LjE0IDYxLjI4IEM4OS4xNSA3Mi4xNyA4OS4xNyA4My4wNiA4OS4xOSA5My45NSBDODkuMjEgMTAzLjQ1IDg5LjIyIDExMi45NSA4OS4yMyAxMjIuNDUgQzg5LjIzIDEyNy40NyA4OS4yNCAxMzIuNSA4OS4yNSAxMzcuNTIgQzg5LjI2IDE0Mi4yNiA4OS4yNyAxNDcgODkuMjcgMTUxLjc0IEM4OS4yNyAxNTMuNDcgODkuMjcgMTU1LjIgODkuMjggMTU2LjkzIEM4OS4zNCAxNzAuNTkgODguOTUgMTg0LjQ1IDg0Ljg1IDE5Ny42MSBDODQuNjQgMTk4LjMxIDg0LjQyIDE5OS4wMSA4NC4yIDE5OS43MyBDNzcuOTQgMjE5LjI0IDY0LjA2IDIzNS41OSA0NS45IDI0NS4xIEMxMi4wOCAyNjEuNjQgLTM1LjY2IDI2MS45OCAtNzEuMDkgMjUwLjYxIEMtOTEuODggMjQyLjk1IC0xMDcuNjcgMjMxLjMgLTExNy4xIDIxMS4wMSBDLTExOS41OSAyMDQuOTcgLTEyMS45NiAxOTcuNDggLTEyMS45NiAxOTAuOTIgQy0xMTIuMDMgMTkwLjY5IC0xMDIuMDkgMTkwLjUxIC05Mi4xNSAxOTAuNCBDLTg3LjU0IDE5MC4zNSAtODIuOTMgMTkwLjI4IC03OC4zMSAxOTAuMTYgQy03My44NiAxOTAuMDUgLTY5LjQgMTkwIC02NC45NSAxODkuOTcgQy02My4yNSAxODkuOTUgLTYxLjU1IDE4OS45MSAtNTkuODYgMTg5Ljg2IEMtNTQuNzMgMTg5LjcgLTQ5Ljk2IDE4OS42NyAtNDQuOTYgMTkwLjkyIEMtNDIuNDYgMTkzLjI5IC00MS4yOSAxOTUuMjYgLTM5Ljk5IDE5OC40MyBDLTM3Ljg1IDIwMy42MSAtMzMuMTUgMjA2LjYxIC0yOC4xNSAyMDguNzkgQy0yMS40OCAyMTAuOTYgLTE0LjM0IDIxMC44MyAtNy45IDIwOCBDMC4zMiAyMDMuNCA0LjkxIDE5Ni43MyA4LjA0IDE4Ny45MiBDOS45NyAxODAuMTggMTAuMyAxNzIuNjggMTAuMTYgMTY0LjczIEMxMC4xNiAxNjMuNjggMTAuMTUgMTYyLjY0IDEwLjE0IDE2MS41NiBDMTAuMTEgMTU5LjAxIDEwLjA4IDE1Ni40NiAxMC4wNCAxNTMuOTIgQzcuMDQgMTUzLjkyIDcuMDQgMTUzLjkyIDUuMjcgMTU1LjYxIEM0LjYgMTU2LjM3IDMuOTIgMTU3LjEzIDMuMjMgMTU3LjkyIEMtOS4wOCAxNzAuNTcgLTI2LjIzIDE3NS45MSAtNDMuNiAxNzYuMTYgQy02My45MiAxNzYuMjIgLTgyIDE3Mi4xNCAtOTcuOTYgMTU4LjkyIEMtOTguMzkgMTU4LjU4IC05OC4zOSAxNTguNTggLTEwMC41NCAxNTYuOSBDLTExOC45NSAxNDEuNjYgLTEyNi40MiAxMTcuMTkgLTEyOC43OCA5NC4yMiBDLTEzMC45MyA2Ny4yNyAtMTI2LjU1IDM4LjcxIC0xMDguOTkgMTcuMjMgQy05My42NiAtMC4yOCAtNzQuNTkgLTEwLjY1IC01MS4xNSAtMTIuOTUgQy0zMy4wNiAtMTQuMDIgLTE0LjQ3IC0xMS45MSAwIDAgWiAiIGZpbGw9IiNGRkZGRkYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMTkuOTYwOTM3NSwxMTAuMDgyMDMxMjUpIiAvPjxwYXRoIGQ9Ik0wIDAgQzguMjggNi43NyAxMi4zNCAxNC45IDEzLjcxIDI1LjQ2IEMxNC43MyA0MS4xNyAxNC41NyA1NS45MSA1LjcxIDY5LjQ2IEM1LjQyIDY5LjkxIDUuNDIgNjkuOTEgMy45NiA3Mi4yMSBDLTIuODcgNzkuMDQgLTEwLjc4IDgwLjc2IC0yMC4xIDgwLjc3IEMtMjUuOTMgODAuNjYgLTMwLjM4IDc5Ljc1IC0zNS4yOSA3Ni40NiBDLTM1Ljk4IDc1Ljk5IC0zNi42OCA3NS41MyAtMzcuMzkgNzUuMDUgQy00Ni4xMyA2OC4zNSAtNTAuMTMgNTcuNzIgLTUxLjYyIDQ3LjEgQy01MS45MiA0NC41NSAtNTIuMTIgNDIuMDIgLTUyLjI5IDM5LjQ2IEMtNTIuMzQgMzguNjggLTUyLjQgMzcuODkgLTUyLjQ1IDM3LjA5IEMtNTIuODggMjUuMTggLTQ5Ljg4IDEzLjk2IC00My4wNCA0LjI3IEMtMzEuNTEgLTcuNTIgLTEzLjc1IC05LjI3IDAgMCBaICIgZmlsbD0iI0VEMDAxQiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMxOS4yODkwNjI1LDE1Ni41NDI5Njg3NSkiIC8+PC9zdmc+';\n","import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { METAG_LOGO_DATA_URI } from '../../theme/brand';\n\n/**\n * Pantalla inicial mientras se consulta la configuración e inicia el proceso.\n * Muestra el logo \"MetaG\" (SVG) con una animación de entrada.\n */\n@Component({\n selector: 'mv-loading',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mv-brand\" role=\"status\" aria-live=\"polite\">\n <span class=\"mv-sr-only\">Comencemos...</span>\n <img class=\"mv-brand-logo\" [src]=\"logo\" alt=\"\" aria-hidden=\"true\" />\n </div>\n <p class=\"mv-signature\">Fundación Génesis Empresarial</p>\n `,\n styles: `\n :host {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n background: var(--mv-surface);\n }\n\n /* Firma sutil al pie de la pantalla. */\n .mv-signature {\n position: absolute;\n left: 16px;\n right: 16px;\n bottom: max(24px, env(safe-area-inset-bottom));\n margin: 0;\n font-family: var(--mv-font);\n font-size: 18px; /* mismo tamaño que el botón \"Tomar Fotografía\" */\n font-weight: 400;\n letter-spacing: 0.01em;\n color: #a1a1aa;\n text-align: center;\n animation: mv-brand-in 0.5s ease-out 0.25s both;\n }\n\n .mv-brand {\n animation: mv-brand-in 0.5s ease-out both;\n }\n\n .mv-brand-logo {\n display: block;\n height: 44px;\n width: auto;\n }\n\n .mv-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n }\n\n @keyframes mv-brand-in {\n from { opacity: 0; transform: translateY(6px); }\n to { opacity: 1; transform: none; }\n }\n\n @media (min-width: 768px) {\n .mv-brand-logo { height: 52px; }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .mv-brand, .mv-signature { animation: none; }\n }\n `,\n})\nexport class LoadingComponent {\n readonly logo = METAG_LOGO_DATA_URI;\n}\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\n\n/** Modal de mensaje (errores). Sin bordes, botón \"De acuerdo\". */\n@Component({\n selector: 'mv-dialog',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mv-dialog-backdrop\">\n <div class=\"mv-dialog\" role=\"alertdialog\" aria-modal=\"true\" aria-labelledby=\"mv-dialog-title\" aria-describedby=\"mv-dialog-message\">\n <span class=\"mv-dialog-icon\" aria-hidden=\"true\">!</span>\n <h2 id=\"mv-dialog-title\" class=\"mv-dialog-title\">{{ title }}</h2>\n <p id=\"mv-dialog-message\" class=\"mv-dialog-message\">{{ message }}</p>\n <button type=\"button\" class=\"mv-dialog-button\" (click)=\"closed.emit()\">{{ buttonLabel }}</button>\n </div>\n </div>\n `,\n styles: `\n @use '../../theme/tokens' as mv;\n\n :host {\n position: absolute;\n inset: 0;\n z-index: 20;\n }\n\n .mv-dialog-backdrop {\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 22px;\n background: rgba(9, 9, 11, 0.55);\n animation: mv-fade 0.2s ease-out both;\n }\n\n .mv-dialog {\n width: 100%;\n max-width: 380px;\n padding: 32px 24px 24px;\n border-radius: 24px;\n background: #ffffff;\n box-shadow: 0 24px 60px -12px rgba(0, 0, 0, 0.4);\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n animation: mv-pop 0.2s ease-out both;\n }\n\n .mv-dialog-icon {\n width: 56px;\n height: 56px;\n margin-bottom: 16px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fdecec;\n color: var(--mv-accent);\n font-family: var(--mv-font);\n font-size: 24px;\n font-weight: 700;\n }\n\n .mv-dialog-title {\n @include mv.title;\n margin-bottom: 8px;\n color: var(--mv-text);\n }\n\n .mv-dialog-message {\n @include mv.text;\n margin-bottom: 20px;\n color: var(--mv-muted);\n }\n\n .mv-dialog-button {\n @include mv.primary-button;\n }\n\n @keyframes mv-fade { from { opacity: 0; } to { opacity: 1; } }\n @keyframes mv-pop { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }\n\n @media (prefers-reduced-motion: reduce) {\n .mv-dialog-backdrop, .mv-dialog { animation: none; }\n }\n `,\n})\nexport class DialogComponent {\n @Input() title = '¡Lo sentimos!';\n @Input() message = 'No se pudo realizar el proceso.';\n @Input() buttonLabel = 'De acuerdo';\n @Output() closed = new EventEmitter<void>();\n}\n","// Brillo de pantalla al máximo mientras la cámara está abierta (mejora la foto con poca luz).\n// Usa el plugin nativo @capacitor-community/screen-brightness a través del objeto global de Capacitor,\n// sin importar el paquete: si la app no lo instaló, o se ejecuta en el navegador, no hace nada.\n\ninterface ScreenBrightnessPlugin {\n getBrightness(): Promise<{ brightness: number }>;\n setBrightness(options: { brightness: number }): Promise<void>;\n}\n\nconst PLUGIN_NAME = 'ScreenBrightness';\n/** En Android, -1 devuelve el brillo que el usuario tenía configurado. */\nconst SYSTEM_DEFAULT = -1;\n\nlet cachedPlugin: ScreenBrightnessPlugin | null | undefined;\n\nfunction getPlugin(): ScreenBrightnessPlugin | null {\n if (cachedPlugin !== undefined) return cachedPlugin;\n const capacitor = (globalThis as any).Capacitor;\n const available =\n capacitor?.isNativePlatform?.() &&\n (typeof capacitor.isPluginAvailable !== 'function' || capacitor.isPluginAvailable(PLUGIN_NAME));\n const plugin: ScreenBrightnessPlugin | null = available\n ? (capacitor.registerPlugin?.(PLUGIN_NAME) ?? capacitor.Plugins?.[PLUGIN_NAME] ?? null)\n : null;\n cachedPlugin = plugin;\n return plugin;\n}\n\n/** Sube el brillo al máximo y lo restaura después. Seguro de llamar varias veces. */\nexport class BrightnessBoost {\n private previous: number | null = null;\n private active = false;\n\n async raise(): Promise<void> {\n const plugin = getPlugin();\n if (!plugin || this.active) return;\n this.active = true;\n try {\n const { brightness } = await plugin.getBrightness();\n this.previous = brightness;\n await plugin.setBrightness({ brightness: 1 });\n } catch {\n this.active = false;\n }\n }\n\n async restore(): Promise<void> {\n if (!this.active) return;\n this.active = false;\n const plugin = getPlugin();\n try {\n await plugin?.setBrightness({ brightness: this.previous ?? SYSTEM_DEFAULT });\n } catch {\n // Si no se puede restaurar, el sistema lo hará al salir de la app.\n }\n }\n}\n","// Apertura de la cámara. La trasera se elige con la misma regla que el SDK actual (captura de DPI):\n// 1) el lente \"camera2 0\" (el principal en Android, con enfoque automático), 2) la trasera con el número\n// más bajo (\"camera 0, facing back\"), 3) cualquiera \"back/rear\", 4) la que entregue facingMode \"environment\".\n\nexport type CameraFacing = 'environment' | 'user';\n\nconst VIDEO_SIZE = { width: { ideal: 1920 }, height: { ideal: 1080 } };\nconst REAR_LABEL = /back|rear|environment/i;\nconst MAIN_REAR_LABEL = /camera2\\s?0/i;\nconst CAMERA_INDEX = /camera2?\\s*(\\d+)/i;\n\nexport async function openCamera(facing: CameraFacing): Promise<MediaStream> {\n if (facing === 'user') {\n return getStream({ ...VIDEO_SIZE, facingMode: 'user' });\n }\n\n // Si ya hay permiso, los nombres están disponibles y se abre directo el lente principal.\n const known = await preferredRearCamera();\n let stream = await getStream(known ? { ...VIDEO_SIZE, deviceId: { exact: known } } : { ...VIDEO_SIZE, facingMode: { ideal: 'environment' } });\n\n // Primera vez: los nombres aparecen después del permiso; si hay un lente mejor, se cambia a ese.\n if (!known) {\n const preferred = await preferredRearCamera();\n const current = stream.getVideoTracks()[0]?.getSettings().deviceId;\n if (preferred && preferred !== current) {\n stopStream(stream);\n stream = await getStream({ ...VIDEO_SIZE, deviceId: { exact: preferred } });\n }\n }\n\n return stream;\n}\n\n/** Indica si el dispositivo tiene más de una cámara (para mostrar el botón de cambiar). */\nexport async function hasMultipleCameras(): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter(d => d.kind === 'videoinput').length > 1;\n } catch {\n return false;\n }\n}\n\n/** Controles que ofrece el lente activo. */\nexport interface CameraControls {\n /** Enfoque al tocar la pantalla (focusMode \"single-shot\" + punto de interés). */\n tapFocus: boolean;\n}\n\ntype ExtendedCapabilities = MediaTrackCapabilities & { focusMode?: string[] };\n\n/** Android reporta los modos de enfoque unos instantes después de abrir la cámara: se reintenta. */\nconst CAPABILITY_ATTEMPTS = 6;\nconst CAPABILITY_RETRY_MS = 250;\n\nexport async function getCameraControls(stream: MediaStream | null): Promise<CameraControls> {\n const caps = await readCapabilities(stream);\n // Enfoque automático continuo cuando el lente lo soporta.\n if (caps?.focusMode?.includes('continuous')) await applyAdvanced(stream, { focusMode: 'continuous' });\n return { tapFocus: caps?.focusMode?.includes('single-shot') === true };\n}\n\n/** Enfoca en un punto del cuadro; x e y van de 0 a 1 sobre la imagen real del lente. */\nexport function focusAt(stream: MediaStream | null, x: number, y: number): Promise<boolean> {\n return applyAdvanced(stream, { focusMode: 'single-shot', pointsOfInterest: [{ x, y }] });\n}\n\n/** Vuelve al enfoque automático continuo después de enfocar al tocar. */\nexport function resumeAutofocus(stream: MediaStream | null): Promise<boolean> {\n return applyAdvanced(stream, { focusMode: 'continuous' });\n}\n\nasync function applyAdvanced(stream: MediaStream | null, constraint: Record<string, unknown>): Promise<boolean> {\n const track = stream?.getVideoTracks()[0];\n if (!track) return false;\n try {\n await track.applyConstraints({ advanced: [constraint as MediaTrackConstraintSet] });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function stopStream(stream: MediaStream | null): void {\n stream?.getTracks().forEach(track => track.stop());\n}\n\nfunction getStream(video: MediaTrackConstraints): Promise<MediaStream> {\n return navigator.mediaDevices.getUserMedia({ video, audio: false });\n}\n\n/**\n * Lee las capacidades del lente esperando a que Android las reporte. ImageCapture obliga a Chrome\n * a cargarlas; luego se reintenta unas veces hasta que aparezcan los modos de enfoque.\n */\nasync function readCapabilities(stream: MediaStream | null): Promise<ExtendedCapabilities | undefined> {\n const track = stream?.getVideoTracks()[0];\n if (!track?.getCapabilities) return undefined;\n\n const ImageCaptureCtor = (globalThis as { ImageCapture?: new (t: MediaStreamTrack) => { getPhotoCapabilities(): Promise<unknown> } }).ImageCapture;\n if (ImageCaptureCtor) {\n try {\n await new ImageCaptureCtor(track).getPhotoCapabilities();\n } catch {\n // Sin soporte: se sigue con los reintentos.\n }\n }\n\n let caps = track.getCapabilities() as ExtendedCapabilities;\n for (let i = 1; i < CAPABILITY_ATTEMPTS && !caps.focusMode?.length; i++) {\n await new Promise(resolve => setTimeout(resolve, CAPABILITY_RETRY_MS));\n if (track.readyState !== 'live') return undefined;\n caps = track.getCapabilities() as ExtendedCapabilities;\n }\n return caps;\n}\n\n/**\n * Android numera las cámaras (\"camera 0, facing back\", \"camera2 2, facing back\"...) y la principal,\n * la que tiene flash y enfoque automático, es la trasera con el número más bajo.\n */\nfunction lowestIndexed(cams: MediaDeviceInfo[]): MediaDeviceInfo | undefined {\n const indexed = cams\n .map(d => ({ d, n: Number(CAMERA_INDEX.exec(d.label)?.[1]) }))\n .filter(c => Number.isFinite(c.n));\n indexed.sort((a, b) => a.n - b.n);\n return indexed[0]?.d;\n}\n\n\nasync function preferredRearCamera(): Promise<string | null> {\n try {\n const cams = (await navigator.mediaDevices.enumerateDevices()).filter(d => d.kind === 'videoinput' && d.label);\n const rear = cams.filter(d => REAR_LABEL.test(d.label));\n const chosen = rear.find(d => MAIN_REAR_LABEL.test(d.label)) ?? lowestIndexed(rear) ?? rear.find(d => /back/i.test(d.label)) ?? rear[0];\n return chosen?.deviceId || null;\n } catch {\n return null;\n }\n}\n\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnDestroy,\n Output,\n ViewChild,\n signal,\n} from '@angular/core';\nimport { DialogComponent } from '../dialog/dialog.component';\nimport { NO_CONNECTION_MESSAGE } from '../../services/metag-api.service';\nimport { isVirtualCamera } from '../../services/virtual-camera';\nimport { G_LOGO_DATA_URI } from '../../theme/brand';\nimport { BrightnessBoost } from '../../services/screen-brightness';\nimport {\n CameraFacing,\n focusAt,\n getCameraControls,\n hasMultipleCameras,\n openCamera,\n resumeAutofocus,\n stopStream,\n} from '../../services/camera';\n\nconst JPEG_QUALITY = 0.75;\n/** Cuenta regresiva antes de tomar la foto: 3, 2, 1. */\nconst COUNTDOWN_FROM = 3;\n/** Tiempo que se muestra cada tip y duración de su salida. */\nconst TIP_INTERVAL_MS = 3000;\nconst TIP_LEAVE_MS = 250;\n\n/** Tips que rotan mientras la persona se prepara (orden fijo: el más importante primero). */\nconst TIPS: ReadonlyArray<{ text: string; icon: string }> = [\n { text: 'Permanece quieto', icon: 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18 M9 10h.01 M15 10h.01 M8.5 14.5c1 1.2 2.2 1.8 3.5 1.8s2.5-.6 3.5-1.8' },\n { text: 'Solo una persona', icon: 'M12 4a4 4 0 1 0 0 8a4 4 0 1 0 0-8 M4 20c1.5-3.5 4.4-5.5 8-5.5s6.5 2 8 5.5' },\n { text: 'Busca buena iluminación', icon: 'M12 8a4 4 0 1 0 0 8a4 4 0 1 0 0-8 M12 2v2 M12 20v2 M4.9 4.9l1.4 1.4 M17.7 17.7l1.4 1.4 M2 12h2 M20 12h2 M4.9 19.1l1.4-1.4 M17.7 6.3l1.4-1.4' },\n { text: 'Sin lentes ni gorra', icon: 'M7 11a3 3 0 1 0 0 6a3 3 0 1 0 0-6 M17 11a3 3 0 1 0 0 6a3 3 0 1 0 0-6 M10 14h4 M3 4l18 16' }\n];\n/** GIF transparente de 1x1 para el poster del video. */\nconst EMPTY_POSTER = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n/** Tiempo que se muestra \"Verificación completada\" antes de cerrar. */\nconst SUCCESS_HOLD_MS = 1200;\n/** Tiempo que se muestra el círculo de enfoque y tras el cual vuelve el enfoque continuo. */\nconst FOCUS_RING_MS = 800;\nconst FOCUS_HOLD_MS = 3000;\nconst CAMERA_ERROR_MESSAGE = 'No pudimos acceder a la cámara. Revisa los permisos e intenta de nuevo.';\n\ntype DialogState = { message: string; fatal: boolean } | null;\n\n/**\n * Foto Selfie, diseño A: cámara al 100% de la pantalla y botón rectangular \"Tomar Fotografía\".\n * La foto se toma al instante; mientras se valida, la barra roja inferior indica el envío.\n */\n@Component({\n selector: 'mv-selfie',\n standalone: true,\n imports: [DialogComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './selfie.component.html',\n styleUrl: './selfie.component.scss',\n})\nexport class SelfieComponent implements AfterViewInit, OnDestroy {\n /** Envía la foto (data URL JPEG). Si lanza error, se muestra el mensaje y se permite reintentar. */\n @Input({ required: true }) submit!: (fileBase64: string) => Promise<void>;\n /** La foto fue aceptada y ya se mostró la confirmación. */\n @Output() completed = new EventEmitter<void>();\n @Output() closed = new EventEmitter<void>();\n @Output() blocked = new EventEmitter<void>();\n @Output() failed = new EventEmitter<string>();\n\n @ViewChild('video', { static: true }) private videoRef!: ElementRef<HTMLVideoElement>;\n\n readonly gLogo = G_LOGO_DATA_URI;\n readonly emptyPoster = EMPTY_POSTER;\n /** La cámara ya está transmitiendo imagen. */\n readonly cameraReady = signal(false);\n /** Por defecto la trasera; la frontal queda disponible con el botón de cambiar cámara. */\n readonly facing = signal<CameraFacing>('environment');\n readonly canSwitchCamera = signal(false);\n private tapFocus = false;\n /** Punto donde se tocó para enfocar (px dentro de la pantalla); el id reinicia la animación. */\n readonly focusPoint = signal<{ x: number; y: number; id: number } | null>(null);\n readonly tips = TIPS;\n readonly tipIndex = signal(0);\n readonly tipLeaving = signal(false);\n readonly sending = signal(false);\n readonly success = signal(false);\n readonly countdown = signal<number | null>(null);\n readonly dialog = signal<DialogState>(null);\n\n private stream: MediaStream | null = null;\n private readonly brightness = new BrightnessBoost();\n private countdownTimer: ReturnType<typeof setInterval> | null = null;\n private tipTimer: ReturnType<typeof setInterval> | null = null;\n private tipLeaveTimer: ReturnType<typeof setTimeout> | null = null;\n private successTimer: ReturnType<typeof setTimeout> | null = null;\n private focusRingTimer: ReturnType<typeof setTimeout> | null = null;\n private focusHoldTimer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n\n async ngAfterViewInit(): Promise<void> {\n this.startTips();\n await this.startCamera();\n }\n\n ngOnDestroy(): void {\n this.destroyed = true;\n this.stopTips();\n if (this.successTimer) clearTimeout(this.successTimer);\n this.clearFocusTimers();\n this.stopCountdown();\n this.stopCamera();\n }\n\n takePhoto(): void {\n if (this.sending() || this.success() || this.countdown() !== null || !this.stream) return;\n this.stopTips();\n this.countdown.set(COUNTDOWN_FROM);\n this.countdownTimer = setInterval(() => {\n const next = (this.countdown() ?? 1) - 1;\n if (next > 0) {\n this.countdown.set(next);\n return;\n }\n this.stopCountdown();\n void this.captureAndSend();\n }, 1000);\n }\n\n switchCamera(): void {\n if (this.sending() || this.success() || this.countdown() !== null || !this.cameraReady()) return;\n this.facing.update(f => (f === 'environment' ? 'user' : 'environment'));\n this.stopCamera();\n void this.startCamera();\n }\n\n /** Enfocar al tocar: se ignoran los toques sobre botones y textos. */\n async onTap(event: MouseEvent): Promise<void> {\n if (!this.tapFocus || !this.cameraReady() || this.sending() || this.success()) return;\n if ((event.target as HTMLElement).closest('button, .mv-hint')) return;\n\n const video = this.videoRef.nativeElement;\n const rect = video.getBoundingClientRect();\n const point = this.toVideoPoint(video, rect, event.clientX, event.clientY);\n if (!point || !(await focusAt(this.stream, point.x, point.y))) return;\n\n this.clearFocusTimers();\n this.focusPoint.set({ x: event.clientX - rect.left, y: event.clientY - rect.top, id: Date.now() });\n this.focusRingTimer = setTimeout(() => this.focusPoint.set(null), FOCUS_RING_MS);\n this.focusHoldTimer = setTimeout(() => void resumeAutofocus(this.stream), FOCUS_HOLD_MS);\n }\n\n close(): void {\n if (this.sending() || this.success()) return;\n this.stopCountdown();\n this.stopCamera();\n this.closed.emit();\n }\n\n onDialogClosed(): void {\n const state = this.dialog();\n this.dialog.set(null);\n if (state?.fatal) {\n this.failed.emit(state.message);\n return;\n }\n // Reintento: se reanuda la cámara y los tips empiezan de nuevo.\n this.startTips();\n void this.videoRef.nativeElement.play().catch(() => undefined);\n }\n\n private async startCamera(): Promise<void> {\n this.cameraReady.set(false);\n try {\n this.stream = await openCamera(this.facing());\n } catch {\n this.dialog.set({ message: CAMERA_ERROR_MESSAGE, fatal: true });\n return;\n }\n\n if (this.destroyed) {\n this.stopCamera();\n return;\n }\n\n if (await isVirtualCamera(this.stream)) {\n this.stopCamera();\n this.blocked.emit();\n return;\n }\n\n const video = this.videoRef.nativeElement;\n video.srcObject = this.stream;\n // El brillo al máximo solo sirve con la frontal: la pantalla ilumina el rostro.\n if (this.facing() === 'user') void this.brightness.raise();\n this.canSwitchCamera.set(await hasMultipleCameras());\n await video.play().catch(() => undefined);\n // Las capacidades se leen con el video ya transmitiendo: algunos Android no reportan la linterna antes.\n const stream = this.stream;\n const controls = await getCameraControls(stream);\n // Si mientras tanto se cambió o cerró la cámara, estos controles ya no aplican.\n if (this.destroyed || stream !== this.stream) return;\n this.tapFocus = controls.tapFocus;\n }\n\n /**\n * Convierte el toque en pantalla a coordenadas 0-1 de la imagen real del lente,\n * considerando el recorte de object-fit: cover y el espejo de la frontal.\n */\n private toVideoPoint(video: HTMLVideoElement, rect: DOMRect, clientX: number, clientY: number): { x: number; y: number } | null {\n if (!video.videoWidth || !video.videoHeight) return null;\n const scale = Math.max(rect.width / video.videoWidth, rect.height / video.videoHeight);\n const shownW = video.videoWidth * scale;\n const shownH = video.videoHeight * scale;\n let x = (clientX - rect.left - (rect.width - shownW) / 2) / shownW;\n const y = (clientY - rect.top - (rect.height - shownH) / 2) / shownH;\n if (this.facing() === 'user') x = 1 - x;\n const clamp = (v: number) => Math.min(1, Math.max(0, v));\n return { x: clamp(x), y: clamp(y) };\n }\n\n private clearFocusTimers(): void {\n if (this.focusRingTimer) clearTimeout(this.focusRingTimer);\n if (this.focusHoldTimer) clearTimeout(this.focusHoldTimer);\n this.focusRingTimer = null;\n this.focusHoldTimer = null;\n }\n\n private async captureAndSend(): Promise<void> {\n const video = this.videoRef.nativeElement;\n const fileBase64 = this.grabFrame(video);\n video.pause();\n\n if (!fileBase64) {\n this.dialog.set({ message: 'No se pudo realizar el proceso.', fatal: false });\n return;\n }\n\n if (typeof navigator !== 'undefined' && navigator.onLine === false) {\n this.dialog.set({ message: NO_CONNECTION_MESSAGE, fatal: false });\n return;\n }\n\n this.sending.set(true);\n try {\n await this.submit(fileBase64);\n } catch (error) {\n const message = error instanceof Error && error.message ? error.message : 'No se pudo realizar el proceso.';\n this.sending.set(false);\n this.dialog.set({ message, fatal: false });\n return;\n }\n\n // Éxito en la misma pantalla: barra completa en verde, texto de confirmación y la foto congelada.\n this.sending.set(false);\n this.success.set(true);\n this.stopCamera();\n this.vibrate();\n this.successTimer = setTimeout(() => this.completed.emit(), SUCCESS_HOLD_MS);\n }\n\n /** Toma el cuadro completo del video (sin espejo) como JPEG. */\n private grabFrame(video: HTMLVideoElement): string | null {\n const width = video.videoWidth || 1920;\n const height = video.videoHeight || 1080;\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) return null;\n ctx.drawImage(video, 0, 0, width, height);\n return canvas.toDataURL('image/jpeg', JPEG_QUALITY);\n }\n\n /** Vibración corta de confirmación (Android; iOS no lo permite desde el navegador). */\n private vibrate(): void {\n try {\n navigator.vibrate?.(60);\n } catch {\n // Sin soporte: no pasa nada.\n }\n }\n\n /** Rota los tips: el actual sale y luego entra el siguiente. */\n private startTips(): void {\n this.stopTips();\n this.tipIndex.set(0);\n this.tipLeaving.set(false);\n this.tipTimer = setInterval(() => {\n this.tipLeaving.set(true);\n this.tipLeaveTimer = setTimeout(() => {\n this.tipIndex.update(i => (i + 1) % TIPS.length);\n this.tipLeaving.set(false);\n }, TIP_LEAVE_MS);\n }, TIP_INTERVAL_MS);\n }\n\n private stopTips(): void {\n if (this.tipTimer) clearInterval(this.tipTimer);\n if (this.tipLeaveTimer) clearTimeout(this.tipLeaveTimer);\n this.tipTimer = null;\n this.tipLeaveTimer = null;\n this.tipLeaving.set(false);\n }\n\n private stopCountdown(): void {\n if (this.countdownTimer) {\n clearInterval(this.countdownTimer);\n this.countdownTimer = null;\n }\n this.countdown.set(null);\n }\n\n private stopCamera(): void {\n stopStream(this.stream);\n this.stream = null;\n this.tapFocus = false;\n this.clearFocusTimers();\n this.focusPoint.set(null);\n void this.brightness.restore();\n }\n}\n","<div class=\"mv-camera\">\n <!-- poster transparente: evita el ícono gris de \"play\" que Android WebView muestra mientras arranca la cámara -->\n <video #video class=\"mv-video\" [class.mv-video--ready]=\"cameraReady()\" [class.mv-video--mirror]=\"facing() === 'user'\" [poster]=\"emptyPoster\"\n muted autoplay playsinline (playing)=\"cameraReady.set(true)\"></video>\n <div class=\"mv-scrim\" aria-hidden=\"true\"></div>\n\n @if (focusPoint(); as p) {\n @for (id of [p.id]; track id) {\n <span class=\"mv-focus-ring\" [style.left.px]=\"p.x\" [style.top.px]=\"p.y\" aria-hidden=\"true\"></span>\n }\n }\n\n <!-- Tocar la imagen enfoca en ese punto (si el lente lo soporta) -->\n <div class=\"mv-ui\" (click)=\"onTap($event)\">\n <header class=\"mv-head\">\n <div class=\"mv-title-group\">\n <img class=\"mv-title-logo\" [src]=\"gLogo\" alt=\"\" aria-hidden=\"true\" />\n <h2 class=\"mv-title\">Foto Selfie</h2>\n </div>\n <!-- La X arriba y debajo los controles en columna, como en las apps de cámara -->\n <div class=\"mv-actions\">\n <button type=\"button\" class=\"mv-close\" aria-label=\"Cerrar\" [disabled]=\"sending() || success()\" (click)=\"close()\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\" /></svg>\n </button>\n @if (!sending() && !success()) {\n <div class=\"mv-tools\">\n @if (canSwitchCamera()) {\n <button type=\"button\" class=\"mv-close mv-tool\" aria-label=\"Cambiar cámara\"\n [disabled]=\"!cameraReady() || countdown() !== null\" (click)=\"switchCamera()\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M11 19H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h5 M13 5h7a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-5 M12 9a3 3 0 1 0 0 6a3 3 0 1 0 0-6 M18 22l-3-3l3-3 M6 2l3 3l-3 3\" /></svg>\n </button>\n }\n </div>\n }\n </div>\n </header>\n\n <div class=\"mv-spacer\"></div>\n\n <footer class=\"mv-foot\">\n @if (countdown() !== null) {\n <!-- @for recrea el elemento en cada número para repetir la animación -->\n @for (n of [countdown()]; track n) {\n <p class=\"mv-hint mv-countdown\" aria-live=\"assertive\">{{ n }}</p>\n }\n } @else if (success()) {\n <p class=\"mv-hint mv-success-text\" role=\"status\" aria-live=\"polite\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M5 12.5l4.5 4.5L19 7.5\" /></svg>\n Verificación completada\n </p>\n } @else {\n @if (sending()) {\n <p class=\"mv-hint\" aria-live=\"polite\">Validando foto...</p>\n } @else {\n <!-- Tips rotativos: el recuadro se queda fijo y solo cambia el contenido -->\n <div class=\"mv-hint mv-tips\">\n <span class=\"mv-sr-only\">{{ tips[0].text }}</span>\n @for (i of [tipIndex()]; track i) {\n <span class=\"mv-tip\" [class.mv-tip--leaving]=\"tipLeaving()\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\"><path [attr.d]=\"tips[i].icon\" /></svg>\n {{ tips[i].text }}\n </span>\n }\n </div>\n }\n }\n @if (sending()) {\n <span class=\"mv-sending-bar\" aria-hidden=\"true\"></span>\n } @else if (success()) {\n <span class=\"mv-success-bar\" aria-hidden=\"true\"></span>\n }\n <!-- Oculto mientras se envía y al confirmar el éxito; vuelve a aparecer si hay error para reintentar -->\n @if (!sending() && !success()) {\n <button type=\"button\" class=\"mv-button\" [disabled]=\"!cameraReady() || countdown() !== null\" (click)=\"takePhoto()\">\n Tomar Fotografía\n </button>\n }\n </footer>\n </div>\n\n @if (dialog(); as d) {\n <mv-dialog [message]=\"d.message\" (closed)=\"onDialogClosed()\"></mv-dialog>\n }\n</div>\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\n\n/** Pantalla de bloqueo cuando se detecta una cámara virtual o no permitida. */\n@Component({\n selector: 'mv-blocked',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <section class=\"mv-step\">\n <h2 class=\"mv-title\">Bloqueo por seguridad</h2>\n <div class=\"mv-content\">\n <span class=\"mv-icon\" aria-hidden=\"true\">!</span>\n <p class=\"mv-text\">Detectamos una cámara virtual o no permitida durante la inicialización del SDK.</p>\n @if (reason) {\n <p class=\"mv-text\">{{ reason }}</p>\n }\n </div>\n <button type=\"button\" class=\"mv-button\" (click)=\"exit.emit()\">Entiendo</button>\n </section>\n `,\n styles: `\n @use '../../theme/tokens' as mv;\n\n :host {\n display: block;\n height: 100%;\n background: var(--mv-surface);\n }\n\n .mv-step {\n height: 100%;\n max-width: 420px;\n margin: 0 auto;\n padding: max(24px, env(safe-area-inset-top)) 22px max(22px, env(safe-area-inset-bottom));\n display: flex;\n flex-direction: column;\n }\n\n .mv-title {\n @include mv.title;\n color: var(--mv-accent);\n }\n\n .mv-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n text-align: center;\n }\n\n .mv-icon {\n width: 72px;\n height: 72px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fdecec;\n color: var(--mv-accent);\n font-family: var(--mv-font);\n font-size: 32px;\n font-weight: 700;\n }\n\n .mv-text {\n @include mv.text;\n max-width: 300px;\n color: var(--mv-muted);\n }\n\n .mv-button {\n @include mv.primary-button;\n flex-shrink: 0;\n }\n `,\n})\nexport class BlockedComponent {\n @Input() reason = '';\n @Output() exit = new EventEmitter<void>();\n}\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output, inject, signal } from '@angular/core';\nimport { MetagVerifyReason, MetagVerifyResult } from './models';\nimport { MetagApiError, MetagApiService } from './services/metag-api.service';\nimport { VIRTUAL_CAMERA_REASON } from './services/virtual-camera';\nimport { METAG_VERIFY_VERSION } from './version';\nimport { LoadingComponent } from './screens/loading/loading.component';\nimport { SelfieComponent } from './screens/selfie/selfie.component';\nimport { BlockedComponent } from './screens/blocked/blocked.component';\n\nconst DEFAULT_ENV = 'PROD_IT_01';\nconst PHOTO_SELFIE_STEP = 5;\n\ntype Screen = 'loading' | 'selfie' | 'blocked';\n\n/**\n * Componente de entrada de metag-verify. Versión 1: flujo Simple Auth con Foto Selfie.\n *\n * Uso:\n * <metag-verify [connection]=\"...\" [apiKey]=\"...\" [env]=\"'QA_IT_01'\" [dpi]=\"...\" (finished)=\"onResult($event)\">\n *\n * Se muestra a pantalla completa sobre la app. Cuando emite (finished), la app debe quitarlo de la vista.\n */\n@Component({\n selector: 'metag-verify',\n standalone: true,\n imports: [LoadingComponent, SelfieComponent, BlockedComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @switch (screen()) {\n @case ('loading') { <mv-loading /> }\n @case ('selfie') {\n <mv-selfie\n [submit]=\"submitSelfie\"\n (completed)=\"finish(true, 'completed')\"\n (closed)=\"finish(false, 'cancelled')\"\n (blocked)=\"screen.set('blocked')\"\n (failed)=\"finish(false, 'error', $event)\" />\n }\n @case ('blocked') {\n <mv-blocked [reason]=\"blockedReason\" (exit)=\"finish(false, 'blocked', blockedReason)\" />\n }\n }\n `,\n styleUrl: './metag-verify.component.scss',\n})\nexport class MetagVerifyComponent implements OnInit {\n /** Identificador de la conexión (connectionString). */\n @Input({ required: true }) connection!: string;\n /** API key del cliente para esa conexión. */\n @Input({ required: true }) apiKey!: string;\n /** Ambiente de MetaG, por ejemplo 'QA_IT_01'. Por defecto 'PROD_IT_01'. */\n @Input() env = DEFAULT_ENV;\n /** Número de DPI de la persona. */\n @Input() dpi = '';\n\n @Output() finished = new EventEmitter<MetagVerifyResult>();\n\n private readonly api = inject(MetagApiService);\n\n readonly screen = signal<Screen>('loading');\n readonly blockedReason = VIRTUAL_CAMERA_REASON;\n\n private endpoint = '';\n private codigo = '';\n private done = false;\n\n /** Se pasa a la pantalla de selfie; si lanza error, la selfie muestra el mensaje y permite reintentar.\n * Si sale bien, la selfie muestra la confirmación y luego emite (completed). */\n readonly submitSelfie = async (fileBase64: string): Promise<void> => {\n await this.api.sendPhotoSelfie(this.endpoint, {\n codigo: this.codigo,\n connection: this.connection,\n apiKey: this.apiKey,\n fileBase64,\n });\n };\n\n ngOnInit(): void {\n void this.start();\n }\n\n finish(success: boolean, reason: MetagVerifyReason, message?: string): void {\n if (this.done) return;\n this.done = true;\n this.finished.emit({ success, reason, ...(message ? { message } : {}) });\n }\n\n private async start(): Promise<void> {\n if (!this.connection || !this.apiKey) {\n this.finish(false, 'error', 'Faltan los datos de conexión (connection y apiKey).');\n return;\n }\n\n try {\n const environment = await this.api.getEnvironment(this.env || DEFAULT_ENV);\n this.endpoint = environment.env_endpoint;\n\n const config = await this.api.getConnectionConfig(this.endpoint, this.connection);\n const firstStep = config.steps[0];\n if (!firstStep || firstStep.type !== PHOTO_SELFIE_STEP) {\n this.finish(false, 'unsupported', 'Esta versión de metag-verify solo soporta el flujo de Foto Selfie.');\n return;\n }\n\n const process = await this.api.initProcess(this.endpoint, {\n dpi: this.dpi,\n connection: this.connection,\n apiKey: this.apiKey,\n version: METAG_VERIFY_VERSION,\n });\n this.codigo = process.codigo;\n\n // Si el proceso ya estaba completo, no hay nada que capturar.\n if (process.completed) {\n this.finish(true, 'completed');\n return;\n }\n\n this.screen.set('selfie');\n } catch (error) {\n const message = error instanceof MetagApiError ? error.message : 'No se pudo realizar el proceso.';\n this.finish(false, 'error', message);\n }\n }\n}\n","/*\n * API pública de metag-verify\n */\n\nexport * from './lib/metag-verify.component';\nexport * from './lib/models';\nexport { METAG_VERIFY_VERSION } from './lib/version';\nexport { METAG_LOGO_DATA_URI, G_LOGO_DATA_URI } from './lib/theme/brand';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AfterViewInit, EventEmitter, OnDestroy } from '@angular/core';
|
|
2
|
+
import { CameraFacing } from '../../services/camera';
|
|
2
3
|
import * as i0 from "@angular/core";
|
|
3
4
|
type DialogState = {
|
|
4
5
|
message: string;
|
|
@@ -21,6 +22,16 @@ export declare class SelfieComponent implements AfterViewInit, OnDestroy {
|
|
|
21
22
|
readonly emptyPoster = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
22
23
|
/** La cámara ya está transmitiendo imagen. */
|
|
23
24
|
readonly cameraReady: import("@angular/core").WritableSignal<boolean>;
|
|
25
|
+
/** Por defecto la trasera; la frontal queda disponible con el botón de cambiar cámara. */
|
|
26
|
+
readonly facing: import("@angular/core").WritableSignal<CameraFacing>;
|
|
27
|
+
readonly canSwitchCamera: import("@angular/core").WritableSignal<boolean>;
|
|
28
|
+
private tapFocus;
|
|
29
|
+
/** Punto donde se tocó para enfocar (px dentro de la pantalla); el id reinicia la animación. */
|
|
30
|
+
readonly focusPoint: import("@angular/core").WritableSignal<{
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
id: number;
|
|
34
|
+
} | null>;
|
|
24
35
|
readonly tips: readonly {
|
|
25
36
|
text: string;
|
|
26
37
|
icon: string;
|
|
@@ -37,13 +48,24 @@ export declare class SelfieComponent implements AfterViewInit, OnDestroy {
|
|
|
37
48
|
private tipTimer;
|
|
38
49
|
private tipLeaveTimer;
|
|
39
50
|
private successTimer;
|
|
51
|
+
private focusRingTimer;
|
|
52
|
+
private focusHoldTimer;
|
|
40
53
|
private destroyed;
|
|
41
54
|
ngAfterViewInit(): Promise<void>;
|
|
42
55
|
ngOnDestroy(): void;
|
|
43
56
|
takePhoto(): void;
|
|
57
|
+
switchCamera(): void;
|
|
58
|
+
/** Enfocar al tocar: se ignoran los toques sobre botones y textos. */
|
|
59
|
+
onTap(event: MouseEvent): Promise<void>;
|
|
44
60
|
close(): void;
|
|
45
61
|
onDialogClosed(): void;
|
|
46
62
|
private startCamera;
|
|
63
|
+
/**
|
|
64
|
+
* Convierte el toque en pantalla a coordenadas 0-1 de la imagen real del lente,
|
|
65
|
+
* considerando el recorte de object-fit: cover y el espejo de la frontal.
|
|
66
|
+
*/
|
|
67
|
+
private toVideoPoint;
|
|
68
|
+
private clearFocusTimers;
|
|
47
69
|
private captureAndSend;
|
|
48
70
|
/** Toma el cuadro completo del video (sin espejo) como JPEG. */
|
|
49
71
|
private grabFrame;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type CameraFacing = 'environment' | 'user';
|
|
2
|
+
export declare function openCamera(facing: CameraFacing): Promise<MediaStream>;
|
|
3
|
+
/** Indica si el dispositivo tiene más de una cámara (para mostrar el botón de cambiar). */
|
|
4
|
+
export declare function hasMultipleCameras(): Promise<boolean>;
|
|
5
|
+
/** Controles que ofrece el lente activo. */
|
|
6
|
+
export interface CameraControls {
|
|
7
|
+
/** Enfoque al tocar la pantalla (focusMode "single-shot" + punto de interés). */
|
|
8
|
+
tapFocus: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function getCameraControls(stream: MediaStream | null): Promise<CameraControls>;
|
|
11
|
+
/** Enfoca en un punto del cuadro; x e y van de 0 a 1 sobre la imagen real del lente. */
|
|
12
|
+
export declare function focusAt(stream: MediaStream | null, x: number, y: number): Promise<boolean>;
|
|
13
|
+
/** Vuelve al enfoque automático continuo después de enfocar al tocar. */
|
|
14
|
+
export declare function resumeAutofocus(stream: MediaStream | null): Promise<boolean>;
|
|
15
|
+
export declare function stopStream(stream: MediaStream | null): void;
|
package/lib/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Versión que se envía en el header sdk-version (el backend no la valida). */
|
|
2
|
-
export declare const METAG_VERIFY_VERSION = "0.1.
|
|
2
|
+
export declare const METAG_VERIFY_VERSION = "0.1.1";
|
package/package.json
CHANGED
package/metag-verify-0.1.0.tgz
DELETED
|
Binary file
|