@umituz/react-native-settings 4.14.0 → 4.16.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 +2 -2
- package/src/index.ts +8 -1
- package/src/presentation/components/DevSettingsSection.tsx +4 -0
- package/src/presentation/screens/components/SettingsContent.tsx +22 -0
- package/src/presentation/screens/hooks/useFeatureDetection.ts +19 -4
- package/src/presentation/screens/types/FeatureConfig.ts +40 -0
- package/src/presentation/screens/types/SettingsConfig.ts +8 -0
- package/src/presentation/screens/types/index.ts +1 -0
- package/src/presentation/screens/utils/normalizeConfig.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.16.0",
|
|
4
4
|
"description": "Settings management for React Native apps - user preferences, theme, language, notifications",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -91,4 +91,4 @@
|
|
|
91
91
|
"README.md",
|
|
92
92
|
"LICENSE"
|
|
93
93
|
]
|
|
94
|
-
}
|
|
94
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -50,7 +50,11 @@ export type {
|
|
|
50
50
|
// PRESENTATION LAYER - Types
|
|
51
51
|
// =============================================================================
|
|
52
52
|
|
|
53
|
-
export type {
|
|
53
|
+
export type {
|
|
54
|
+
SettingsConfig,
|
|
55
|
+
CustomSettingsSection,
|
|
56
|
+
SubscriptionConfig,
|
|
57
|
+
} from './presentation/screens/types';
|
|
54
58
|
|
|
55
59
|
// =============================================================================
|
|
56
60
|
// PRESENTATION LAYER - Components
|
|
@@ -78,3 +82,6 @@ export type { StorageClearSettingProps } from './presentation/components/Storage
|
|
|
78
82
|
|
|
79
83
|
export { DevSettingsSection } from './presentation/components/DevSettingsSection';
|
|
80
84
|
export type { DevSettingsProps } from './presentation/components/DevSettingsSection';
|
|
85
|
+
|
|
86
|
+
export { OnboardingResetSetting } from './presentation/components/OnboardingResetSetting';
|
|
87
|
+
export type { OnboardingResetSettingProps } from './presentation/components/OnboardingResetSetting';
|
|
@@ -42,12 +42,15 @@ export interface DevSettingsProps {
|
|
|
42
42
|
onAfterClear?: () => Promise<void>;
|
|
43
43
|
/** Custom texts (optional - defaults to English) */
|
|
44
44
|
texts?: Partial<typeof DEFAULT_TEXTS>;
|
|
45
|
+
/** Custom dev components to render before the clear data button */
|
|
46
|
+
customDevComponents?: React.ReactNode[];
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
export const DevSettingsSection: React.FC<DevSettingsProps> = ({
|
|
48
50
|
enabled = true,
|
|
49
51
|
onAfterClear,
|
|
50
52
|
texts = {},
|
|
53
|
+
customDevComponents = [],
|
|
51
54
|
}) => {
|
|
52
55
|
const tokens = useAppDesignTokens();
|
|
53
56
|
|
|
@@ -102,6 +105,7 @@ export const DevSettingsSection: React.FC<DevSettingsProps> = ({
|
|
|
102
105
|
|
|
103
106
|
return (
|
|
104
107
|
<SettingsSection title={t.sectionTitle}>
|
|
108
|
+
{customDevComponents.map((component) => component)}
|
|
105
109
|
<SettingItem
|
|
106
110
|
icon={TrashIcon}
|
|
107
111
|
title={t.clearTitle}
|
|
@@ -32,6 +32,18 @@ try {
|
|
|
32
32
|
// Package not available
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// Optional subscription component
|
|
36
|
+
let SubscriptionSection: React.ComponentType<any> | null = null;
|
|
37
|
+
try {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
|
+
const module = require("@umituz/react-native-subscription");
|
|
40
|
+
if (module?.SubscriptionSection) {
|
|
41
|
+
SubscriptionSection = module.SubscriptionSection;
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
// Package not available
|
|
45
|
+
}
|
|
46
|
+
|
|
35
47
|
interface SettingsContentProps {
|
|
36
48
|
normalizedConfig: NormalizedConfig;
|
|
37
49
|
config?: any; // Original config for emptyStateText
|
|
@@ -43,6 +55,7 @@ interface SettingsContentProps {
|
|
|
43
55
|
legal: boolean;
|
|
44
56
|
disclaimer: boolean;
|
|
45
57
|
userProfile: boolean;
|
|
58
|
+
subscription: boolean;
|
|
46
59
|
};
|
|
47
60
|
showUserProfile?: boolean;
|
|
48
61
|
userProfile?: {
|
|
@@ -88,6 +101,7 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
88
101
|
features.about ||
|
|
89
102
|
features.legal ||
|
|
90
103
|
features.disclaimer ||
|
|
104
|
+
features.subscription ||
|
|
91
105
|
customSections.length > 0,
|
|
92
106
|
[features, customSections.length]
|
|
93
107
|
);
|
|
@@ -125,6 +139,14 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
125
139
|
</View>
|
|
126
140
|
)}
|
|
127
141
|
|
|
142
|
+
{features.subscription &&
|
|
143
|
+
SubscriptionSection &&
|
|
144
|
+
normalizedConfig.subscription.config?.sectionConfig && (
|
|
145
|
+
<SubscriptionSection
|
|
146
|
+
config={normalizedConfig.subscription.config.sectionConfig}
|
|
147
|
+
/>
|
|
148
|
+
)}
|
|
149
|
+
|
|
128
150
|
{features.appearance && (
|
|
129
151
|
<AppearanceSection
|
|
130
152
|
config={{
|
|
@@ -61,10 +61,19 @@ export function useFeatureDetection(
|
|
|
61
61
|
},
|
|
62
62
|
) {
|
|
63
63
|
return useMemo(() => {
|
|
64
|
-
const {
|
|
65
|
-
|
|
64
|
+
const {
|
|
65
|
+
appearance,
|
|
66
|
+
language,
|
|
67
|
+
notifications,
|
|
68
|
+
about,
|
|
69
|
+
legal,
|
|
70
|
+
disclaimer,
|
|
71
|
+
userProfile,
|
|
72
|
+
subscription,
|
|
73
|
+
} = normalizedConfig;
|
|
66
74
|
|
|
67
|
-
const notificationServiceAvailable =
|
|
75
|
+
const notificationServiceAvailable =
|
|
76
|
+
options?.notificationServiceAvailable ?? notificationService !== null;
|
|
68
77
|
|
|
69
78
|
return {
|
|
70
79
|
appearance:
|
|
@@ -106,8 +115,14 @@ export function useFeatureDetection(
|
|
|
106
115
|
disclaimer.enabled &&
|
|
107
116
|
(disclaimer.config?.enabled === true ||
|
|
108
117
|
(disclaimer.config?.enabled !== false &&
|
|
109
|
-
hasNavigationScreen(
|
|
118
|
+
hasNavigationScreen(
|
|
119
|
+
navigation,
|
|
120
|
+
disclaimer.config?.route || "Disclaimer",
|
|
121
|
+
))),
|
|
110
122
|
userProfile: userProfile.enabled,
|
|
123
|
+
subscription:
|
|
124
|
+
subscription.enabled &&
|
|
125
|
+
subscription.config?.sectionConfig !== undefined,
|
|
111
126
|
};
|
|
112
127
|
}, [normalizedConfig, navigation, options]);
|
|
113
128
|
}
|
|
@@ -128,3 +128,43 @@ export interface UserProfileConfig {
|
|
|
128
128
|
/** Navigation route for account settings (shows chevron if set) */
|
|
129
129
|
accountSettingsRoute?: string;
|
|
130
130
|
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Subscription Settings Configuration
|
|
134
|
+
* App must provide all data via sectionConfig (no internal fetch)
|
|
135
|
+
*/
|
|
136
|
+
export interface SubscriptionConfig {
|
|
137
|
+
/** Show subscription section */
|
|
138
|
+
enabled?: FeatureVisibility;
|
|
139
|
+
/** Section configuration (app provides all data) */
|
|
140
|
+
sectionConfig?: {
|
|
141
|
+
statusType: "active" | "expired" | "none";
|
|
142
|
+
isPremium: boolean;
|
|
143
|
+
expirationDate?: string | null;
|
|
144
|
+
purchaseDate?: string | null;
|
|
145
|
+
isLifetime?: boolean;
|
|
146
|
+
daysRemaining?: number | null;
|
|
147
|
+
credits?: Array<{
|
|
148
|
+
id: string;
|
|
149
|
+
label: string;
|
|
150
|
+
current: number;
|
|
151
|
+
total: number;
|
|
152
|
+
}>;
|
|
153
|
+
translations: {
|
|
154
|
+
title: string;
|
|
155
|
+
statusLabel: string;
|
|
156
|
+
expiresLabel: string;
|
|
157
|
+
purchasedLabel: string;
|
|
158
|
+
creditsTitle?: string;
|
|
159
|
+
remainingLabel?: string;
|
|
160
|
+
manageButton?: string;
|
|
161
|
+
upgradeButton?: string;
|
|
162
|
+
lifetimeLabel?: string;
|
|
163
|
+
statusActive?: string;
|
|
164
|
+
statusExpired?: string;
|
|
165
|
+
statusFree?: string;
|
|
166
|
+
};
|
|
167
|
+
onManageSubscription?: () => void;
|
|
168
|
+
onUpgrade?: () => void;
|
|
169
|
+
};
|
|
170
|
+
}
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
LegalConfig,
|
|
13
13
|
DisclaimerConfig,
|
|
14
14
|
UserProfileConfig,
|
|
15
|
+
SubscriptionConfig,
|
|
15
16
|
} from "./FeatureConfig";
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -88,6 +89,13 @@ export interface SettingsConfig {
|
|
|
88
89
|
*/
|
|
89
90
|
userProfile?: boolean | UserProfileConfig;
|
|
90
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Subscription/Premium settings
|
|
94
|
+
* App must provide all data via sectionConfig
|
|
95
|
+
* @default false
|
|
96
|
+
*/
|
|
97
|
+
subscription?: FeatureVisibility | SubscriptionConfig;
|
|
98
|
+
|
|
91
99
|
/**
|
|
92
100
|
* Custom empty state text when no settings are available
|
|
93
101
|
*/
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
LegalConfig,
|
|
13
13
|
DisclaimerConfig,
|
|
14
14
|
UserProfileConfig,
|
|
15
|
+
SubscriptionConfig,
|
|
15
16
|
SettingsConfig,
|
|
16
17
|
} from "../types";
|
|
17
18
|
|
|
@@ -44,6 +45,10 @@ export interface NormalizedConfig {
|
|
|
44
45
|
enabled: boolean;
|
|
45
46
|
config?: UserProfileConfig;
|
|
46
47
|
};
|
|
48
|
+
subscription: {
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
config?: SubscriptionConfig;
|
|
51
|
+
};
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
/**
|
|
@@ -85,6 +90,7 @@ export function normalizeSettingsConfig(
|
|
|
85
90
|
legal: normalizeConfigValue(config?.legal, "auto"),
|
|
86
91
|
disclaimer: normalizeConfigValue(config?.disclaimer, false),
|
|
87
92
|
userProfile: normalizeConfigValue(config?.userProfile, false),
|
|
93
|
+
subscription: normalizeConfigValue(config?.subscription, false),
|
|
88
94
|
};
|
|
89
95
|
}
|
|
90
96
|
|