react-native-biometric-verifier 0.0.2 → 0.0.3
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 +1 -1
- package/src/Asset/gif/Face.gif +0 -0
- package/src/Asset/gif/Fingerprint.gif +0 -0
- package/src/Asset/gif/Location.gif +0 -0
- package/src/components/Loader.js +58 -0
- package/src/index.js +16 -23
- package/src/utils/getLoaderGif.js +27 -0
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StyleSheet,
|
|
3
|
+
Dimensions,
|
|
4
|
+
View,
|
|
5
|
+
Modal,
|
|
6
|
+
} from "react-native";
|
|
7
|
+
import { normalize } from "react-native-elements";
|
|
8
|
+
import FastImage from "react-native-fast-image";
|
|
9
|
+
|
|
10
|
+
export default function Loader({ visible = true,source }) {
|
|
11
|
+
return (
|
|
12
|
+
<Modal
|
|
13
|
+
animationType="none"
|
|
14
|
+
transparent={true}
|
|
15
|
+
visible={visible}
|
|
16
|
+
onRequestClose={() => {}}
|
|
17
|
+
>
|
|
18
|
+
<View style={styles.container}>
|
|
19
|
+
<View style={styles.loaderBox}>
|
|
20
|
+
<FastImage
|
|
21
|
+
style={styles.icon}
|
|
22
|
+
source={source}
|
|
23
|
+
/>
|
|
24
|
+
</View>
|
|
25
|
+
</View>
|
|
26
|
+
</Modal>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const { width, height } = Dimensions.get("window");
|
|
31
|
+
|
|
32
|
+
const styles = StyleSheet.create({
|
|
33
|
+
container: {
|
|
34
|
+
justifyContent: "center",
|
|
35
|
+
alignItems: "center",
|
|
36
|
+
height,
|
|
37
|
+
width,
|
|
38
|
+
backgroundColor: "rgba(0,0,0,0.3)", // semi-transparent backdrop
|
|
39
|
+
},
|
|
40
|
+
loaderBox: {
|
|
41
|
+
borderRadius: normalize(20),
|
|
42
|
+
padding: 10,
|
|
43
|
+
backgroundColor: "white",
|
|
44
|
+
borderWidth: 1,
|
|
45
|
+
borderColor: "lightblue",
|
|
46
|
+
elevation: 5, // shadow on Android
|
|
47
|
+
shadowColor: "#000", // shadow on iOS
|
|
48
|
+
shadowOpacity: 0.2,
|
|
49
|
+
shadowOffset: { width: 0, height: 2 },
|
|
50
|
+
shadowRadius: 4,
|
|
51
|
+
},
|
|
52
|
+
icon: {
|
|
53
|
+
height: normalize(70),
|
|
54
|
+
width: normalize(70),
|
|
55
|
+
justifyContent: "center",
|
|
56
|
+
alignItems: "center",
|
|
57
|
+
},
|
|
58
|
+
});
|
package/src/index.js
CHANGED
|
@@ -4,15 +4,12 @@ import {
|
|
|
4
4
|
TouchableOpacity,
|
|
5
5
|
Text,
|
|
6
6
|
Modal,
|
|
7
|
-
Dimensions,
|
|
8
7
|
} from 'react-native';
|
|
9
8
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
10
|
-
|
|
11
9
|
import { useCountdown } from './hooks/useCountdown';
|
|
12
10
|
import { useGeolocation } from './hooks/useGeolocation';
|
|
13
11
|
import { useImageProcessing } from './hooks/useImageProcessing';
|
|
14
12
|
import { useNotifyMessage } from './hooks/useNotifyMessage';
|
|
15
|
-
import { createLogger } from './utils/logger';
|
|
16
13
|
import { getDistanceInMeters } from './utils/distanceCalculator';
|
|
17
14
|
import {
|
|
18
15
|
ANIMATION_STATES,
|
|
@@ -21,7 +18,7 @@ import {
|
|
|
21
18
|
MAX_DISTANCE_METERS,
|
|
22
19
|
RECOGNIZE_URL,
|
|
23
20
|
} from './utils/constants';
|
|
24
|
-
|
|
21
|
+
import Loader from './components/Loader';
|
|
25
22
|
import { CountdownTimer } from './components/CountdownTimer';
|
|
26
23
|
import { EmployeeCard } from './components/EmployeeCard';
|
|
27
24
|
import { Notification } from './components/Notification';
|
|
@@ -29,6 +26,7 @@ import { StateIndicator } from './components/StateIndicator';
|
|
|
29
26
|
import { styles } from './components/styles';
|
|
30
27
|
import { useNavigation } from '@react-navigation/native';
|
|
31
28
|
import networkServiceCall from './utils/NetworkServiceCall';
|
|
29
|
+
import { getLoaderGif } from './utils/getLoaderGif';
|
|
32
30
|
|
|
33
31
|
const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback }) => {
|
|
34
32
|
const navigation = useNavigation();
|
|
@@ -48,7 +46,6 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
|
|
|
48
46
|
|
|
49
47
|
const dataRef = useRef(data);
|
|
50
48
|
const mountedRef = useRef(true);
|
|
51
|
-
const qrscanRef = useRef(qrscan);
|
|
52
49
|
|
|
53
50
|
useEffect(() => {
|
|
54
51
|
return () => {
|
|
@@ -58,8 +55,7 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
|
|
|
58
55
|
|
|
59
56
|
useEffect(() => {
|
|
60
57
|
dataRef.current = data;
|
|
61
|
-
|
|
62
|
-
}, [data, qrscan]);
|
|
58
|
+
}, [data]);
|
|
63
59
|
|
|
64
60
|
const updateState = useCallback((newState) => {
|
|
65
61
|
if (mountedRef.current) {
|
|
@@ -109,19 +105,19 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
|
|
|
109
105
|
try {
|
|
110
106
|
const body = { image: base64 }
|
|
111
107
|
const header = { hrenemp: currentData }
|
|
112
|
-
const response = await networkServiceCall("POST",
|
|
108
|
+
const response = await networkServiceCall("POST",RECOGNIZE_URL,header,body);
|
|
113
109
|
if (response.httpstatus === 200) {
|
|
114
110
|
notifyMessage('Identity verified successfully!', 'success');
|
|
115
111
|
updateState({
|
|
116
112
|
employeeData: response.data?.data,
|
|
117
113
|
animationState: ANIMATION_STATES.SUCCESS,
|
|
118
114
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
|
|
116
|
+
if (qrscan) {
|
|
117
|
+
// If QR scanning is required, continue with QR Scan
|
|
122
118
|
setTimeout(() => startQRCodeScan(), 1500);
|
|
123
119
|
} else {
|
|
124
|
-
// If only
|
|
120
|
+
// If only Face recognition → finish process
|
|
125
121
|
setTimeout(() => {
|
|
126
122
|
callback?.(dataRef.current);
|
|
127
123
|
updateState({ modalVisible: false });
|
|
@@ -138,7 +134,7 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
|
|
|
138
134
|
} finally {
|
|
139
135
|
updateState({ isLoading: false });
|
|
140
136
|
}
|
|
141
|
-
}, [convertImageToBase64, notifyMessage,
|
|
137
|
+
}, [convertImageToBase64, notifyMessage, qrscan, resetState, updateState, callback]);
|
|
142
138
|
|
|
143
139
|
const handleStartFaceScan = useCallback(() => {
|
|
144
140
|
updateState({
|
|
@@ -163,7 +159,7 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
|
|
|
163
159
|
cameramoduletype: 2,
|
|
164
160
|
onSelect: handleQRScanned,
|
|
165
161
|
});
|
|
166
|
-
}, [navigation, updateState
|
|
162
|
+
}, [navigation, updateState]);
|
|
167
163
|
|
|
168
164
|
const handleQRScanned = useCallback(async (qrCodeData) => {
|
|
169
165
|
updateState({
|
|
@@ -232,14 +228,7 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
|
|
|
232
228
|
|
|
233
229
|
const startProcess = useCallback(() => {
|
|
234
230
|
startCountdown(COUNTDOWN_DURATION, handleCountdownFinish);
|
|
235
|
-
|
|
236
|
-
if (qrscanRef.current) {
|
|
237
|
-
// Start with face scan if QR scanning is enabled
|
|
238
|
-
handleStartFaceScan();
|
|
239
|
-
} else {
|
|
240
|
-
// If only face recognition is needed, start directly with face scan
|
|
241
|
-
handleStartFaceScan();
|
|
242
|
-
}
|
|
231
|
+
handleStartFaceScan();
|
|
243
232
|
}, [handleCountdownFinish, handleStartFaceScan, startCountdown]);
|
|
244
233
|
|
|
245
234
|
useEffect(() => {
|
|
@@ -295,9 +284,13 @@ const BiometricVerificationModal = React.memo(({ data, qrscan = false, callback
|
|
|
295
284
|
duration={COUNTDOWN_DURATION}
|
|
296
285
|
currentTime={countdown}
|
|
297
286
|
/>
|
|
287
|
+
|
|
288
|
+
{state.isLoading && getLoaderGif(state.animationState, state.currentStep) && (
|
|
289
|
+
<Loader source={getLoaderGif(state.animationState, state.currentStep)} />
|
|
290
|
+
)}
|
|
298
291
|
</View>
|
|
299
292
|
</Modal>
|
|
300
293
|
);
|
|
301
294
|
});
|
|
302
295
|
|
|
303
|
-
export default BiometricVerificationModal;
|
|
296
|
+
export default BiometricVerificationModal;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import FaceGif from '../Asset/gif/Face.gif';
|
|
2
|
+
import LocationGif from '../Asset/gif/Location.gif';
|
|
3
|
+
import { ANIMATION_STATES } from '../utils/constants';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Decides which GIF should be shown based on animationState or currentStep
|
|
7
|
+
* @param {string} animationState - Current animation state
|
|
8
|
+
* @param {string} currentStep - Current step of verification
|
|
9
|
+
* @returns {any} - Gif image source or null
|
|
10
|
+
*/
|
|
11
|
+
export const getLoaderGif = (animationState, currentStep) => {
|
|
12
|
+
if (
|
|
13
|
+
animationState === ANIMATION_STATES.FACE_SCAN ||
|
|
14
|
+
currentStep === 'Identity Verification'
|
|
15
|
+
) {
|
|
16
|
+
return FaceGif;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
animationState === ANIMATION_STATES.QR_SCAN ||
|
|
21
|
+
currentStep === 'Location Verification'
|
|
22
|
+
) {
|
|
23
|
+
return LocationGif;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return null;
|
|
27
|
+
};
|