@neofaceid/web-sdk 1.25.4 → 1.25.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -3
- package/dist/neoface-id-sdk.es.js +151 -97
- package/dist/neoface-id-sdk.umd.js +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export declare interface ApplicationRegistrationData {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Application registration result
|
|
14
|
+
* Application registration result.
|
|
15
|
+
* `app_token` só vem na criação/rotação; em GETs de leitura vem só `app_token_last4`.
|
|
15
16
|
*/
|
|
16
17
|
export declare interface ApplicationRegistrationResult {
|
|
17
18
|
success: boolean;
|
|
@@ -20,7 +21,8 @@ export declare interface ApplicationRegistrationResult {
|
|
|
20
21
|
application_name: string;
|
|
21
22
|
domain: string;
|
|
22
23
|
accept_only_email_with_same_domain: boolean;
|
|
23
|
-
app_token
|
|
24
|
+
app_token?: string;
|
|
25
|
+
app_token_last4?: string;
|
|
24
26
|
is_active: boolean;
|
|
25
27
|
created_at: string;
|
|
26
28
|
};
|
|
@@ -494,6 +496,7 @@ export declare const ENVIRONMENT_URLS: Record<Environment, string>;
|
|
|
494
496
|
*/
|
|
495
497
|
export declare enum ErrorType {
|
|
496
498
|
NETWORK = "NetworkError",
|
|
499
|
+
/** @deprecated Use `ErrorType.NETWORK`. Mantido para compatibilidade com consumidores existentes do SDK. */
|
|
497
500
|
NETWORK_ERROR = "NetworkError",
|
|
498
501
|
INVALID_TOKEN = "InvalidTokenError",
|
|
499
502
|
RECOGNITION_FAILED = "RecognitionFailedError",
|
|
@@ -1360,6 +1363,6 @@ export declare const validateToken: (applicationToken: string) => Promise<boolea
|
|
|
1360
1363
|
* MINOR: Incrementado quando adicionamos funcionalidades mantendo compatibilidade
|
|
1361
1364
|
* PATCH: Incrementado quando corrigimos bugs mantendo compatibilidade
|
|
1362
1365
|
*/
|
|
1363
|
-
export declare const VERSION = "1.25.
|
|
1366
|
+
export declare const VERSION = "1.25.6";
|
|
1364
1367
|
|
|
1365
1368
|
export { }
|
|
@@ -5336,9 +5336,15 @@ function init(options = {}) {
|
|
|
5336
5336
|
}
|
|
5337
5337
|
if (applicationToken) {
|
|
5338
5338
|
globalConfig.applicationToken = applicationToken;
|
|
5339
|
+
} else if (applicationToken === "") {
|
|
5340
|
+
console.warn(
|
|
5341
|
+
"[NeoFaceID SDK] applicationToken vazio em init() — 401 esperado em chamadas autenticadas."
|
|
5342
|
+
);
|
|
5339
5343
|
}
|
|
5340
5344
|
globalConfig.initialized = true;
|
|
5341
|
-
console.log(
|
|
5345
|
+
console.log(
|
|
5346
|
+
`[NeoFaceID SDK] Inicializado - Ambiente: ${globalConfig.environment}, URL: ${globalConfig.baseUrl}`
|
|
5347
|
+
);
|
|
5342
5348
|
}
|
|
5343
5349
|
function getBaseUrl() {
|
|
5344
5350
|
if (!globalConfig.initialized) {
|
|
@@ -5408,8 +5414,8 @@ const compressDocumentImage = async (imageBlob) => new Promise((resolve, reject)
|
|
|
5408
5414
|
const img = new Image();
|
|
5409
5415
|
img.onload = () => {
|
|
5410
5416
|
const MAX_SIZE = 1280;
|
|
5411
|
-
let width = img
|
|
5412
|
-
let height = img
|
|
5417
|
+
let { width } = img;
|
|
5418
|
+
let { height } = img;
|
|
5413
5419
|
if (width > height && width > MAX_SIZE) {
|
|
5414
5420
|
height = height * MAX_SIZE / width;
|
|
5415
5421
|
width = MAX_SIZE;
|
|
@@ -6027,6 +6033,11 @@ const registerPersonWithoutFace = async (personData, applicationToken, options)
|
|
|
6027
6033
|
}
|
|
6028
6034
|
];
|
|
6029
6035
|
}
|
|
6036
|
+
if (!applicationToken) {
|
|
6037
|
+
console.warn(
|
|
6038
|
+
"[NeoFaceID SDK] registerPersonWithoutFace sem applicationToken — 401 esperado."
|
|
6039
|
+
);
|
|
6040
|
+
}
|
|
6030
6041
|
const response = await fetch(`${getApiBaseUrl()}/api/v1/signup/donor/`, {
|
|
6031
6042
|
method: "POST",
|
|
6032
6043
|
headers: {
|
|
@@ -6161,6 +6172,11 @@ const registerPersonWithBiometric = async (personData, facePhotos, applicationTo
|
|
|
6161
6172
|
}
|
|
6162
6173
|
];
|
|
6163
6174
|
}
|
|
6175
|
+
if (!applicationToken) {
|
|
6176
|
+
console.warn(
|
|
6177
|
+
"[NeoFaceID SDK] registerPersonWithBiometric sem applicationToken — 401 esperado."
|
|
6178
|
+
);
|
|
6179
|
+
}
|
|
6164
6180
|
const response = await fetch(`${getApiBaseUrl()}/api/v1/signup/donor/`, {
|
|
6165
6181
|
method: "POST",
|
|
6166
6182
|
headers: {
|
|
@@ -6701,18 +6717,16 @@ const startProofOfLife = async (videoBase64, applicationToken) => {
|
|
|
6701
6717
|
throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK_ERROR);
|
|
6702
6718
|
}
|
|
6703
6719
|
};
|
|
6704
|
-
const videoToBase64 = async (videoBlob) => {
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
});
|
|
6715
|
-
};
|
|
6720
|
+
const videoToBase64 = async (videoBlob) => new Promise((resolve, reject) => {
|
|
6721
|
+
const reader = new FileReader();
|
|
6722
|
+
reader.onload = () => {
|
|
6723
|
+
const result = reader.result;
|
|
6724
|
+
const base642 = result.includes(",") ? result.split(",")[1] : result;
|
|
6725
|
+
resolve(base642);
|
|
6726
|
+
};
|
|
6727
|
+
reader.onerror = () => reject(new NeoFaceError("Failed to convert video to base64", ErrorType.CAPTURE_ERROR));
|
|
6728
|
+
reader.readAsDataURL(videoBlob);
|
|
6729
|
+
});
|
|
6716
6730
|
const blobToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
6717
6731
|
const reader = new FileReader();
|
|
6718
6732
|
reader.onload = () => {
|
|
@@ -6775,13 +6789,19 @@ const registerDocumentByImage = async (personId, jwtToken, images) => {
|
|
|
6775
6789
|
throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK_ERROR);
|
|
6776
6790
|
}
|
|
6777
6791
|
};
|
|
6778
|
-
const getTaskStatus = async (taskId) => {
|
|
6792
|
+
const getTaskStatus = async (taskId, applicationToken) => {
|
|
6779
6793
|
const controller = createTimeoutController();
|
|
6794
|
+
{
|
|
6795
|
+
console.warn(
|
|
6796
|
+
"[NeoFaceID SDK] getTaskStatus sem applicationToken — /tasks/status/ vai responder 401."
|
|
6797
|
+
);
|
|
6798
|
+
}
|
|
6780
6799
|
try {
|
|
6781
6800
|
const response = await fetch(`${getApiBaseUrl()}/api/v1/tasks/status/?task_id=${taskId}`, {
|
|
6782
6801
|
method: "GET",
|
|
6783
6802
|
headers: {
|
|
6784
|
-
"Content-Type": "application/json"
|
|
6803
|
+
"Content-Type": "application/json",
|
|
6804
|
+
...applicationToken ? { "X-App-Token": applicationToken } : {}
|
|
6785
6805
|
},
|
|
6786
6806
|
signal: controller.signal
|
|
6787
6807
|
});
|
|
@@ -6813,7 +6833,7 @@ const identifyPersonAsync = async (image, applicationToken, options = {}) => {
|
|
|
6813
6833
|
person: initialResponse.person
|
|
6814
6834
|
};
|
|
6815
6835
|
}
|
|
6816
|
-
const taskId = initialResponse
|
|
6836
|
+
const { taskId } = initialResponse;
|
|
6817
6837
|
if (!taskId) {
|
|
6818
6838
|
return { personFound: false };
|
|
6819
6839
|
}
|
|
@@ -7647,7 +7667,9 @@ function BiometricRegistrationModal({
|
|
|
7647
7667
|
const captureStateRef = useRef(null);
|
|
7648
7668
|
const [state, dispatch] = useReducer(modalReducer, void 0, createInitialState);
|
|
7649
7669
|
const [faceDetected, setFaceDetected] = useState(false);
|
|
7650
|
-
const [faceDistance, setFaceDistance] = useState(
|
|
7670
|
+
const [faceDistance, setFaceDistance] = useState(
|
|
7671
|
+
"ok"
|
|
7672
|
+
);
|
|
7651
7673
|
const [cameraReady, setCameraReady] = useState(false);
|
|
7652
7674
|
useEffect(() => {
|
|
7653
7675
|
if (state.status === "liveness") {
|
|
@@ -7778,15 +7800,13 @@ function BiometricRegistrationModal({
|
|
|
7778
7800
|
}
|
|
7779
7801
|
}, 50);
|
|
7780
7802
|
}
|
|
7781
|
-
} else {
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
progressIntervalRef.current = null;
|
|
7787
|
-
}
|
|
7788
|
-
dispatch({ type: "UPDATE_PROGRESS", progress: 0 });
|
|
7803
|
+
} else if (holdStartTimeRef.current) {
|
|
7804
|
+
holdStartTimeRef.current = null;
|
|
7805
|
+
if (progressIntervalRef.current) {
|
|
7806
|
+
clearInterval(progressIntervalRef.current);
|
|
7807
|
+
progressIntervalRef.current = null;
|
|
7789
7808
|
}
|
|
7809
|
+
dispatch({ type: "UPDATE_PROGRESS", progress: 0 });
|
|
7790
7810
|
}
|
|
7791
7811
|
};
|
|
7792
7812
|
useEffect(() => {
|
|
@@ -7813,8 +7833,8 @@ function BiometricRegistrationModal({
|
|
|
7813
7833
|
};
|
|
7814
7834
|
loadModels();
|
|
7815
7835
|
}, []);
|
|
7816
|
-
useEffect(
|
|
7817
|
-
|
|
7836
|
+
useEffect(
|
|
7837
|
+
() => () => {
|
|
7818
7838
|
if (streamRef.current) {
|
|
7819
7839
|
streamRef.current.getTracks().forEach((track) => {
|
|
7820
7840
|
track.stop();
|
|
@@ -7836,8 +7856,9 @@ function BiometricRegistrationModal({
|
|
|
7836
7856
|
clearTimeout(stepTimeoutTimerRef.current);
|
|
7837
7857
|
stepTimeoutTimerRef.current = null;
|
|
7838
7858
|
}
|
|
7839
|
-
}
|
|
7840
|
-
|
|
7859
|
+
},
|
|
7860
|
+
[]
|
|
7861
|
+
);
|
|
7841
7862
|
useEffect(() => {
|
|
7842
7863
|
let mounted = true;
|
|
7843
7864
|
const initCamera = async () => {
|
|
@@ -7979,15 +8000,13 @@ function BiometricRegistrationModal({
|
|
|
7979
8000
|
);
|
|
7980
8001
|
manageHoldAndCapture(positionCorrect);
|
|
7981
8002
|
}
|
|
7982
|
-
} else {
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
progressIntervalRef.current = null;
|
|
7988
|
-
}
|
|
7989
|
-
dispatch({ type: "UPDATE_PROGRESS", progress: 0 });
|
|
8003
|
+
} else if (holdStartTimeRef.current) {
|
|
8004
|
+
holdStartTimeRef.current = null;
|
|
8005
|
+
if (progressIntervalRef.current) {
|
|
8006
|
+
clearInterval(progressIntervalRef.current);
|
|
8007
|
+
progressIntervalRef.current = null;
|
|
7990
8008
|
}
|
|
8009
|
+
dispatch({ type: "UPDATE_PROGRESS", progress: 0 });
|
|
7991
8010
|
}
|
|
7992
8011
|
} catch (error) {
|
|
7993
8012
|
}
|
|
@@ -8016,38 +8035,37 @@ function BiometricRegistrationModal({
|
|
|
8016
8035
|
}
|
|
8017
8036
|
holdStartTimeRef.current = null;
|
|
8018
8037
|
};
|
|
8019
|
-
} else {
|
|
8020
|
-
const onCanPlay = () => {
|
|
8021
|
-
if (isRunning) startDetection();
|
|
8022
|
-
};
|
|
8023
|
-
let pollCount = 0;
|
|
8024
|
-
const MAX_POLLS = 50;
|
|
8025
|
-
const pollTimer = window.setInterval(() => {
|
|
8026
|
-
pollCount++;
|
|
8027
|
-
if (!isRunning) {
|
|
8028
|
-
clearInterval(pollTimer);
|
|
8029
|
-
return;
|
|
8030
|
-
}
|
|
8031
|
-
if (videoRef.current && videoRef.current.readyState >= 2) {
|
|
8032
|
-
clearInterval(pollTimer);
|
|
8033
|
-
videoRef.current.removeEventListener("canplay", onCanPlay);
|
|
8034
|
-
startDetection();
|
|
8035
|
-
} else if (pollCount >= MAX_POLLS) {
|
|
8036
|
-
clearInterval(pollTimer);
|
|
8037
|
-
}
|
|
8038
|
-
}, 300);
|
|
8039
|
-
video == null ? void 0 : video.addEventListener("canplay", onCanPlay, { once: true });
|
|
8040
|
-
return () => {
|
|
8041
|
-
isRunning = false;
|
|
8042
|
-
clearInterval(pollTimer);
|
|
8043
|
-
video == null ? void 0 : video.removeEventListener("canplay", onCanPlay);
|
|
8044
|
-
if (progressIntervalRef.current) {
|
|
8045
|
-
clearInterval(progressIntervalRef.current);
|
|
8046
|
-
progressIntervalRef.current = null;
|
|
8047
|
-
}
|
|
8048
|
-
holdStartTimeRef.current = null;
|
|
8049
|
-
};
|
|
8050
8038
|
}
|
|
8039
|
+
const onCanPlay = () => {
|
|
8040
|
+
if (isRunning) startDetection();
|
|
8041
|
+
};
|
|
8042
|
+
let pollCount = 0;
|
|
8043
|
+
const MAX_POLLS = 50;
|
|
8044
|
+
const pollTimer = window.setInterval(() => {
|
|
8045
|
+
pollCount++;
|
|
8046
|
+
if (!isRunning) {
|
|
8047
|
+
clearInterval(pollTimer);
|
|
8048
|
+
return;
|
|
8049
|
+
}
|
|
8050
|
+
if (videoRef.current && videoRef.current.readyState >= 2) {
|
|
8051
|
+
clearInterval(pollTimer);
|
|
8052
|
+
videoRef.current.removeEventListener("canplay", onCanPlay);
|
|
8053
|
+
startDetection();
|
|
8054
|
+
} else if (pollCount >= MAX_POLLS) {
|
|
8055
|
+
clearInterval(pollTimer);
|
|
8056
|
+
}
|
|
8057
|
+
}, 300);
|
|
8058
|
+
video == null ? void 0 : video.addEventListener("canplay", onCanPlay, { once: true });
|
|
8059
|
+
return () => {
|
|
8060
|
+
isRunning = false;
|
|
8061
|
+
clearInterval(pollTimer);
|
|
8062
|
+
video == null ? void 0 : video.removeEventListener("canplay", onCanPlay);
|
|
8063
|
+
if (progressIntervalRef.current) {
|
|
8064
|
+
clearInterval(progressIntervalRef.current);
|
|
8065
|
+
progressIntervalRef.current = null;
|
|
8066
|
+
}
|
|
8067
|
+
holdStartTimeRef.current = null;
|
|
8068
|
+
};
|
|
8051
8069
|
}, [state.status]);
|
|
8052
8070
|
const capturePhoto = async () => {
|
|
8053
8071
|
if (!videoRef.current || !canvasRef.current || isCapturingRef.current) {
|
|
@@ -8151,7 +8169,7 @@ function BiometricRegistrationModal({
|
|
|
8151
8169
|
const renderLivenessDetection = () => {
|
|
8152
8170
|
if (state.status !== "liveness") return null;
|
|
8153
8171
|
const progress = `${state.currentStepIndex + 1}/${state.stepSequence.length - 1}`;
|
|
8154
|
-
const stepProgress = state
|
|
8172
|
+
const { stepProgress } = state;
|
|
8155
8173
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "liveness-container", children: [
|
|
8156
8174
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "progress-indicator", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "progress-text", children: progress }) }),
|
|
8157
8175
|
faceDetected && faceDistance !== "ok" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `status-badge ${faceDistance === "not-centered" ? "warning" : "error"}`, children: [
|
|
@@ -8180,7 +8198,14 @@ function BiometricRegistrationModal({
|
|
|
8180
8198
|
stepProgress > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "progress-bar", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "progress-fill", style: { width: `${stepProgress}%` } }) })
|
|
8181
8199
|
] }),
|
|
8182
8200
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "branding-small", children: [
|
|
8183
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8201
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8202
|
+
"span",
|
|
8203
|
+
{
|
|
8204
|
+
className: "brand-logo-small",
|
|
8205
|
+
style: { display: "inline-flex", width: 18, height: 18, color: "currentColor" },
|
|
8206
|
+
dangerouslySetInnerHTML: { __html: NEOFACEID_MARK_MONO_SVG }
|
|
8207
|
+
}
|
|
8208
|
+
),
|
|
8184
8209
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "NeoFaceId by" }),
|
|
8185
8210
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "brand-name", children: "OCTA" })
|
|
8186
8211
|
] })
|
|
@@ -8227,8 +8252,16 @@ function BiometricRegistrationModal({
|
|
|
8227
8252
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: "Não foi possível processar" }),
|
|
8228
8253
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: state.message }),
|
|
8229
8254
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "button-group", children: [
|
|
8230
|
-
state.retryable && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8231
|
-
|
|
8255
|
+
state.retryable && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8256
|
+
"button",
|
|
8257
|
+
{
|
|
8258
|
+
type: "button",
|
|
8259
|
+
className: "secondary-button",
|
|
8260
|
+
onClick: () => dispatch({ type: "RESET" }),
|
|
8261
|
+
children: "Tentar Novamente"
|
|
8262
|
+
}
|
|
8263
|
+
),
|
|
8264
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ghost-button", onClick: onClose, children: "Cancelar" })
|
|
8232
8265
|
] })
|
|
8233
8266
|
] });
|
|
8234
8267
|
};
|
|
@@ -8271,7 +8304,7 @@ function BiometricRegistrationModal({
|
|
|
8271
8304
|
] }) }),
|
|
8272
8305
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: onPhotosCaptured ? "Captura concluída!" : "Verificação concluída!" }),
|
|
8273
8306
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: onPhotosCaptured ? "Suas capturas faciais foram realizadas" : "Sua biometria foi registrada com sucesso" }),
|
|
8274
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "primary-button", onClick: onClose, children: "Continuar" })
|
|
8307
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "primary-button", onClick: onClose, children: "Continuar" })
|
|
8275
8308
|
] });
|
|
8276
8309
|
const renderDuplicate = () => {
|
|
8277
8310
|
if (state.status !== "duplicate") return null;
|
|
@@ -8283,6 +8316,7 @@ function BiometricRegistrationModal({
|
|
|
8283
8316
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8284
8317
|
"button",
|
|
8285
8318
|
{
|
|
8319
|
+
type: "button",
|
|
8286
8320
|
className: "primary-button",
|
|
8287
8321
|
onClick: () => {
|
|
8288
8322
|
onClose();
|
|
@@ -8294,6 +8328,7 @@ function BiometricRegistrationModal({
|
|
|
8294
8328
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8295
8329
|
"button",
|
|
8296
8330
|
{
|
|
8331
|
+
type: "button",
|
|
8297
8332
|
className: "secondary-button",
|
|
8298
8333
|
style: { marginTop: "12px" },
|
|
8299
8334
|
onClick: () => {
|
|
@@ -8308,6 +8343,7 @@ function BiometricRegistrationModal({
|
|
|
8308
8343
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8309
8344
|
"button",
|
|
8310
8345
|
{
|
|
8346
|
+
type: "button",
|
|
8311
8347
|
className: "ghost-button",
|
|
8312
8348
|
onClick: () => window.open("https://support.neofaceid.com", "_blank"),
|
|
8313
8349
|
children: "Falar com Suporte"
|
|
@@ -8975,7 +9011,7 @@ function BiometricRegistrationModal({
|
|
|
8975
9011
|
}
|
|
8976
9012
|
` }),
|
|
8977
9013
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "modal-overlay", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "modal-content", children: [
|
|
8978
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "close-button", onClick: onClose, children: "×" }),
|
|
9014
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "close-button", onClick: onClose, children: "×" }),
|
|
8979
9015
|
state.status === "liveness" && renderLivenessDetection(),
|
|
8980
9016
|
state.status === "camera-loading" && renderCameraLoading(),
|
|
8981
9017
|
state.status === "processing" && renderProcessing(),
|
|
@@ -9241,7 +9277,7 @@ class BiometricCaptureModal {
|
|
|
9241
9277
|
} catch (error) {
|
|
9242
9278
|
this.options.onError(
|
|
9243
9279
|
new NeoFaceError(
|
|
9244
|
-
|
|
9280
|
+
`Erro ao inicializar câmera: ${error.message}`,
|
|
9245
9281
|
ErrorType.CAMERA_ERROR
|
|
9246
9282
|
)
|
|
9247
9283
|
);
|
|
@@ -9323,7 +9359,7 @@ class BiometricCaptureModal {
|
|
|
9323
9359
|
this.canvas.width = this.video.videoWidth;
|
|
9324
9360
|
this.canvas.height = this.video.videoHeight;
|
|
9325
9361
|
} catch (error) {
|
|
9326
|
-
throw new Error(
|
|
9362
|
+
throw new Error(`Não foi possível acessar a câmera: ${error.message}`);
|
|
9327
9363
|
}
|
|
9328
9364
|
}
|
|
9329
9365
|
/**
|
|
@@ -9377,13 +9413,13 @@ class BiometricCaptureModal {
|
|
|
9377
9413
|
const imageData = this.canvas.toDataURL("image/jpeg", 0.8);
|
|
9378
9414
|
const base64Data = imageData.split(",")[1];
|
|
9379
9415
|
const dataUrl = `data:image/jpeg;base64,${base64Data}`;
|
|
9380
|
-
|
|
9416
|
+
const detectedType = this.options.mode === "auto" ? await this.detectBiometricType(base64Data) : this.options.mode;
|
|
9381
9417
|
this.close();
|
|
9382
9418
|
this.options.onSuccess(dataUrl, detectedType);
|
|
9383
9419
|
} catch (error) {
|
|
9384
9420
|
this.options.onError(
|
|
9385
9421
|
new NeoFaceError(
|
|
9386
|
-
|
|
9422
|
+
`Erro ao capturar imagem: ${error.message}`,
|
|
9387
9423
|
ErrorType.CAPTURE_ERROR
|
|
9388
9424
|
)
|
|
9389
9425
|
);
|
|
@@ -10687,7 +10723,7 @@ async function captureFaceSilently() {
|
|
|
10687
10723
|
cleanup();
|
|
10688
10724
|
reject(
|
|
10689
10725
|
new NeoFaceError(
|
|
10690
|
-
|
|
10726
|
+
`Erro ao reproduzir câmera: ${err.message}`,
|
|
10691
10727
|
ErrorType.CAMERA_ERROR
|
|
10692
10728
|
)
|
|
10693
10729
|
);
|
|
@@ -10703,7 +10739,7 @@ async function captureFaceSilently() {
|
|
|
10703
10739
|
cleanup();
|
|
10704
10740
|
reject(
|
|
10705
10741
|
new NeoFaceError(
|
|
10706
|
-
|
|
10742
|
+
`Não foi possível acessar a câmera: ${error.message}`,
|
|
10707
10743
|
ErrorType.CAMERA_ERROR
|
|
10708
10744
|
)
|
|
10709
10745
|
);
|
|
@@ -11204,9 +11240,12 @@ async function detectBiometricType(imageData) {
|
|
|
11204
11240
|
async function detectFace(img) {
|
|
11205
11241
|
try {
|
|
11206
11242
|
if (typeof window !== "undefined" && window.faceapi) {
|
|
11207
|
-
const faceapi2 = window
|
|
11243
|
+
const { faceapi: faceapi2 } = window;
|
|
11208
11244
|
await loadFaceApiModels();
|
|
11209
|
-
const tinyOptions = new faceapi2.TinyFaceDetectorOptions({
|
|
11245
|
+
const tinyOptions = new faceapi2.TinyFaceDetectorOptions({
|
|
11246
|
+
inputSize: 320,
|
|
11247
|
+
scoreThreshold: 0.5
|
|
11248
|
+
});
|
|
11210
11249
|
const detections = await faceapi2.detectAllFaces(img, tinyOptions).withFaceLandmarks();
|
|
11211
11250
|
if (detections && detections.length > 0) {
|
|
11212
11251
|
const bestDetection = detections.reduce(
|
|
@@ -11305,7 +11344,7 @@ async function loadFaceApiModels() {
|
|
|
11305
11344
|
if (typeof window === "undefined" || !window.faceapi) {
|
|
11306
11345
|
return;
|
|
11307
11346
|
}
|
|
11308
|
-
const faceapi2 = window
|
|
11347
|
+
const { faceapi: faceapi2 } = window;
|
|
11309
11348
|
if (faceapi2.nets.tinyFaceDetector.isLoaded) {
|
|
11310
11349
|
return;
|
|
11311
11350
|
}
|
|
@@ -11336,7 +11375,7 @@ const biometricDetection = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
|
|
|
11336
11375
|
initializeBiometricDetection,
|
|
11337
11376
|
isAdvancedDetectionAvailable
|
|
11338
11377
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
11339
|
-
const VERSION = "1.25.
|
|
11378
|
+
const VERSION = "1.25.6";
|
|
11340
11379
|
const RELEASE_DATE = "2026-08-29";
|
|
11341
11380
|
class OnboardingCaptureModal {
|
|
11342
11381
|
constructor(options) {
|
|
@@ -11364,7 +11403,10 @@ class OnboardingCaptureModal {
|
|
|
11364
11403
|
await this.runFaceCaptureCountdown();
|
|
11365
11404
|
this.faceBlob = await this.captureFrame();
|
|
11366
11405
|
this.step = "document";
|
|
11367
|
-
this.updateTexts(
|
|
11406
|
+
this.updateTexts(
|
|
11407
|
+
"Captura do Documento",
|
|
11408
|
+
'Posicione seu documento visível e clique em "Capturar"'
|
|
11409
|
+
);
|
|
11368
11410
|
await this.waitForUserCaptureClick();
|
|
11369
11411
|
this.documentBlob = await this.captureFrame();
|
|
11370
11412
|
await this.close();
|
|
@@ -11462,7 +11504,9 @@ class OnboardingCaptureModal {
|
|
|
11462
11504
|
async runFaceCaptureCountdown() {
|
|
11463
11505
|
if (!this.overlay) return;
|
|
11464
11506
|
const countdownEl = this.overlay.querySelector(".neofaceid-countdown");
|
|
11465
|
-
const countdownNumberEl = this.overlay.querySelector(
|
|
11507
|
+
const countdownNumberEl = this.overlay.querySelector(
|
|
11508
|
+
".neofaceid-countdown-number"
|
|
11509
|
+
);
|
|
11466
11510
|
const statusText = this.overlay.querySelector(".neofaceid-status-text");
|
|
11467
11511
|
countdownEl.style.display = "flex";
|
|
11468
11512
|
statusText.textContent = "Prepare-se! Capturando seu rosto...";
|
|
@@ -11509,7 +11553,11 @@ class OnboardingCaptureModal {
|
|
|
11509
11553
|
this.canvas.height = this.video.videoHeight;
|
|
11510
11554
|
ctx.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
|
|
11511
11555
|
const blob = await new Promise((resolve, reject) => {
|
|
11512
|
-
this.canvas.toBlob(
|
|
11556
|
+
this.canvas.toBlob(
|
|
11557
|
+
(b) => b ? resolve(b) : reject(new Error("Falha ao gerar imagem")),
|
|
11558
|
+
"image/jpeg",
|
|
11559
|
+
0.92
|
|
11560
|
+
);
|
|
11513
11561
|
});
|
|
11514
11562
|
return blob;
|
|
11515
11563
|
}
|
|
@@ -12139,13 +12187,15 @@ class DocumentCaptureModal {
|
|
|
12139
12187
|
|
|
12140
12188
|
<div class="neoface-doc-body">
|
|
12141
12189
|
<div class="neoface-doc-select-grid">
|
|
12142
|
-
${Object.entries(DOCUMENT_INFO).filter(([type]) => type !== "CPF").map(
|
|
12190
|
+
${Object.entries(DOCUMENT_INFO).filter(([type]) => type !== "CPF").map(
|
|
12191
|
+
([type, info]) => `
|
|
12143
12192
|
<button class="neoface-doc-select-option" data-type="${type}">
|
|
12144
12193
|
<span class="neoface-doc-select-icon">${info.icon}</span>
|
|
12145
12194
|
<span class="neoface-doc-select-name">${info.name}</span>
|
|
12146
12195
|
<svg class="neoface-doc-select-arrow" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>
|
|
12147
12196
|
</button>
|
|
12148
|
-
`
|
|
12197
|
+
`
|
|
12198
|
+
).join("")}
|
|
12149
12199
|
</div>
|
|
12150
12200
|
|
|
12151
12201
|
<div class="neoface-doc-tips">
|
|
@@ -12363,8 +12413,8 @@ class DocumentCaptureModal {
|
|
|
12363
12413
|
const img = new Image();
|
|
12364
12414
|
img.onload = () => {
|
|
12365
12415
|
const MAX_SIZE = 1280;
|
|
12366
|
-
let width = img
|
|
12367
|
-
let height = img
|
|
12416
|
+
let { width } = img;
|
|
12417
|
+
let { height } = img;
|
|
12368
12418
|
if (width > height && width > MAX_SIZE) {
|
|
12369
12419
|
height = height * MAX_SIZE / width;
|
|
12370
12420
|
width = MAX_SIZE;
|
|
@@ -12384,7 +12434,9 @@ class DocumentCaptureModal {
|
|
|
12384
12434
|
canvas.toBlob(
|
|
12385
12435
|
(blob) => {
|
|
12386
12436
|
if (blob) {
|
|
12387
|
-
console.log(
|
|
12437
|
+
console.log(
|
|
12438
|
+
`[DocumentCapture] Compressed image from ${(file.size / 1024).toFixed(0)}KB to ${(blob.size / 1024).toFixed(0)}KB`
|
|
12439
|
+
);
|
|
12388
12440
|
resolve(blob);
|
|
12389
12441
|
} else {
|
|
12390
12442
|
reject(new Error("Failed to compress image"));
|
|
@@ -12405,7 +12457,9 @@ class DocumentCaptureModal {
|
|
|
12405
12457
|
const retakeBtn = (_b = this.overlay) == null ? void 0 : _b.querySelector(".neoface-doc-retake-btn");
|
|
12406
12458
|
confirmBtn == null ? void 0 : confirmBtn.addEventListener("click", () => this.handleConfirm());
|
|
12407
12459
|
retakeBtn == null ? void 0 : retakeBtn.addEventListener("click", () => this.handleRetake());
|
|
12408
|
-
const previewImg = (_c = this.overlay) == null ? void 0 : _c.querySelector(
|
|
12460
|
+
const previewImg = (_c = this.overlay) == null ? void 0 : _c.querySelector(
|
|
12461
|
+
".neoface-doc-preview-current"
|
|
12462
|
+
);
|
|
12409
12463
|
if (previewImg) {
|
|
12410
12464
|
const blob = this.currentStep === "preview-front" ? this.frontBlob : this.backBlob;
|
|
12411
12465
|
if (blob) previewImg.src = URL.createObjectURL(blob);
|
|
@@ -12474,8 +12528,8 @@ class DocumentCaptureModal {
|
|
|
12474
12528
|
if (loading) loading.style.display = "flex";
|
|
12475
12529
|
const ctx = this.canvas.getContext("2d");
|
|
12476
12530
|
if (!ctx) return;
|
|
12477
|
-
const videoWidth = this.video
|
|
12478
|
-
const videoHeight = this.video
|
|
12531
|
+
const { videoWidth } = this.video;
|
|
12532
|
+
const { videoHeight } = this.video;
|
|
12479
12533
|
const frameWidthPercent = 0.75;
|
|
12480
12534
|
const frameHeightPercent = 0.65;
|
|
12481
12535
|
const cropWidth = Math.floor(videoWidth * frameWidthPercent);
|