react-native-biometric-verifier 0.0.6 → 0.0.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-biometric-verifier",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "A React Native module for biometric verification with face recognition and QR code scanning",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -2,10 +2,10 @@ import React, { useState } from 'react';
2
2
  import { View, Text, Image } from 'react-native';
3
3
  import Icon from 'react-native-vector-icons/MaterialIcons';
4
4
  import PropTypes from 'prop-types';
5
- import { COLORS ,GIF_URL,IMAGE_URL} from '../utils/constants';
5
+ import { COLORS} from '../utils/constants';
6
6
  import { styles } from './styles';
7
7
 
8
- export const EmployeeCard = ({ employeeData }) => {
8
+ export const EmployeeCard = ({ employeeData,apiurl }) => {
9
9
  const [imageError, setImageError] = useState(false);
10
10
 
11
11
  if (!employeeData || typeof employeeData !== 'object') {
@@ -18,8 +18,8 @@ export const EmployeeCard = ({ employeeData }) => {
18
18
  const employeeName = facename || 'Unknown Employee';
19
19
  const employeeId = faceid || 'N/A';
20
20
  const imageSource = !imageError && imageurl
21
- ? { uri: `${IMAGE_URL}${imageurl}` }
22
- : { uri: `${GIF_URL}camera.png` }; // Add a local fallback image in assets
21
+ ? { uri: `${apiurl}file/filedownload/photo/${imageurl}` }
22
+ : { uri: `${apiurl}file/getCommonFile/image/camera.png` }; // Add a local fallback image in assets
23
23
 
24
24
  return (
25
25
  <View style={styles.employeeCard}>
package/src/index.js CHANGED
@@ -16,7 +16,6 @@ import {
16
16
  COLORS,
17
17
  COUNTDOWN_DURATION,
18
18
  MAX_DISTANCE_METERS,
19
- RECOGNIZE_URL,
20
19
  } from './utils/constants';
21
20
  import Loader from './components/Loader';
22
21
  import { CountdownTimer } from './components/CountdownTimer';
@@ -28,9 +27,9 @@ import { useNavigation } from '@react-navigation/native';
28
27
  import networkServiceCall from './utils/NetworkServiceCall';
29
28
  import { getLoaderGif } from './utils/getLoaderGif';
30
29
 
31
- const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback }) => {
30
+ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback, apiurl }) => {
32
31
  const navigation = useNavigation();
33
-
32
+
34
33
  const { countdown, startCountdown, resetCountdown } = useCountdown();
35
34
  const { requestLocationPermission, getCurrentLocation } = useGeolocation();
36
35
  const { convertImageToBase64 } = useImageProcessing();
@@ -80,19 +79,39 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
80
79
  animationState: ANIMATION_STATES.ERROR,
81
80
  });
82
81
  resetState();
83
- navigation.goBack();
82
+ if (navigation.canGoBack()) navigation.goBack();
84
83
  }, [navigation, notifyMessage, resetState, updateState]);
85
84
 
85
+ const validateApiUrl = useCallback(() => {
86
+ if (!apiurl || typeof apiurl !== 'string') {
87
+ notifyMessage('Invalid API URL configuration.', 'error');
88
+ updateState({ animationState: ANIMATION_STATES.ERROR });
89
+ return false;
90
+ }
91
+ return true;
92
+ }, [apiurl, notifyMessage, updateState]);
93
+
86
94
  const uploadFaceScan = useCallback(async (selfie) => {
95
+ if (!validateApiUrl()) return;
96
+
87
97
  const currentData = dataRef.current;
88
- const base64 = await convertImageToBase64(selfie.uri);
89
98
  if (!currentData) {
90
99
  notifyMessage('Employee data not found.', 'error');
91
100
  updateState({ animationState: ANIMATION_STATES.ERROR });
92
101
  return;
93
102
  }
103
+
104
+ let base64;
105
+ try {
106
+ base64 = await convertImageToBase64(selfie?.uri);
107
+ } catch (err) {
108
+ notifyMessage('Image conversion failed.', 'error');
109
+ updateState({ animationState: ANIMATION_STATES.ERROR });
110
+ return;
111
+ }
112
+
94
113
  if (!base64) {
95
- notifyMessage('convert Image To Base64 Failed.', 'error');
114
+ notifyMessage('Failed to process image.', 'error');
96
115
  updateState({ animationState: ANIMATION_STATES.ERROR });
97
116
  return;
98
117
  }
@@ -103,38 +122,50 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
103
122
  });
