react-native-biometric-verifier 0.0.55 → 0.0.57
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 +4 -16
- package/src/components/CaptureImageWithoutEdit.js +3 -4
- package/src/components/Loader.js +84 -96
- package/src/components/Notification.js +38 -14
- package/src/hooks/useFaceDetectionFrameProcessor.js +26 -26
- package/src/hooks/useGeolocation.js +46 -224
- package/src/index.js +430 -560
- package/src/utils/Global.js +0 -1
- package/src/hooks/useBluetoothService.js +0 -195
- package/src/hooks/useWifiService.js +0 -175
|
@@ -1,249 +1,71 @@
|
|
|
1
|
-
import { useCallback
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
2
|
import { Platform, PermissionsAndroid } from 'react-native';
|
|
3
3
|
import Geolocation from 'react-native-geolocation-service';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Custom hook for requesting location permission and fetching current location.
|
|
7
|
+
*
|
|
8
|
+
* @param {Function} notifyMessage - Callback to show notifications (message, type).
|
|
9
|
+
* @returns {Object} { requestLocationPermission, getCurrentLocation }
|
|
7
10
|
*/
|
|
8
11
|
export const useGeolocation = (notifyMessage) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
/* -------------------------------------------------------------------------- */
|
|
12
|
+
/**
|
|
13
|
+
* Requests location permission (Android only).
|
|
14
|
+
* @returns {Promise<boolean>} - True if permission granted, else false.
|
|
15
|
+
*/
|
|
14
16
|
const requestLocationPermission = useCallback(async () => {
|
|
15
|
-
|
|
16
|
-
if (Platform.OS !== 'android') return true;
|
|
17
|
+
if (Platform.OS !== 'android') return true;
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
try {
|
|
20
|
+
const granted = await PermissionsAndroid.request(
|
|
19
21
|
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
status => status === PermissionsAndroid.RESULTS.GRANTED
|
|
22
|
+
{
|
|
23
|
+
title: 'Location Permission Required',
|
|
24
|
+
message: 'This app needs your location to verify QR code scans.',
|
|
25
|
+
buttonPositive: 'OK',
|
|
26
|
+
buttonNegative: 'Cancel',
|
|
27
|
+
}
|
|
27
28
|
);
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const hasPermission = granted === PermissionsAndroid.RESULTS.GRANTED;
|
|
31
|
+
|
|
32
|
+
if (!hasPermission) {
|
|
33
|
+
notifyMessage?.('Cannot get location without permission.', 'error');
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
return
|
|
34
|
-
} catch (
|
|
35
|
-
console.error('
|
|
36
|
+
return hasPermission;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error('Location permission error:', error);
|
|
39
|
+
notifyMessage?.('Location permission error.', 'error');
|
|
36
40
|
return false;
|
|
37
41
|
}
|
|
38
42
|
}, [notifyMessage]);
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
}, []);
|
|
49
|
-
|
|
50
|
-
/* -------------------------------------------------------------------------- */
|
|
51
|
-
/* FAST + ACCURATE LOCATION FETCH */
|
|
52
|
-
/* -------------------------------------------------------------------------- */
|
|
53
|
-
const getCurrentLocation = useCallback((options = {}) => {
|
|
54
|
-
return new Promise((resolve, reject) => {
|
|
55
|
-
let samples = [];
|
|
56
|
-
let resolved = false;
|
|
57
|
-
|
|
58
|
-
const defaultOptions = {
|
|
59
|
-
enableHighAccuracy: true,
|
|
60
|
-
timeout: 8000, // ⏱ fast
|
|
61
|
-
maximumAge: 2000, // allow cached fix
|
|
62
|
-
forceRequestLocation: true,
|
|
63
|
-
showLocationDialog: true,
|
|
64
|
-
interval: 800,
|
|
65
|
-
fastestInterval: 500,
|
|
66
|
-
distanceFilter: 0,
|
|
67
|
-
...options,
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
/* ---------------- FAST FIRST FIX ---------------- */
|
|
44
|
+
/**
|
|
45
|
+
* Fetches the current location of the device.
|
|
46
|
+
* @returns {Promise<GeolocationCoordinates>}
|
|
47
|
+
*/
|
|
48
|
+
const getCurrentLocation = useCallback(
|
|
49
|
+
() =>
|
|
50
|
+
new Promise((resolve, reject) => {
|
|
72
51
|
Geolocation.getCurrentPosition(
|
|
73
|
-
(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const {
|
|
77
|
-
latitude,
|
|
78
|
-
longitude,
|
|
79
|
-
accuracy,
|
|
80
|
-
altitude = 0,
|
|
81
|
-
speed = 0,
|
|
82
|
-
heading = 0,
|
|
83
|
-
} = pos.coords;
|
|
84
|
-
|
|
85
|
-
// Accept immediately if good enough for verification
|
|
86
|
-
if (accuracy <= 15) {
|
|
87
|
-
resolved = true;
|
|
88
|
-
resolve({
|
|
89
|
-
latitude,
|
|
90
|
-
longitude,
|
|
91
|
-
altitude,
|
|
92
|
-
accuracy,
|
|
93
|
-
speed,
|
|
94
|
-
heading,
|
|
95
|
-
timestamp: pos.timestamp,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
samples.push({
|
|
100
|
-
latitude,
|
|
101
|
-
longitude,
|
|
102
|
-
altitude,
|
|
103
|
-
accuracy,
|
|
104
|
-
speed,
|
|
105
|
-
heading,
|
|
106
|
-
timestamp: pos.timestamp,
|
|
107
|
-
});
|
|
108
|
-
},
|
|
109
|
-
(err) => {
|
|
110
|
-
console.warn('[Geo Fast Fix Failed]', err);
|
|
111
|
-
},
|
|
112
|
-
defaultOptions
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
/* ---------------- BACKGROUND IMPROVEMENT ---------------- */
|
|
116
|
-
locationWatchId.current = Geolocation.watchPosition(
|
|
117
|
-
(p) => {
|
|
118
|
-
if (!p?.coords) return;
|
|
119
|
-
|
|
120
|
-
const {
|
|
121
|
-
latitude,
|
|
122
|
-
longitude,
|
|
123
|
-
accuracy,
|
|
124
|
-
altitude = 0,
|
|
125
|
-
speed = 0,
|
|
126
|
-
heading = 0,
|
|
127
|
-
} = p.coords;
|
|
128
|
-
|
|
129
|
-
/* -------- LIGHT NOISE FILTERS -------- */
|
|
130
|
-
if (accuracy > 40) return;
|
|
131
|
-
if (speed > 50) return;
|
|
132
|
-
|
|
133
|
-
samples.push({
|
|
134
|
-
latitude,
|
|
135
|
-
longitude,
|
|
136
|
-
altitude,
|
|
137
|
-
accuracy,
|
|
138
|
-
speed,
|
|
139
|
-
heading,
|
|
140
|
-
timestamp: p.timestamp,
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
if (samples.length > 8) samples.shift();
|
|
144
|
-
|
|
145
|
-
samples.sort((a, b) => a.accuracy - b.accuracy);
|
|
146
|
-
const best = samples[0];
|
|
147
|
-
|
|
148
|
-
// Upgrade accuracy silently
|
|
149
|
-
if (best.accuracy <= 6 && !resolved) {
|
|
150
|
-
resolved = true;
|
|
151
|
-
stopLocationWatching();
|
|
152
|
-
resolve(best);
|
|
153
|
-
}
|
|
52
|
+
(position) => {
|
|
53
|
+
resolve(position.coords);
|
|
154
54
|
},
|
|
155
|
-
(
|
|
156
|
-
|
|
157
|
-
|
|
55
|
+
(error) => {
|
|
56
|
+
notifyMessage?.('Unable to fetch current location.', 'error');
|
|
57
|
+
reject(error);
|
|
158
58
|
},
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (!resolved && samples.length) {
|
|
165
|
-
resolved = true;
|
|
166
|
-
stopLocationWatching();
|
|
167
|
-
samples.sort((a, b) => a.accuracy - b.accuracy);
|
|
168
|
-
resolve(samples[0]);
|
|
59
|
+
{
|
|
60
|
+
enableHighAccuracy: true,
|
|
61
|
+
timeout: 15000,
|
|
62
|
+
maximumAge: 10000,
|
|
63
|
+
distanceFilter: 1,
|
|
169
64
|
}
|
|
170
|
-
}, 5000);
|
|
171
|
-
} catch (err) {
|
|
172
|
-
stopLocationWatching();
|
|
173
|
-
notifyMessage?.('Failed to get location', 'error');
|
|
174
|
-
reject(err);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}, [notifyMessage, stopLocationWatching]);
|
|
178
|
-
|
|
179
|
-
/* -------------------------------------------------------------------------- */
|
|
180
|
-
/* DISTANCE CALCULATION */
|
|
181
|
-
/* -------------------------------------------------------------------------- */
|
|
182
|
-
const calculateEnhancedDistance = useCallback(
|
|
183
|
-
(lat1, lon1, lat2, lon2, alt1 = 0, alt2 = 0) => {
|
|
184
|
-
try {
|
|
185
|
-
if (
|
|
186
|
-
typeof lat1 !== 'number' ||
|
|
187
|
-
typeof lon1 !== 'number' ||
|
|
188
|
-
typeof lat2 !== 'number' ||
|
|
189
|
-
typeof lon2 !== 'number'
|
|
190
|
-
) return Infinity;
|
|
191
|
-
|
|
192
|
-
const toRad = deg => deg * Math.PI / 180;
|
|
193
|
-
const R = 6371e3;
|
|
194
|
-
|
|
195
|
-
const φ1 = toRad(lat1);
|
|
196
|
-
const φ2 = toRad(lat2);
|
|
197
|
-
const Δφ = toRad(lat2 - lat1);
|
|
198
|
-
const Δλ = toRad(lon2 - lon1);
|
|
199
|
-
|
|
200
|
-
const a =
|
|
201
|
-
Math.sin(Δφ / 2) ** 2 +
|
|
202
|
-
Math.cos(φ1) * Math.cos(φ2) *
|
|
203
|
-
Math.sin(Δλ / 2) ** 2;
|
|
204
|
-
|
|
205
|
-
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
206
|
-
const surfaceDistance = R * c;
|
|
207
|
-
|
|
208
|
-
const heightDiff = Math.abs(alt1 - alt2);
|
|
209
|
-
return Math.sqrt(surfaceDistance ** 2 + heightDiff ** 2);
|
|
210
|
-
} catch {
|
|
211
|
-
return Infinity;
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
[]
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
const calculateSafeDistance = useCallback(
|
|
218
|
-
(p1, p2) => {
|
|
219
|
-
try {
|
|
220
|
-
const lat1 = p1.latitude ?? p1.lat;
|
|
221
|
-
const lon1 = p1.longitude ?? p1.lng ?? p1.lon;
|
|
222
|
-
const alt1 = p1.altitude ?? p1.alt ?? 0;
|
|
223
|
-
|
|
224
|
-
const lat2 = p2.latitude ?? p2.lat;
|
|
225
|
-
const lon2 = p2.longitude ?? p2.lng ?? p2.lon;
|
|
226
|
-
const alt2 = p2.altitude ?? p2.alt ?? 0;
|
|
227
|
-
|
|
228
|
-
return calculateEnhancedDistance(
|
|
229
|
-
lat1, lon1, lat2, lon2, alt1, alt2
|
|
230
65
|
);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
[calculateEnhancedDistance]
|
|
66
|
+
}),
|
|
67
|
+
[notifyMessage]
|
|
236
68
|
);
|
|
237
69
|
|
|
238
|
-
|
|
239
|
-
/* API */
|
|
240
|
-
/* -------------------------------------------------------------------------- */
|
|
241
|
-
return {
|
|
242
|
-
requestLocationPermission,
|
|
243
|
-
getCurrentLocation,
|
|
244
|
-
stopLocationWatching,
|
|
245
|
-
getCurrentWatchId: () => locationWatchId.current,
|
|
246
|
-
calculateEnhancedDistance,
|
|
247
|
-
calculateSafeDistance,
|
|
248
|
-
};
|
|
70
|
+
return { requestLocationPermission, getCurrentLocation };
|
|
249
71
|
};
|