react-native-biometric-verifier 0.0.10 → 0.0.11

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.10",
3
+ "version": "0.0.11",
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": {
@@ -1,58 +1,113 @@
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 }) {
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { Animated, Easing, View } from 'react-native';
3
+ import Icon from 'react-native-vector-icons/MaterialIcons';
4
+ import { ANIMATION_STATES, COLORS } from '../utils/constants';
5
+ import { styles } from './styles';
6
+ import FastImage from 'react-native-fast-image';
7
+
8
+ export const Loader = ({ state, source, isLoading = false }) => {
9
+ const spinValue = useRef(new Animated.Value(0)).current;
10
+ const pulseValue = useRef(new Animated.Value(1)).current;
11
+ const spinAnimation = useRef(null);
12
+ const pulseAnimation = useRef(null);
13
+
14
+ const size = 120; // Define the size constant
15
+
16
+ useEffect(() => {
17
+ // Stop ongoing animations when state changes
18
+ spinAnimation.current?.stop();
19
+ pulseAnimation.current?.stop();
20
+
21
+ if (
22
+ state === ANIMATION_STATES.PROCESSING ||
23
+ state === ANIMATION_STATES.FACE_SCAN ||
24
+ state === ANIMATION_STATES.QR_SCAN
25
+ ) {
26
+ spinAnimation.current = Animated.loop(
27
+ Animated.timing(spinValue, {
28
+ toValue: 1,
29
+ duration: 1500,
30
+ easing: Easing.linear,
31
+ useNativeDriver: true,
32
+ })
33
+ );
34
+ spinAnimation.current.start();
35
+ }
36
+ else if (
37
+ state === ANIMATION_STATES.SUCCESS ||
38
+ state === ANIMATION_STATES.ERROR
39
+ ) {
40
+ pulseAnimation.current = Animated.loop(
41
+ Animated.sequence([
42
+ Animated.timing(pulseValue, {
43
+ toValue: 1.1,
44
+ duration: 500,
45
+ useNativeDriver: true,
46
+ }),
47
+ Animated.timing(pulseValue, {
48
+ toValue: 1,
49
+ duration: 500,
50
+ useNativeDriver: true,
51
+ }),
52
+ ]),
53
+ { iterations: 2 }
54
+ );
55
+ pulseAnimation.current.start();
56
+ }
57
+ else {
58
+ spinValue.setValue(0);
59
+ pulseValue.setValue(1);
60
+ }
61
+
62
+ return () => {
63
+ spinAnimation.current?.stop();
64
+ pulseAnimation.current?.stop();
65
+ };
66
+ }, [state, spinValue, pulseValue]);
67
+
68
+ const getIcon = () => {
69
+ switch (state) {
70
+ case ANIMATION_STATES.FACE_SCAN:
71
+ return <Icon name="face" size={size * 0.5} color={COLORS.primary} />;
72
+ case ANIMATION_STATES.QR_SCAN:
73
+ return <Icon name="qr-code-scanner" size={size * 0.5} color={COLORS.primary} />;
74
+ case ANIMATION_STATES.PROCESSING:
75
+ return <Icon name="settings" size={size * 0.5} color={COLORS.info} />;
76
+ case ANIMATION_STATES.SUCCESS:
77
+ return <Icon name="check-circle" size={size * 0.5} color={COLORS.success} />;
78
+ case ANIMATION_STATES.ERROR:
79
+ return <Icon name="error" size={size * 0.5} color={COLORS.error} />;
80
+ default:
81
+ return <Icon name="hourglass-empty" size={size * 0.5} color={COLORS.gray} />;
82
+ }
83
+ };
84
+
11
85
  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}>
86
+ <View style={styles.indicatorWrapper}>
87
+ <Animated.View
88
+ style={[
89
+ styles.indicatorContainer,
90
+ {
91
+ width: size,
92
+ height: size,
93
+ transform: [
94
+ { scale: pulseValue },
95
+ ],
96
+ },
97
+ ]}
98
+ >
99
+ {isLoading && source ? (
20
100
  <FastImage
21
- style={styles.icon}
101
+ style={[styles.icon, { width: size * 0.8, height: size * 0.8 }]}
22
102
  source={source}
103
+ resizeMode={FastImage.resizeMode.contain}
23
104
  />
24
- </View>
25
- </View>
26
- </Modal>
105
+ ) : (
106
+ getIcon()
107
+ )}
108
+ </Animated.View>
109
+ </View>
27
110
  );
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
- });
111
+ };
112
+
113
+ export default Loader;
@@ -179,4 +179,22 @@ export const styles = StyleSheet.create({
179
179
  opacity: 0.8,
180
180
  fontFamily: Platform.OS === 'ios' ? 'Helvetica Neue' : 'sans-serif',
181
181
  },
182
+ capturedImageContainer: {
183
+ marginVertical: 15,
184
+ alignItems: 'center',
185
+ justifyContent: 'center',
186
+ },
187
+ capturedImage: {
188
+ width: 120,
189
+ height: 120,
190
+ borderRadius: 10,
191
+ borderWidth: 2,
192
+ borderColor: COLORS.primary,
193
+ },
194
+ capturedImageText: {
195
+ marginTop: 8,
196
+ fontSize: 14,
197
+ color: COLORS.light,
198
+ textAlign: 'center',
199
+ },
182
200
  });
package/src/index.js CHANGED
@@ -28,7 +28,6 @@ import Loader from "./components/Loader";
28
28
  import { CountdownTimer } from "./components/CountdownTimer";
29
29
  import { EmployeeCard } from "./components/EmployeeCard";