104
123
 
105
124
  try {
106
- const body = { image: base64 }
107
- const header = { faceid: currentData }
108
- const response = await networkServiceCall("POST",RECOGNIZE_URL,header,body);
109
- if (response.httpstatus === 200) {
125
+ const body = { image: base64 };
126
+ const header = { faceid: currentData };
127
+ const buttonapi = `${apiurl}python/recognize`;
128
+
129
+ console.log("buttonapi--------------------", buttonapi);
130
+
131
+ const response = await networkServiceCall("POST", buttonapi, header, body);
132
+
133
+ if (response?.httpstatus === 200) {
110
134
  notifyMessage('Identity verified successfully!', 'success');
111
135
  updateState({
112
- employeeData: response.data?.data,
136
+ employeeData: response.data?.data || null,
113
137
  animationState: ANIMATION_STATES.SUCCESS,
114
138
  });
115
139
 
116
140
  if (qrscan) {
117
- // If QR scanning is required, continue with QR Scan
118
141
  setTimeout(() => startQRCodeScan(), 1500);
119
142
  } else {
120
- // If only Face recognition → finish process
121
143
  setTimeout(() => {
122
- callback?.(dataRef.current);
144
+ try {
145
+ callback?.(dataRef.current);
146
+ } catch (err) {
147
+ console.error("Callback execution failed:", err);
148
+ notifyMessage('Unexpected error after verification.', 'error');
149
+ }
123
150
  updateState({ modalVisible: false });
124
151
  resetState();
125
152
  }, 1500);
126
153
  }
127
154
  } else {
155
+ notifyMessage(
156
+ response?.data?.error?.message || 'Face not recognized. Please try again.',
157
+ 'error'
158
+ );
128
159
  updateState({ animationState: ANIMATION_STATES.ERROR });
129
- notifyMessage(response.data?.error?.message || 'Face not recognized. Please try again.', 'error');
130
160
  }
131
161
  } catch (error) {
132
- updateState({ animationState: ANIMATION_STATES.ERROR });
162
+ console.error("Face recognition API error:", error);
133
163
  notifyMessage('Connection error. Please check your network.', 'error');
164
+ updateState({ animationState: ANIMATION_STATES.ERROR });
134
165
  } finally {
135
166
  updateState({ isLoading: false });
136
167
  }
137
- }, [convertImageToBase64, notifyMessage, qrscan, resetState, updateState, callback]);
168
+ }, [convertImageToBase64, notifyMessage, qrscan, resetState, updateState, callback, validateApiUrl]);
138
169
 
