@modhamanish/rn-mm-template 1.0.4 → 1.1.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.
Files changed (50) hide show
  1. package/MMTemplate/.eslintrc.js +95 -1
  2. package/MMTemplate/.husky/pre-commit +2 -0
  3. package/MMTemplate/.prettierrc.js +2 -0
  4. package/MMTemplate/App.tsx +27 -21
  5. package/MMTemplate/README.md +76 -35
  6. package/MMTemplate/__tests__/App.test.tsx +5 -3
  7. package/MMTemplate/babel.config.js +24 -1
  8. package/MMTemplate/index.js +1 -0
  9. package/MMTemplate/lint_errors.txt +7 -0
  10. package/MMTemplate/package.json +24 -4
  11. package/MMTemplate/src/components/AnimationView.tsx +54 -69
  12. package/MMTemplate/src/components/AppText.tsx +7 -4
  13. package/MMTemplate/src/components/CustomAlert.tsx +203 -0
  14. package/MMTemplate/src/components/CustomToast.tsx +2 -1
  15. package/MMTemplate/src/components/ErrorBoundaryFallback.tsx +127 -0
  16. package/MMTemplate/src/components/FeatureItem.tsx +8 -6
  17. package/MMTemplate/src/components/FullScreenContainer.tsx +9 -7
  18. package/MMTemplate/src/components/InfoCard.tsx +8 -6
  19. package/MMTemplate/src/components/LanguageSwitcher.tsx +8 -6
  20. package/MMTemplate/src/components/TextInput.tsx +25 -15
  21. package/MMTemplate/src/components/ThemeSwitcher.tsx +4 -3
  22. package/MMTemplate/src/context/AuthContext.tsx +5 -4
  23. package/MMTemplate/src/context/ThemeContext.tsx +10 -19
  24. package/MMTemplate/src/locales/en.json +4 -1
  25. package/MMTemplate/src/locales/hi.json +4 -1
  26. package/MMTemplate/src/navigation/AppNavigator.tsx +7 -8
  27. package/MMTemplate/src/navigation/AppStack.tsx +6 -6
  28. package/MMTemplate/src/navigation/AuthCheck.tsx +11 -10
  29. package/MMTemplate/src/navigation/AuthStack.tsx +6 -4
  30. package/MMTemplate/src/navigation/MainTab.tsx +19 -13
  31. package/MMTemplate/src/screens/AddNoteScreen.tsx +20 -14
  32. package/MMTemplate/src/screens/HomeScreen.tsx +21 -15
  33. package/MMTemplate/src/screens/LoginScreen.tsx +21 -18
  34. package/MMTemplate/src/screens/NoteScreen.tsx +18 -16
  35. package/MMTemplate/src/screens/ProfileScreen.tsx +16 -13
  36. package/MMTemplate/src/screens/SettingsScreen.tsx +14 -11
  37. package/MMTemplate/src/screens/WelcomeScreen.tsx +19 -13
  38. package/MMTemplate/src/services/axiosInstance.ts +7 -5
  39. package/MMTemplate/src/services/note.query.ts +7 -5
  40. package/MMTemplate/src/theme/{Colors.ts → colors.ts} +6 -0
  41. package/MMTemplate/src/types/components.types.ts +38 -0
  42. package/MMTemplate/src/types/navigation.types.ts +1 -1
  43. package/MMTemplate/src/utils/i18n.ts +8 -6
  44. package/MMTemplate/src/utils/navigationUtils.ts +2 -1
  45. package/MMTemplate/src/utils/storageHelper.ts +8 -8
  46. package/MMTemplate/src/utils/utilsHelper.ts +1 -0
  47. package/MMTemplate/tsconfig.json +27 -0
  48. package/README.md +3 -1
  49. package/package.json +4 -1
  50. package/release.js +75 -0