30
30
  import { Notification } from "./components/Notification";
31
- import { StateIndicator } from "./components/StateIndicator";
32
31
  import { styles } from "./components/styles";
33
32
  import { useNavigation } from "@react-navigation/native";
34
33
  import networkServiceCall from "./utils/NetworkServiceCall";
@@ -342,8 +341,6 @@ const BiometricVerificationModal = React.memo(
342
341
  <Text style={styles.title}>Biometric Verification</Text>
343
342
  <Text style={styles.subTitle}>{state.currentStep}</Text>
344
343
 
345
- <StateIndicator state={state.animationState} size={120} />
346
-
347
344
  {state.employeeData && (
348
345
  <EmployeeCard
349
346
  employeeData={state.employeeData}
@@ -361,8 +358,12 @@ const BiometricVerificationModal = React.memo(
361
358
  duration={COUNTDOWN_DURATION}
362
359
  currentTime={countdown}
363
360
  />
364
-
365
- {loaderSource && <Loader source={loaderSource} />}
361
+
362
+ <Loader
363
+ state={state.animationState}
364
+ source={loaderSource}
365
+ isLoading={state.isLoading}
366
+ />
366
367
  </View>
367
368
  </Modal>
368
369
  )}
@@ -371,4 +372,4 @@ const BiometricVerificationModal = React.memo(
371
372
  }
372
373
  );
373
374
 
374
- export default BiometricVerificationModal;
375
+ export default BiometricVerificationModal;
@@ -1,109 +0,0 @@
1
- import React, { useEffect, useRef } from 'react';
2
- import { Animated, Easing } from 'react-native';
3
- import Icon from 'react-native-vector-icons/MaterialIcons';
4
- import { ANIMATION_STATES, COLORS } from '../utils/constants';
5
- import { styles } from './styles';
6
-
7
- export const StateIndicator = ({ state, size = 100 }) => {
8
- const spinValue = useRef(new Animated.Value(0)).current;
9
- const pulseValue = useRef(new Animated.Value(1)).current;
10
- const spinAnimation = useRef(null);
11
- const pulseAnimation = useRef(null);
12
-
13
- useEffect(() => {
14
- // Stop ongoing animations when state changes
15
- spinValue.stopAnimation();
16
- pulseValue.stopAnimation();
17
-
18
- if (
19
- state === ANIMATION_STATES.PROCESSING ||
20
- state === ANIMATION_STATES.FACE_SCAN ||
21
- state === ANIMATION_STATES.QR_SCAN
22
- ) {
23
- spinAnimation.current = Animated.loop(
24
- Animated.timing(spinValue, {
25
- toValue: 1,
26
- duration: 1500,
27
- easing: Easing.linear,
28
- useNativeDriver: true,
29
- })
30
- );
31
- spinAnimation.current.start();
32
- }
33
- else if (
34
- state === ANIMATION_STATES.SUCCESS ||
35
- state === ANIMATION_STATES.ERROR
36
- ) {
37
- pulseAnimation.current = Animated.loop(
38
- Animated.sequence([
39
- Animated.timing(pulseValue, {
40
- toValue: 1.1,
41
- duration: 500,
42
- useNativeDriver: true,
43
- }),
44
- Animated.timing(pulseValue, {
45
- toValue: 1,
46
- duration: 500,
47
- useNativeDriver: true,
48
- }),
49
- ]),
50
- { iterations: 2 }
51
- );
52
- pulseAnimation.current.start();
53
- }
54
- else {
55
- spinValue.setValue(0);
56
- pulseValue.setValue(1);
57
- }
58
- }, [state, spinValue, pulseValue]);
59
-
60
- const spin = spinValue.interpolate({
61
- inputRange: [0, 1],
62
- outputRange: ['0deg', '360deg'],
63
- });
64
-
65
- const getIcon = () => {
66
- switch (state) {
67
- case ANIMATION_STATES.FACE_SCAN:
68
- return <Icon name="face" size={size * 0.5} color={COLORS.primary} />;
69
- case ANIMATION_STATES.QR_SCAN:
70
- return <Icon name="qr-code-scanner" size={size * 0.5} color={COLORS.primary} />;
71
- case ANIMATION_STATES.PROCESSING:
72
- return <Icon name="settings" size={size * 0.5} color={COLORS.info} />;
73
- case ANIMATION_STATES.SUCCESS:
74
- return <Icon name="check-circle" size={size * 0.5} color={COLORS.success} />;
75
- case ANIMATION_STATES.ERROR:
76
- return <Icon name="error" size={size * 0.5} color={COLORS.error} />;
77
- default:
78
- return <Icon name="hourglass-empty" size={size * 0.5} color={COLORS.gray} />;
79
- }
80
- };
81
-
82
- return (
83
- <Animated.View
84
- style={[
85
- styles.indicatorContainer,
86
- {
87
- width: size,
88
- height: size,
89
- transform: [
90
- { scale: pulseValue },
91
- ...(state === ANIMATION_STATES.PROCESSING ||
92
- state === ANIMATION_STATES.FACE_SCAN ||
93
- state === ANIMATION_STATES.QR_SCAN
94
- ? [{ rotate: spin }]
95
- : []),
96
- ],
97
- },
98
- ]}
99
- >
100
- {(state === ANIMATION_STATES.PROCESSING ||
101
- state === ANIMATION_STATES.FACE_SCAN ||
102
- state === ANIMATION_STATES.QR_SCAN) ? (
103
- null
104
- ) : (
105
- getIcon()
106
- )}
107
- </Animated.View>
108
- );
109
- };