@hexar/biometric-identity-sdk-react-native 1.0.2 → 1.0.4
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/dist/components/BiometricIdentityFlow.d.ts +5 -0
- package/dist/components/BiometricIdentityFlow.d.ts.map +1 -1
- package/dist/components/BiometricIdentityFlow.js +5 -5
- package/dist/components/InstructionsScreen.d.ts +5 -0
- package/dist/components/InstructionsScreen.d.ts.map +1 -1
- package/dist/components/InstructionsScreen.js +103 -53
- package/package.json +1 -1
- package/src/components/BiometricIdentityFlow.tsx +10 -3
- package/src/components/InstructionsScreen.tsx +80 -53
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Main UI component for identity verification with backend AI support
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
|
+
import { ViewStyle } from 'react-native';
|
|
6
7
|
import { ValidationResult, ThemeConfig, BiometricError, SupportedLanguage } from '@hexar/biometric-identity-sdk-core';
|
|
7
8
|
export interface BiometricIdentityFlowProps {
|
|
8
9
|
onValidationComplete: (result: ValidationResult) => void;
|
|
@@ -11,6 +12,10 @@ export interface BiometricIdentityFlowProps {
|
|
|
11
12
|
language?: SupportedLanguage;
|
|
12
13
|
customTranslations?: Record<string, string>;
|
|
13
14
|
smartLivenessMode?: boolean;
|
|
15
|
+
styles?: {
|
|
16
|
+
container?: ViewStyle;
|
|
17
|
+
content?: ViewStyle;
|
|
18
|
+
};
|
|
14
19
|
}
|
|
15
20
|
export declare const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps>;
|
|
16
21
|
export default BiometricIdentityFlow;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BiometricIdentityFlow.d.ts","sourceRoot":"","sources":["../../src/components/BiometricIdentityFlow.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"BiometricIdentityFlow.d.ts","sourceRoot":"","sources":["../../src/components/BiometricIdentityFlow.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;AAChE,OAAO,EAOL,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,cAAc,EAId,iBAAiB,EAClB,MAAM,oCAAoC,CAAC;AAU5C,MAAM,WAAW,0BAA0B;IACzC,oBAAoB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACzC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,OAAO,CAAC,EAAE,SAAS,CAAC;KACrB,CAAC;CACH;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAuStE,CAAC;AAiOF,eAAe,qBAAqB,CAAC"}
|
|
@@ -48,7 +48,7 @@ const ValidationProgress_1 = require("./ValidationProgress");
|
|
|
48
48
|
const ResultScreen_1 = require("./ResultScreen");
|
|
49
49
|
const ErrorScreen_1 = require("./ErrorScreen");
|
|
50
50
|
const InstructionsScreen_1 = require("./InstructionsScreen");
|
|
51
|
-
const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language, customTranslations, smartLivenessMode = true, }) => {
|
|
51
|
+
const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language, customTranslations, smartLivenessMode = true, styles: customStyles, }) => {
|
|
52
52
|
const { sdk, state, isInitialized, isUsingBackend, challenges, uploadFrontID, uploadBackID, storeVideoRecording, fetchChallenges, validateIdentity, reset, } = (0, useBiometricSDK_1.useBiometricSDK)();
|
|
53
53
|
const [showCamera, setShowCamera] = (0, react_1.useState)(false);
|
|
54
54
|
const [cameraMode, setCameraMode] = (0, react_1.useState)('front');
|
|
@@ -145,14 +145,14 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
|
|
|
145
145
|
}, [reset]);
|
|
146
146
|
// Show loading while initializing
|
|
147
147
|
if (!isInitialized) {
|
|
148
|
-
return (react_1.default.createElement(react_native_1.SafeAreaView, { style: styles.container },
|
|
148
|
+
return (react_1.default.createElement(react_native_1.SafeAreaView, { style: [styles.container, customStyles?.container] },
|
|
149
149
|
react_1.default.createElement(react_native_1.View, { style: styles.loadingFullScreen },
|
|
150
150
|
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: theme?.primaryColor || '#6366F1' }),
|
|
151
151
|
react_1.default.createElement(react_native_1.Text, { style: styles.loadingText }, strings.initialization.initializing))));
|
|
152
152
|
}
|
|
153
153
|
// Show instructions on first load
|
|
154
154
|
if (showInstructions) {
|
|
155
|
-
return (react_1.default.createElement(InstructionsScreen_1.InstructionsScreen, { theme: theme, language: language, onStart: () => setShowInstructions(false) }));
|
|
155
|
+
return (react_1.default.createElement(InstructionsScreen_1.InstructionsScreen, { theme: theme, language: language, onStart: () => setShowInstructions(false), styles: customStyles }));
|
|
156
156
|
}
|
|
157
157
|
// Show camera/video recorder
|
|
158
158
|
if (showCamera) {
|
|
@@ -176,8 +176,8 @@ const BiometricIdentityFlow = ({ onValidationComplete, onError, theme, language,
|
|
|
176
176
|
if (state.currentStep === biometric_identity_sdk_core_1.SDKStep.ERROR && state.error) {
|
|
177
177
|
return (react_1.default.createElement(ErrorScreen_1.ErrorScreen, { error: state.error, theme: theme, language: language, onRetry: handleRetry, onClose: () => onError(state.error) }));
|
|
178
178
|
}
|
|
179
|
-
return (react_1.default.createElement(react_native_1.SafeAreaView, { style: styles.container },
|
|
180
|
-
react_1.default.createElement(react_native_1.View, { style: styles.content },
|
|
179
|
+
return (react_1.default.createElement(react_native_1.SafeAreaView, { style: [styles.container, customStyles?.container] },
|
|
180
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.content, customStyles?.content] },
|
|
181
181
|
react_1.default.createElement(react_native_1.Text, { style: styles.title }, strings.instructions.title),
|
|
182
182
|
react_1.default.createElement(react_native_1.Text, { style: styles.subtitle }, strings.instructions.subtitle),
|
|
183
183
|
isUsingBackend && (react_1.default.createElement(react_native_1.View, { style: styles.backendBadge },
|
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
* Shows initial instructions before starting verification
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
|
+
import { ViewStyle } from 'react-native';
|
|
6
7
|
import { ThemeConfig, SupportedLanguage } from '@hexar/biometric-identity-sdk-core';
|
|
7
8
|
export interface InstructionsScreenProps {
|
|
8
9
|
theme?: ThemeConfig;
|
|
9
10
|
language?: SupportedLanguage;
|
|
10
11
|
onStart: () => void;
|
|
12
|
+
styles?: {
|
|
13
|
+
container?: ViewStyle;
|
|
14
|
+
content?: ViewStyle;
|
|
15
|
+
};
|
|
11
16
|
}
|
|
12
17
|
export declare const InstructionsScreen: React.FC<InstructionsScreenProps>;
|
|
13
18
|
export default InstructionsScreen;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstructionsScreen.d.ts","sourceRoot":"","sources":["../../src/components/InstructionsScreen.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"InstructionsScreen.d.ts","sourceRoot":"","sources":["../../src/components/InstructionsScreen.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,EAML,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAA2B,MAAM,oCAAoC,CAAC;AAE7G,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,OAAO,CAAC,EAAE,SAAS,CAAC;KACrB,CAAC;CACH;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAoFhE,CAAC;AAuLF,eAAe,kBAAkB,CAAC"}
|
|
@@ -3,36 +3,76 @@
|
|
|
3
3
|
* Instructions Screen Component
|
|
4
4
|
* Shows initial instructions before starting verification
|
|
5
5
|
*/
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
9
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
40
|
exports.InstructionsScreen = void 0;
|
|
11
|
-
const react_1 =
|
|
41
|
+
const react_1 = __importStar(require("react"));
|
|
12
42
|
const react_native_1 = require("react-native");
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
43
|
+
const biometric_identity_sdk_core_1 = require("@hexar/biometric-identity-sdk-core");
|
|
44
|
+
const InstructionsScreen = ({ theme, language = 'en', onStart, styles: customStyles, }) => {
|
|
45
|
+
// Set language when prop changes
|
|
46
|
+
(0, react_1.useEffect)(() => {
|
|
47
|
+
if (language) {
|
|
48
|
+
(0, biometric_identity_sdk_core_1.setLanguage)(language);
|
|
49
|
+
}
|
|
50
|
+
}, [language]);
|
|
51
|
+
const strings = (0, biometric_identity_sdk_core_1.getStrings)();
|
|
52
|
+
// Get tips and privacy message based on language
|
|
53
|
+
const tipsContent = getTipsContent(language);
|
|
54
|
+
const privacyContent = getPrivacyContent(language);
|
|
55
|
+
return (react_1.default.createElement(react_native_1.View, { style: [styles.container, customStyles?.container] },
|
|
56
|
+
react_1.default.createElement(react_native_1.ScrollView, { contentContainerStyle: [styles.content, customStyles?.content] },
|
|
57
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.title, { color: theme?.textColor || '#000000' }] }, strings.instructions.title),
|
|
58
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.subtitle, { color: theme?.secondaryTextColor || '#6B7280' }] }, strings.instructions.subtitle),
|
|
19
59
|
react_1.default.createElement(react_native_1.View, { style: styles.stepsContainer },
|
|
20
|
-
react_1.default.createElement(InstructionStep, { number: 1, title:
|
|
21
|
-
react_1.default.createElement(InstructionStep, { number: 2, title:
|
|
22
|
-
react_1.default.createElement(InstructionStep, { number: 3, title:
|
|
60
|
+
react_1.default.createElement(InstructionStep, { number: 1, title: strings.capture.frontId.title, description: strings.capture.frontId.instruction, theme: theme }),
|
|
61
|
+
react_1.default.createElement(InstructionStep, { number: 2, title: strings.capture.backId.title, description: strings.capture.backId.instruction, theme: theme }),
|
|
62
|
+
react_1.default.createElement(InstructionStep, { number: 3, title: strings.liveness.title, description: strings.liveness.instructions.stayStill, theme: theme })),
|
|
23
63
|
react_1.default.createElement(react_native_1.View, { style: styles.tipsContainer },
|
|
24
|
-
react_1.default.createElement(react_native_1.Text, { style: [styles.tipsTitle, { color: theme?.textColor || '#000000' }] },
|
|
25
|
-
|
|
64
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.tipsTitle, { color: theme?.textColor || '#000000' }] }, tipsContent.title),
|
|
65
|
+
tipsContent.tips.map((tip, index) => (react_1.default.createElement(react_native_1.Text, { key: index, style: styles.tipText },
|
|
26
66
|
"\u2022 ",
|
|
27
67
|
tip)))),
|
|
28
68
|
react_1.default.createElement(react_native_1.View, { style: styles.privacyContainer },
|
|
29
|
-
react_1.default.createElement(react_native_1.Text, { style: styles.privacyText },
|
|
69
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.privacyText }, privacyContent))),
|
|
30
70
|
react_1.default.createElement(react_native_1.View, { style: styles.footer },
|
|
31
71
|
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
|
|
32
72
|
styles.button,
|
|
33
73
|
{ backgroundColor: theme?.primaryColor || '#6366F1' },
|
|
34
74
|
], onPress: onStart },
|
|
35
|
-
react_1.default.createElement(react_native_1.Text, { style: styles.buttonText },
|
|
75
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.buttonText }, strings.instructions.startButton)))));
|
|
36
76
|
};
|
|
37
77
|
exports.InstructionsScreen = InstructionsScreen;
|
|
38
78
|
const InstructionStep = ({ number, title, description, theme, }) => (react_1.default.createElement(react_native_1.View, { style: stepStyles.container },
|
|
@@ -140,42 +180,52 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
140
180
|
fontWeight: '600',
|
|
141
181
|
},
|
|
142
182
|
});
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
183
|
+
// Helper function to get tips content based on language
|
|
184
|
+
const getTipsContent = (language) => {
|
|
185
|
+
switch (language) {
|
|
186
|
+
case 'es':
|
|
187
|
+
case 'es-AR':
|
|
188
|
+
return {
|
|
189
|
+
title: 'Consejos para el Éxito',
|
|
190
|
+
tips: [
|
|
191
|
+
'Asegura buena iluminación sin brillos o sombras',
|
|
192
|
+
'Mantén tu documento plano y todos los bordes visibles',
|
|
193
|
+
'Quítate los lentes y cubiertas faciales',
|
|
194
|
+
'Encuentra un lugar tranquilo sin distracciones',
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
case 'pt-BR':
|
|
198
|
+
return {
|
|
199
|
+
title: 'Dicas para o Sucesso',
|
|
200
|
+
tips: [
|
|
201
|
+
'Garanta boa iluminação sem brilhos ou sombras',
|
|
202
|
+
'Mantenha seu documento plano e todas as bordas visíveis',
|
|
203
|
+
'Remova óculos e coberturas faciais',
|
|
204
|
+
'Encontre um lugar tranquilo sem distrações',
|
|
205
|
+
],
|
|
206
|
+
};
|
|
207
|
+
default:
|
|
208
|
+
return {
|
|
209
|
+
title: 'Tips for Success',
|
|
210
|
+
tips: [
|
|
211
|
+
'Ensure good lighting without glare or shadows',
|
|
212
|
+
'Keep your ID flat and all edges visible',
|
|
213
|
+
'Remove glasses and face coverings',
|
|
214
|
+
'Find a quiet place without distractions',
|
|
215
|
+
],
|
|
216
|
+
};
|
|
217
|
+
}
|
|
161
218
|
};
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
'Asegura buena iluminación sin brillos o sombras',
|
|
174
|
-
'Mantén tu documento plano y todos los bordes visibles',
|
|
175
|
-
'Quítate los lentes y cubiertas faciales',
|
|
176
|
-
'Encuentra un lugar tranquilo sin distracciones',
|
|
177
|
-
],
|
|
178
|
-
privacy: '🔒 Tus datos están encriptados y procesados de forma segura. No almacenamos tus datos biométricos localmente.',
|
|
179
|
-
startButton: 'Iniciar Verificación',
|
|
219
|
+
// Helper function to get privacy message based on language
|
|
220
|
+
const getPrivacyContent = (language) => {
|
|
221
|
+
switch (language) {
|
|
222
|
+
case 'es':
|
|
223
|
+
case 'es-AR':
|
|
224
|
+
return '🔒 Tus datos están encriptados y procesados de forma segura. No almacenamos tus datos biométricos localmente.';
|
|
225
|
+
case 'pt-BR':
|
|
226
|
+
return '🔒 Seus dados estão criptografados e processados com segurança. Não armazenamos seus dados biométricos localmente.';
|
|
227
|
+
default:
|
|
228
|
+
return '🔒 Your data is encrypted and processed securely. We do not store your biometric data locally.';
|
|
229
|
+
}
|
|
180
230
|
};
|
|
181
231
|
exports.default = exports.InstructionsScreen;
|
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
TouchableOpacity,
|
|
12
12
|
ActivityIndicator,
|
|
13
13
|
SafeAreaView,
|
|
14
|
+
ViewStyle,
|
|
14
15
|
} from 'react-native';
|
|
15
16
|
import {
|
|
16
17
|
ValidationResult,
|
|
@@ -37,6 +38,10 @@ export interface BiometricIdentityFlowProps {
|
|
|
37
38
|
language?: SupportedLanguage;
|
|
38
39
|
customTranslations?: Record<string, string>;
|
|
39
40
|
smartLivenessMode?: boolean;
|
|
41
|
+
styles?: {
|
|
42
|
+
container?: ViewStyle;
|
|
43
|
+
content?: ViewStyle;
|
|
44
|
+
};
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
@@ -46,6 +51,7 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
46
51
|
language,
|
|
47
52
|
customTranslations,
|
|
48
53
|
smartLivenessMode = true,
|
|
54
|
+
styles: customStyles,
|
|
49
55
|
}) => {
|
|
50
56
|
const {
|
|
51
57
|
sdk,
|
|
@@ -165,7 +171,7 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
165
171
|
// Show loading while initializing
|
|
166
172
|
if (!isInitialized) {
|
|
167
173
|
return (
|
|
168
|
-
<SafeAreaView style={styles.container}>
|
|
174
|
+
<SafeAreaView style={[styles.container, customStyles?.container]}>
|
|
169
175
|
<View style={styles.loadingFullScreen}>
|
|
170
176
|
<ActivityIndicator size="large" color={theme?.primaryColor || '#6366F1'} />
|
|
171
177
|
<Text style={styles.loadingText}>{strings.initialization.initializing}</Text>
|
|
@@ -181,6 +187,7 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
181
187
|
theme={theme}
|
|
182
188
|
language={language}
|
|
183
189
|
onStart={() => setShowInstructions(false)}
|
|
190
|
+
styles={customStyles}
|
|
184
191
|
/>
|
|
185
192
|
);
|
|
186
193
|
}
|
|
@@ -251,8 +258,8 @@ export const BiometricIdentityFlow: React.FC<BiometricIdentityFlowProps> = ({
|
|
|
251
258
|
}
|
|
252
259
|
|
|
253
260
|
return (
|
|
254
|
-
<SafeAreaView style={styles.container}>
|
|
255
|
-
<View style={styles.content}>
|
|
261
|
+
<SafeAreaView style={[styles.container, customStyles?.container]}>
|
|
262
|
+
<View style={[styles.content, customStyles?.content]}>
|
|
256
263
|
<Text style={styles.title}>{strings.instructions.title}</Text>
|
|
257
264
|
<Text style={styles.subtitle}>{strings.instructions.subtitle}</Text>
|
|
258
265
|
|
|
@@ -3,58 +3,75 @@
|
|
|
3
3
|
* Shows initial instructions before starting verification
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useEffect } from 'react';
|
|
7
7
|
import {
|
|
8
8
|
View,
|
|
9
9
|
Text,
|
|
10
10
|
StyleSheet,
|
|
11
11
|
TouchableOpacity,
|
|
12
12
|
ScrollView,
|
|
13
|
+
ViewStyle,
|
|
13
14
|
} from 'react-native';
|
|
14
|
-
import { ThemeConfig, SupportedLanguage, getStrings } from '@hexar/biometric-identity-sdk-core';
|
|
15
|
+
import { ThemeConfig, SupportedLanguage, getStrings, setLanguage } from '@hexar/biometric-identity-sdk-core';
|
|
15
16
|
|
|
16
17
|
export interface InstructionsScreenProps {
|
|
17
18
|
theme?: ThemeConfig;
|
|
18
19
|
language?: SupportedLanguage;
|
|
19
20
|
onStart: () => void;
|
|
21
|
+
styles?: {
|
|
22
|
+
container?: ViewStyle;
|
|
23
|
+
content?: ViewStyle;
|
|
24
|
+
};
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
export const InstructionsScreen: React.FC<InstructionsScreenProps> = ({
|
|
23
28
|
theme,
|
|
24
29
|
language = 'en',
|
|
25
30
|
onStart,
|
|
31
|
+
styles: customStyles,
|
|
26
32
|
}) => {
|
|
27
|
-
|
|
33
|
+
// Set language when prop changes
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (language) {
|
|
36
|
+
setLanguage(language);
|
|
37
|
+
}
|
|
38
|
+
}, [language]);
|
|
39
|
+
|
|
40
|
+
const strings = getStrings();
|
|
41
|
+
|
|
42
|
+
// Get tips and privacy message based on language
|
|
43
|
+
const tipsContent = getTipsContent(language);
|
|
44
|
+
const privacyContent = getPrivacyContent(language);
|
|
28
45
|
|
|
29
46
|
return (
|
|
30
|
-
<View style={styles.container}>
|
|
31
|
-
<ScrollView contentContainerStyle={styles.content}>
|
|
47
|
+
<View style={[styles.container, customStyles?.container]}>
|
|
48
|
+
<ScrollView contentContainerStyle={[styles.content, customStyles?.content]}>
|
|
32
49
|
<Text style={[styles.title, { color: theme?.textColor || '#000000' }]}>
|
|
33
|
-
{
|
|
50
|
+
{strings.instructions.title}
|
|
34
51
|
</Text>
|
|
35
52
|
|
|
36
53
|
<Text style={[styles.subtitle, { color: theme?.secondaryTextColor || '#6B7280' }]}>
|
|
37
|
-
{
|
|
54
|
+
{strings.instructions.subtitle}
|
|
38
55
|
</Text>
|
|
39
56
|
|
|
40
57
|
{/* Steps */}
|
|
41
58
|
<View style={styles.stepsContainer}>
|
|
42
59
|
<InstructionStep
|
|
43
60
|
number={1}
|
|
44
|
-
title={
|
|
45
|
-
description={
|
|
61
|
+
title={strings.capture.frontId.title}
|
|
62
|
+
description={strings.capture.frontId.instruction}
|
|
46
63
|
theme={theme}
|
|
47
64
|
/>
|
|
48
65
|
<InstructionStep
|
|
49
66
|
number={2}
|
|
50
|
-
title={
|
|
51
|
-
description={
|
|
67
|
+
title={strings.capture.backId.title}
|
|
68
|
+
description={strings.capture.backId.instruction}
|
|
52
69
|
theme={theme}
|
|
53
70
|
/>
|
|
54
71
|
<InstructionStep
|
|
55
72
|
number={3}
|
|
56
|
-
title={
|
|
57
|
-
description={
|
|
73
|
+
title={strings.liveness.title}
|
|
74
|
+
description={strings.liveness.instructions.stayStill}
|
|
58
75
|
theme={theme}
|
|
59
76
|
/>
|
|
60
77
|
</View>
|
|
@@ -62,9 +79,9 @@ export const InstructionsScreen: React.FC<InstructionsScreenProps> = ({
|
|
|
62
79
|
{/* Tips */}
|
|
63
80
|
<View style={styles.tipsContainer}>
|
|
64
81
|
<Text style={[styles.tipsTitle, { color: theme?.textColor || '#000000' }]}>
|
|
65
|
-
{
|
|
82
|
+
{tipsContent.title}
|
|
66
83
|
</Text>
|
|
67
|
-
{
|
|
84
|
+
{tipsContent.tips.map((tip, index) => (
|
|
68
85
|
<Text key={index} style={styles.tipText}>
|
|
69
86
|
• {tip}
|
|
70
87
|
</Text>
|
|
@@ -73,7 +90,7 @@ export const InstructionsScreen: React.FC<InstructionsScreenProps> = ({
|
|
|
73
90
|
|
|
74
91
|
{/* Privacy Notice */}
|
|
75
92
|
<View style={styles.privacyContainer}>
|
|
76
|
-
<Text style={styles.privacyText}>{
|
|
93
|
+
<Text style={styles.privacyText}>{privacyContent}</Text>
|
|
77
94
|
</View>
|
|
78
95
|
</ScrollView>
|
|
79
96
|
|
|
@@ -86,7 +103,7 @@ export const InstructionsScreen: React.FC<InstructionsScreenProps> = ({
|
|
|
86
103
|
]}
|
|
87
104
|
onPress={onStart}
|
|
88
105
|
>
|
|
89
|
-
<Text style={styles.buttonText}>{
|
|
106
|
+
<Text style={styles.buttonText}>{strings.instructions.startButton}</Text>
|
|
90
107
|
</TouchableOpacity>
|
|
91
108
|
</View>
|
|
92
109
|
</View>
|
|
@@ -224,44 +241,54 @@ const styles = StyleSheet.create({
|
|
|
224
241
|
},
|
|
225
242
|
});
|
|
226
243
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
244
|
+
// Helper function to get tips content based on language
|
|
245
|
+
const getTipsContent = (language?: SupportedLanguage) => {
|
|
246
|
+
switch (language) {
|
|
247
|
+
case 'es':
|
|
248
|
+
case 'es-AR':
|
|
249
|
+
return {
|
|
250
|
+
title: 'Consejos para el Éxito',
|
|
251
|
+
tips: [
|
|
252
|
+
'Asegura buena iluminación sin brillos o sombras',
|
|
253
|
+
'Mantén tu documento plano y todos los bordes visibles',
|
|
254
|
+
'Quítate los lentes y cubiertas faciales',
|
|
255
|
+
'Encuentra un lugar tranquilo sin distracciones',
|
|
256
|
+
],
|
|
257
|
+
};
|
|
258
|
+
case 'pt-BR':
|
|
259
|
+
return {
|
|
260
|
+
title: 'Dicas para o Sucesso',
|
|
261
|
+
tips: [
|
|
262
|
+
'Garanta boa iluminação sem brilhos ou sombras',
|
|
263
|
+
'Mantenha seu documento plano e todas as bordas visíveis',
|
|
264
|
+
'Remova óculos e coberturas faciais',
|
|
265
|
+
'Encontre um lugar tranquilo sem distrações',
|
|
266
|
+
],
|
|
267
|
+
};
|
|
268
|
+
default:
|
|
269
|
+
return {
|
|
270
|
+
title: 'Tips for Success',
|
|
271
|
+
tips: [
|
|
272
|
+
'Ensure good lighting without glare or shadows',
|
|
273
|
+
'Keep your ID flat and all edges visible',
|
|
274
|
+
'Remove glasses and face coverings',
|
|
275
|
+
'Find a quiet place without distractions',
|
|
276
|
+
],
|
|
277
|
+
};
|
|
278
|
+
}
|
|
245
279
|
};
|
|
246
280
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
'Asegura buena iluminación sin brillos o sombras',
|
|
259
|
-
'Mantén tu documento plano y todos los bordes visibles',
|
|
260
|
-
'Quítate los lentes y cubiertas faciales',
|
|
261
|
-
'Encuentra un lugar tranquilo sin distracciones',
|
|
262
|
-
],
|
|
263
|
-
privacy: '🔒 Tus datos están encriptados y procesados de forma segura. No almacenamos tus datos biométricos localmente.',
|
|
264
|
-
startButton: 'Iniciar Verificación',
|
|
281
|
+
// Helper function to get privacy message based on language
|
|
282
|
+
const getPrivacyContent = (language?: SupportedLanguage): string => {
|
|
283
|
+
switch (language) {
|
|
284
|
+
case 'es':
|
|
285
|
+
case 'es-AR':
|
|
286
|
+
return '🔒 Tus datos están encriptados y procesados de forma segura. No almacenamos tus datos biométricos localmente.';
|
|
287
|
+
case 'pt-BR':
|
|
288
|
+
return '🔒 Seus dados estão criptografados e processados com segurança. Não armazenamos seus dados biométricos localmente.';
|
|
289
|
+
default:
|
|
290
|
+
return '🔒 Your data is encrypted and processed securely. We do not store your biometric data locally.';
|
|
291
|
+
}
|
|
265
292
|
};
|
|
266
293
|
|
|
267
294
|
export default InstructionsScreen;
|