@umituz/react-native-settings 4.20.10 → 4.20.16
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/domains/appearance/presentation/components/ThemeOption.tsx +40 -30
- package/src/domains/appearance/presentation/screens/AppearanceScreen.tsx +36 -21
- package/src/domains/feedback/presentation/components/SupportSection.tsx +15 -4
- package/src/presentation/navigation/SettingsStackNavigator.tsx +3 -2
- package/src/presentation/screens/components/sections/FeatureSettingsSection.tsx +1 -1
- package/src/presentation/screens/types/FeatureConfig.ts +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.20.
|
|
3
|
+
"version": "4.20.16",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, about, legal, appearance, feedback, FAQs, and rating",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -14,9 +14,10 @@ import type { ThemeMode } from "../../types";
|
|
|
14
14
|
interface ThemeOptionProps {
|
|
15
15
|
mode: ThemeMode;
|
|
16
16
|
title: string;
|
|
17
|
-
subtitle
|
|
18
|
-
description
|
|
19
|
-
features
|
|
17
|
+
subtitle?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
features?: string[];
|
|
20
|
+
featuresTitle?: string;
|
|
20
21
|
isSelected: boolean;
|
|
21
22
|
onSelect: () => void;
|
|
22
23
|
}
|
|
@@ -27,6 +28,7 @@ export const ThemeOption: React.FC<ThemeOptionProps> = ({
|
|
|
27
28
|
subtitle,
|
|
28
29
|
description,
|
|
29
30
|
features,
|
|
31
|
+
featuresTitle,
|
|
30
32
|
isSelected,
|
|
31
33
|
onSelect,
|
|
32
34
|
}) => {
|
|
@@ -47,9 +49,11 @@ export const ThemeOption: React.FC<ThemeOptionProps> = ({
|
|
|
47
49
|
<AtomicText type="titleLarge" color="primary">
|
|
48
50
|
{title}
|
|
49
51
|
</AtomicText>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
{subtitle ? (
|
|
53
|
+
<AtomicText type="bodyMedium" color="secondary">
|
|
54
|
+
{subtitle}
|
|
55
|
+
</AtomicText>
|
|
56
|
+
) : null}
|
|
53
57
|
</View>
|
|
54
58
|
<AtomicIcon
|
|
55
59
|
name={isSelected ? "checkmark-circle-outline" : "ellipse-outline"}
|
|
@@ -58,33 +62,39 @@ export const ThemeOption: React.FC<ThemeOptionProps> = ({
|
|
|
58
62
|
/>
|
|
59
63
|
</View>
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
type="bodyMedium"
|
|
63
|
-
color="secondary"
|
|
64
|
-
style={styles.description}
|
|
65
|
-
>
|
|
66
|
-
{description}
|
|
67
|
-
</AtomicText>
|
|
68
|
-
|
|
69
|
-
<View style={styles.featuresContainer}>
|
|
65
|
+
{description ? (
|
|
70
66
|
<AtomicText
|
|
71
|
-
type="
|
|
72
|
-
color="
|
|
73
|
-
style={styles.
|
|
67
|
+
type="bodyMedium"
|
|
68
|
+
color="secondary"
|
|
69
|
+
style={styles.description}
|
|
74
70
|
>
|
|
75
|
-
|
|
71
|
+
{description}
|
|
76
72
|
</AtomicText>
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
73
|
+
) : null}
|
|
74
|
+
|
|
75
|
+
{features && features.length > 0 ? (
|
|
76
|
+
<View style={styles.featuresContainer}>
|
|
77
|
+
{featuresTitle ? (
|
|
78
|
+
<AtomicText
|
|
79
|
+
type="labelLarge"
|
|
80
|
+
color="primary"
|
|
81
|
+
style={styles.featuresTitle}
|
|
82
|
+
>
|
|
83
|
+
{featuresTitle}
|
|
84
|
+
</AtomicText>
|
|
85
|
+
) : null}
|
|
86
|
+
{features.map((feature, index) => (
|
|
87
|
+
<AtomicText
|
|
88
|
+
key={index}
|
|
89
|
+
type="bodySmall"
|
|
90
|
+
color="secondary"
|
|
91
|
+
style={styles.feature}
|
|
92
|
+
>
|
|
93
|
+
• {feature}
|
|
94
|
+
</AtomicText>
|
|
95
|
+
))}
|
|
96
|
+
</View>
|
|
97
|
+
) : null}
|
|
88
98
|
</TouchableOpacity>
|
|
89
99
|
);
|
|
90
100
|
};
|
|
@@ -64,36 +64,51 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
64
64
|
const themeSectionMemo = useMemo(() => {
|
|
65
65
|
if (!showThemeSection) return null;
|
|
66
66
|
|
|
67
|
-
const
|
|
67
|
+
const defaultLightMode: ThemeOptionConfig = {
|
|
68
|
+
mode: "light",
|
|
69
|
+
title: "Light Mode",
|
|
70
|
+
subtitle: "Bright and clean",
|
|
71
|
+
description: "Perfect for daytime use with vibrant colors.",
|
|
72
|
+
features: ["Bright colors", "High contrast", "Easy on eyes during day"],
|
|
73
|
+
};
|
|
68
74
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
});
|
|
77
|
-
}
|
|
75
|
+
const defaultDarkMode: ThemeOptionConfig = {
|
|
76
|
+
mode: "dark",
|
|
77
|
+
title: "Dark Mode",
|
|
78
|
+
subtitle: "Easy on eyes",
|
|
79
|
+
description: "Ideal for low-light environments.",
|
|
80
|
+
features: ["Reduced eye strain", "Better battery life", "Comfortable at night"],
|
|
81
|
+
};
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
const themes: ThemeOptionConfig[] = [
|
|
84
|
+
texts?.lightMode
|
|
85
|
+
? {
|
|
86
|
+
mode: "light",
|
|
87
|
+
title: texts.lightMode.title,
|
|
88
|
+
subtitle: texts.lightMode.subtitle,
|
|
89
|
+
description: texts.lightMode.description,
|
|
90
|
+
features: texts.lightMode.features,
|
|
91
|
+
}
|
|
92
|
+
: defaultLightMode,
|
|
93
|
+
texts?.darkMode
|
|
94
|
+
? {
|
|
95
|
+
mode: "dark",
|
|
96
|
+
title: texts.darkMode.title,
|
|
97
|
+
subtitle: texts.darkMode.subtitle,
|
|
98
|
+
description: texts.darkMode.description,
|
|
99
|
+
features: texts.darkMode.features,
|
|
100
|
+
}
|
|
101
|
+
: defaultDarkMode,
|
|
102
|
+
];
|
|
88
103
|
|
|
89
104
|
return (
|
|
90
105
|
<ThemeModeSection
|
|
91
106
|
tokens={tokens}
|
|
92
107
|
themeMode={themeMode}
|
|
93
108
|
onThemeSelect={handleThemeSelect}
|
|
94
|
-
title={texts?.themeSectionTitle}
|
|
109
|
+
title={texts?.themeSectionTitle ?? "Theme Mode"}
|
|
95
110
|
description={texts?.themeSectionDescription}
|
|
96
|
-
themes={themes
|
|
111
|
+
themes={themes}
|
|
97
112
|
/>
|
|
98
113
|
);
|
|
99
114
|
}, [
|
|
@@ -83,9 +83,20 @@ export const SupportSection: React.FC<SupportSectionProps> = ({
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
if (config?.storeUrl) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
try {
|
|
87
|
+
// Safely handle URL for App Store - itunes.apple.com is more reliable for deep links
|
|
88
|
+
let url = config.storeUrl;
|
|
89
|
+
if (url.includes('apps.apple.com')) {
|
|
90
|
+
url = url.replace('apps.apple.com', 'itunes.apple.com');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Try opening the modified URL
|
|
94
|
+
await Linking.openURL(url);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
// Final fallback to original URL
|
|
97
|
+
if (config.storeUrl) {
|
|
98
|
+
Linking.openURL(config.storeUrl).catch(() => {});
|
|
99
|
+
}
|
|
89
100
|
}
|
|
90
101
|
}
|
|
91
102
|
}, [ratingConfig.config]);
|
|
@@ -110,7 +121,7 @@ export const SupportSection: React.FC<SupportSectionProps> = ({
|
|
|
110
121
|
{showFeedback && feedbackConfig.config?.description && renderItem({
|
|
111
122
|
title: feedbackConfig.config.description,
|
|
112
123
|
icon: "mail",
|
|
113
|
-
onPress: () => setModalVisible(true),
|
|
124
|
+
onPress: feedbackConfig.config.onPress || (() => setModalVisible(true)),
|
|
114
125
|
isLast: !showRating
|
|
115
126
|
})}
|
|
116
127
|
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* Can be extended by apps to add custom screens
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React from "react";
|
|
8
|
+
import React, { useMemo } from "react";
|
|
9
9
|
import { createStackNavigator } from "@react-navigation/stack";
|
|
10
10
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
11
11
|
import { SettingsScreen } from "../screens/SettingsScreen";
|
|
12
12
|
import { AppearanceScreen } from "../screens/AppearanceScreen";
|
|
13
|
-
import type { SettingsConfig, CustomSettingsSection } from "../screens/types";
|
|
13
|
+
import type { SettingsConfig, CustomSettingsSection, AppearanceConfig } from "../screens/types";
|
|
14
14
|
import type { DevSettingsProps } from "../components/DevSettingsSection";
|
|
15
|
+
import type { AppearanceTexts } from "../../domains/appearance/types";
|
|
15
16
|
|
|
16
17
|
// Default param list - can be extended by apps
|
|
17
18
|
export type SettingsStackParamList = {
|
|
@@ -30,7 +30,7 @@ export const FeatureSettingsSection: React.FC<FeatureSettingsSectionProps> = ({
|
|
|
30
30
|
const currentLanguageData = getLanguageByCode(currentLanguage);
|
|
31
31
|
const languageDisplayName = currentLanguageData
|
|
32
32
|
? `${currentLanguageData.flag} ${currentLanguageData.nativeName}`
|
|
33
|
-
: currentLanguage
|
|
33
|
+
: currentLanguage;
|
|
34
34
|
|
|
35
35
|
return (
|
|
36
36
|
<>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Core types for feature visibility and configuration
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type { AppearanceTexts } from "../../../domains/appearance/types";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Feature visibility configuration
|
|
@@ -33,6 +33,8 @@ export interface AppearanceConfig {
|
|
|
33
33
|
sectionTitle?: string;
|
|
34
34
|
/** Default route name when no custom route provided */
|
|
35
35
|
defaultRoute?: string;
|
|
36
|
+
/** Appearance screen texts (theme mode labels, descriptions, etc.) */
|
|
37
|
+
texts?: AppearanceTexts;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
/**
|
|
@@ -169,6 +171,8 @@ export interface FeedbackConfig {
|
|
|
169
171
|
initialType?: FeedbackType;
|
|
170
172
|
/** Feedback submission handler */
|
|
171
173
|
onSubmit?: (data: { type: any; rating: number; description: string; title: string }) => Promise<void>;
|
|
174
|
+
/** Custom handler to open feedback screen (overrides default modal) */
|
|
175
|
+
onPress?: () => void;
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
export interface FAQConfig {
|