@@ -1,4 +1,5 @@
1
- import React, { memo, useEffect } from 'react';
1
+ import React, { FC, memo, useEffect } from 'react';
2
+
2
3
  import Animated, {
3
4
  Easing,
4
5
  useAnimatedStyle,
@@ -7,62 +8,49 @@ import Animated, {
7
8
  withTiming,
8
9
  } from 'react-native-reanimated';
9
10
 
10
- const AnimationView = ({
11
+ import { AnimationViewProps } from '@src/types/components.types';
12
+
13
+ const AnimationView: FC<AnimationViewProps> = ({
11
14
  children,
12
15
  animType,
13
16
  duration = 500,
14
17
  delay = 0,
15
18
  rotateValue = 360,
16
19
  style,
17
- }: {
18
- children: React.ReactNode;
19
- animType:
20
- | 'FadeIn'
21
- | 'FadeOut'
22
- | 'ZoomIn'
23
- | 'ZoomOut'
24
- | 'RotateIn'
25
- | 'RotateOut'
26
- | 'SlideInDown';
27
- duration?: number;
28
- delay?: number;
29
- rotateValue?: number;
30
- style?: any;
31
20
  }) => {
32
- const fadeAnim = useSharedValue(0);
33
- const zoomAnim = useSharedValue(0);
34
- const rotateAnim = useSharedValue(0);
35
- const translateAnim = useSharedValue(-100);
21
+ const getInitialValue = () => {
22
+ switch (animType) {
23
+ case 'SlideInDown':
24
+ return -100;
25
+ case 'FadeOut':
26
+ case 'ZoomOut':
27
+ return 1;
28
+ default:
29
+ return 0;
30
+ }
31
+ };
32
+ const animValue = useSharedValue(getInitialValue());
36
33
 
37
34
  const animStyle = useAnimatedStyle(() => {
38
35
  switch (animType) {
39
36
  case 'FadeIn':
40
- return {
41
- opacity: fadeAnim.value,
42
- };
43
37
  case 'FadeOut':
44
38
  return {
45
- opacity: fadeAnim.value,
39
+ opacity: animValue.value,
46
40
  };
47
41
  case 'ZoomIn':
48
- return {
49
- transform: [{ scale: zoomAnim.value }],
50
- };
51
42
  case 'ZoomOut':
52
43
  return {
53
- transform: [{ scale: zoomAnim.value }],
44
+ transform: [{ scale: animValue.value }],
54
45
  };
55
46
  case 'RotateIn':
56
- return {
57
- transform: [{ rotate: rotateAnim.value + 'deg' }],
58
- };
59
47
  case 'RotateOut':
60
48
  return {
61
- transform: [{ rotate: rotateAnim.value + 'deg' }],
49
+ transform: [{ rotate: animValue.value + 'deg' }],
62
50
  };
63
51
  case 'SlideInDown':
64
52
  return {
65
- transform: [{ translateY: translateAnim.value }],
53
+ transform: [{ translateY: animValue.value }],
66
54
  };
67
55
  default:
68
56
  return {};
@@ -70,43 +58,40 @@ const AnimationView = ({
70
58
  });
71
59
 
72
60
  useEffect(() => {
73
- if (animType === 'FadeIn') {
74
- fadeAnim.value = withDelay(delay, withTiming(1, { duration: duration }));
75
- } else if (animType === 'FadeOut') {
76
- fadeAnim.value = withDelay(delay, withTiming(0, { duration: duration }));
77
- } else if (animType === 'ZoomIn') {
78
- zoomAnim.value = withDelay(
79
- delay,
80
- withTiming(1, { duration: duration, easing: Easing.elastic(1) }),
81
- );
82
- } else if (animType === 'ZoomOut') {
83
- zoomAnim.value = withDelay(
84
- delay,
85
- withTiming(0, { duration: duration, easing: Easing.elastic(1) }),
86
- );
87
- } else if (animType === 'RotateIn') {
88
- rotateAnim.value = withDelay(
89
- delay,
90
- withTiming(rotateValue, {
91
- duration: duration,
92
- easing: Easing.elastic(1),
93
- }),
94
- );
95
- } else if (animType === 'RotateOut') {
96
- rotateAnim.value = withDelay(
97
- delay,
98
- withTiming(rotateValue, {
99
- duration: duration,
100
- easing: Easing.elastic(1),
101
- }),
102
- );
103
- } else if (animType === 'SlideInDown') {
104
- translateAnim.value = withDelay(
105
- delay,
106
- withTiming(0, { duration: duration, easing: Easing.elastic(1) }),
107
- );
61
+ let targetValue = 0;
62
+ let easing = Easing.inOut(Easing.ease);
63
+
64
+ switch (animType) {
65
+ case 'FadeIn':
66
+ targetValue = 1;
67
+ break;
68
+ case 'FadeOut':
69
+ targetValue = 0;
70
+ break;
71
+ case 'ZoomIn':
72
+ targetValue = 1;
73
+ easing = Easing.elastic(1);
74
+ break;
75
+ case 'ZoomOut':
76
+ targetValue = 0;
77
+ easing = Easing.elastic(1);
78
+ break;
79
+ case 'RotateIn':
80
+ case 'RotateOut':
81
+ targetValue = rotateValue;
82
+ easing = Easing.elastic(1);
83
+ break;
84
+ case 'SlideInDown':
85
+ targetValue = 0;
86
+ easing = Easing.elastic(1);
87
+ break;
108
88
  }
109
- }, [animType, duration, delay, rotateValue]);
89
+
90
+ animValue.value = withDelay(
91
+ delay,
92
+ withTiming(targetValue, { duration, easing }),
93
+ );
94
+ }, [animType, duration, delay, rotateValue, animValue]);
110
95
  return <Animated.View style={[animStyle, style]}>{children}</Animated.View>;
111
96
  };
112
97
 
@@ -1,7 +1,8 @@
1
1
  import React, { FC, memo } from 'react';
2
2
  import { Text, TextStyle } from 'react-native';
3
- import { useTheme } from '../context/ThemeContext';
4
- import { AppTextProps, AppTextSize } from '../types/components.types';
3
+
4
+ import { AppTextProps, AppTextSize } from '@app-types/components.types';
5
+ import { useTheme } from '@context/ThemeContext';
5
6
 
6
7
  const FONTS: Record<string, string> | undefined = {
7
8
  // Define custom font families here. If empty or undefined, the component will use default system fonts with font weights.
@@ -41,7 +42,9 @@ const AppText: FC<AppTextProps> = ({
41
42
  return SIZES[s as string] || SIZES.normal;
42
43
  };
43
44
 
44
- const getTransform = (t?: string): any => {
45
+ const getTransform = (
46
+ t?: string,
47
+ ): 'uppercase' | 'lowercase' | 'capitalize' | undefined => {
45
48
  if (!t) return undefined;
46
49
  switch (t) {
47
50
  case 'capital':
@@ -54,7 +57,7 @@ const AppText: FC<AppTextProps> = ({
54
57
  case 'capitalize':
55
58
  return 'capitalize';
56
59
  default:
57
- return t;
60
+ return undefined;
58
61
  }
59
62
  };
60
63
 
@@ -0,0 +1,203 @@
1
+ import React, { FC, memo, useState, useMemo } from 'react';
2
+ import { Modal, StyleSheet, TouchableOpacity, View } from 'react-native';
3
+
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import AppText from '@components/AppText';
7
+ import { useTheme } from '@src/context/ThemeContext';
8
+ import { ThemeType } from '@src/theme/colors';
9
+ import { AlertOptionsProps } from '@src/types/components.types';
10
+ import { hexWithOpacity } from '@src/utils/utilsHelper';
11
+
12
+ let externalShow: ((opts: AlertOptionsProps) => void) | null = null;
13
+
14
+ const CustomAlert: FC = () => {
15
+ const [stack, setStack] = useState<AlertOptionsProps[]>([]);
16
+ const { t } = useTranslation();
17
+ const theme = useTheme();
18
+ const { colors } = theme;
19
+ const styles = useMemo(() => getStyles(theme), [theme]);
20
+
21
+ const show = (opts: AlertOptionsProps) => {
22
+ const item: AlertOptionsProps = {
23
+ title: opts.title || '',
24
+ message: opts.message || '',
25
+ onConfirm: opts.onConfirm,
26
+ onCancel: opts.onCancel,
27
+ onClose: opts.onClose,
28
+ confirmText: opts.confirmText || t('common.ok'),
29
+ cancelText: opts.cancelText || t('common.cancel'),
30
+ boxStyle: opts.boxStyle,
31
+ titleStyle: opts.titleStyle,
32
+ messageStyle: opts.messageStyle,
33
+ confirmButtonStyle: opts.confirmButtonStyle,
34
+ cancelButtonStyle: opts.cancelButtonStyle,
35
+ confirmTextStyle: opts.confirmTextStyle,
36
+ cancelTextStyle: opts.cancelTextStyle,
37
+ isCancellable: opts.isCancellable || false,
38
+ isError: opts.isError || false,
39
+ };
40
+
41
+ setStack(prev => [...prev, item]);
42
+ };
43
+
44
+ const hideTop = () => {
45
+ setStack(prev => prev.slice(0, -1));
46
+ };
47
+
48
+ externalShow = show;
49
+
50
+ if (stack.length === 0) {
51
+ return null;
52
+ }
53
+
54
+ const item = stack[stack.length - 1];
55
+
56
+ return (
57
+ <Modal visible transparent animationType="fade">
58
+ <TouchableOpacity
59
+ style={styles.overlay}
60
+ activeOpacity={1}
61
+ onPress={() => {
62
+ if (item.isCancellable || (!item.onCancel && !item.onConfirm)) {
63
+ hideTop();
64
+ item.onClose && item.onClose();
65
+ }
66
+ }}
67
+ >
68
+ <TouchableOpacity
69
+ activeOpacity={1}
70
+ onPress={() => {}}
71
+ style={[styles.box, item.boxStyle]}
72
+ >
73
+ {!!item.title && (
74
+ <AppText
75
+ variant="semiBold"
76
+ size="xlarge"
77
+ style={[
78
+ styles.title,
79
+ { color: item.isError ? colors.error : colors.primary },
80
+ item.titleStyle,
81
+ ]}
82
+ >
83
+ {item.title}
84
+ </AppText>
85
+ )}
86
+ {!!item.message && (
87
+ <AppText
88
+ variant="regular"
89
+ size="normal"
90
+ color={colors.textColor}
91
+ style={[styles.message, item.messageStyle]}
92
+ >
93
+ {item.message}
94
+ </AppText>
95
+ )}
96
+
97
+ {item.onCancel || item.onConfirm ? (
98
+ <View style={styles.btnRow}>
99
+ {Boolean(item.onCancel || item.isCancellable) && (
100
+ <TouchableOpacity
101
+ style={[
102
+ styles.btn,
103
+ { backgroundColor: colors.backgroundColor },
104
+ item.cancelButtonStyle,
105
+ ]}
106
+ onPress={() => {
107
+ hideTop();
108
+ item.onCancel && item.onCancel();
109
+ }}
110
+ >
111
+ <AppText
112
+ variant="medium"
113
+ color={colors.textColor}
114
+ style={item.cancelTextStyle}
115
+ >
116
+ {item.cancelText}
117
+ </AppText>
118
+ </TouchableOpacity>
119
+ )}
120
+
121
+ {item.onConfirm && (
122
+ <TouchableOpacity
123
+ style={[
124
+ styles.btn,
125
+ {
126
+ backgroundColor: item.isError
127
+ ? colors.error
128
+ : colors.primary,
129
+ },
130
+ item.confirmButtonStyle,
131
+ ]}
132
+ onPress={() => {
133
+ hideTop();
134
+ item.onConfirm && item.onConfirm();
135
+ }}
136
+ >
137
+ <AppText
138
+ variant="medium"
139
+ color={colors.white}
140
+ style={item.confirmTextStyle}
141
+ >
142
+ {item.confirmText}
143
+ </AppText>
144
+ </TouchableOpacity>
145
+ )}
146
+ </View>
147
+ ) : null}
148
+ </TouchableOpacity>
149
+ </TouchableOpacity>
150
+ </Modal>
151
+ );
152
+ };
153
+
154
+ const MemoAlert = memo(CustomAlert);
155
+
156
+ (
157
+ MemoAlert as typeof MemoAlert & { show: (opts: AlertOptionsProps) => void }
158
+ ).show = (opts: AlertOptionsProps) => externalShow && externalShow(opts);
159
+
160
+ export default MemoAlert as typeof MemoAlert & {
161
+ show: (opts: AlertOptionsProps) => void;
162
+ };
163
+
164
+ export const getStyles = ({ colors }: ThemeType) =>
165
+ StyleSheet.create({
166
+ overlay: {
167
+ flex: 1,
168
+ backgroundColor: hexWithOpacity(colors.black, 50),
169
+ justifyContent: 'center',
170
+ },
171
+ box: {
172
+ margin: 24,
173
+ padding: 24,
174
+ borderRadius: 16,
175
+ borderWidth: 1,
176
+ backgroundColor: colors.backgroundColor,
177
+ borderColor: colors.borderColor,
178
+ shadowColor: colors.textColor,
179
+ shadowOffset: { width: 0, height: 4 },
180
+ shadowOpacity: 0.1,
181
+ shadowRadius: 12,
182
+ elevation: 5,
183
+ },
184
+ title: {
185
+ marginBottom: 12,
186
+ },
187
+ message: {
188
+ lineHeight: 20,
189
+ },
190
+ btnRow: {
191
+ marginTop: 24,
192
+ flexDirection: 'row',
193
+ justifyContent: 'flex-end',
194
+ },
195
+ btn: {
196
+ paddingVertical: 10,
197
+ paddingHorizontal: 20,
198
+ marginLeft: 12,
199
+ borderRadius: 12,
200
+ minWidth: 80,
201
+ alignItems: 'center',
202
+ },
203
+ });
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { StyleSheet, TouchableOpacity, View } from 'react-native';
3
- import AppText from './AppText';
3
+
4
+ import AppText from '@components/AppText';
4
5
 
5
6
  type CustomToastProps = {
6
7
  text1?: string;
@@ -0,0 +1,127 @@
1
+ import React, { useMemo } from 'react';
2
+ import { StyleSheet, View, TouchableOpacity, ScrollView } from 'react-native';
3
+
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import AppText from '@components/AppText';
7
+ import FullScreenContainer from '@components/FullScreenContainer';
8
+ import { useTheme } from '@context/ThemeContext';
9
+ import { ThemeType } from '@src/theme/colors';
10
+ import { hexWithOpacity } from '@utils/utilsHelper';
11
+
12
+ interface Props {
13
+ error: Error;
14
+ resetError: () => void;
15
+ }
16
+
17
+ const ErrorBoundaryFallback = (props: Props) => {
18
+ const { t } = useTranslation();
19
+ const theme = useTheme();
20
+ const { colors } = theme;
21
+ const styles = useMemo(() => getStyles(theme), [theme]);
22
+
23
+ return (
24
+ <FullScreenContainer style={styles.container}>
25
+ <View style={styles.content}>
26
+ <View style={styles.iconContainer}>
27
+ <AppText style={styles.icon}>⚠️</AppText>
28
+ </View>
29
+
30
+ <AppText variant="h1" style={styles.title}>
31
+ {t('common.errorOccurred')}
32
+ </AppText>
33
+
34
+ <AppText variant="regular" style={styles.subtitle}>
35
+ {t('common.errorDescription')}
36
+ </AppText>
37
+
38
+ <View style={styles.errorBox}>
39
+ <ScrollView bounces={false}>
40
+ <AppText
41
+ size="small"
42
+ color={colors.primary}
43
+ style={styles.errorText}
44
+ >
45
+ {props.error.toString()}
46
+ </AppText>
47
+ </ScrollView>
48
+ </View>
49
+
50
+ <TouchableOpacity
51
+ style={styles.button}
52
+ onPress={props.resetError}
53
+ activeOpacity={0.8}
54
+ >
55
+ <AppText variant="semiBold" color={colors.white}>
56
+ {t('common.tryAgain')}
57
+ </AppText>
58
+ </TouchableOpacity>
59
+ </View>
60
+ </FullScreenContainer>
61
+ );
62
+ };
63
+
64
+ export const getStyles = (theme: ThemeType) => {
65
+ const { colors } = theme;
66
+ return StyleSheet.create({
67
+ container: {
68
+ flex: 1,
69
+ justifyContent: 'center',
70
+ padding: 24,
71
+ },
72
+ content: {
73
+ alignItems: 'center',
74
+ },
75
+ iconContainer: {
76
+ width: 80,
77
+ height: 80,
78
+ borderRadius: 40,
79
+ justifyContent: 'center',
80
+ alignItems: 'center',
81
+ marginBottom: 24,
82
+ backgroundColor: hexWithOpacity(colors.primary, 15),
83
+ },
84
+ icon: {
85
+ fontSize: 40,
86
+ },
87
+ title: {
88
+ textAlign: 'center',
89
+ marginBottom: 12,
90
+ },
91
+ subtitle: {
92
+ textAlign: 'center',
93
+ marginBottom: 32,
94
+ lineHeight: 22,
95
+ color: hexWithOpacity(colors.textColor, 80),
96
+ },
97
+ errorBox: {
98
+ width: '100%',
99
+ maxHeight: 200,
100
+ borderRadius: 12,
101
+ borderWidth: 1,
102
+ padding: 16,
103
+ marginBottom: 32,
104
+ backgroundColor: colors.backgroundColor,
105
+ borderColor: colors.borderColor,
106
+ },
107
+ errorText: {
108
+ lineHeight: 18,
109
+ fontFamily: 'monospace',
110
+ },
111
+ button: {
112
+ width: '100%',
113
+ height: 56,
114
+ borderRadius: 16,
115
+ justifyContent: 'center',
116
+ alignItems: 'center',
117
+ shadowColor: colors.black,
118
+ shadowOffset: { width: 0, height: 4 },
119
+ shadowOpacity: 0.1,
120
+ shadowRadius: 8,
121
+ elevation: 4,
122
+ backgroundColor: colors.primary,
123
+ },
124
+ });
125
+ };
126
+
127
+ export default ErrorBoundaryFallback;
@@ -1,8 +1,10 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
- import AppText from './AppText';
4
- import { useTheme } from '../context/ThemeContext';
5
- import { ThemeType } from '../theme/Colors';
3
+
4
+ import AppText from '@components/AppText';
5
+ import { useTheme } from '@context/ThemeContext';
6
+ import { ThemeType } from '@src/theme/colors';
7
+ import { hexWithOpacity } from '@utils/utilsHelper';
6
8
 
7
9
  interface FeatureItemProps {
8
10
  icon: string;
@@ -16,7 +18,7 @@ const FeatureItem: React.FC<FeatureItemProps> = ({
16
18
  description,
17
19
  }) => {
18
20
  const theme = useTheme();
19
- const styles = getStyles(theme);
21
+ const styles = useMemo(() => getStyles(theme), [theme]);
20
22
 
21
23
  return (
22
24
  <View style={styles.container}>
@@ -56,7 +58,7 @@ const getStyles = ({ colors }: ThemeType) =>
56
58
  marginBottom: 2,
57
59
  },
58
60
  description: {
59
- color: colors.textColor + 'CC',
61
+ color: hexWithOpacity(colors.textColor, 80),
60
62
  lineHeight: 18,
61
63
  },
62
64
  });
@@ -1,12 +1,14 @@
1
+ import React, { FC, memo, useMemo } from 'react';
1
2
  import { StatusBar, StyleSheet } from 'react-native';
2
- import React, { FC, memo } from 'react';
3
- import { SafeAreaView } from 'react-native-safe-area-context';
3
+
4
4
  import { KeyboardAvoidingView } from 'react-native-keyboard-controller';
5
- import { FullScreenContainerProps } from '../types/components.types';
6
- import { useTheme } from '../context/ThemeContext';
7
- import { ThemeType } from '../theme/Colors';
5
+ import { SafeAreaView } from 'react-native-safe-area-context';
6
+
7
+ import { FullScreenContainerProps } from '@app-types/components.types';
8
+ import { useTheme } from '@context/ThemeContext';
9
+ import { ThemeType } from '@src/theme/colors';
8
10
 
9
- export const FullScreenContainer: FC<FullScreenContainerProps> = ({
11
+ const FullScreenContainer: FC<FullScreenContainerProps> = ({
10
12
  children,
11
13
  style,
12
14
  edges = ['top'],
@@ -16,7 +18,7 @@ export const FullScreenContainer: FC<FullScreenContainerProps> = ({
16
18
  isKeyboardAvoidingView = false,
17
19
  }) => {
18
20
  const theme = useTheme();
19
- const styles = getStyles(theme);
21
+ const styles = useMemo(() => getStyles(theme), [theme]);
20
22
 
21
23
  const appBarStyle =
22
24
  barStyle ??
@@ -1,8 +1,10 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
- import AppText from './AppText';
4
- import { useTheme } from '../context/ThemeContext';
5
- import { ThemeType } from '../theme/Colors';
3
+
4
+ import AppText from '@components/AppText';
5
+ import { useTheme } from '@context/ThemeContext';
6
+ import { ThemeType } from '@src/theme/colors';
7
+ import { hexWithOpacity } from '@utils/utilsHelper';
6
8
 
7
9
  interface InfoCardProps {
8
10
  title: string;
@@ -12,7 +14,7 @@ interface InfoCardProps {
12
14
 
13
15
  const InfoCard: React.FC<InfoCardProps> = ({ title, children, icon }) => {
14
16
  const theme = useTheme();
15
- const styles = getStyles(theme);
17
+ const styles = useMemo(() => getStyles(theme), [theme]);
16
18
 
17
19
  return (
18
20
  <View style={styles.card}>
@@ -41,7 +43,7 @@ const getStyles = ({ colors }: ThemeType) =>
41
43
  padding: 16,
42
44
  marginBottom: 16,
43
45
  borderWidth: 1,
44
- borderColor: colors.primary + '20',
46
+ borderColor: hexWithOpacity(colors.primary, 12),
45
47
  shadowColor: colors.textColor,
46
48
  shadowOffset: { width: 0, height: 2 },
47
49
  shadowOpacity: 0.1,
@@ -1,15 +1,17 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { View, TouchableOpacity, StyleSheet } from 'react-native';
3
- import AppText from './AppText';
3
+
4
4
  import { useTranslation } from 'react-i18next';
5
- import { useTheme } from '../context/ThemeContext';
6
- import { ThemeType } from '../theme/Colors';
7
- import StorageHelper from '../utils/storageHelper';
5
+
6
+ import AppText from '@components/AppText';
7
+ import { useTheme } from '@context/ThemeContext';
8
+ import { ThemeType } from '@src/theme/colors';
9
+ import StorageHelper from '@utils/storageHelper';
8
10
 
9
11
  const LanguageSwitcher = () => {
10
12
  const { i18n } = useTranslation();
11
13
  const theme = useTheme();
12
- const styles = getStyles(theme);
14
+ const styles = useMemo(() => getStyles(theme), [theme]);
13
15
 
14
16
  const changeLanguage = (lng: string) => {
15
17
  i18n.changeLanguage(lng);