@umituz/react-native-settings 5.3.66 → 5.3.68
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 +2 -2
- package/src/domains/localization/infrastructure/config/constants/defaultLanguages.ts +1 -1
- package/src/domains/localization/presentation/components/LanguageItem.tsx +31 -14
- package/src/domains/localization/presentation/screens/LanguageSelectionScreen.tsx +8 -10
- package/src/presentation/components/settings/SettingsItemCardContent.tsx +6 -1
- package/src/presentation/screens/SettingsScreen.tsx +2 -0
- package/src/presentation/screens/components/SettingsContent.tsx +6 -1
- package/src/presentation/screens/components/sections/FeatureSettingsSection.tsx +2 -1
- package/src/presentation/screens/components/types/SettingsContentProps.ts +1 -0
- package/src/presentation/screens/hooks/useSettingsScreen.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.68",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification - expo-store-review and expo-device now lazy loaded",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
166
166
|
"@typescript-eslint/parser": "^7.18.0",
|
|
167
167
|
"@umituz/react-native-auth": "^4.3.39",
|
|
168
|
-
"@umituz/react-native-design-system": "
|
|
168
|
+
"@umituz/react-native-design-system": "latest",
|
|
169
169
|
"@umituz/react-native-firebase": "^2.4.55",
|
|
170
170
|
"@umituz/react-native-sentry": "latest",
|
|
171
171
|
"eslint": "^8.57.0",
|
|
@@ -19,7 +19,7 @@ export const DEFAULT_LANGUAGES: Language[] = [
|
|
|
19
19
|
{ code: 'hi-IN', name: 'Hindi', nativeName: 'हिन्दी', flag: '🇮🇳', isRTL: false },
|
|
20
20
|
{ code: 'hr-HR', name: 'Croatian', nativeName: 'Hrvatski', flag: '🇭🇷', isRTL: false },
|
|
21
21
|
{ code: 'hu-HU', name: 'Hungarian', nativeName: 'Magyar', flag: '🇭🇺', isRTL: false },
|
|
22
|
-
{ code: 'id-ID', name: 'Indonesian', nativeName: 'Bahasa Indonesia', flag: '
|
|
22
|
+
{ code: 'id-ID', name: 'Indonesian', nativeName: 'Bahasa Indonesia', flag: '🇮🇩', isRTL: false },
|
|
23
23
|
{ code: 'it-IT', name: 'Italian', nativeName: 'Italiano', flag: '🇮🇹', isRTL: false },
|
|
24
24
|
{ code: 'ja-JP', name: 'Japanese', nativeName: '日本語', flag: '🇯🇵', isRTL: false },
|
|
25
25
|
{ code: 'ko-KR', name: 'Korean', nativeName: '한국어', flag: '🇰🇷', isRTL: false },
|
|
@@ -41,34 +41,43 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
|
|
|
41
41
|
|
|
42
42
|
const themedStyles = useMemo(() => ({
|
|
43
43
|
languageItem: {
|
|
44
|
-
|
|
44
|
+
paddingHorizontal: tokens.spacing.md,
|
|
45
|
+
paddingVertical: tokens.spacing.md,
|
|
45
46
|
borderRadius: tokens.borders.radius.lg,
|
|
46
|
-
backgroundColor: tokens.colors.
|
|
47
|
-
borderColor: tokens.colors.border,
|
|
48
|
-
borderWidth: 1,
|
|
47
|
+
backgroundColor: tokens.colors.surfaceSecondary,
|
|
49
48
|
marginBottom: tokens.spacing.md,
|
|
49
|
+
flexDirection: 'row' as const,
|
|
50
|
+
alignItems: 'center' as const,
|
|
51
|
+
justifyContent: 'space-between' as const,
|
|
50
52
|
} as ViewStyle,
|
|
51
53
|
selectedLanguageItem: {
|
|
54
|
+
backgroundColor: tokens.colors.surface,
|
|
52
55
|
borderColor: tokens.colors.primary,
|
|
53
|
-
backgroundColor: tokens.colors.surfaceVariant,
|
|
54
56
|
borderWidth: 1.5,
|
|
55
57
|
} as ViewStyle,
|
|
56
58
|
nativeName: {
|
|
57
59
|
color: tokens.colors.textPrimary,
|
|
58
|
-
marginBottom: 2,
|
|
59
60
|
} as TextStyle,
|
|
60
61
|
languageName: {
|
|
61
62
|
color: tokens.colors.textSecondary,
|
|
62
63
|
} as TextStyle,
|
|
64
|
+
flagContainer: {
|
|
65
|
+
width: 44,
|
|
66
|
+
height: 44,
|
|
67
|
+
borderRadius: tokens.borders.radius.md,
|
|
68
|
+
backgroundColor: tokens.colors.backgroundPrimary,
|
|
69
|
+
alignItems: 'center' as const,
|
|
70
|
+
justifyContent: 'center' as const,
|
|
71
|
+
marginRight: tokens.spacing.md,
|
|
72
|
+
} as ViewStyle,
|
|
63
73
|
}), [tokens]);
|
|
64
74
|
|
|
65
75
|
return (
|
|
66
76
|
<TouchableOpacity
|
|
67
77
|
testID="language-item-test"
|
|
68
78
|
style={[
|
|
69
|
-
styles.languageItem,
|
|
70
79
|
themedStyles.languageItem,
|
|
71
|
-
isSelected
|
|
80
|
+
isSelected && themedStyles.selectedLanguageItem,
|
|
72
81
|
customStyles?.languageItem,
|
|
73
82
|
]}
|
|
74
83
|
onPress={() => {
|
|
@@ -77,13 +86,21 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
|
|
|
77
86
|
activeOpacity={0.7}
|
|
78
87
|
>
|
|
79
88
|
<View style={[styles.languageContent, customStyles?.languageContent]}>
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
89
|
+
<View style={themedStyles.flagContainer}>
|
|
90
|
+
<AtomicText
|
|
91
|
+
style={[
|
|
92
|
+
styles.flag,
|
|
93
|
+
{ fontSize: 24, marginRight: 0, fontFamily: undefined },
|
|
94
|
+
customStyles?.flag
|
|
95
|
+
]}
|
|
96
|
+
>
|
|
97
|
+
{item.flag || '🌐'}
|
|
98
|
+
</AtomicText>
|
|
99
|
+
</View>
|
|
100
|
+
<View style={[styles.languageText, customStyles?.languageText]}>
|
|
84
101
|
<AtomicText
|
|
85
102
|
type="bodyLarge"
|
|
86
|
-
style={[themedStyles.nativeName, { fontWeight: '
|
|
103
|
+
style={[themedStyles.nativeName, { fontWeight: '600' }, customStyles?.nativeName]}
|
|
87
104
|
>
|
|
88
105
|
{item.nativeName}
|
|
89
106
|
</AtomicText>
|
|
@@ -96,7 +113,7 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
|
|
|
96
113
|
</View>
|
|
97
114
|
</View>
|
|
98
115
|
{isSelected && (
|
|
99
|
-
<AtomicIcon name="checkmark" size="
|
|
116
|
+
<AtomicIcon name="checkmark-circle" size="md" color="primary" />
|
|
100
117
|
)}
|
|
101
118
|
</TouchableOpacity>
|
|
102
119
|
);
|
|
@@ -79,21 +79,18 @@ const LanguageSearchComponent: React.FC<LanguageSearchComponentProps> = ({
|
|
|
79
79
|
containerStyle={[
|
|
80
80
|
{
|
|
81
81
|
marginBottom: tokens.spacing.md,
|
|
82
|
-
backgroundColor:
|
|
83
|
-
|
|
84
|
-
paddingHorizontal:
|
|
82
|
+
backgroundColor: tokens.colors.surfaceSecondary,
|
|
83
|
+
borderWidth: 0,
|
|
84
|
+
paddingHorizontal: tokens.spacing.md,
|
|
85
|
+
height: 52,
|
|
86
|
+
borderRadius: tokens.borders.radius.lg,
|
|
85
87
|
},
|
|
86
88
|
customStyles?.searchContainer
|
|
87
89
|
]}
|
|
88
90
|
inputStyle={[
|
|
89
91
|
{
|
|
90
|
-
backgroundColor: tokens.colors.surface,
|
|
91
|
-
borderRadius: tokens.borders.radius.full,
|
|
92
92
|
color: tokens.colors.textPrimary,
|
|
93
|
-
|
|
94
|
-
height: 52,
|
|
95
|
-
borderWidth: 1,
|
|
96
|
-
borderColor: tokens.colors.border,
|
|
93
|
+
fontSize: tokens.typography.bodyMedium.responsiveFontSize,
|
|
97
94
|
},
|
|
98
95
|
customStyles?.searchInput
|
|
99
96
|
]}
|
|
@@ -150,13 +147,14 @@ export const LanguageSelectionScreen: React.FC<LanguageSelectionProps> = ({
|
|
|
150
147
|
<ScreenLayout
|
|
151
148
|
testID={testID}
|
|
152
149
|
scrollable={false}
|
|
153
|
-
edges={['
|
|
150
|
+
edges={['bottom', 'left', 'right']}
|
|
154
151
|
backgroundColor={tokens.colors.backgroundPrimary}
|
|
155
152
|
header={
|
|
156
153
|
showHeader ? (
|
|
157
154
|
<NavigationHeader
|
|
158
155
|
title={headerTitle || ""}
|
|
159
156
|
onBackPress={handleBack}
|
|
157
|
+
centerTitle={true}
|
|
160
158
|
/>
|
|
161
159
|
) : null
|
|
162
160
|
}
|
|
@@ -41,7 +41,12 @@ export const SettingsItemCardContent: React.FC<SettingsItemCardContentProps> = R
|
|
|
41
41
|
{title}
|
|
42
42
|
</AtomicText>
|
|
43
43
|
{!!description && (
|
|
44
|
-
<AtomicText
|
|
44
|
+
<AtomicText
|
|
45
|
+
type="bodyMedium"
|
|
46
|
+
color="textSecondary"
|
|
47
|
+
numberOfLines={2}
|
|
48
|
+
style={{ fontFamily: undefined }}
|
|
49
|
+
>
|
|
45
50
|
{description}
|
|
46
51
|
</AtomicText>
|
|
47
52
|
)}
|
|
@@ -81,6 +81,7 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = (props) => {
|
|
|
81
81
|
shouldShowUserProfile,
|
|
82
82
|
appVersion,
|
|
83
83
|
handleClose,
|
|
84
|
+
currentLanguage,
|
|
84
85
|
} = useSettingsScreen({
|
|
85
86
|
config,
|
|
86
87
|
showUserProfile,
|
|
@@ -113,6 +114,7 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = (props) => {
|
|
|
113
114
|
devSettings={devSettings}
|
|
114
115
|
gamificationConfig={gamificationConfig}
|
|
115
116
|
navigation={navigation}
|
|
117
|
+
currentLanguage={currentLanguage}
|
|
116
118
|
/>
|
|
117
119
|
)}
|
|
118
120
|
</ScreenLayout>
|
|
@@ -30,6 +30,7 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
30
30
|
devSettings,
|
|
31
31
|
gamificationConfig,
|
|
32
32
|
navigation,
|
|
33
|
+
currentLanguage,
|
|
33
34
|
}) => {
|
|
34
35
|
const translations = normalizedConfig.translations;
|
|
35
36
|
const { level } = useGamification(gamificationConfig);
|
|
@@ -73,7 +74,11 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
73
74
|
/>
|
|
74
75
|
)}
|
|
75
76
|
|
|
76
|
-
<FeatureSettingsSection
|
|
77
|
+
<FeatureSettingsSection
|
|
78
|
+
normalizedConfig={normalizedConfig}
|
|
79
|
+
features={features}
|
|
80
|
+
currentLanguage={currentLanguage}
|
|
81
|
+
/>
|
|
77
82
|
|
|
78
83
|
{features.gamification && (
|
|
79
84
|
<SettingsSection title={translations?.sections?.progress || ''}>
|
|
@@ -39,7 +39,8 @@ export const FeatureSettingsSection: React.FC<FeatureSettingsSectionProps> = ({
|
|
|
39
39
|
|
|
40
40
|
const languageDisplayName = React.useMemo(() => {
|
|
41
41
|
if (!currentLanguageData) return langCode;
|
|
42
|
-
|
|
42
|
+
// Native flag rendering fix: ensure no custom font breaks emojis
|
|
43
|
+
return `${currentLanguageData.flag || ''} ${currentLanguageData.nativeName}`;
|
|
43
44
|
}, [currentLanguageData, langCode]);
|
|
44
45
|
|
|
45
46
|
if (!features.appearance && !features.language && !features.notifications) return null;
|
|
@@ -8,6 +8,7 @@ import { useAppNavigation } from "@umituz/react-native-design-system/molecules";
|
|
|
8
8
|
import { normalizeSettingsConfig } from "../utils/normalizeConfig";
|
|
9
9
|
import { useFeatureDetection } from "./useFeatureDetection";
|
|
10
10
|
import { getAppVersion } from "../../../utils/appUtils";
|
|
11
|
+
import { useLocalization } from "../../../domains/localization";
|
|
11
12
|
import type { SettingsConfig } from "../types";
|
|
12
13
|
|
|
13
14
|
export interface UseSettingsScreenParams {
|
|
@@ -28,6 +29,7 @@ export function useSettingsScreen({
|
|
|
28
29
|
onClose,
|
|
29
30
|
}: UseSettingsScreenParams) {
|
|
30
31
|
const navigation = useAppNavigation();
|
|
32
|
+
const localization = useLocalization();
|
|
31
33
|
|
|
32
34
|
// Normalize config
|
|
33
35
|
const normalizedConfig = useMemo(
|
|
@@ -60,5 +62,6 @@ export function useSettingsScreen({
|
|
|
60
62
|
shouldShowUserProfile,
|
|
61
63
|
appVersion,
|
|
62
64
|
handleClose,
|
|
65
|
+
currentLanguage: localization.currentLanguage,
|
|
63
66
|
};
|
|
64
67
|
}
|