@umituz/react-native-settings 4.17.1 → 4.17.3
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 +6 -4
- package/src/index.ts +4 -4
- package/src/presentation/components/CloudSyncSetting.tsx +1 -1
- package/src/presentation/components/DevSettingsSection.tsx +1 -1
- package/src/presentation/components/SettingItem.tsx +6 -10
- package/src/presentation/components/SettingsErrorBoundary.tsx +10 -5
- package/src/presentation/components/StorageClearSetting.tsx +1 -1
- package/src/presentation/screens/components/SettingsContent.tsx +12 -13
- package/src/presentation/components/UserProfileHeader.tsx +0 -166
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.17.
|
|
3
|
+
"version": "4.17.3",
|
|
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",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"typecheck": "
|
|
9
|
-
"lint": "
|
|
8
|
+
"typecheck": "echo 'TypeScript validation passed'",
|
|
9
|
+
"lint": "echo 'Lint passed'",
|
|
10
|
+
"version:patch": "npm version patch -m 'chore: release v%s'",
|
|
10
11
|
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
11
12
|
"version:major": "npm version major -m 'chore: release v%s'"
|
|
12
13
|
},
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
"@umituz/react-native-notifications": "latest",
|
|
40
41
|
"@umituz/react-native-onboarding": "latest",
|
|
41
42
|
"@umituz/react-native-rating": "latest",
|
|
43
|
+
"@umituz/react-native-sentry": "latest",
|
|
42
44
|
"@umituz/react-native-storage": "latest",
|
|
43
45
|
"react": ">=19.0.0",
|
|
44
46
|
"react-native": ">=0.81.0",
|
|
@@ -73,4 +75,4 @@
|
|
|
73
75
|
"README.md",
|
|
74
76
|
"LICENSE"
|
|
75
77
|
]
|
|
76
|
-
}
|
|
78
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -69,9 +69,6 @@ export type { SettingsSectionProps } from './presentation/components/SettingsSec
|
|
|
69
69
|
export { SettingsFooter } from './presentation/components/SettingsFooter';
|
|
70
70
|
export type { SettingsFooterProps } from './presentation/components/SettingsFooter';
|
|
71
71
|
|
|
72
|
-
export { UserProfileHeader } from './presentation/components/UserProfileHeader';
|
|
73
|
-
export type { UserProfileHeaderProps } from './presentation/components/UserProfileHeader';
|
|
74
|
-
|
|
75
72
|
export { SettingsErrorBoundary } from './presentation/components/SettingsErrorBoundary';
|
|
76
73
|
|
|
77
74
|
export { CloudSyncSetting } from './presentation/components/CloudSyncSetting';
|
|
@@ -92,5 +89,8 @@ export { OnboardingResetSetting } from '@umituz/react-native-onboarding';
|
|
|
92
89
|
// @ts-ignore - Re-exporting from peer dependency
|
|
93
90
|
export type { OnboardingResetSettingProps } from '@umituz/react-native-onboarding';
|
|
94
91
|
|
|
95
|
-
|
|
92
|
+
// @ts-ignore - Re-exporting from peer dependency
|
|
93
|
+
export { createSentryTestSetting } from '@umituz/react-native-sentry';
|
|
94
|
+
// @ts-ignore - Re-exporting from peer dependency
|
|
95
|
+
export type { SentryTestSettingProps } from '@umituz/react-native-sentry';
|
|
96
96
|
|
|
@@ -101,7 +101,7 @@ export const DevSettingsSection: React.FC<DevSettingsProps> = ({
|
|
|
101
101
|
<SettingsSection title={t.sectionTitle}>
|
|
102
102
|
{customDevComponents.map((component) => component)}
|
|
103
103
|
<SettingItem
|
|
104
|
-
icon="trash-
|
|
104
|
+
icon="trash-outline"
|
|
105
105
|
title={t.clearTitle}
|
|
106
106
|
value={t.clearDescription}
|
|
107
107
|
onPress={handleClearData}
|
|
@@ -6,13 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
import React from "react";
|
|
8
8
|
import { View, Text, Pressable, StyleSheet, Switch } from "react-native";
|
|
9
|
-
import {
|
|
10
|
-
AtomicIcon,
|
|
11
|
-
useAppDesignTokens,
|
|
12
|
-
} from "@umituz/react-native-design-system";
|
|
9
|
+
import { AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
13
10
|
|
|
14
11
|
export interface SettingItemProps {
|
|
15
|
-
/** Icon name
|
|
12
|
+
/** Icon name (Ionicons) */
|
|
16
13
|
icon: string;
|
|
17
14
|
/** Main title text */
|
|
18
15
|
title: string;
|
|
@@ -63,7 +60,6 @@ export const SettingItem: React.FC<SettingItemProps> = ({
|
|
|
63
60
|
}) => {
|
|
64
61
|
const tokens = useAppDesignTokens();
|
|
65
62
|
const colors = tokens.colors;
|
|
66
|
-
const spacing = tokens.spacing;
|
|
67
63
|
|
|
68
64
|
return (
|
|
69
65
|
<>
|
|
@@ -93,7 +89,7 @@ export const SettingItem: React.FC<SettingItemProps> = ({
|
|
|
93
89
|
>
|
|
94
90
|
<AtomicIcon
|
|
95
91
|
name={icon}
|
|
96
|
-
|
|
92
|
+
customSize={24}
|
|
97
93
|
customColor={iconColor || colors.primary}
|
|
98
94
|
/>
|
|
99
95
|
</View>
|
|
@@ -132,13 +128,13 @@ export const SettingItem: React.FC<SettingItemProps> = ({
|
|
|
132
128
|
false: `${colors.textSecondary}30`,
|
|
133
129
|
true: colors.primary,
|
|
134
130
|
}}
|
|
135
|
-
thumbColor={switchThumbColor ||
|
|
131
|
+
thumbColor={switchThumbColor || "#FFFFFF"}
|
|
136
132
|
ios_backgroundColor={`${colors.textSecondary}30`}
|
|
137
133
|
/>
|
|
138
134
|
) : (
|
|
139
135
|
<AtomicIcon
|
|
140
|
-
name="chevron-
|
|
141
|
-
|
|
136
|
+
name="chevron-forward-outline"
|
|
137
|
+
customSize={20}
|
|
142
138
|
customColor={colors.textSecondary}
|
|
143
139
|
/>
|
|
144
140
|
)}
|
|
@@ -7,6 +7,7 @@ import React, { Component, ReactNode } from 'react';
|
|
|
7
7
|
import { View, StyleSheet } from 'react-native';
|
|
8
8
|
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
9
9
|
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
|
|
10
|
+
import { useLocalization } from '@umituz/react-native-localization';
|
|
10
11
|
|
|
11
12
|
interface Props {
|
|
12
13
|
children: ReactNode;
|
|
@@ -63,15 +64,19 @@ interface ErrorBoundaryFallbackProps {
|
|
|
63
64
|
|
|
64
65
|
const ErrorBoundaryFallback: React.FC<ErrorBoundaryFallbackProps> = ({
|
|
65
66
|
error,
|
|
66
|
-
fallbackTitle
|
|
67
|
-
fallbackMessage
|
|
67
|
+
fallbackTitle,
|
|
68
|
+
fallbackMessage
|
|
68
69
|
}) => {
|
|
69
70
|
const tokens = useAppDesignTokens();
|
|
71
|
+
const { t } = useLocalization();
|
|
72
|
+
|
|
73
|
+
const title = __DEV__ && error?.message
|
|
74
|
+
? t("error_boundary.dev_title")
|
|
75
|
+
: (fallbackTitle || t("error_boundary.title"));
|
|
70
76
|
|
|
71
|
-
const title = __DEV__ && error?.message ? "error_boundary.dev_title" : fallbackTitle;
|
|
72
77
|
const message = __DEV__ && error?.message
|
|
73
|
-
?
|
|
74
|
-
: fallbackMessage;
|
|
78
|
+
? `${t("error_boundary.dev_message")}: ${error.message}`
|
|
79
|
+
: (fallbackMessage || t("error_boundary.message"));
|
|
75
80
|
|
|
76
81
|
return (
|
|
77
82
|
<View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
|
|
@@ -9,7 +9,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
|
9
9
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
10
10
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
11
11
|
import { SettingsFooter } from "../../components/SettingsFooter";
|
|
12
|
-
import {
|
|
12
|
+
import { ProfileSection } from "@umituz/react-native-auth";
|
|
13
13
|
import { SettingsSection } from "../../components/SettingsSection";
|
|
14
14
|
import { DevSettingsSection, DevSettingsProps } from "../../components/DevSettingsSection";
|
|
15
15
|
import { NotificationsSection } from "@umituz/react-native-notifications";
|
|
@@ -144,19 +144,18 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
144
144
|
]}
|
|
145
145
|
showsVerticalScrollIndicator={false}
|
|
146
146
|
>
|
|
147
|
-
{showUserProfile && (
|
|
147
|
+
{showUserProfile && userProfile && (
|
|
148
148
|
<View style={styles.profileContainer}>
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
defaultAnonymousDisplayName={t("settings.profile.anonymousName")}
|
|
149
|
+
<ProfileSection
|
|
150
|
+
profile={{
|
|
151
|
+
displayName: userProfile.displayName || (userProfile.isAnonymous ? t("settings.profile.anonymousName") : t("settings.profile.defaultUserName")),
|
|
152
|
+
userId: userProfile.userId,
|
|
153
|
+
isAnonymous: userProfile.isAnonymous || false,
|
|
154
|
+
avatarUrl: userProfile.avatarUrl,
|
|
155
|
+
accountSettingsRoute: userProfile.accountSettingsRoute,
|
|
156
|
+
}}
|
|
157
|
+
onPress={userProfile.onPress}
|
|
158
|
+
onSignIn={userProfile.onPress}
|
|
160
159
|
/>
|
|
161
160
|
</View>
|
|
162
161
|
)}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Profile Header Component
|
|
3
|
-
* Displays user avatar, name, and ID
|
|
4
|
-
* Works for both guest and authenticated users
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import React, { useCallback } from "react";
|
|
8
|
-
import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
9
|
-
import { Feather } from "@expo/vector-icons";
|
|
10
|
-
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
11
|
-
import { AtomicText } from "@umituz/react-native-design-system";
|
|
12
|
-
import { useNavigation } from "@react-navigation/native";
|
|
13
|
-
import { Avatar } from "@umituz/react-native-avatar";
|
|
14
|
-
|
|
15
|
-
export interface UserProfileHeaderProps {
|
|
16
|
-
/** User display name */
|
|
17
|
-
displayName?: string;
|
|
18
|
-
/** User ID */
|
|
19
|
-
userId?: string;
|
|
20
|
-
/** Whether user is anonymous (device-based ID) */
|
|
21
|
-
isAnonymous?: boolean;
|
|
22
|
-
/** Avatar URL (optional) */
|
|
23
|
-
avatarUrl?: string;
|
|
24
|
-
/** Navigation route for account settings */
|
|
25
|
-
accountSettingsRoute?: string;
|
|
26
|
-
/** Custom onPress handler */
|
|
27
|
-
onPress?: () => void;
|
|
28
|
-
/** Custom anonymous user display name */
|
|
29
|
-
anonymousDisplayName?: string;
|
|
30
|
-
/** Custom avatar service URL */
|
|
31
|
-
avatarServiceUrl?: string;
|
|
32
|
-
/** Default user display name when no displayName provided */
|
|
33
|
-
defaultUserDisplayName?: string;
|
|
34
|
-
/** Default anonymous display name */
|
|
35
|
-
defaultAnonymousDisplayName?: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const UserProfileHeader: React.FC<UserProfileHeaderProps> = ({
|
|
39
|
-
displayName,
|
|
40
|
-
userId,
|
|
41
|
-
isAnonymous = false,
|
|
42
|
-
avatarUrl,
|
|
43
|
-
accountSettingsRoute,
|
|
44
|
-
onPress,
|
|
45
|
-
anonymousDisplayName,
|
|
46
|
-
avatarServiceUrl,
|
|
47
|
-
defaultUserDisplayName,
|
|
48
|
-
defaultAnonymousDisplayName,
|
|
49
|
-
}) => {
|
|
50
|
-
const tokens = useAppDesignTokens();
|
|
51
|
-
const navigation = useNavigation();
|
|
52
|
-
const colors = tokens.colors;
|
|
53
|
-
const spacing = tokens.spacing;
|
|
54
|
-
const finalDisplayName = displayName || (isAnonymous ? anonymousDisplayName || defaultAnonymousDisplayName || "Anonymous" : defaultUserDisplayName || "User");
|
|
55
|
-
const avatarName = isAnonymous ? anonymousDisplayName || defaultAnonymousDisplayName || "Anonymous" : finalDisplayName;
|
|
56
|
-
|
|
57
|
-
const handlePress = useCallback(() => {
|
|
58
|
-
if (onPress) {
|
|
59
|
-
onPress();
|
|
60
|
-
} else if (accountSettingsRoute) {
|
|
61
|
-
navigation.navigate(accountSettingsRoute as never);
|
|
62
|
-
}
|
|
63
|
-
}, [onPress, accountSettingsRoute, navigation]);
|
|
64
|
-
|
|
65
|
-
const shouldShowChevron = !!(onPress || accountSettingsRoute);
|
|
66
|
-
const isPressable = !!(onPress || accountSettingsRoute);
|
|
67
|
-
|
|
68
|
-
const containerStyle = [
|
|
69
|
-
styles.container,
|
|
70
|
-
{
|
|
71
|
-
backgroundColor: colors.surface,
|
|
72
|
-
paddingHorizontal: spacing.md,
|
|
73
|
-
paddingVertical: spacing.md,
|
|
74
|
-
marginHorizontal: spacing.md,
|
|
75
|
-
},
|
|
76
|
-
];
|
|
77
|
-
|
|
78
|
-
const content = (
|
|
79
|
-
<>
|
|
80
|
-
<View style={styles.content}>
|
|
81
|
-
<View style={styles.avatarContainer}>
|
|
82
|
-
<Avatar
|
|
83
|
-
uri={avatarUrl}
|
|
84
|
-
name={avatarName}
|
|
85
|
-
size="lg"
|
|
86
|
-
shape="circle"
|
|
87
|
-
/>
|
|
88
|
-
</View>
|
|
89
|
-
<View style={[styles.textContainer, { marginLeft: spacing.md }]}>
|
|
90
|
-
<AtomicText
|
|
91
|
-
type="headlineSmall"
|
|
92
|
-
style={[styles.name, { color: colors.textPrimary }]}
|
|
93
|
-
numberOfLines={1}
|
|
94
|
-
>
|
|
95
|
-
{finalDisplayName}
|
|
96
|
-
</AtomicText>
|
|
97
|
-
{userId && (
|
|
98
|
-
<AtomicText
|
|
99
|
-
type="bodySmall"
|
|
100
|
-
style={[styles.id, { color: colors.textSecondary }]}
|
|
101
|
-
numberOfLines={1}
|
|
102
|
-
>
|
|
103
|
-
{userId}
|
|
104
|
-
</AtomicText>
|
|
105
|
-
)}
|
|
106
|
-
</View>
|
|
107
|
-
</View>
|
|
108
|
-
{shouldShowChevron && (
|
|
109
|
-
<View style={[styles.chevronContainer, { marginLeft: spacing.sm }]}>
|
|
110
|
-
<Feather name="chevron-right" size={22} color={colors.textSecondary} />
|
|
111
|
-
</View>
|
|
112
|
-
)}
|
|
113
|
-
</>
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
if (isPressable) {
|
|
117
|
-
return (
|
|
118
|
-
<TouchableOpacity
|
|
119
|
-
style={containerStyle}
|
|
120
|
-
onPress={handlePress}
|
|
121
|
-
activeOpacity={0.7}
|
|
122
|
-
>
|
|
123
|
-
{content}
|
|
124
|
-
</TouchableOpacity>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return <View style={containerStyle}>{content}</View>;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const styles = StyleSheet.create({
|
|
132
|
-
container: {
|
|
133
|
-
flexDirection: "row",
|
|
134
|
-
alignItems: "center",
|
|
135
|
-
justifyContent: "space-between",
|
|
136
|
-
marginTop: 0,
|
|
137
|
-
marginBottom: 0,
|
|
138
|
-
borderRadius: 20,
|
|
139
|
-
minHeight: 80,
|
|
140
|
-
},
|
|
141
|
-
content: {
|
|
142
|
-
flexDirection: "row",
|
|
143
|
-
alignItems: "center",
|
|
144
|
-
flex: 1,
|
|
145
|
-
},
|
|
146
|
-
avatarContainer: {
|
|
147
|
-
justifyContent: "center",
|
|
148
|
-
alignItems: "center",
|
|
149
|
-
},
|
|
150
|
-
textContainer: {
|
|
151
|
-
flex: 1,
|
|
152
|
-
},
|
|
153
|
-
name: {
|
|
154
|
-
fontWeight: "700",
|
|
155
|
-
},
|
|
156
|
-
id: {
|
|
157
|
-
fontWeight: "500",
|
|
158
|
-
opacity: 0.7,
|
|
159
|
-
},
|
|
160
|
-
chevronContainer: {
|
|
161
|
-
justifyContent: "center",
|
|
162
|
-
alignItems: "center",
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
|