@umituz/react-native-settings 1.4.0 → 1.5.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/package.json +1 -1
- package/src/presentation/components/DisclaimerSetting.tsx +1 -1
- package/src/presentation/components/SettingItem.tsx +51 -137
- package/src/presentation/screens/AppearanceScreen.tsx +26 -10
- package/src/presentation/screens/LanguageSelectionScreen.tsx +3 -2
- package/src/presentation/screens/SettingsScreen.tsx +55 -34
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
} from 'react-native';
|
|
28
28
|
|
|
29
29
|
import { useAppDesignTokens, withAlpha } from '@umituz/react-native-design-system-theme';
|
|
30
|
-
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
|
|
30
|
+
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system-atoms';
|
|
31
31
|
import { useLocalization } from '@umituz/react-native-localization';
|
|
32
32
|
|
|
33
33
|
type DesignTokens = ReturnType<typeof useAppDesignTokens>;
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import React from 'react';
|
|
15
|
-
import { View, StyleSheet,
|
|
15
|
+
import { View, StyleSheet, Pressable } from 'react-native';
|
|
16
16
|
import { LinearGradient } from 'expo-linear-gradient';
|
|
17
|
-
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
|
|
17
|
+
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system-atoms';
|
|
18
18
|
import { useAppDesignTokens } from '@umituz/react-native-design-system-theme';
|
|
19
|
-
import type { IconName } from '@umituz/react-native-design-system';
|
|
20
|
-
import type { DesignTokens } from '@umituz/react-native-design-system';
|
|
19
|
+
import type { IconName } from '@umituz/react-native-design-system-atoms';
|
|
20
|
+
import type { DesignTokens } from '@umituz/react-native-design-system-theme';
|
|
21
21
|
|
|
22
22
|
interface SettingItemProps {
|
|
23
23
|
/** Icon name from Lucide library */
|
|
@@ -62,86 +62,9 @@ export const SettingItem: React.FC<SettingItemProps> = ({
|
|
|
62
62
|
? (iconGradient as unknown as readonly [string, string, ...string[]])
|
|
63
63
|
: [tokens.colors.surface, tokens.colors.surface] as const;
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
onPress={onPress}
|
|
69
|
-
disabled={disabled}
|
|
70
|
-
activeOpacity={0.7}
|
|
71
|
-
style={[styles.listItem, disabled && styles.disabled]}
|
|
72
|
-
testID={testID}
|
|
73
|
-
>
|
|
74
|
-
{/* Left: Gradient Icon */}
|
|
75
|
-
<View style={styles.leftContainer}>
|
|
76
|
-
<LinearGradient
|
|
77
|
-
colors={gradientColors}
|
|
78
|
-
start={{ x: 0, y: 0 }}
|
|
79
|
-
end={{ x: 1, y: 1 }}
|
|
80
|
-
style={styles.iconContainer}
|
|
81
|
-
>
|
|
82
|
-
<AtomicIcon name={icon} size="md" customColor="#FFFFFF" />
|
|
83
|
-
</LinearGradient>
|
|
84
|
-
</View>
|
|
85
|
-
|
|
86
|
-
{/* Center: Title and Description */}
|
|
87
|
-
<View style={styles.contentContainer}>
|
|
88
|
-
<AtomicText
|
|
89
|
-
type="bodyLarge"
|
|
90
|
-
color={disabled ? "textDisabled" : "onSurface"}
|
|
91
|
-
style={styles.title}
|
|
92
|
-
numberOfLines={2}
|
|
93
|
-
ellipsizeMode="tail"
|
|
94
|
-
>
|
|
95
|
-
{title}
|
|
96
|
-
</AtomicText>
|
|
97
|
-
{description && (
|
|
98
|
-
<AtomicText
|
|
99
|
-
type="bodySmall"
|
|
100
|
-
color="textSecondary"
|
|
101
|
-
style={styles.description}
|
|
102
|
-
numberOfLines={2}
|
|
103
|
-
ellipsizeMode="tail"
|
|
104
|
-
>
|
|
105
|
-
{description}
|
|
106
|
-
</AtomicText>
|
|
107
|
-
)}
|
|
108
|
-
</View>
|
|
109
|
-
|
|
110
|
-
{/* Right: Value, Chevron, or Custom Element */}
|
|
111
|
-
{rightElement ? (
|
|
112
|
-
<View style={styles.rightContainer}>{rightElement}</View>
|
|
113
|
-
) : value ? (
|
|
114
|
-
<View style={styles.rightContainer}>
|
|
115
|
-
<AtomicText
|
|
116
|
-
type="bodyMedium"
|
|
117
|
-
color="textSecondary"
|
|
118
|
-
style={styles.value}
|
|
119
|
-
numberOfLines={2}
|
|
120
|
-
textAlign="right"
|
|
121
|
-
>
|
|
122
|
-
{value}
|
|
123
|
-
</AtomicText>
|
|
124
|
-
</View>
|
|
125
|
-
) : (showChevron ?? true) ? (
|
|
126
|
-
<View style={styles.rightContainer}>
|
|
127
|
-
<AtomicIcon
|
|
128
|
-
name="ChevronRight"
|
|
129
|
-
size="sm"
|
|
130
|
-
color="textSecondary"
|
|
131
|
-
style={styles.chevron}
|
|
132
|
-
/>
|
|
133
|
-
</View>
|
|
134
|
-
) : null}
|
|
135
|
-
</TouchableOpacity>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<View
|
|
141
|
-
style={[styles.listItem, disabled && styles.disabled]}
|
|
142
|
-
testID={testID}
|
|
143
|
-
>
|
|
144
|
-
{/* Left: Gradient Icon */}
|
|
65
|
+
const content = (
|
|
66
|
+
<View style={[styles.listItem, disabled && styles.disabled]}>
|
|
67
|
+
{/* Left: Icon with gradient */}
|
|
145
68
|
<View style={styles.leftContainer}>
|
|
146
69
|
<LinearGradient
|
|
147
70
|
colors={gradientColors}
|
|
@@ -149,111 +72,102 @@ export const SettingItem: React.FC<SettingItemProps> = ({
|
|
|
149
72
|
end={{ x: 1, y: 1 }}
|
|
150
73
|
style={styles.iconContainer}
|
|
151
74
|
>
|
|
152
|
-
<AtomicIcon name={icon} size="md"
|
|
75
|
+
<AtomicIcon name={icon} size="md" color="primary" />
|
|
153
76
|
</LinearGradient>
|
|
154
77
|
</View>
|
|
155
78
|
|
|
156
|
-
{/* Center: Title and
|
|
79
|
+
{/* Center: Title and description */}
|
|
157
80
|
<View style={styles.contentContainer}>
|
|
158
|
-
<AtomicText
|
|
159
|
-
type="bodyLarge"
|
|
160
|
-
color={disabled ? "textDisabled" : "onSurface"}
|
|
161
|
-
style={styles.title}
|
|
162
|
-
numberOfLines={2}
|
|
163
|
-
ellipsizeMode="tail"
|
|
164
|
-
>
|
|
81
|
+
<AtomicText type="bodyLarge" color="textPrimary" style={styles.title} numberOfLines={2}>
|
|
165
82
|
{title}
|
|
166
83
|
</AtomicText>
|
|
167
84
|
{description && (
|
|
168
|
-
<AtomicText
|
|
169
|
-
type="bodySmall"
|
|
170
|
-
color="textSecondary"
|
|
171
|
-
style={styles.description}
|
|
172
|
-
numberOfLines={2}
|
|
173
|
-
ellipsizeMode="tail"
|
|
174
|
-
>
|
|
85
|
+
<AtomicText type="bodySmall" color="textSecondary" style={styles.description} numberOfLines={2}>
|
|
175
86
|
{description}
|
|
176
87
|
</AtomicText>
|
|
177
88
|
)}
|
|
178
89
|
</View>
|
|
179
90
|
|
|
180
|
-
{/* Right: Value,
|
|
181
|
-
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
<AtomicText
|
|
186
|
-
type="bodyMedium"
|
|
187
|
-
color="textSecondary"
|
|
188
|
-
style={styles.value}
|
|
189
|
-
numberOfLines={2}
|
|
190
|
-
textAlign="right"
|
|
191
|
-
>
|
|
91
|
+
{/* Right: Value, chevron, or custom element */}
|
|
92
|
+
<View style={styles.rightContainer}>
|
|
93
|
+
{rightElement ? (
|
|
94
|
+
rightElement
|
|
95
|
+
) : value ? (
|
|
96
|
+
<AtomicText type="bodyMedium" color="textSecondary" style={styles.value} numberOfLines={2}>
|
|
192
97
|
{value}
|
|
193
98
|
</AtomicText>
|
|
194
|
-
|
|
195
|
-
|
|
99
|
+
) : (showChevron ?? true) && onPress ? (
|
|
100
|
+
<AtomicIcon name="ChevronRight" size="sm" customColor={tokens.colors.textSecondary} style={styles.chevron} />
|
|
101
|
+
) : null}
|
|
102
|
+
</View>
|
|
196
103
|
</View>
|
|
197
104
|
);
|
|
105
|
+
|
|
106
|
+
if (onPress && !disabled) {
|
|
107
|
+
return (
|
|
108
|
+
<Pressable onPress={onPress} testID={testID} style={styles.pressable}>
|
|
109
|
+
{content}
|
|
110
|
+
</Pressable>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return <View testID={testID}>{content}</View>;
|
|
198
115
|
};
|
|
199
116
|
|
|
200
117
|
const getStyles = (tokens: DesignTokens) =>
|
|
201
118
|
StyleSheet.create({
|
|
119
|
+
pressable: {
|
|
120
|
+
borderRadius: tokens.borders.radius.md,
|
|
121
|
+
},
|
|
202
122
|
listItem: {
|
|
203
123
|
flexDirection: 'row',
|
|
204
124
|
alignItems: 'center',
|
|
205
|
-
paddingVertical: tokens.spacing.
|
|
206
|
-
paddingHorizontal: tokens.spacing.
|
|
207
|
-
minHeight:
|
|
125
|
+
paddingVertical: tokens.spacing.sm,
|
|
126
|
+
paddingHorizontal: tokens.spacing.md,
|
|
127
|
+
minHeight: 64,
|
|
208
128
|
},
|
|
209
129
|
disabled: {
|
|
210
130
|
opacity: 0.5,
|
|
211
131
|
},
|
|
132
|
+
contentContainer: {
|
|
133
|
+
flex: 1,
|
|
134
|
+
marginLeft: tokens.spacing.md,
|
|
135
|
+
marginRight: tokens.spacing.md,
|
|
136
|
+
},
|
|
212
137
|
leftContainer: {
|
|
213
138
|
marginRight: tokens.spacing.md,
|
|
214
139
|
justifyContent: 'center',
|
|
215
140
|
},
|
|
216
141
|
iconContainer: {
|
|
217
|
-
width:
|
|
218
|
-
height:
|
|
219
|
-
borderRadius:
|
|
142
|
+
width: 44,
|
|
143
|
+
height: 44,
|
|
144
|
+
borderRadius: 22,
|
|
220
145
|
alignItems: 'center',
|
|
221
146
|
justifyContent: 'center',
|
|
222
147
|
overflow: 'hidden',
|
|
223
148
|
borderWidth: 1,
|
|
224
|
-
borderColor: `${tokens.colors.primary}
|
|
225
|
-
},
|
|
226
|
-
contentContainer: {
|
|
227
|
-
flex: 1,
|
|
228
|
-
justifyContent: 'center',
|
|
229
|
-
minWidth: 0,
|
|
149
|
+
borderColor: `${tokens.colors.primary}20`,
|
|
230
150
|
},
|
|
231
151
|
title: {
|
|
232
|
-
fontSize: tokens.typography.bodyLarge.fontSize,
|
|
233
152
|
fontWeight: '600',
|
|
234
|
-
|
|
235
|
-
lineHeight: tokens.typography.bodyLarge.fontSize * 1.4,
|
|
153
|
+
marginBottom: tokens.spacing.xs,
|
|
236
154
|
},
|
|
237
155
|
description: {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
opacity: 0.7,
|
|
241
|
-
flexShrink: 1,
|
|
242
|
-
lineHeight: tokens.typography.bodySmall.fontSize * 1.4,
|
|
156
|
+
marginTop: tokens.spacing.xs,
|
|
157
|
+
opacity: 0.8,
|
|
243
158
|
},
|
|
244
159
|
rightContainer: {
|
|
245
160
|
justifyContent: 'center',
|
|
246
161
|
alignItems: 'flex-end',
|
|
247
|
-
marginLeft: tokens.spacing.md,
|
|
248
162
|
maxWidth: '50%',
|
|
249
163
|
flexShrink: 0,
|
|
250
164
|
},
|
|
251
165
|
value: {
|
|
252
166
|
fontWeight: '500',
|
|
253
|
-
|
|
167
|
+
textAlign: 'right',
|
|
254
168
|
},
|
|
255
169
|
chevron: {
|
|
256
|
-
opacity: 0.
|
|
170
|
+
opacity: 0.6,
|
|
257
171
|
},
|
|
258
172
|
});
|
|
259
173
|
|
|
@@ -13,15 +13,16 @@ import React from 'react';
|
|
|
13
13
|
import { View, StyleSheet } from 'react-native';
|
|
14
14
|
|
|
15
15
|
import { useNavigation } from '@react-navigation/native';
|
|
16
|
-
import {
|
|
17
|
-
import { AtomicText
|
|
16
|
+
import { useDesignSystemTheme, useAppDesignTokens, type DesignTokens } from '@umituz/react-native-design-system-theme';
|
|
17
|
+
import { AtomicText } from '@umituz/react-native-design-system-atoms';
|
|
18
|
+
import { ScreenLayout } from '@umituz/react-native-design-system-organisms';
|
|
18
19
|
import { useLocalization, getLanguageByCode } from '@umituz/react-native-localization';
|
|
19
20
|
import { SettingItem } from '../components/SettingItem';
|
|
20
21
|
|
|
21
22
|
export const AppearanceScreen: React.FC = () => {
|
|
22
23
|
const { t, currentLanguage } = useLocalization();
|
|
23
24
|
const navigation = useNavigation();
|
|
24
|
-
const { themeMode,
|
|
25
|
+
const { themeMode, setThemeMode } = useDesignSystemTheme();
|
|
25
26
|
const tokens = useAppDesignTokens();
|
|
26
27
|
const styles = getStyles(tokens);
|
|
27
28
|
|
|
@@ -34,7 +35,8 @@ export const AppearanceScreen: React.FC = () => {
|
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const handleThemeToggle = () => {
|
|
37
|
-
|
|
38
|
+
const newMode = themeMode === 'dark' ? 'light' : 'dark';
|
|
39
|
+
setThemeMode(newMode);
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
return (
|
|
@@ -50,8 +52,10 @@ export const AppearanceScreen: React.FC = () => {
|
|
|
50
52
|
</View>
|
|
51
53
|
|
|
52
54
|
{/* Language Section */}
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
+
<View style={{ marginBottom: tokens.spacing.md }}>
|
|
56
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
57
|
+
{t('settings.language')}
|
|
58
|
+
</AtomicText>
|
|
55
59
|
<SettingItem
|
|
56
60
|
icon="Languages"
|
|
57
61
|
iconGradient={((tokens.colors as any).settingGradients?.language as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
|
|
@@ -60,11 +64,13 @@ export const AppearanceScreen: React.FC = () => {
|
|
|
60
64
|
onPress={handleLanguagePress}
|
|
61
65
|
testID="language-button"
|
|
62
66
|
/>
|
|
63
|
-
</
|
|
67
|
+
</View>
|
|
64
68
|
|
|
65
69
|
{/* Theme Section */}
|
|
66
|
-
<
|
|
67
|
-
<
|
|
70
|
+
<View style={{ marginBottom: tokens.spacing.md }}>
|
|
71
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
72
|
+
{t('settings.appearance.darkMode')}
|
|
73
|
+
</AtomicText>
|
|
68
74
|
<SettingItem
|
|
69
75
|
icon={themeMode === 'dark' ? 'Moon' : 'Sun'}
|
|
70
76
|
iconGradient={
|
|
@@ -77,7 +83,7 @@ export const AppearanceScreen: React.FC = () => {
|
|
|
77
83
|
onPress={handleThemeToggle}
|
|
78
84
|
testID="theme-button"
|
|
79
85
|
/>
|
|
80
|
-
</
|
|
86
|
+
</View>
|
|
81
87
|
</ScreenLayout>
|
|
82
88
|
);
|
|
83
89
|
};
|
|
@@ -87,11 +93,21 @@ const getStyles = (tokens: DesignTokens) =>
|
|
|
87
93
|
header: {
|
|
88
94
|
paddingBottom: tokens.spacing.lg,
|
|
89
95
|
paddingTop: tokens.spacing.md,
|
|
96
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
90
97
|
},
|
|
91
98
|
headerSubtitle: {
|
|
92
99
|
marginTop: tokens.spacing.sm,
|
|
93
100
|
lineHeight: 20,
|
|
94
101
|
opacity: 0.8,
|
|
95
102
|
},
|
|
103
|
+
sectionHeader: {
|
|
104
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
105
|
+
paddingTop: tokens.spacing.lg,
|
|
106
|
+
paddingBottom: tokens.spacing.md,
|
|
107
|
+
textTransform: 'uppercase',
|
|
108
|
+
letterSpacing: 1,
|
|
109
|
+
fontWeight: '600',
|
|
110
|
+
fontSize: 12,
|
|
111
|
+
},
|
|
96
112
|
});
|
|
97
113
|
|
|
@@ -15,8 +15,9 @@ import {
|
|
|
15
15
|
TextInput,
|
|
16
16
|
} from 'react-native';
|
|
17
17
|
import { useNavigation } from '@react-navigation/native';
|
|
18
|
-
import {
|
|
19
|
-
import { AtomicIcon, AtomicText
|
|
18
|
+
import { useAppDesignTokens, withAlpha, STATIC_TOKENS, type DesignTokens } from '@umituz/react-native-design-system-theme';
|
|
19
|
+
import { AtomicIcon, AtomicText } from '@umituz/react-native-design-system-atoms';
|
|
20
|
+
import { ScreenLayout } from '@umituz/react-native-design-system-organisms';
|
|
20
21
|
import { useLocalization, searchLanguages, Language, LANGUAGES } from '@umituz/react-native-localization';
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -16,8 +16,9 @@ import { DeviceEventEmitter, Alert, View, TouchableOpacity, StyleSheet } from 'r
|
|
|
16
16
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
17
17
|
|
|
18
18
|
import { useNavigation, CommonActions } from '@react-navigation/native';
|
|
19
|
-
import {
|
|
20
|
-
import { ScreenLayout
|
|
19
|
+
import { useDesignSystemTheme, useAppDesignTokens } from '@umituz/react-native-design-system-theme';
|
|
20
|
+
import { ScreenLayout } from '@umituz/react-native-design-system-organisms';
|
|
21
|
+
import { AtomicIcon, AtomicText } from '@umituz/react-native-design-system-atoms';
|
|
21
22
|
import { SettingItem } from '../components/SettingItem';
|
|
22
23
|
import { getLanguageByCode, useLocalization } from '@umituz/react-native-localization';
|
|
23
24
|
import { SettingsConfig } from './types';
|
|
@@ -86,10 +87,11 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
|
86
87
|
config = {}
|
|
87
88
|
}) => {
|
|
88
89
|
const navigation = useNavigation();
|
|
89
|
-
const {
|
|
90
|
+
const { themeMode } = useDesignSystemTheme();
|
|
90
91
|
const tokens = useAppDesignTokens();
|
|
91
92
|
const insets = useSafeAreaInsets();
|
|
92
93
|
const { currentLanguage, t } = useLocalization();
|
|
94
|
+
const styles = getStyles(tokens);
|
|
93
95
|
|
|
94
96
|
const currentLang = getLanguageByCode(currentLanguage);
|
|
95
97
|
const languageDisplay = currentLang ? `${currentLang.flag} ${currentLang.nativeName}` : 'English';
|
|
@@ -246,12 +248,12 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
|
246
248
|
<View style={[
|
|
247
249
|
styles.header,
|
|
248
250
|
{
|
|
249
|
-
borderBottomColor:
|
|
250
|
-
backgroundColor:
|
|
251
|
+
borderBottomColor: tokens.colors.borderLight,
|
|
252
|
+
backgroundColor: tokens.colors.surface,
|
|
251
253
|
paddingTop: insets.top,
|
|
252
254
|
}
|
|
253
255
|
]}>
|
|
254
|
-
<AtomicText type="headlineLarge" style={{ color:
|
|
256
|
+
<AtomicText type="headlineLarge" style={{ color: tokens.colors.textPrimary, flex: 1 }}>
|
|
255
257
|
{t('navigation.settings') || 'Settings'}
|
|
256
258
|
</AtomicText>
|
|
257
259
|
<TouchableOpacity
|
|
@@ -266,103 +268,122 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
|
266
268
|
|
|
267
269
|
{/* Appearance Section */}
|
|
268
270
|
{features.appearance && (
|
|
269
|
-
<
|
|
270
|
-
<
|
|
271
|
+
<View style={{ marginBottom: tokens.spacing.md }}>
|
|
272
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
273
|
+
{t('settings.sections.appearance')}
|
|
274
|
+
</AtomicText>
|
|
271
275
|
<SettingItem
|
|
272
276
|
icon="Palette"
|
|
273
|
-
iconGradient={
|
|
277
|
+
iconGradient={((tokens.colors as any).settingGradients?.themeLight as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
|
|
274
278
|
title={t('settings.appearance.title')}
|
|
275
279
|
description={t('settings.appearance.themeDescription')}
|
|
276
280
|
onPress={handleAppearancePress}
|
|
277
281
|
testID="appearance-button"
|
|
278
282
|
/>
|
|
279
|
-
</
|
|
283
|
+
</View>
|
|
280
284
|
)}
|
|
281
285
|
|
|
282
286
|
{/* General Section - Notifications */}
|
|
283
287
|
{features.notifications && (
|
|
284
|
-
<
|
|
285
|
-
<
|
|
288
|
+
<View style={{ marginBottom: tokens.spacing.md }}>
|
|
289
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
290
|
+
{t('settings.sections.general')}
|
|
291
|
+
</AtomicText>
|
|
286
292
|
<SettingItem
|
|
287
293
|
icon="Bell"
|
|
288
|
-
iconGradient={
|
|
294
|
+
iconGradient={((tokens.colors as any).settingGradients?.notifications as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
|
|
289
295
|
title={t('settings.notifications.title')}
|
|
290
296
|
description={t('settings.notifications.description')}
|
|
291
297
|
onPress={handleNotificationsPress}
|
|
292
298
|
testID="notifications-button"
|
|
293
299
|
/>
|
|
294
|
-
</
|
|
300
|
+
</View>
|
|
295
301
|
)}
|
|
296
302
|
|
|
297
303
|
{/* Development/Test: Show Onboarding */}
|
|
298
304
|
{__DEV__ && useOnboardingStore && (
|
|
299
|
-
<
|
|
300
|
-
<
|
|
305
|
+
<View style={{ marginBottom: tokens.spacing.md }}>
|
|
306
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
307
|
+
Development
|
|
308
|
+
</AtomicText>
|
|
301
309
|
<SettingItem
|
|
302
310
|
icon="Play"
|
|
303
|
-
iconGradient={
|
|
311
|
+
iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
|
|
304
312
|
title="Show Onboarding (Dev)"
|
|
305
313
|
description="Navigate to onboarding screen"
|
|
306
314
|
onPress={handleShowOnboarding}
|
|
307
315
|
testID="show-onboarding-button"
|
|
308
316
|
/>
|
|
309
|
-
</
|
|
317
|
+
</View>
|
|
310
318
|
)}
|
|
311
319
|
|
|
312
320
|
{/* About & Legal Section */}
|
|
313
321
|
{(features.about || features.legal) && (
|
|
314
|
-
<
|
|
315
|
-
<
|
|
322
|
+
<View style={{ marginBottom: tokens.spacing.md }}>
|
|
323
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
324
|
+
{t('settings.sections.about')}
|
|
325
|
+
</AtomicText>
|
|
316
326
|
{features.about && (
|
|
317
327
|
<SettingItem
|
|
318
328
|
icon="Info"
|
|
319
|
-
iconGradient={
|
|
329
|
+
iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
|
|
320
330
|
title={t('settings.about.title')}
|
|
321
331
|
description={t('settings.about.description')}
|
|
322
332
|
onPress={handleAboutPress}
|
|
323
333
|
testID="about-button"
|
|
324
334
|
/>
|
|
325
335
|
)}
|
|
326
|
-
{features.about && features.legal &&
|
|
336
|
+
{features.about && features.legal && (
|
|
337
|
+
<View style={{ height: 1, backgroundColor: tokens.colors.borderLight, marginVertical: tokens.spacing.sm }} />
|
|
338
|
+
)}
|
|
327
339
|
{features.legal && (
|
|
328
340
|
<SettingItem
|
|
329
341
|
icon="FileText"
|
|
330
|
-
iconGradient={
|
|
342
|
+
iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
|
|
331
343
|
title={t('settings.legal.title')}
|
|
332
344
|
description={t('settings.legal.description')}
|
|
333
345
|
onPress={handleLegalPress}
|
|
334
346
|
testID="legal-button"
|
|
335
347
|
/>
|
|
336
348
|
)}
|
|
337
|
-
</
|
|
349
|
+
</View>
|
|
338
350
|
)}
|
|
339
351
|
|
|
340
352
|
{/* Fallback: Show message if no features are enabled */}
|
|
341
353
|
{!hasAnyFeatures && (
|
|
342
|
-
<
|
|
343
|
-
<
|
|
354
|
+
<View>
|
|
355
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
344
356
|
{t('settings.noOptionsAvailable') || 'No settings available'}
|
|
345
|
-
</
|
|
346
|
-
</
|
|
357
|
+
</AtomicText>
|
|
358
|
+
</View>
|
|
347
359
|
)}
|
|
348
360
|
</ScreenLayout>
|
|
349
361
|
);
|
|
350
362
|
};
|
|
351
363
|
|
|
352
|
-
const
|
|
364
|
+
const getStyles = (tokens: any) => StyleSheet.create({
|
|
353
365
|
header: {
|
|
354
366
|
flexDirection: 'row',
|
|
355
367
|
alignItems: 'center',
|
|
356
368
|
justifyContent: 'space-between',
|
|
357
|
-
paddingHorizontal:
|
|
358
|
-
paddingBottom:
|
|
359
|
-
paddingTop:
|
|
369
|
+
paddingHorizontal: tokens.spacing.md,
|
|
370
|
+
paddingBottom: tokens.spacing.md,
|
|
371
|
+
paddingTop: tokens.spacing.md,
|
|
360
372
|
borderBottomWidth: 1,
|
|
361
373
|
zIndex: 1000,
|
|
362
374
|
},
|
|
375
|
+
sectionHeader: {
|
|
376
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
377
|
+
paddingTop: tokens.spacing.lg,
|
|
378
|
+
paddingBottom: tokens.spacing.md,
|
|
379
|
+
textTransform: 'uppercase',
|
|
380
|
+
letterSpacing: 1,
|
|
381
|
+
fontWeight: '600',
|
|
382
|
+
fontSize: 12,
|
|
383
|
+
},
|
|
363
384
|
closeButton: {
|
|
364
|
-
padding:
|
|
365
|
-
marginLeft:
|
|
385
|
+
padding: tokens.spacing.sm,
|
|
386
|
+
marginLeft: tokens.spacing.sm,
|
|
366
387
|
},
|
|
367
388
|
});
|
|
368
389
|
|