@umituz/react-native-settings 4.20.11 → 4.20.17
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/ThemeModeSection.tsx +5 -3
- package/src/domains/appearance/presentation/components/ThemeOption.tsx +40 -30
- package/src/domains/appearance/presentation/screens/AppearanceScreen.tsx +20 -22
- package/src/domains/appearance/types/index.ts +1 -0
- package/src/domains/feedback/presentation/components/SupportSection.tsx +16 -4
- package/src/presentation/navigation/SettingsStackNavigator.tsx +3 -2
- 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.17",
|
|
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",
|
|
@@ -15,7 +15,8 @@ export interface ThemeOptionConfig {
|
|
|
15
15
|
title: string;
|
|
16
16
|
subtitle?: string;
|
|
17
17
|
description?: string;
|
|
18
|
-
features
|
|
18
|
+
features?: string[];
|
|
19
|
+
featuresTitle?: string;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export interface ThemeModeSectionProps {
|
|
@@ -58,9 +59,10 @@ export const ThemeModeSection: React.FC<ThemeModeSectionProps> = ({
|
|
|
58
59
|
key={theme.mode}
|
|
59
60
|
mode={theme.mode}
|
|
60
61
|
title={theme.title}
|
|
61
|
-
subtitle={theme.subtitle
|
|
62
|
-
description={theme.description
|
|
62
|
+
subtitle={theme.subtitle}
|
|
63
|
+
description={theme.description}
|
|
63
64
|
features={theme.features}
|
|
65
|
+
featuresTitle={theme.featuresTitle}
|
|
64
66
|
isSelected={themeMode === theme.mode}
|
|
65
67
|
onSelect={() => handleThemeSelect(theme.mode)}
|
|
66
68
|
/>
|
|
@@ -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,27 +64,24 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
64
64
|
const themeSectionMemo = useMemo(() => {
|
|
65
65
|
if (!showThemeSection) return null;
|
|
66
66
|
|
|
67
|
-
const themes: ThemeOptionConfig[] = [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
features: texts.darkMode.features
|
|
86
|
-
});
|
|
87
|
-
}
|
|
67
|
+
const themes: ThemeOptionConfig[] = [
|
|
68
|
+
{
|
|
69
|
+
mode: "light",
|
|
70
|
+
title: texts?.lightMode?.title ?? "settings.themeMode.light.title",
|
|
71
|
+
subtitle: texts?.lightMode?.subtitle,
|
|
72
|
+
description: texts?.lightMode?.description,
|
|
73
|
+
features: texts?.lightMode?.features,
|
|
74
|
+
featuresTitle: texts?.featuresSectionTitle,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
mode: "dark",
|
|
78
|
+
title: texts?.darkMode?.title ?? "settings.themeMode.dark.title",
|
|
79
|
+
subtitle: texts?.darkMode?.subtitle,
|
|
80
|
+
description: texts?.darkMode?.description,
|
|
81
|
+
features: texts?.darkMode?.features,
|
|
82
|
+
featuresTitle: texts?.featuresSectionTitle,
|
|
83
|
+
},
|
|
84
|
+
];
|
|
88
85
|
|
|
89
86
|
return (
|
|
90
87
|
<ThemeModeSection
|
|
@@ -93,7 +90,7 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
93
90
|
onThemeSelect={handleThemeSelect}
|
|
94
91
|
title={texts?.themeSectionTitle}
|
|
95
92
|
description={texts?.themeSectionDescription}
|
|
96
|
-
themes={themes
|
|
93
|
+
themes={themes}
|
|
97
94
|
/>
|
|
98
95
|
);
|
|
99
96
|
}, [
|
|
@@ -105,6 +102,7 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
105
102
|
texts?.themeSectionDescription,
|
|
106
103
|
texts?.lightMode,
|
|
107
104
|
texts?.darkMode,
|
|
105
|
+
texts?.featuresSectionTitle,
|
|
108
106
|
]);
|
|
109
107
|
|
|
110
108
|
const colorsSectionMemo = useMemo(() => {
|
|
@@ -15,6 +15,7 @@ export interface FeedbackConfig {
|
|
|
15
15
|
description?: string;
|
|
16
16
|
initialType?: FeedbackType;
|
|
17
17
|
onSubmit?: (data: { type: any; rating: number; description: string; title: string }) => Promise<void>;
|
|
18
|
+
onPress?: () => void;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export interface RatingConfig {
|
|
@@ -83,9 +84,20 @@ export const SupportSection: React.FC<SupportSectionProps> = ({
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
if (config?.storeUrl) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
try {
|
|
88
|
+
// Safely handle URL for App Store - itunes.apple.com is more reliable for deep links
|
|
89
|
+
let url = config.storeUrl;
|
|
90
|
+
if (url.includes('apps.apple.com')) {
|
|
91
|
+
url = url.replace('apps.apple.com', 'itunes.apple.com');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Try opening the modified URL
|
|
95
|
+
await Linking.openURL(url);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
// Final fallback to original URL
|
|
98
|
+
if (config.storeUrl) {
|
|
99
|
+
Linking.openURL(config.storeUrl).catch(() => {});
|
|
100
|
+
}
|
|
89
101
|
}
|
|
90
102
|
}
|
|
91
103
|
}, [ratingConfig.config]);
|
|
@@ -110,7 +122,7 @@ export const SupportSection: React.FC<SupportSectionProps> = ({
|
|
|
110
122
|
{showFeedback && feedbackConfig.config?.description && renderItem({
|
|
111
123
|
title: feedbackConfig.config.description,
|
|
112
124
|
icon: "mail",
|
|
113
|
-
onPress: () => setModalVisible(true),
|
|
125
|
+
onPress: feedbackConfig.config.onPress || (() => setModalVisible(true)),
|
|
114
126
|
isLast: !showRating
|
|
115
127
|
})}
|
|
116
128
|
|
|
@@ -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 = {
|
|
@@ -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 {
|