@hexar/biometric-identity-sdk-react-native 1.0.25 → 1.0.26
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.
|
@@ -45,16 +45,16 @@ const useBiometricSDK_1 = require("../hooks/useBiometricSDK");
|
|
|
45
45
|
const CameraCapture_1 = require("./CameraCapture");
|
|
46
46
|
const VideoRecorder_1 = require("./VideoRecorder");
|
|
47
47
|
const getInstructionMap = (strings) => ({
|
|
48
|
-
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT'
|
|
49
|
-
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT'
|
|
50
|
-
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP'
|
|
51
|
-
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN'
|
|
52
|
-
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT'
|
|
53
|
-
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT'
|
|
54
|
-
smile: { text: strings.liveness.instructions.smile || 'Smile
|
|
55
|
-
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally'
|
|
56
|
-
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly'
|
|
57
|
-
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions'
|
|
48
|
+
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT' },
|
|
49
|
+
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT' },
|
|
50
|
+
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP' },
|
|
51
|
+
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN' },
|
|
52
|
+
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT' },
|
|
53
|
+
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT' },
|
|
54
|
+
smile: { text: strings.liveness.instructions.smile || 'Smile' },
|
|
55
|
+
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally' },
|
|
56
|
+
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly' },
|
|
57
|
+
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions' },
|
|
58
58
|
});
|
|
59
59
|
const ValidationProgress_1 = require("./ValidationProgress");
|
|
60
60
|
const ResultScreen_1 = require("./ResultScreen");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAaxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAE1I,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,UAAU,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,iCAAiC;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAaxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAE1I,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,UAAU,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,iCAAiC;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0CD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAs1BtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
|
|
@@ -49,41 +49,37 @@ const getDefaultChallenges = (strings) => [
|
|
|
49
49
|
instruction: strings.liveness.instructions.lookLeft || 'Slowly turn your head to the LEFT',
|
|
50
50
|
duration_ms: 2500,
|
|
51
51
|
order: 1,
|
|
52
|
-
icon: '←',
|
|
53
52
|
},
|
|
54
53
|
{
|
|
55
54
|
action: 'look_right',
|
|
56
55
|
instruction: strings.liveness.instructions.lookRight || 'Slowly turn your head to the RIGHT',
|
|
57
56
|
duration_ms: 2500,
|
|
58
57
|
order: 2,
|
|
59
|
-
icon: '→',
|
|
60
58
|
},
|
|
61
59
|
{
|
|
62
60
|
action: 'blink',
|
|
63
61
|
instruction: strings.liveness.instructions.blink || 'Blink your eyes naturally',
|
|
64
62
|
duration_ms: 2000,
|
|
65
63
|
order: 3,
|
|
66
|
-
icon: '👁',
|
|
67
64
|
},
|
|
68
65
|
{
|
|
69
66
|
action: 'smile',
|
|
70
|
-
instruction: strings.liveness.instructions.smile || 'Smile
|
|
67
|
+
instruction: strings.liveness.instructions.smile || 'Smile',
|
|
71
68
|
duration_ms: 2000,
|
|
72
69
|
order: 4,
|
|
73
|
-
icon: '😊',
|
|
74
70
|
},
|
|
75
71
|
];
|
|
76
72
|
const getInstructionMap = (strings) => ({
|
|
77
|
-
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT'
|
|
78
|
-
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT'
|
|
79
|
-
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP'
|
|
80
|
-
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN'
|
|
81
|
-
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT'
|
|
82
|
-
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT'
|
|
83
|
-
smile: { text: strings.liveness.instructions.smile || 'Smile
|
|
84
|
-
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally'
|
|
85
|
-
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly'
|
|
86
|
-
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions'
|
|
73
|
+
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT' },
|
|
74
|
+
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT' },
|
|
75
|
+
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP' },
|
|
76
|
+
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN' },
|
|
77
|
+
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT' },
|
|
78
|
+
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT' },
|
|
79
|
+
smile: { text: strings.liveness.instructions.smile || 'Smile' },
|
|
80
|
+
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally' },
|
|
81
|
+
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly' },
|
|
82
|
+
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions' },
|
|
87
83
|
});
|
|
88
84
|
const VideoRecorder = ({ theme, language, duration, instructions, challenges: propChallenges, sessionId, smartMode = true, onComplete, onCancel, onFetchChallenges, }) => {
|
|
89
85
|
(0, react_1.useEffect)(() => {
|
|
@@ -183,7 +179,6 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
183
179
|
instruction: currentStrings.liveness.instructions.stayStill || 'Look at the camera and stay still',
|
|
184
180
|
duration_ms: duration || 5000,
|
|
185
181
|
order: 1,
|
|
186
|
-
icon: '📷',
|
|
187
182
|
},
|
|
188
183
|
];
|
|
189
184
|
}
|
|
@@ -346,11 +341,35 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
346
341
|
});
|
|
347
342
|
if (photo) {
|
|
348
343
|
consecutiveErrors = 0;
|
|
344
|
+
let base64Data = null;
|
|
349
345
|
try {
|
|
350
346
|
const RNFS = require('react-native-fs');
|
|
351
|
-
|
|
347
|
+
base64Data = await RNFS.readFile(photo.path, 'base64');
|
|
348
|
+
}
|
|
349
|
+
catch (fsError) {
|
|
350
|
+
try {
|
|
351
|
+
const fileUri = react_native_1.Platform.OS === 'android' ? `file://${photo.path}` : photo.path;
|
|
352
|
+
const response = await fetch(fileUri);
|
|
353
|
+
const blob = await response.blob();
|
|
354
|
+
base64Data = await new Promise((resolve, reject) => {
|
|
355
|
+
const reader = new FileReader();
|
|
356
|
+
reader.onloadend = () => {
|
|
357
|
+
const result = reader.result;
|
|
358
|
+
const base64 = result.includes(',') ? result.split(',')[1] : result;
|
|
359
|
+
resolve(base64);
|
|
360
|
+
};
|
|
361
|
+
reader.onerror = reject;
|
|
362
|
+
reader.readAsDataURL(blob);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
catch (fetchError) {
|
|
366
|
+
biometric_identity_sdk_core_1.logger.error('Failed to read photo file as base64:', fetchError);
|
|
367
|
+
base64Data = null;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (base64Data) {
|
|
352
371
|
setFrames(prev => {
|
|
353
|
-
const newFrames = prev.length < 100 ? [...prev,
|
|
372
|
+
const newFrames = prev.length < 100 ? [...prev, base64Data] : prev;
|
|
354
373
|
framesRef.current = newFrames;
|
|
355
374
|
if (newFrames.length % 10 === 0) {
|
|
356
375
|
biometric_identity_sdk_core_1.logger.info('Captured frames:', newFrames.length);
|
|
@@ -358,13 +377,8 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
358
377
|
return newFrames;
|
|
359
378
|
});
|
|
360
379
|
}
|
|
361
|
-
|
|
362
|
-
biometric_identity_sdk_core_1.logger.warn('Could not
|
|
363
|
-
setFrames(prev => {
|
|
364
|
-
const newFrames = prev.length < 100 ? [...prev, photo.path] : prev;
|
|
365
|
-
framesRef.current = newFrames;
|
|
366
|
-
return newFrames;
|
|
367
|
-
});
|
|
380
|
+
else {
|
|
381
|
+
biometric_identity_sdk_core_1.logger.warn('Could not convert photo to base64, skipping frame');
|
|
368
382
|
}
|
|
369
383
|
}
|
|
370
384
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexar/biometric-identity-sdk-react-native",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"description": "React Native wrapper for Biometric Identity SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"clean": "rm -rf dist"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"@hexar/biometric-identity-sdk-core": ">=1.0.
|
|
14
|
+
"@hexar/biometric-identity-sdk-core": ">=1.0.16",
|
|
15
15
|
"react": ">=18.0.0",
|
|
16
16
|
"react-native": ">=0.70.0",
|
|
17
17
|
"react-native-permissions": ">=4.0.0",
|
|
@@ -29,17 +29,17 @@ import { useBiometricSDK } from '../hooks/useBiometricSDK';
|
|
|
29
29
|
import { CameraCapture } from './CameraCapture';
|
|
30
30
|
import { VideoRecorder, VideoRecordingResult } from './VideoRecorder';
|
|
31
31
|
|
|
32
|
-
const getInstructionMap = (strings: any): Record<string, { text: string; icon
|
|
33
|
-
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT'
|
|
34
|
-
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT'
|
|
35
|
-
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP'
|
|
36
|
-
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN'
|
|
37
|
-
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT'
|
|
38
|
-
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT'
|
|
39
|
-
smile: { text: strings.liveness.instructions.smile || 'Smile
|
|
40
|
-
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally'
|
|
41
|
-
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly'
|
|
42
|
-
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions'
|
|
32
|
+
const getInstructionMap = (strings: any): Record<string, { text: string; icon?: string }> => ({
|
|
33
|
+
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT' },
|
|
34
|
+
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT' },
|
|
35
|
+
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP' },
|
|
36
|
+
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN' },
|
|
37
|
+
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT' },
|
|
38
|
+
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT' },
|
|
39
|
+
smile: { text: strings.liveness.instructions.smile || 'Smile' },
|
|
40
|
+
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally' },
|
|
41
|
+
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly' },
|
|
42
|
+
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions' },
|
|
43
43
|
});
|
|
44
44
|
import { ValidationProgress } from './ValidationProgress';
|
|
45
45
|
import { ResultScreen } from './ResultScreen';
|
|
@@ -62,42 +62,38 @@ const getDefaultChallenges = (strings: any): ChallengeAction[] => [
|
|
|
62
62
|
instruction: strings.liveness.instructions.lookLeft || 'Slowly turn your head to the LEFT',
|
|
63
63
|
duration_ms: 2500,
|
|
64
64
|
order: 1,
|
|
65
|
-
icon: '←',
|
|
66
65
|
},
|
|
67
66
|
{
|
|
68
67
|
action: 'look_right',
|
|
69
68
|
instruction: strings.liveness.instructions.lookRight || 'Slowly turn your head to the RIGHT',
|
|
70
69
|
duration_ms: 2500,
|
|
71
70
|
order: 2,
|
|
72
|
-
icon: '→',
|
|
73
71
|
},
|
|
74
72
|
{
|
|
75
73
|
action: 'blink',
|
|
76
74
|
instruction: strings.liveness.instructions.blink || 'Blink your eyes naturally',
|
|
77
75
|
duration_ms: 2000,
|
|
78
76
|
order: 3,
|
|
79
|
-
icon: '👁',
|
|
80
77
|
},
|
|
81
78
|
{
|
|
82
79
|
action: 'smile',
|
|
83
|
-
instruction: strings.liveness.instructions.smile || 'Smile
|
|
80
|
+
instruction: strings.liveness.instructions.smile || 'Smile',
|
|
84
81
|
duration_ms: 2000,
|
|
85
82
|
order: 4,
|
|
86
|
-
icon: '😊',
|
|
87
83
|
},
|
|
88
84
|
];
|
|
89
85
|
|
|
90
|
-
const getInstructionMap = (strings: any): Record<string, { text: string; icon
|
|
91
|
-
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT'
|
|
92
|
-
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT'
|
|
93
|
-
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP'
|
|
94
|
-
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN'
|
|
95
|
-
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT'
|
|
96
|
-
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT'
|
|
97
|
-
smile: { text: strings.liveness.instructions.smile || 'Smile
|
|
98
|
-
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally'
|
|
99
|
-
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly'
|
|
100
|
-
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions'
|
|
86
|
+
const getInstructionMap = (strings: any): Record<string, { text: string; icon?: string }> => ({
|
|
87
|
+
look_left: { text: strings.liveness.instructions.lookLeft || 'Slowly turn your head LEFT' },
|
|
88
|
+
look_right: { text: strings.liveness.instructions.lookRight || 'Slowly turn your head RIGHT' },
|
|
89
|
+
look_up: { text: strings.liveness.instructions.lookUp || 'Look UP' },
|
|
90
|
+
look_down: { text: strings.liveness.instructions.lookDown || 'Look DOWN' },
|
|
91
|
+
turn_head_left: { text: strings.liveness.instructions.turnHeadLeft || 'Turn your head LEFT' },
|
|
92
|
+
turn_head_right: { text: strings.liveness.instructions.turnHeadRight || 'Turn your head RIGHT' },
|
|
93
|
+
smile: { text: strings.liveness.instructions.smile || 'Smile' },
|
|
94
|
+
blink: { text: strings.liveness.instructions.blink || 'Blink your eyes naturally' },
|
|
95
|
+
open_mouth: { text: strings.liveness.instructions.openMouth || 'Open your mouth slightly' },
|
|
96
|
+
stay_still: { text: strings.liveness.instructions.stayStill || 'Look at the camera and follow the instructions' },
|
|
101
97
|
});
|
|
102
98
|
|
|
103
99
|
export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
@@ -213,17 +209,16 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
213
209
|
order: idx + 1,
|
|
214
210
|
icon: instructionMap[inst]?.icon,
|
|
215
211
|
}));
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
212
|
+
} else {
|
|
213
|
+
challengeList = smartMode ? getDefaultChallenges(currentStrings) : [
|
|
214
|
+
{
|
|
215
|
+
action: 'stay_still',
|
|
216
|
+
instruction: currentStrings.liveness.instructions.stayStill || 'Look at the camera and stay still',
|
|
217
|
+
duration_ms: duration || 5000,
|
|
218
|
+
order: 1,
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
}
|
|
227
222
|
|
|
228
223
|
setChallenges(challengeList);
|
|
229
224
|
setPhase('countdown');
|
|
@@ -416,24 +411,43 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
416
411
|
|
|
417
412
|
if (photo) {
|
|
418
413
|
consecutiveErrors = 0;
|
|
414
|
+
let base64Data: string | null = null;
|
|
415
|
+
|
|
419
416
|
try {
|
|
420
417
|
const RNFS = require('react-native-fs');
|
|
421
|
-
|
|
418
|
+
base64Data = await RNFS.readFile(photo.path, 'base64');
|
|
419
|
+
} catch (fsError) {
|
|
420
|
+
try {
|
|
421
|
+
const fileUri = Platform.OS === 'android' ? `file://${photo.path}` : photo.path;
|
|
422
|
+
const response = await fetch(fileUri);
|
|
423
|
+
const blob = await response.blob();
|
|
424
|
+
base64Data = await new Promise<string>((resolve, reject) => {
|
|
425
|
+
const reader = new FileReader();
|
|
426
|
+
reader.onloadend = () => {
|
|
427
|
+
const result = reader.result as string;
|
|
428
|
+
const base64 = result.includes(',') ? result.split(',')[1] : result;
|
|
429
|
+
resolve(base64);
|
|
430
|
+
};
|
|
431
|
+
reader.onerror = reject;
|
|
432
|
+
reader.readAsDataURL(blob);
|
|
433
|
+
});
|
|
434
|
+
} catch (fetchError) {
|
|
435
|
+
logger.error('Failed to read photo file as base64:', fetchError);
|
|
436
|
+
base64Data = null;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (base64Data) {
|
|
422
441
|
setFrames(prev => {
|
|
423
|
-
const newFrames = prev.length < 100 ? [...prev,
|
|
442
|
+
const newFrames = prev.length < 100 ? [...prev, base64Data!] : prev;
|
|
424
443
|
framesRef.current = newFrames;
|
|
425
444
|
if (newFrames.length % 10 === 0) {
|
|
426
445
|
logger.info('Captured frames:', newFrames.length);
|
|
427
446
|
}
|
|
428
447
|
return newFrames;
|
|
429
448
|
});
|
|
430
|
-
}
|
|
431
|
-
logger.warn('Could not
|
|
432
|
-
setFrames(prev => {
|
|
433
|
-
const newFrames = prev.length < 100 ? [...prev, photo.path] : prev;
|
|
434
|
-
framesRef.current = newFrames;
|
|
435
|
-
return newFrames;
|
|
436
|
-
});
|
|
449
|
+
} else {
|
|
450
|
+
logger.warn('Could not convert photo to base64, skipping frame');
|
|
437
451
|
}
|
|
438
452
|
}
|
|
439
453
|
} catch (error: any) {
|