@hexar/biometric-identity-sdk-react-native 1.12.0 → 1.13.0
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/components/CameraCapture.d.ts.map +1 -1
- package/dist/components/CameraCapture.js +16 -0
- package/dist/components/VideoRecorder.d.ts.map +1 -1
- package/dist/components/VideoRecorder.js +18 -0
- package/package.json +1 -1
- package/src/components/CameraCapture.tsx +26 -2
- package/src/components/VideoRecorder.tsx +27 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CameraCapture.d.ts","sourceRoot":"","sources":["../../src/components/CameraCapture.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAsC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"CameraCapture.d.ts","sourceRoot":"","sources":["../../src/components/CameraCapture.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAIrH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqQtD,CAAC;AA0JF,eAAe,aAAa,CAAC"}
|
|
@@ -47,6 +47,7 @@ const { width, height } = react_native_1.Dimensions.get('window');
|
|
|
47
47
|
const CameraCapture = ({ mode, theme, language, onCapture, onCancel, }) => {
|
|
48
48
|
const [isCapturing, setIsCapturing] = (0, react_1.useState)(false);
|
|
49
49
|
const [hasPermission, setHasPermission] = (0, react_1.useState)(false);
|
|
50
|
+
const [deviceReady, setDeviceReady] = (0, react_1.useState)(false);
|
|
50
51
|
const cameraRef = (0, react_1.useRef)(null);
|
|
51
52
|
const { hasPermission: cameraPermission, requestPermission } = (0, react_native_vision_camera_1.useCameraPermission)();
|
|
52
53
|
if (language) {
|
|
@@ -58,6 +59,15 @@ const CameraCapture = ({ mode, theme, language, onCapture, onCancel, }) => {
|
|
|
58
59
|
(0, react_1.useEffect)(() => {
|
|
59
60
|
checkPermissions();
|
|
60
61
|
}, []);
|
|
62
|
+
// Wait for camera device to become available
|
|
63
|
+
(0, react_1.useEffect)(() => {
|
|
64
|
+
if (device) {
|
|
65
|
+
setDeviceReady(true);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const timeout = setTimeout(() => setDeviceReady(true), 5000);
|
|
69
|
+
return () => clearTimeout(timeout);
|
|
70
|
+
}, [device]);
|
|
61
71
|
const checkPermissions = async () => {
|
|
62
72
|
try {
|
|
63
73
|
// First check if we already have permission from the hook
|
|
@@ -172,6 +182,12 @@ const CameraCapture = ({ mode, theme, language, onCapture, onCancel, }) => {
|
|
|
172
182
|
react_1.default.createElement(react_native_1.Text, { style: styles.buttonText }, strings.common.cancel || 'Cancel')))));
|
|
173
183
|
}
|
|
174
184
|
if (!device) {
|
|
185
|
+
if (!deviceReady) {
|
|
186
|
+
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
187
|
+
react_1.default.createElement(react_native_1.View, { style: styles.permissionContainer },
|
|
188
|
+
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: theme?.primaryColor || '#6366F1' }),
|
|
189
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.permissionText, { marginTop: 16 }] }, strings.liveness.preparing || 'Preparing camera...'))));
|
|
190
|
+
}
|
|
175
191
|
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
176
192
|
react_1.default.createElement(react_native_1.View, { style: styles.permissionContainer },
|
|
177
193
|
react_1.default.createElement(react_native_1.Text, { style: styles.permissionText }, strings.errors.cameraNotAvailable || 'Camera not available'),
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAcxE,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;AA2CD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAy6BtD,CAAC;AA6OF,eAAe,aAAa,CAAC"}
|
|
@@ -100,6 +100,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
100
100
|
const [frames, setFrames] = (0, react_1.useState)([]);
|
|
101
101
|
const framesRef = (0, react_1.useRef)([]);
|
|
102
102
|
const [hasPermission, setHasPermission] = (0, react_1.useState)(false);
|
|
103
|
+
const [deviceReady, setDeviceReady] = (0, react_1.useState)(false);
|
|
103
104
|
const cameraRef = (0, react_1.useRef)(null);
|
|
104
105
|
const { hasPermission: cameraPermission, requestPermission } = (0, react_native_vision_camera_1.useCameraPermission)();
|
|
105
106
|
const device = (0, react_native_vision_camera_1.useCameraDevice)('front');
|
|
@@ -144,6 +145,16 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
144
145
|
};
|
|
145
146
|
checkPermissions();
|
|
146
147
|
}, [cameraPermission, requestPermission]);
|
|
148
|
+
// Wait for camera device to become available (some Android OEMs
|
|
149
|
+
// take a few hundred ms to enumerate cameras after permission grant).
|
|
150
|
+
(0, react_1.useEffect)(() => {
|
|
151
|
+
if (device) {
|
|
152
|
+
setDeviceReady(true);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const timeout = setTimeout(() => setDeviceReady(true), 5000);
|
|
156
|
+
return () => clearTimeout(timeout);
|
|
157
|
+
}, [device]);
|
|
147
158
|
(0, react_1.useEffect)(() => {
|
|
148
159
|
const initChallenges = async () => {
|
|
149
160
|
try {
|
|
@@ -687,6 +698,13 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
687
698
|
react_1.default.createElement(react_native_1.Text, { style: [styles.cancelButtonText, { color: theme?.errorColor || '#EF4444' }] }, strings.common.cancel || 'Cancel')))));
|
|
688
699
|
}
|
|
689
700
|
if (!device) {
|
|
701
|
+
// Still waiting for camera to enumerate — show loading instead of error
|
|
702
|
+
if (!deviceReady) {
|
|
703
|
+
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
704
|
+
react_1.default.createElement(react_native_1.View, { style: styles.permissionContainer },
|
|
705
|
+
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: theme?.primaryColor || '#6366F1' }),
|
|
706
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.permissionText, { marginTop: 16 }] }, strings.liveness.preparing || 'Preparing camera...'))));
|
|
707
|
+
}
|
|
690
708
|
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
691
709
|
react_1.default.createElement(react_native_1.View, { style: styles.permissionContainer },
|
|
692
710
|
react_1.default.createElement(react_native_1.Text, { style: styles.permissionText }, strings.errors.cameraNotAvailable || 'Camera not available'),
|
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
Dimensions,
|
|
13
13
|
Platform,
|
|
14
14
|
Alert,
|
|
15
|
+
ActivityIndicator,
|
|
15
16
|
} from 'react-native';
|
|
16
17
|
import { Camera, useCameraDevice, useCameraPermission } from 'react-native-vision-camera';
|
|
17
18
|
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions';
|
|
@@ -36,14 +37,15 @@ export const CameraCapture: React.FC<CameraCaptureProps> = ({
|
|
|
36
37
|
}) => {
|
|
37
38
|
const [isCapturing, setIsCapturing] = useState(false);
|
|
38
39
|
const [hasPermission, setHasPermission] = useState(false);
|
|
40
|
+
const [deviceReady, setDeviceReady] = useState(false);
|
|
39
41
|
const cameraRef = useRef<Camera>(null);
|
|
40
42
|
const { hasPermission: cameraPermission, requestPermission } = useCameraPermission();
|
|
41
|
-
|
|
43
|
+
|
|
42
44
|
if (language) {
|
|
43
45
|
setLanguage(language);
|
|
44
46
|
}
|
|
45
47
|
const strings = getStrings();
|
|
46
|
-
|
|
48
|
+
|
|
47
49
|
// Get camera device (back camera for document capture)
|
|
48
50
|
const device = useCameraDevice('back');
|
|
49
51
|
|
|
@@ -51,6 +53,16 @@ export const CameraCapture: React.FC<CameraCaptureProps> = ({
|
|
|
51
53
|
checkPermissions();
|
|
52
54
|
}, []);
|
|
53
55
|
|
|
56
|
+
// Wait for camera device to become available
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (device) {
|
|
59
|
+
setDeviceReady(true);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const timeout = setTimeout(() => setDeviceReady(true), 5000);
|
|
63
|
+
return () => clearTimeout(timeout);
|
|
64
|
+
}, [device]);
|
|
65
|
+
|
|
54
66
|
const checkPermissions = async () => {
|
|
55
67
|
try {
|
|
56
68
|
// First check if we already have permission from the hook
|
|
@@ -190,6 +202,18 @@ export const CameraCapture: React.FC<CameraCaptureProps> = ({
|
|
|
190
202
|
}
|
|
191
203
|
|
|
192
204
|
if (!device) {
|
|
205
|
+
if (!deviceReady) {
|
|
206
|
+
return (
|
|
207
|
+
<View style={styles.container}>
|
|
208
|
+
<View style={styles.permissionContainer}>
|
|
209
|
+
<ActivityIndicator size="large" color={theme?.primaryColor || '#6366F1'} />
|
|
210
|
+
<Text style={[styles.permissionText, { marginTop: 16 }]}>
|
|
211
|
+
{strings.liveness.preparing || 'Preparing camera...'}
|
|
212
|
+
</Text>
|
|
213
|
+
</View>
|
|
214
|
+
</View>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
193
217
|
return (
|
|
194
218
|
<View style={styles.container}>
|
|
195
219
|
<View style={styles.permissionContainer}>
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
Easing,
|
|
14
14
|
Platform,
|
|
15
15
|
Alert,
|
|
16
|
+
ActivityIndicator,
|
|
16
17
|
} from 'react-native';
|
|
17
18
|
import { Camera, useCameraDevice, useCameraPermission } from 'react-native-vision-camera';
|
|
18
19
|
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions';
|
|
@@ -127,7 +128,8 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
127
128
|
const [frames, setFrames] = useState<string[]>([]);
|
|
128
129
|
const framesRef = useRef<string[]>([]);
|
|
129
130
|
const [hasPermission, setHasPermission] = useState(false);
|
|
130
|
-
|
|
131
|
+
const [deviceReady, setDeviceReady] = useState(false);
|
|
132
|
+
|
|
131
133
|
const cameraRef = useRef<Camera>(null);
|
|
132
134
|
const { hasPermission: cameraPermission, requestPermission } = useCameraPermission();
|
|
133
135
|
const device = useCameraDevice('front');
|
|
@@ -183,6 +185,17 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
183
185
|
checkPermissions();
|
|
184
186
|
}, [cameraPermission, requestPermission]);
|
|
185
187
|
|
|
188
|
+
// Wait for camera device to become available (some Android OEMs
|
|
189
|
+
// take a few hundred ms to enumerate cameras after permission grant).
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
if (device) {
|
|
192
|
+
setDeviceReady(true);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const timeout = setTimeout(() => setDeviceReady(true), 5000);
|
|
196
|
+
return () => clearTimeout(timeout);
|
|
197
|
+
}, [device]);
|
|
198
|
+
|
|
186
199
|
useEffect(() => {
|
|
187
200
|
const initChallenges = async () => {
|
|
188
201
|
try {
|
|
@@ -824,6 +837,19 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
824
837
|
}
|
|
825
838
|
|
|
826
839
|
if (!device) {
|
|
840
|
+
// Still waiting for camera to enumerate — show loading instead of error
|
|
841
|
+
if (!deviceReady) {
|
|
842
|
+
return (
|
|
843
|
+
<View style={styles.container}>
|
|
844
|
+
<View style={styles.permissionContainer}>
|
|
845
|
+
<ActivityIndicator size="large" color={theme?.primaryColor || '#6366F1'} />
|
|
846
|
+
<Text style={[styles.permissionText, { marginTop: 16 }]}>
|
|
847
|
+
{strings.liveness.preparing || 'Preparing camera...'}
|
|
848
|
+
</Text>
|
|
849
|
+
</View>
|
|
850
|
+
</View>
|
|
851
|
+
);
|
|
852
|
+
}
|
|
827
853
|
return (
|
|
828
854
|
<View style={styles.container}>
|
|
829
855
|
<View style={styles.permissionContainer}>
|