@trustchex/react-native-sdk 1.249.0 → 1.253.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/lib/module/Screens/Static/VerificationSessionCheckScreen.js +44 -73
- package/lib/module/Shared/Components/FaceCamera.js +5 -3
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +5 -3
- package/lib/module/Shared/Components/LanguageSelector.js +14 -10
- package/lib/module/Shared/Components/NavigationManager.js +2 -2
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +4 -1
- package/lib/module/Shared/Components/StyledButton.js +108 -9
- package/lib/module/Shared/Components/StyledTextInput.js +87 -0
- package/lib/module/Shared/Contexts/ThemeContext.js +40 -0
- package/lib/module/Translation/index.js +12 -5
- package/lib/module/Trustchex.js +16 -28
- package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/LanguageSelector.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/StyledButton.d.ts +12 -2
- package/lib/typescript/src/Shared/Components/StyledButton.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/StyledTextInput.d.ts +15 -0
- package/lib/typescript/src/Shared/Components/StyledTextInput.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Contexts/ThemeContext.d.ts +26 -0
- package/lib/typescript/src/Shared/Contexts/ThemeContext.d.ts.map +1 -0
- package/lib/typescript/src/Translation/index.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/package.json +1 -6
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +53 -85
- package/src/Shared/Components/FaceCamera.tsx +4 -2
- package/src/Shared/Components/IdentityDocumentCamera.tsx +4 -2
- package/src/Shared/Components/LanguageSelector.tsx +12 -11
- package/src/Shared/Components/NavigationManager.tsx +3 -3
- package/src/Shared/Components/QrCodeScannerCamera.tsx +3 -1
- package/src/Shared/Components/StyledButton.tsx +141 -10
- package/src/Shared/Components/StyledTextInput.tsx +128 -0
- package/src/Shared/Contexts/ThemeContext.tsx +67 -0
- package/src/Translation/index.ts +12 -10
- package/src/Trustchex.tsx +22 -37
|
@@ -8,8 +8,9 @@ import httpClient, { NotFoundError } from "../../Shared/Libs/http-client.js";
|
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
import LanguageSelector from "../../Shared/Components/LanguageSelector.js";
|
|
10
10
|
import NavigationManager from "../../Shared/Components/NavigationManager.js";
|
|
11
|
-
import { TextInput, useTheme } from 'react-native-paper';
|
|
12
11
|
import StyledButton from "../../Shared/Components/StyledButton.js";
|
|
12
|
+
import StyledTextInput from "../../Shared/Components/StyledTextInput.js";
|
|
13
|
+
import { useTheme } from "../../Shared/Contexts/ThemeContext.js";
|
|
13
14
|
import LottieView from 'lottie-react-native';
|
|
14
15
|
import { getSimulatedDemoData, isDemoSession } from "../../Shared/Libs/demo.utils.js";
|
|
15
16
|
import { useNavigation } from '@react-navigation/native';
|
|
@@ -28,9 +29,10 @@ const VerificationSessionCheckScreen = () => {
|
|
|
28
29
|
} = useTranslation();
|
|
29
30
|
const navigationManagerRef = React.useRef(null);
|
|
30
31
|
const navigation = useNavigation();
|
|
31
|
-
const theme = useTheme();
|
|
32
32
|
const initialized = useRef(false);
|
|
33
33
|
const insets = useSafeAreaInsets();
|
|
34
|
+
const theme = useTheme();
|
|
35
|
+
const primaryColor = theme.colors.primary;
|
|
34
36
|
const apiUrl = useMemo(() => `${appContext.baseUrl}/api/app/mobile`, [appContext.baseUrl]);
|
|
35
37
|
const validateSessionCode = useCallback(value => {
|
|
36
38
|
return SESSION_CODE_VALIDATION_PATTERN.test(value.toUpperCase());
|
|
@@ -109,9 +111,6 @@ const VerificationSessionCheckScreen = () => {
|
|
|
109
111
|
appContext.workflowSteps = session?.workflowSteps;
|
|
110
112
|
if (session?.branding) {
|
|
111
113
|
appContext.branding = appContext.branding || session.branding;
|
|
112
|
-
theme.colors.primary = appContext.branding.primaryColor;
|
|
113
|
-
theme.colors.secondary = appContext.branding.secondaryColor;
|
|
114
|
-
theme.colors.tertiary = appContext.branding.tertiaryColor;
|
|
115
114
|
}
|
|
116
115
|
if (session?.sendOTP) {
|
|
117
116
|
return sendOTPCode(session.id);
|
|
@@ -125,7 +124,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
125
124
|
}, 1000);
|
|
126
125
|
});
|
|
127
126
|
}
|
|
128
|
-
}, [appContext, appContext.identificationInfo.sessionId, getSession, sendOTPCode
|
|
127
|
+
}, [appContext, appContext.identificationInfo.sessionId, getSession, sendOTPCode]);
|
|
129
128
|
return /*#__PURE__*/_jsx(SafeAreaView, {
|
|
130
129
|
style: styles.safeAreaContainer,
|
|
131
130
|
children: /*#__PURE__*/_jsx(KeyboardAvoidingView, {
|
|
@@ -160,57 +159,50 @@ const VerificationSessionCheckScreen = () => {
|
|
|
160
159
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
161
160
|
style: styles.mainText,
|
|
162
161
|
children: t('verificationSessionCheckScreen.mainText')
|
|
163
|
-
}), /*#__PURE__*/
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (alphanumericText.length
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
appContext.identificationInfo.sessionId = session.id;
|
|
183
|
-
} else {
|
|
184
|
-
setSessionCode('');
|
|
185
|
-
}
|
|
186
|
-
} catch {
|
|
162
|
+
}), /*#__PURE__*/_jsx(StyledTextInput, {
|
|
163
|
+
autoCapitalize: "characters",
|
|
164
|
+
placeholder: t('verificationSessionCheckScreen.enterSessionCode'),
|
|
165
|
+
borderColor: primaryColor,
|
|
166
|
+
focusedBorderColor: primaryColor,
|
|
167
|
+
inputStyle: styles.sessionCodeTextInput,
|
|
168
|
+
placeholderStyle: styles.sessionCodeTextInputPlaceholder,
|
|
169
|
+
value: sessionCode.toUpperCase(),
|
|
170
|
+
onChangeText: async text => {
|
|
171
|
+
const alphanumericText = text.toUpperCase().replace(SESSION_CODE_CHARSET_PATTERN, '');
|
|
172
|
+
if (alphanumericText.length <= 8) {
|
|
173
|
+
setSessionCode(alphanumericText);
|
|
174
|
+
if (validateSessionCode(alphanumericText) && alphanumericText.length === 8) {
|
|
175
|
+
try {
|
|
176
|
+
setIsCheckingSession(true);
|
|
177
|
+
const session = await getSessionByCode(alphanumericText);
|
|
178
|
+
if (session?.id) {
|
|
179
|
+
appContext.identificationInfo.sessionId = session.id;
|
|
180
|
+
} else {
|
|
187
181
|
setSessionCode('');
|
|
188
|
-
} finally {
|
|
189
|
-
setTimeout(() => {
|
|
190
|
-
setIsCheckingSession(false);
|
|
191
|
-
}, 1000);
|
|
192
182
|
}
|
|
183
|
+
} catch {
|
|
184
|
+
setSessionCode('');
|
|
185
|
+
} finally {
|
|
186
|
+
setTimeout(() => {
|
|
187
|
+
setIsCheckingSession(false);
|
|
188
|
+
}, 1000);
|
|
193
189
|
}
|
|
194
190
|
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}), !sessionCode && /*#__PURE__*/_jsx(Text, {
|
|
199
|
-
style: styles.placeholderText,
|
|
200
|
-
children: t('verificationSessionCheckScreen.enterSessionCode')
|
|
201
|
-
})]
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
maxLength: 8
|
|
202
194
|
}), /*#__PURE__*/_jsxs(View, {
|
|
203
195
|
style: styles.horizontalLineContainer,
|
|
204
196
|
children: [/*#__PURE__*/_jsx(View, {
|
|
205
197
|
style: [styles.horizontalLine, {
|
|
206
|
-
backgroundColor:
|
|
198
|
+
backgroundColor: primaryColor
|
|
207
199
|
}]
|
|
208
200
|
}), /*#__PURE__*/_jsx(Text, {
|
|
209
201
|
style: styles.mainText,
|
|
210
202
|
children: t('verificationSessionCheckScreen.or')
|
|
211
203
|
}), /*#__PURE__*/_jsx(View, {
|
|
212
204
|
style: [styles.horizontalLine, {
|
|
213
|
-
backgroundColor:
|
|
205
|
+
backgroundColor: primaryColor
|
|
214
206
|
}]
|
|
215
207
|
})]
|
|
216
208
|
}), /*#__PURE__*/_jsx(StyledButton, {
|
|
@@ -224,14 +216,12 @@ const VerificationSessionCheckScreen = () => {
|
|
|
224
216
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
225
217
|
style: styles.mainText,
|
|
226
218
|
children: t('verificationSessionCheckScreen.codeText')
|
|
227
|
-
}), /*#__PURE__*/_jsx(
|
|
228
|
-
mode: "outlined",
|
|
219
|
+
}), /*#__PURE__*/_jsx(StyledTextInput, {
|
|
229
220
|
autoFocus: true,
|
|
230
221
|
placeholder: "",
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
contentStyle: styles.otpCodeInputWithText,
|
|
222
|
+
borderColor: primaryColor,
|
|
223
|
+
focusedBorderColor: primaryColor,
|
|
224
|
+
inputStyle: styles.otpCodeTextInput,
|
|
235
225
|
keyboardType: "number-pad",
|
|
236
226
|
textContentType: "oneTimeCode",
|
|
237
227
|
autoComplete: "sms-otp",
|
|
@@ -313,7 +303,7 @@ const styles = StyleSheet.create({
|
|
|
313
303
|
},
|
|
314
304
|
horizontalLine: {
|
|
315
305
|
flex: 1,
|
|
316
|
-
height:
|
|
306
|
+
height: 1
|
|
317
307
|
},
|
|
318
308
|
loadingAnimation: {
|
|
319
309
|
width: '100%',
|
|
@@ -382,40 +372,21 @@ const styles = StyleSheet.create({
|
|
|
382
372
|
alignItems: 'center',
|
|
383
373
|
position: 'absolute'
|
|
384
374
|
},
|
|
385
|
-
inputContainer: {
|
|
386
|
-
position: 'relative',
|
|
387
|
-
width: '100%'
|
|
388
|
-
},
|
|
389
375
|
sessionCodeTextInput: {
|
|
390
|
-
backgroundColor: 'white'
|
|
391
|
-
},
|
|
392
|
-
sessionCodeInputWithText: {
|
|
393
376
|
textTransform: 'uppercase',
|
|
394
377
|
fontWeight: '800',
|
|
395
378
|
fontSize: 28,
|
|
396
379
|
textAlign: 'center',
|
|
397
380
|
letterSpacing: 8
|
|
398
381
|
},
|
|
399
|
-
|
|
400
|
-
position: 'absolute',
|
|
401
|
-
top: 0,
|
|
402
|
-
left: 0,
|
|
403
|
-
right: 0,
|
|
404
|
-
height: '100%',
|
|
405
|
-
lineHeight: 56,
|
|
382
|
+
sessionCodeTextInputPlaceholder: {
|
|
406
383
|
fontSize: 16,
|
|
407
|
-
|
|
384
|
+
fontWeight: '400',
|
|
385
|
+
letterSpacing: 0,
|
|
408
386
|
textAlign: 'center',
|
|
409
|
-
|
|
410
|
-
},
|
|
411
|
-
sessionCodeInputPlaceholder: {
|
|
412
|
-
fontSize: 16,
|
|
413
|
-
textAlign: 'center'
|
|
387
|
+
textTransform: 'none'
|
|
414
388
|
},
|
|
415
389
|
otpCodeTextInput: {
|
|
416
|
-
backgroundColor: 'white'
|
|
417
|
-
},
|
|
418
|
-
otpCodeInputWithText: {
|
|
419
390
|
fontWeight: '800',
|
|
420
391
|
fontSize: 28,
|
|
421
392
|
textAlign: 'center',
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useIsFocused } from '@react-navigation/native';
|
|
4
4
|
import { useKeepAwake } from "../Libs/native-keep-awake.utils.js";
|
|
5
5
|
import React, { useEffect, useState } from 'react';
|
|
6
|
-
import { StyleSheet, Text, View, Platform, Linking, Dimensions } from 'react-native';
|
|
6
|
+
import { StyleSheet, Text, View, Platform, Linking, Dimensions, ActivityIndicator } from 'react-native';
|
|
7
7
|
import { useCameraDevice, useCameraPermission, Camera, useFrameProcessor, useCameraFormat, runAtTargetFps, useMicrophonePermission } from 'react-native-vision-camera';
|
|
8
8
|
import { runAsync } from "../Libs/worklet.utils.js";
|
|
9
9
|
import { useFaceDetector } from "../VisionCameraPlugins/FaceDetector/index.js";
|
|
@@ -11,8 +11,8 @@ import { Worklets, useSharedValue } from 'react-native-worklets-core';
|
|
|
11
11
|
import { crop } from "../VisionCameraPlugins/Cropper/index.js";
|
|
12
12
|
import { isFrameBright } from "../Libs/camera.utils.js";
|
|
13
13
|
import { useTranslation } from 'react-i18next';
|
|
14
|
-
import { ActivityIndicator } from 'react-native-paper';
|
|
15
14
|
import StyledButton from "./StyledButton.js";
|
|
15
|
+
import { useTheme } from "../Contexts/ThemeContext.js";
|
|
16
16
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
17
17
|
const VIDEO_WIDTH = 1280;
|
|
18
18
|
const VIDEO_HEIGHT = 720;
|
|
@@ -23,6 +23,7 @@ const FaceCamera = ({
|
|
|
23
23
|
onCameraInitialized
|
|
24
24
|
}) => {
|
|
25
25
|
useKeepAwake();
|
|
26
|
+
const theme = useTheme();
|
|
26
27
|
const cameraPermission = useCameraPermission();
|
|
27
28
|
const microphonePermission = useMicrophonePermission();
|
|
28
29
|
const [permissionsRequested, setPermissionsRequested] = useState(false);
|
|
@@ -132,7 +133,8 @@ const FaceCamera = ({
|
|
|
132
133
|
return /*#__PURE__*/_jsx(View, {
|
|
133
134
|
style: styles.permissionContainer,
|
|
134
135
|
children: /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
135
|
-
size: "large"
|
|
136
|
+
size: "large",
|
|
137
|
+
color: theme.colors.primary
|
|
136
138
|
})
|
|
137
139
|
});
|
|
138
140
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/* eslint-disable react-native/no-inline-styles */
|
|
4
4
|
import React, { useEffect, useState } from 'react';
|
|
5
|
-
import { View, StyleSheet, Text as TextView, Platform, Vibration, TouchableOpacity, Text, Linking, Image } from 'react-native';
|
|
5
|
+
import { View, StyleSheet, Text as TextView, Platform, Vibration, TouchableOpacity, Text, Linking, Image, ActivityIndicator } from 'react-native';
|
|
6
6
|
import { Camera, runAtTargetFps, useCameraDevice, useCameraFormat, useCameraPermission, useFrameProcessor } from 'react-native-vision-camera';
|
|
7
7
|
import { runAsync } from "../Libs/worklet.utils.js";
|
|
8
8
|
import { useRunOnJS, useSharedValue } from 'react-native-worklets-core';
|
|
@@ -17,11 +17,11 @@ import { AdaptiveThresholdTypes, ColorConversionCodes, DataTypes, ObjectType, Op
|
|
|
17
17
|
import { getAverageBrightness } from "../Libs/camera.utils.js";
|
|
18
18
|
import { useTranslation } from 'react-i18next';
|
|
19
19
|
import LottieView from 'lottie-react-native';
|
|
20
|
-
import { ActivityIndicator } from 'react-native-paper';
|
|
21
20
|
import StyledButton from "./StyledButton.js";
|
|
22
21
|
import { scanCodes } from "../VisionCameraPlugins/BarcodeScanner/index.js";
|
|
23
22
|
import { speakWithDebounce } from "../Libs/tts.utils.js";
|
|
24
23
|
import AppContext from "../Contexts/AppContext.js";
|
|
24
|
+
import { useTheme } from "../Contexts/ThemeContext.js";
|
|
25
25
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
26
26
|
// const windowWidth = Dimensions.get('window').width;
|
|
27
27
|
// const windowHeight = Dimensions.get('window').height;
|
|
@@ -38,6 +38,7 @@ const IdentityDocumentCamera = ({
|
|
|
38
38
|
showDebugImages = false
|
|
39
39
|
}) => {
|
|
40
40
|
useKeepAwake();
|
|
41
|
+
const theme = useTheme();
|
|
41
42
|
const appContext = React.useContext(AppContext);
|
|
42
43
|
const cameraRef = React.useRef(null);
|
|
43
44
|
const cameraPermission = useCameraPermission();
|
|
@@ -622,7 +623,8 @@ const IdentityDocumentCamera = ({
|
|
|
622
623
|
return /*#__PURE__*/_jsx(View, {
|
|
623
624
|
style: styles.permissionContainer,
|
|
624
625
|
children: /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
625
|
-
size: "large"
|
|
626
|
+
size: "large",
|
|
627
|
+
color: theme.colors.primary
|
|
626
628
|
})
|
|
627
629
|
});
|
|
628
630
|
}
|
|
@@ -3,26 +3,32 @@
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
5
|
import i18n from "../../Translation/index.js";
|
|
6
|
-
import
|
|
6
|
+
import { useTheme } from "../Contexts/ThemeContext.js";
|
|
7
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
8
|
const LanguageSelector = () => {
|
|
9
|
-
const
|
|
9
|
+
const theme = useTheme();
|
|
10
|
+
const isEnglish = i18n.language.startsWith('en');
|
|
11
|
+
const isTurkish = i18n.language.startsWith('tr');
|
|
10
12
|
return /*#__PURE__*/_jsxs(View, {
|
|
11
13
|
style: styles.container,
|
|
12
14
|
children: [/*#__PURE__*/_jsx(Pressable, {
|
|
13
15
|
onPress: () => i18n.changeLanguage('en'),
|
|
14
16
|
children: /*#__PURE__*/_jsx(Text, {
|
|
15
|
-
style: [styles.buttonText,
|
|
16
|
-
color:
|
|
17
|
+
style: [styles.buttonText, isEnglish && styles.buttonTextSelected, isEnglish && {
|
|
18
|
+
color: theme.colors.primary
|
|
17
19
|
}],
|
|
18
20
|
children: "EN"
|
|
19
21
|
})
|
|
20
22
|
}), /*#__PURE__*/_jsx(View, {
|
|
21
|
-
style: styles.verticalSeperator
|
|
23
|
+
style: [styles.verticalSeperator, {
|
|
24
|
+
borderColor: theme.colors.border
|
|
25
|
+
}]
|
|
22
26
|
}), /*#__PURE__*/_jsx(Pressable, {
|
|
23
27
|
onPress: () => i18n.changeLanguage('tr'),
|
|
24
28
|
children: /*#__PURE__*/_jsx(Text, {
|
|
25
|
-
style: [styles.buttonText,
|
|
29
|
+
style: [styles.buttonText, isTurkish && styles.buttonTextSelected, isTurkish && {
|
|
30
|
+
color: theme.colors.primary
|
|
31
|
+
}],
|
|
26
32
|
children: "TR"
|
|
27
33
|
})
|
|
28
34
|
})]
|
|
@@ -38,16 +44,14 @@ const styles = StyleSheet.create({
|
|
|
38
44
|
},
|
|
39
45
|
buttonText: {
|
|
40
46
|
fontSize: 18,
|
|
41
|
-
color: '
|
|
47
|
+
color: '#999999'
|
|
42
48
|
},
|
|
43
49
|
buttonTextSelected: {
|
|
44
|
-
color: '#000000',
|
|
45
50
|
fontWeight: 'bold'
|
|
46
51
|
},
|
|
47
52
|
verticalSeperator: {
|
|
48
53
|
borderLeftWidth: 1,
|
|
49
|
-
height: 24
|
|
50
|
-
borderColor: 'black'
|
|
54
|
+
height: 24
|
|
51
55
|
}
|
|
52
56
|
});
|
|
53
57
|
export default LanguageSelector;
|
|
@@ -6,7 +6,7 @@ import { CommonActions, useNavigation, usePreventRemove } from '@react-navigatio
|
|
|
6
6
|
import { View, StyleSheet, Alert } from 'react-native';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import i18n from "../../Translation/index.js";
|
|
9
|
-
import
|
|
9
|
+
import StyledButton from "./StyledButton.js";
|
|
10
10
|
|
|
11
11
|
// Simple global navigation lock
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -150,7 +150,7 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
|
|
|
150
150
|
}));
|
|
151
151
|
return appContext.currentWorkflowStep && (!appContext.currentWorkflowStep?.required || canSkipStep) && /*#__PURE__*/_jsx(View, {
|
|
152
152
|
style: styles.container,
|
|
153
|
-
children: /*#__PURE__*/_jsx(
|
|
153
|
+
children: /*#__PURE__*/_jsx(StyledButton, {
|
|
154
154
|
mode: "text",
|
|
155
155
|
onPress: goToNextRouteWithAlert,
|
|
156
156
|
children: t('navigationManager.skipStepLabel')
|
|
@@ -10,11 +10,13 @@ import { useTranslation } from 'react-i18next';
|
|
|
10
10
|
import LottieView from 'lottie-react-native';
|
|
11
11
|
import { scanCodes } from "../VisionCameraPlugins/BarcodeScanner/index.js";
|
|
12
12
|
import StyledButton from "./StyledButton.js";
|
|
13
|
+
import { useTheme } from "../Contexts/ThemeContext.js";
|
|
13
14
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
15
|
const QrCodeScannerCamera = ({
|
|
15
16
|
onQrCodeScanned
|
|
16
17
|
}) => {
|
|
17
18
|
useKeepAwake();
|
|
19
|
+
const theme = useTheme();
|
|
18
20
|
const cameraPermission = useCameraPermission();
|
|
19
21
|
const [permissionsRequested, setPermissionsRequested] = React.useState(false);
|
|
20
22
|
const [isActive, setIsActive] = React.useState(false);
|
|
@@ -123,7 +125,8 @@ const QrCodeScannerCamera = ({
|
|
|
123
125
|
return /*#__PURE__*/_jsx(View, {
|
|
124
126
|
style: styles.permissionContainer,
|
|
125
127
|
children: /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
126
|
-
size: "large"
|
|
128
|
+
size: "large",
|
|
129
|
+
color: theme.colors.primary
|
|
127
130
|
})
|
|
128
131
|
});
|
|
129
132
|
}
|
|
@@ -1,18 +1,89 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { StyleSheet } from 'react-native';
|
|
5
|
-
import {
|
|
4
|
+
import { StyleSheet, TouchableOpacity, Text, ActivityIndicator } from 'react-native';
|
|
5
|
+
import { useTheme } from "../Contexts/ThemeContext.js";
|
|
6
|
+
|
|
7
|
+
// Calculate if a color is light or dark to determine text color
|
|
6
8
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
+
const isLightColor = color => {
|
|
10
|
+
// Remove # if present
|
|
11
|
+
const hex = color.replace('#', '');
|
|
12
|
+
|
|
13
|
+
// Convert to RGB
|
|
14
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
15
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
16
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
17
|
+
|
|
18
|
+
// Calculate relative luminance using WCAG formula
|
|
19
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
20
|
+
|
|
21
|
+
// Return true if light (luminance > 0.5)
|
|
22
|
+
return luminance > 0.5;
|
|
23
|
+
};
|
|
7
24
|
const StyledButton = ({
|
|
25
|
+
mode = 'contained',
|
|
26
|
+
onPress,
|
|
27
|
+
disabled = false,
|
|
28
|
+
loading = false,
|
|
29
|
+
children,
|
|
8
30
|
style,
|
|
9
31
|
labelStyle,
|
|
10
|
-
|
|
32
|
+
buttonColor,
|
|
33
|
+
textColor
|
|
11
34
|
}) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
35
|
+
const theme = useTheme();
|
|
36
|
+
const primaryColor = buttonColor || theme.colors.primary;
|
|
37
|
+
|
|
38
|
+
// Determine text color based on background color for contained mode
|
|
39
|
+
const getContainedTextColor = () => {
|
|
40
|
+
if (textColor) return textColor;
|
|
41
|
+
return isLightColor(primaryColor) ? '#000000' : '#FFFFFF';
|
|
42
|
+
};
|
|
43
|
+
const containedTextColor = getContainedTextColor();
|
|
44
|
+
const getButtonStyle = () => {
|
|
45
|
+
const baseStyle = [styles.button, style];
|
|
46
|
+
if (mode === 'contained') {
|
|
47
|
+
return [...baseStyle, styles.containedButton, {
|
|
48
|
+
backgroundColor: primaryColor
|
|
49
|
+
}, disabled && styles.disabledButton];
|
|
50
|
+
}
|
|
51
|
+
if (mode === 'outlined') {
|
|
52
|
+
return [...baseStyle, styles.outlinedButton, {
|
|
53
|
+
borderColor: primaryColor
|
|
54
|
+
}, disabled && styles.disabledButton];
|
|
55
|
+
}
|
|
56
|
+
return [...baseStyle, styles.textButton];
|
|
57
|
+
};
|
|
58
|
+
const getTextStyle = () => {
|
|
59
|
+
const baseStyle = [styles.label, labelStyle];
|
|
60
|
+
if (mode === 'contained') {
|
|
61
|
+
return [...baseStyle, styles.containedLabel, {
|
|
62
|
+
color: containedTextColor
|
|
63
|
+
}, disabled && styles.disabledLabel];
|
|
64
|
+
}
|
|
65
|
+
if (mode === 'outlined') {
|
|
66
|
+
return [...baseStyle, styles.outlinedLabel, {
|
|
67
|
+
color: primaryColor
|
|
68
|
+
}, disabled && styles.disabledLabel];
|
|
69
|
+
}
|
|
70
|
+
return [...baseStyle, styles.textLabel, {
|
|
71
|
+
color: primaryColor
|
|
72
|
+
}, disabled && styles.disabledLabel];
|
|
73
|
+
};
|
|
74
|
+
const loadingColor = mode === 'contained' ? containedTextColor : primaryColor;
|
|
75
|
+
return /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
76
|
+
style: getButtonStyle(),
|
|
77
|
+
onPress: onPress,
|
|
78
|
+
disabled: disabled || loading,
|
|
79
|
+
activeOpacity: 0.7,
|
|
80
|
+
children: loading ? /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
81
|
+
size: "small",
|
|
82
|
+
color: loadingColor
|
|
83
|
+
}) : /*#__PURE__*/_jsx(Text, {
|
|
84
|
+
style: getTextStyle(),
|
|
85
|
+
children: children
|
|
86
|
+
})
|
|
16
87
|
});
|
|
17
88
|
};
|
|
18
89
|
const styles = StyleSheet.create({
|
|
@@ -20,11 +91,39 @@ const styles = StyleSheet.create({
|
|
|
20
91
|
borderRadius: 8,
|
|
21
92
|
height: 56,
|
|
22
93
|
justifyContent: 'center',
|
|
23
|
-
|
|
94
|
+
alignItems: 'center',
|
|
95
|
+
paddingHorizontal: 16
|
|
96
|
+
},
|
|
97
|
+
containedButton: {
|
|
98
|
+
elevation: 2,
|
|
99
|
+
shadowColor: '#000',
|
|
100
|
+
shadowOffset: {
|
|
101
|
+
width: 0,
|
|
102
|
+
height: 2
|
|
103
|
+
},
|
|
104
|
+
shadowOpacity: 0.25,
|
|
105
|
+
shadowRadius: 3.84
|
|
106
|
+
},
|
|
107
|
+
outlinedButton: {
|
|
108
|
+
backgroundColor: 'transparent',
|
|
109
|
+
borderWidth: 2
|
|
110
|
+
},
|
|
111
|
+
textButton: {
|
|
112
|
+
backgroundColor: 'transparent'
|
|
113
|
+
},
|
|
114
|
+
disabledButton: {
|
|
115
|
+
opacity: 0.5
|
|
24
116
|
},
|
|
25
117
|
label: {
|
|
26
118
|
fontWeight: 'bold',
|
|
27
|
-
fontSize: 16
|
|
119
|
+
fontSize: 16,
|
|
120
|
+
textAlign: 'center'
|
|
121
|
+
},
|
|
122
|
+
containedLabel: {},
|
|
123
|
+
outlinedLabel: {},
|
|
124
|
+
textLabel: {},
|
|
125
|
+
disabledLabel: {
|
|
126
|
+
opacity: 0.6
|
|
28
127
|
}
|
|
29
128
|
});
|
|
30
129
|
export default StyledButton;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { StyleSheet, TextInput, View, Text } from 'react-native';
|
|
5
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
const StyledTextInput = /*#__PURE__*/React.forwardRef(({
|
|
7
|
+
containerStyle,
|
|
8
|
+
inputStyle,
|
|
9
|
+
placeholderStyle,
|
|
10
|
+
borderColor = '#DDDDDD',
|
|
11
|
+
focusedBorderColor,
|
|
12
|
+
backgroundColor = '#FFFFFF',
|
|
13
|
+
textColor = '#000000',
|
|
14
|
+
placeholderColor = '#999999',
|
|
15
|
+
style,
|
|
16
|
+
placeholderTextColor,
|
|
17
|
+
onFocus,
|
|
18
|
+
onBlur,
|
|
19
|
+
value,
|
|
20
|
+
...props
|
|
21
|
+
}, ref) => {
|
|
22
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
23
|
+
const hasValue = value !== undefined && value !== '';
|
|
24
|
+
const handleFocus = e => {
|
|
25
|
+
setIsFocused(true);
|
|
26
|
+
onFocus?.(e);
|
|
27
|
+
};
|
|
28
|
+
const handleBlur = e => {
|
|
29
|
+
setIsFocused(false);
|
|
30
|
+
onBlur?.(e);
|
|
31
|
+
};
|
|
32
|
+
const currentBorderColor = isFocused ? focusedBorderColor || borderColor : borderColor;
|
|
33
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
34
|
+
style: [styles.container, containerStyle],
|
|
35
|
+
children: [/*#__PURE__*/_jsx(TextInput, {
|
|
36
|
+
ref: ref,
|
|
37
|
+
...props,
|
|
38
|
+
value: value,
|
|
39
|
+
placeholder: "",
|
|
40
|
+
style: [styles.input, {
|
|
41
|
+
backgroundColor,
|
|
42
|
+
borderColor: currentBorderColor,
|
|
43
|
+
color: textColor
|
|
44
|
+
}, inputStyle, style],
|
|
45
|
+
onFocus: handleFocus,
|
|
46
|
+
onBlur: handleBlur
|
|
47
|
+
}), !hasValue && props.placeholder && /*#__PURE__*/_jsx(View, {
|
|
48
|
+
style: styles.placeholderContainer,
|
|
49
|
+
pointerEvents: "none",
|
|
50
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
51
|
+
style: [styles.placeholderText, {
|
|
52
|
+
color: placeholderColor || placeholderTextColor || '#999'
|
|
53
|
+
}, placeholderStyle],
|
|
54
|
+
children: props.placeholder
|
|
55
|
+
})
|
|
56
|
+
})]
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
StyledTextInput.displayName = 'StyledTextInput';
|
|
60
|
+
const styles = StyleSheet.create({
|
|
61
|
+
container: {
|
|
62
|
+
width: '100%',
|
|
63
|
+
position: 'relative'
|
|
64
|
+
},
|
|
65
|
+
input: {
|
|
66
|
+
borderWidth: 2,
|
|
67
|
+
borderRadius: 8,
|
|
68
|
+
height: 56,
|
|
69
|
+
paddingHorizontal: 16,
|
|
70
|
+
fontSize: 16,
|
|
71
|
+
fontWeight: '400'
|
|
72
|
+
},
|
|
73
|
+
placeholderContainer: {
|
|
74
|
+
position: 'absolute',
|
|
75
|
+
top: 0,
|
|
76
|
+
left: 0,
|
|
77
|
+
right: 0,
|
|
78
|
+
bottom: 0,
|
|
79
|
+
justifyContent: 'center',
|
|
80
|
+
paddingHorizontal: 16
|
|
81
|
+
},
|
|
82
|
+
placeholderText: {
|
|
83
|
+
fontSize: 16,
|
|
84
|
+
fontWeight: '400'
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
export default StyledTextInput;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, useMemo } from 'react';
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
const defaultColors = {
|
|
6
|
+
primary: '#000000',
|
|
7
|
+
secondary: '#CCCCCC',
|
|
8
|
+
tertiary: '#FF0000',
|
|
9
|
+
background: '#FFFFFF',
|
|
10
|
+
surface: '#F5F5F5',
|
|
11
|
+
text: '#000000',
|
|
12
|
+
textSecondary: '#666666',
|
|
13
|
+
border: '#DDDDDD',
|
|
14
|
+
error: '#E53935',
|
|
15
|
+
success: '#43A047'
|
|
16
|
+
};
|
|
17
|
+
const ThemeContext = /*#__PURE__*/createContext({
|
|
18
|
+
colors: defaultColors
|
|
19
|
+
});
|
|
20
|
+
export const useTheme = () => useContext(ThemeContext);
|
|
21
|
+
export const ThemeProvider = ({
|
|
22
|
+
children,
|
|
23
|
+
primaryColor,
|
|
24
|
+
secondaryColor,
|
|
25
|
+
tertiaryColor
|
|
26
|
+
}) => {
|
|
27
|
+
const colors = useMemo(() => ({
|
|
28
|
+
...defaultColors,
|
|
29
|
+
primary: primaryColor || defaultColors.primary,
|
|
30
|
+
secondary: secondaryColor || defaultColors.secondary,
|
|
31
|
+
tertiary: tertiaryColor || defaultColors.tertiary
|
|
32
|
+
}), [primaryColor, secondaryColor, tertiaryColor]);
|
|
33
|
+
const value = useMemo(() => ({
|
|
34
|
+
colors
|
|
35
|
+
}), [colors]);
|
|
36
|
+
return /*#__PURE__*/_jsx(ThemeContext.Provider, {
|
|
37
|
+
value: value,
|
|
38
|
+
children: children
|
|
39
|
+
});
|
|
40
|
+
};
|
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
import i18n from 'i18next';
|
|
4
4
|
import { initReactI18next } from 'react-i18next';
|
|
5
5
|
import * as resources from "./Resources/index.js";
|
|
6
|
-
import { Platform, NativeModules } from 'react-native';
|
|
7
6
|
const getCurrentLanguage = () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
try {
|
|
8
|
+
if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) {
|
|
9
|
+
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
10
|
+
if (locale) {
|
|
11
|
+
// Extract language code from locale (e.g., "en-US" -> "en", "tr-TR" -> "tr")
|
|
12
|
+
return locale.split(/[-_]/)[0].toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return 'en';
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('Error detecting language:', error);
|
|
18
|
+
return 'en';
|
|
11
19
|
}
|
|
12
|
-
return deviceLanguage;
|
|
13
20
|
};
|
|
14
21
|
i18n.use(initReactI18next).init({
|
|
15
22
|
compatibilityJSON: 'v4',
|