139
170
  const handleStartFaceScan = useCallback(() => {
140
171
  updateState({
@@ -162,9 +193,11 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
162
193
  }, [navigation, updateState]);
163
194
 
164
195
  const handleQRScanned = useCallback(async (qrCodeData) => {
165
- updateState({
196
+ if (!validateApiUrl()) return;
197
+
198
+ updateState({
166
199
  animationState: ANIMATION_STATES.PROCESSING,
167
- isLoading: true
200
+ isLoading: true,
168
201
  });
169
202
 
170
203
  try {
@@ -175,7 +208,7 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
175
208
  return;
176
209
  }
177
210
 
178
- const qrString = typeof qrCodeData === 'object' ? qrCodeData.data : qrCodeData;
211
+ const qrString = typeof qrCodeData === 'object' ? qrCodeData?.data : qrCodeData;
179
212
  if (!qrString || typeof qrString !== 'string') {
180
213
  notifyMessage('Invalid QR code. Please try again.', 'error');
181
214
  updateState({ animationState: ANIMATION_STATES.ERROR });
@@ -188,18 +221,19 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
188
221
  const lng = parseFloat(lngStr);
189
222
 
190
223
  const validCoords = !isNaN(lat) && !isNaN(lng);
191
- const validDev = !isNaN(location.latitude) && !isNaN(location.longitude);
224
+ const validDev = !isNaN(location?.latitude) && !isNaN(location?.longitude);
192
225
 
193
226
  if (validCoords && validDev) {
194
- const distance = getDistanceInMeters(
195
- lat,
196
- lng,
197
- location.latitude,
198
- location.longitude
199
- );
227
+ const distance = getDistanceInMeters(lat, lng, location.latitude, location.longitude);
200
228
 
201
229
  if (distance <= MAX_DISTANCE_METERS) {
202
- callback?.(dataRef.current);
230
+ try {
231
+ callback?.(dataRef.current);
232
+ } catch (err) {
233
+ console.error("Callback execution failed:", err);
234
+ notifyMessage('Unexpected error during location verification.', 'error');
235
+ }
236
+
203
237
  notifyMessage('Location verified successfully!', 'success');
204
238
  updateState({ animationState: ANIMATION_STATES.SUCCESS });
205
239
 
@@ -218,13 +252,14 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
218
252
  resetState();
219
253
  }
220
254
  } catch (error) {
255
+ console.error("QR scan handling failed:", error);
221
256
  notifyMessage('Unable to verify location. Please try again.', 'error');
222
257
  updateState({ animationState: ANIMATION_STATES.ERROR });
223
258
  resetState();
224
259
  } finally {
225
260
  updateState({ isLoading: false });
226
261
  }
227
- }, [callback, getCurrentLocation, notifyMessage, requestLocationPermission, resetState, updateState]);
262
+ }, [callback, getCurrentLocation, notifyMessage, requestLocationPermission, resetState, updateState, validateApiUrl]);
228
263
 
229
264
  const startProcess = useCallback(() => {
230
265
  startCountdown(COUNTDOWN_DURATION, handleCountdownFinish);
@@ -270,7 +305,7 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
270
305
  {state.employeeData && (
271
306
  <EmployeeCard
272
307
  employeeData={state.employeeData}
273
- hrenemp={dataRef.current?.data?.userdata?.hrenemp}
308
+ apiurl={apiurl}
274
309
  />
275
310
  )}
276
311
 
@@ -285,8 +320,8 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
285
320
  currentTime={countdown}
286
321
  />
287
322
 
288
- {state.isLoading && getLoaderGif(state.animationState, state.currentStep) && (
289
- <Loader source={getLoaderGif(state.animationState, state.currentStep)} />
323
+ {state.isLoading && getLoaderGif(state.animationState, state.currentStep, apiurl) && (
324
+ <Loader source={getLoaderGif(state.animationState, state.currentStep, apiurl)} />
290
325
  )}
291
326
  </View>
292
327
  </Modal>
@@ -1,15 +1,3 @@
1
- import { Global } from "./Global";
2
-
3
- // ====== BASE CONFIG ======
4
- export const BASE_URL = Global.ipAddress;
5
- export const PORT = Global.port;
6
- export const APIURL = `http://${BASE_URL}:${PORT}/`;
7
-
8
- // ====== API ENDPOINTS ======
9
- export const RECOGNIZE_URL = APIURL + "python/recognize";
10
- export const IMAGE_URL = APIURL + "file/filedownload/photo/";
11
- export const GIF_URL = APIURL + "file/getCommonFile/image/";
12
-
13
1
 
14
2
  // ====== COLORS ======
15
3
  export const COLORS = {
@@ -1,4 +1,4 @@
1
- import { ANIMATION_STATES, GIF_URL } from '../utils/constants';
1
+ import { ANIMATION_STATES} from '../utils/constants';
2
2
 
3
3
  /**
4
4
  * Decides which GIF should be shown based on animationState or currentStep
@@ -6,11 +6,11 @@ import { ANIMATION_STATES, GIF_URL } from '../utils/constants';
6
6
  * @param {string} currentStep - Current step of verification
7
7
  * @returns {any} - Gif image source or null
8
8
  */
9
- export const getLoaderGif = (animationState, currentStep) => {
9
+ export const getLoaderGif = (animationState, currentStep,APIURL) => {
10
10
  const FaceGifUrl =
11
- `${GIF_URL}Face.gif`;
11
+ `${APIURL}file/getCommonFile/image/Face.gif`;
12
12
  const LocationGifUrl =
13
- `${GIF_URL}Location.gif`;
13
+ `${APIURL}file/getCommonFile/image/Location.gif`;
14
14
 
15
15
  if (
16
16
  animationState === ANIMATION_STATES.FACE_SCAN ||
@@ -1,6 +0,0 @@
1
- export class Global {
2
- static ipAddress = "api.amalaplus.org";
3
- static port = "9090";
4
-
5
- }
6
-