@trustchex/react-native-sdk 1.253.0 → 1.266.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/README.md +43 -2
- package/android/src/main/java/com/trustchex/reactnativesdk/DeviceBrightnessModule.kt +66 -0
- package/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKPackage.kt +12 -0
- package/ios/DeviceBrightnessModule.h +4 -0
- package/ios/DeviceBrightnessModule.m +27 -0
- package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +25 -0
- package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +19 -0
- package/lib/module/Screens/Dynamic/IdentityDocumentScanningScreen.js +19 -0
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +18 -5
- package/lib/module/Screens/Static/QrCodeScanningScreen.js +10 -2
- package/lib/module/Screens/Static/ResultScreen.js +52 -3
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +41 -2
- package/lib/module/Shared/Components/EIDScanner.js +63 -3
- package/lib/module/Shared/Components/FaceCamera.js +69 -4
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +4 -1
- package/lib/module/Shared/Components/NavigationManager.js +2 -0
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +2 -0
- package/lib/module/Shared/Contexts/AppContext.js +3 -1
- package/lib/module/Shared/Libs/analytics.utils.js +430 -0
- package/lib/module/Shared/Libs/camera.utils.js +58 -2
- package/lib/module/Shared/Libs/deeplink.utils.js +8 -0
- package/lib/module/Shared/Libs/http-client.js +89 -28
- package/lib/module/Shared/Services/AnalyticsService.js +404 -0
- package/lib/module/Shared/Types/analytics.types.js +111 -0
- package/lib/module/Shared/VisionCameraPlugins/BarcodeScanner/hooks/useCameraPermissions.js +1 -0
- package/lib/module/Translation/index.js +5 -0
- package/lib/module/Trustchex.js +47 -4
- package/lib/module/index.js +3 -0
- package/lib/typescript/src/Screens/Dynamic/ContractAcceptanceScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/QrCodeScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts +7 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts +2 -0
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts +98 -0
- package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/camera.utils.d.ts +19 -1
- package/lib/typescript/src/Shared/Libs/camera.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/deeplink.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Services/AnalyticsService.d.ts +86 -0
- package/lib/typescript/src/Shared/Services/AnalyticsService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts +146 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -0
- package/lib/typescript/src/Shared/VisionCameraPlugins/BarcodeScanner/hooks/useCameraPermissions.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/Translation/index.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts +1 -0
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +35 -1
- package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +30 -0
- package/src/Screens/Dynamic/IdentityDocumentScanningScreen.tsx +30 -0
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +30 -4
- package/src/Screens/Static/QrCodeScanningScreen.tsx +12 -2
- package/src/Screens/Static/ResultScreen.tsx +79 -4
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +65 -10
- package/src/Shared/Components/EIDScanner.tsx +132 -3
- package/src/Shared/Components/FaceCamera.tsx +77 -2
- package/src/Shared/Components/IdentityDocumentCamera.tsx +4 -4
- package/src/Shared/Components/NavigationManager.tsx +2 -0
- package/src/Shared/Components/QrCodeScannerCamera.tsx +2 -0
- package/src/Shared/Contexts/AppContext.ts +4 -0
- package/src/Shared/Libs/analytics.utils.ts +644 -0
- package/src/Shared/Libs/camera.utils.ts +74 -2
- package/src/Shared/Libs/deeplink.utils.ts +5 -0
- package/src/Shared/Libs/http-client.ts +105 -31
- package/src/Shared/Services/AnalyticsService.ts +470 -0
- package/src/Shared/Types/analytics.types.ts +179 -0
- package/src/Shared/VisionCameraPlugins/BarcodeScanner/hooks/useCameraPermissions.ts +1 -0
- package/src/Translation/Resources/tr.ts +2 -1
- package/src/Translation/index.ts +9 -0
- package/src/Trustchex.tsx +54 -2
- package/src/index.tsx +33 -0
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { Frame } from 'react-native-vision-camera';
|
|
2
2
|
|
|
3
|
+
interface Rect {
|
|
4
|
+
minX: number;
|
|
5
|
+
minY: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get average brightness for entire frame (center area)
|
|
12
|
+
*/
|
|
3
13
|
const getAverageBrightness = (frame: Frame): number => {
|
|
4
14
|
'worklet';
|
|
5
15
|
const buffer = frame.toArrayBuffer();
|
|
@@ -26,9 +36,71 @@ const getAverageBrightness = (frame: Frame): number => {
|
|
|
26
36
|
return luminanceSum / pixelCount;
|
|
27
37
|
};
|
|
28
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Get average brightness for a specific circular region (for face detection)
|
|
41
|
+
* Calculates brightness only for pixels inside the circle defined by centerX, centerY, and radius
|
|
42
|
+
*/
|
|
43
|
+
const getCircularRegionBrightness = (
|
|
44
|
+
frame: Frame,
|
|
45
|
+
circleRect: Rect
|
|
46
|
+
): number => {
|
|
47
|
+
'worklet';
|
|
48
|
+
const buffer = frame.toArrayBuffer();
|
|
49
|
+
const data = new Uint8Array(buffer);
|
|
50
|
+
const width = frame.width;
|
|
51
|
+
const height = frame.height;
|
|
52
|
+
|
|
53
|
+
// Calculate circle parameters from rect
|
|
54
|
+
const centerX = Math.floor(circleRect.minX + circleRect.width / 2);
|
|
55
|
+
const centerY = Math.floor(circleRect.minY + circleRect.height / 2);
|
|
56
|
+
const radius = Math.floor(Math.min(circleRect.width, circleRect.height) / 2);
|
|
57
|
+
|
|
58
|
+
let luminanceSum = 0;
|
|
59
|
+
let pixelCount = 0;
|
|
60
|
+
|
|
61
|
+
// Calculate bounding box for the circle to optimize iteration
|
|
62
|
+
const minX = Math.max(0, centerX - radius);
|
|
63
|
+
const maxX = Math.min(width - 1, centerX + radius);
|
|
64
|
+
const minY = Math.max(0, centerY - radius);
|
|
65
|
+
const maxY = Math.min(height - 1, centerY + radius);
|
|
66
|
+
|
|
67
|
+
// Iterate only over pixels in the bounding box
|
|
68
|
+
for (let y = minY; y <= maxY; y++) {
|
|
69
|
+
for (let x = minX; x <= maxX; x++) {
|
|
70
|
+
// Check if pixel is inside the circle
|
|
71
|
+
const dx = x - centerX;
|
|
72
|
+
const dy = y - centerY;
|
|
73
|
+
const distanceSquared = dx * dx + dy * dy;
|
|
74
|
+
|
|
75
|
+
if (distanceSquared <= radius * radius) {
|
|
76
|
+
const index = y * width + x;
|
|
77
|
+
if (data[index] !== undefined) {
|
|
78
|
+
luminanceSum += data[index];
|
|
79
|
+
pixelCount++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return pixelCount > 0 ? luminanceSum / pixelCount : 0;
|
|
86
|
+
};
|
|
87
|
+
|
|
29
88
|
const isFrameBright = (frame: Frame): boolean => {
|
|
30
89
|
'worklet';
|
|
31
|
-
return getAverageBrightness(frame) >
|
|
90
|
+
return getAverageBrightness(frame) > 60;
|
|
32
91
|
};
|
|
33
92
|
|
|
34
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Check if a circular region in the frame is bright enough
|
|
95
|
+
*/
|
|
96
|
+
const isCircularRegionBright = (frame: Frame, circleRect: Rect, threshold: number = 60): boolean => {
|
|
97
|
+
'worklet';
|
|
98
|
+
return getCircularRegionBrightness(frame, circleRect) > threshold;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
isFrameBright,
|
|
103
|
+
getAverageBrightness,
|
|
104
|
+
getCircularRegionBrightness,
|
|
105
|
+
isCircularRegionBright
|
|
106
|
+
};
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
const handleDeepLink = ({ url }: { url: string }) => {
|
|
2
|
+
console.log('[handleDeepLink] Received URL:', url);
|
|
2
3
|
const isHttps = url.includes('https');
|
|
3
4
|
const route = url.replace(/http(s)?(:)?(\/\/)?/g, '');
|
|
4
5
|
const segments = route.split('/');
|
|
6
|
+
console.log('[handleDeepLink] Parsed segments:', segments);
|
|
5
7
|
let baseUrl = '';
|
|
6
8
|
let sessionId = '';
|
|
7
9
|
|
|
8
10
|
for (let i = 0; i < segments.length; i++) {
|
|
9
11
|
if (segments[i] === 'verification-session') {
|
|
10
12
|
sessionId = segments[i + 1] ?? '';
|
|
13
|
+
console.log('[handleDeepLink] Found sessionId:', sessionId);
|
|
11
14
|
} else if (segments[i] === 'app-url') {
|
|
12
15
|
baseUrl = `${isHttps ? 'https' : 'http'}://${segments[i + 1]}`;
|
|
16
|
+
console.log('[handleDeepLink] Found baseUrl:', baseUrl);
|
|
13
17
|
}
|
|
14
18
|
}
|
|
15
19
|
|
|
20
|
+
console.log('[handleDeepLink] Returning:', { baseUrl, sessionId });
|
|
16
21
|
return [baseUrl, sessionId];
|
|
17
22
|
};
|
|
18
23
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { trackApiCall, trackError } from './analytics.utils';
|
|
2
|
+
|
|
1
3
|
interface ErrorResponse {
|
|
2
4
|
message: string;
|
|
3
5
|
}
|
|
@@ -52,49 +54,121 @@ const request = async <TResponse, TBody>(
|
|
|
52
54
|
});
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
'Content-Type': 'application/json',
|
|
59
|
-
},
|
|
60
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
let responseJson = null;
|
|
57
|
+
const startTime = Date.now();
|
|
58
|
+
let statusCode = 0;
|
|
59
|
+
let success = false;
|
|
64
60
|
|
|
65
61
|
try {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
62
|
+
const response = await fetch(url, {
|
|
63
|
+
method: httpMethod,
|
|
64
|
+
headers: {
|
|
65
|
+
'Content-Type': 'application/json',
|
|
66
|
+
},
|
|
67
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
68
|
+
});
|
|
73
69
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
70
|
+
statusCode = response.status;
|
|
71
|
+
success = response.ok;
|
|
77
72
|
|
|
78
|
-
|
|
79
|
-
throw new ForbiddenError(message);
|
|
80
|
-
}
|
|
73
|
+
let responseJson = null;
|
|
81
74
|
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
try {
|
|
76
|
+
responseJson = await response.json();
|
|
77
|
+
} catch (error) {
|
|
78
|
+
// Invalid JSON response
|
|
84
79
|
}
|
|
85
80
|
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
// Track API call performance (non-blocking)
|
|
82
|
+
// Wrap in try-catch to ensure analytics failures never mask HTTP errors
|
|
83
|
+
try {
|
|
84
|
+
const duration = Date.now() - startTime;
|
|
85
|
+
trackApiCall(url, duration, statusCode, success).catch(() => { });
|
|
86
|
+
} catch { }
|
|
87
|
+
|
|
88
|
+
if (response && !response.ok && responseJson) {
|
|
89
|
+
const message = (responseJson as unknown as ErrorResponse).message;
|
|
90
|
+
|
|
91
|
+
const getErrorCodeFromStatus = (status: number): string => {
|
|
92
|
+
switch (status) {
|
|
93
|
+
case 400:
|
|
94
|
+
return 'BAD_REQUEST';
|
|
95
|
+
case 401:
|
|
96
|
+
return 'UNAUTHORIZED';
|
|
97
|
+
case 403:
|
|
98
|
+
return 'FORBIDDEN';
|
|
99
|
+
case 404:
|
|
100
|
+
return 'NOT_FOUND';
|
|
101
|
+
case 500:
|
|
102
|
+
return 'INTERNAL_SERVER_ERROR';
|
|
103
|
+
case 502:
|
|
104
|
+
return 'BAD_GATEWAY';
|
|
105
|
+
case 503:
|
|
106
|
+
return 'SERVICE_UNAVAILABLE';
|
|
107
|
+
case 504:
|
|
108
|
+
return 'GATEWAY_TIMEOUT';
|
|
109
|
+
default:
|
|
110
|
+
return `API_ERROR_${status}`;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const getSeverityFromStatus = (status: number): 'low' | 'medium' | 'high' | 'critical' => {
|
|
115
|
+
if (status >= 500) return 'high';
|
|
116
|
+
if (status === 401 || status === 403) return 'medium';
|
|
117
|
+
if (status === 400 || status === 404) return 'low';
|
|
118
|
+
return 'medium';
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Track API error (non-blocking)
|
|
122
|
+
// Wrap in try-catch to ensure analytics failures never mask HTTP errors
|
|
123
|
+
try {
|
|
124
|
+
trackError(
|
|
125
|
+
getErrorCodeFromStatus(statusCode),
|
|
126
|
+
message || 'API request failed',
|
|
127
|
+
'http_client',
|
|
128
|
+
getSeverityFromStatus(statusCode)
|
|
129
|
+
).catch(() => { });
|
|
130
|
+
} catch { }
|
|
131
|
+
|
|
132
|
+
if (response.status === 401) {
|
|
133
|
+
throw new UnauthorizedError(message);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (response.status === 403) {
|
|
137
|
+
throw new ForbiddenError(message);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (response.status === 404) {
|
|
141
|
+
throw new NotFoundError(message);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (response.status >= 500) {
|
|
145
|
+
throw new InternalServerError(message);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (response.status >= 400) {
|
|
149
|
+
throw new BadRequestError(message);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
throw new Error(message);
|
|
88
153
|
}
|
|
89
154
|
|
|
90
|
-
|
|
91
|
-
|
|
155
|
+
return responseJson as Promise<TResponse>;
|
|
156
|
+
} catch (error) {
|
|
157
|
+
// Only track network errors for actual network failures, not HTTP errors
|
|
158
|
+
// HTTP errors (4xx, 5xx) are already tracked above before throwing
|
|
159
|
+
if (!(error instanceof HttpClientError)) {
|
|
160
|
+
try {
|
|
161
|
+
const duration = Date.now() - startTime;
|
|
162
|
+
const errorMessage =
|
|
163
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
164
|
+
|
|
165
|
+
trackApiCall(url, duration, statusCode, false).catch(() => { });
|
|
166
|
+
trackError('NETWORK_ERROR', errorMessage, 'http_client', 'high').catch(() => { });
|
|
167
|
+
} catch { }
|
|
92
168
|
}
|
|
93
169
|
|
|
94
|
-
throw
|
|
170
|
+
throw error;
|
|
95
171
|
}
|
|
96
|
-
|
|
97
|
-
return responseJson as Promise<TResponse>;
|
|
98
172
|
};
|
|
99
173
|
|
|
100
174
|
const get = <TResponse>(url: string, simulatedResponse?: TResponse) => {
|