@umituz/react-native-settings 5.3.76 → 5.3.77
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.77",
|
|
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",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React, { useState, useCallback } from "react";
|
|
1
|
+
import React, { useState, useCallback, useMemo } from "react";
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
StyleSheet,
|
|
5
5
|
TouchableOpacity,
|
|
6
|
-
|
|
6
|
+
FlatList,
|
|
7
7
|
ActivityIndicator,
|
|
8
8
|
} from "react-native";
|
|
9
9
|
import {
|
|
@@ -83,7 +83,7 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
const filteredRequests = (() => {
|
|
86
|
+
const filteredRequests = useMemo(() => {
|
|
87
87
|
switch (activeTab) {
|
|
88
88
|
case 'my':
|
|
89
89
|
return requests.filter(r => r.createdBy === userId);
|
|
@@ -92,9 +92,9 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
92
92
|
default:
|
|
93
93
|
return requests;
|
|
94
94
|
}
|
|
95
|
-
})
|
|
95
|
+
}, [requests, activeTab, userId]);
|
|
96
96
|
|
|
97
|
-
const renderRequestCard = (item: FeatureRequestItem) => {
|
|
97
|
+
const renderRequestCard = useCallback(({ item }: { item: FeatureRequestItem }) => {
|
|
98
98
|
const voted = userVotes[item.id] || null;
|
|
99
99
|
|
|
100
100
|
return (
|
|
@@ -144,9 +144,13 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
144
144
|
</View>
|
|
145
145
|
</View>
|
|
146
146
|
);
|
|
147
|
-
};
|
|
147
|
+
}, [userVotes, vote, tokens.colors, getStatusColor, statusLabels, t]);
|
|
148
|
+
|
|
149
|
+
const keyExtractor = useCallback((item: FeatureRequestItem) => item.id, []);
|
|
148
150
|
|
|
149
|
-
const
|
|
151
|
+
const tabs = useMemo(() => (['all', 'my', 'roadmap'] as const), []);
|
|
152
|
+
|
|
153
|
+
const header = useMemo(() => (
|
|
150
154
|
<View style={styles.header}>
|
|
151
155
|
<AtomicText style={styles.headerTitle}>{screenTitle}</AtomicText>
|
|
152
156
|
<TouchableOpacity
|
|
@@ -160,7 +164,7 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
160
164
|
/>
|
|
161
165
|
</TouchableOpacity>
|
|
162
166
|
</View>
|
|
163
|
-
);
|
|
167
|
+
), [screenTitle, tokens.colors.primary, tokens.colors.onPrimary]);
|
|
164
168
|
|
|
165
169
|
if (isLoading) {
|
|
166
170
|
return (
|
|
@@ -175,7 +179,7 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
175
179
|
return (
|
|
176
180
|
<ScreenLayout header={header} edges={['top', 'bottom']}>
|
|
177
181
|
<View style={styles.tabsContainer}>
|
|
178
|
-
{
|
|
182
|
+
{tabs.map((tab) => (
|
|
179
183
|
<TouchableOpacity
|
|
180
184
|
key={tab}
|
|
181
185
|
onPress={() => setActiveTab(tab)}
|
|
@@ -188,28 +192,34 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
188
192
|
))}
|
|
189
193
|
</View>
|
|
190
194
|
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
195
|
+
<FlatList
|
|
196
|
+
data={filteredRequests}
|
|
197
|
+
renderItem={renderRequestCard}
|
|
198
|
+
keyExtractor={(item) => item.id}
|
|
199
|
+
ListHeaderComponent={
|
|
200
|
+
<View style={styles.container}>
|
|
201
|
+
<View style={[styles.banner, { backgroundColor: tokens.colors.primary + '10', borderColor: tokens.colors.primary + '20' }]}>
|
|
202
|
+
<View style={styles.bannerIconContainer}>
|
|
203
|
+
<AtomicIcon
|
|
204
|
+
svgPath={ICON_PATHS['users']}
|
|
205
|
+
customSize={24}
|
|
206
|
+
customColor={tokens.colors.primary}
|
|
207
|
+
/>
|
|
208
|
+
<View style={styles.pulseDot} />
|
|
209
|
+
</View>
|
|
210
|
+
<View>
|
|
211
|
+
<AtomicText style={styles.bannerTitle}>{bannerTitle}</AtomicText>
|
|
212
|
+
<AtomicText style={[styles.bannerSub, { color: tokens.colors.textSecondary }]}>
|
|
213
|
+
{bannerSub}
|
|
214
|
+
</AtomicText>
|
|
215
|
+
</View>
|
|
216
|
+
</View>
|
|
210
217
|
|
|
211
|
-
|
|
212
|
-
|
|
218
|
+
<AtomicText style={styles.sectionTitle}>{trendingTitle}</AtomicText>
|
|
219
|
+
</View>
|
|
220
|
+
}
|
|
221
|
+
ListEmptyComponent={
|
|
222
|
+
<View style={[styles.emptyState, { paddingHorizontal: tokens.spacing.md }]}>
|
|
213
223
|
<AtomicIcon
|
|
214
224
|
svgPath={ICON_PATHS['chatbubble-outline']}
|
|
215
225
|
customSize={32}
|
|
@@ -219,12 +229,13 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
219
229
|
{t.empty || "No requests yet. Be the first!"}
|
|
220
230
|
</AtomicText>
|
|
221
231
|
</View>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
232
|
+
}
|
|
233
|
+
contentContainerStyle={styles.listContent}
|
|
234
|
+
showsVerticalScrollIndicator={false}
|
|
235
|
+
removeClippedSubviews={true}
|
|
236
|
+
maxToRenderPerBatch={10}
|
|
237
|
+
windowSize={5}
|
|
238
|
+
/>
|
|
228
239
|
|
|
229
240
|
{isModalVisible && (
|
|
230
241
|
<FeedbackModal
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { useMemo, useCallback } from 'react';
|
|
7
|
-
import { View, StyleSheet, TouchableOpacity } from 'react-native';
|
|
7
|
+
import { View, StyleSheet, TouchableOpacity, FlatList } from 'react-native';
|
|
8
8
|
import { AtomicText, AtomicIcon, AtomicSpinner } from '@umituz/react-native-design-system/atoms';
|
|
9
9
|
import { ScreenLayout } from '@umituz/react-native-design-system/layouts';
|
|
10
10
|
import { useAppDesignTokens } from '@umituz/react-native-design-system/theme';
|
|
@@ -54,10 +54,45 @@ export const ReminderListScreen: React.FC<ReminderListScreenProps> = ({
|
|
|
54
54
|
|
|
55
55
|
const fab = canAddMore ? (
|
|
56
56
|
<TouchableOpacity style={styles.fab} onPress={onAddPress} activeOpacity={0.8}>
|
|
57
|
-
<AtomicIcon
|
|
57
|
+
<AtomicIcon
|
|
58
|
+
svgPath="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"
|
|
59
|
+
customSize={20}
|
|
60
|
+
customColor={tokens.colors.onPrimary}
|
|
61
|
+
/>
|
|
58
62
|
<AtomicText type="bodyMedium" style={styles.fabText}>{translations.addButtonLabel}</AtomicText>
|
|
59
63
|
</TouchableOpacity>
|
|
60
|
-
) :
|
|
64
|
+
) : null;
|
|
65
|
+
|
|
66
|
+
const renderEmptyState = useCallback(() => (
|
|
67
|
+
<View style={styles.emptyContainer}>
|
|
68
|
+
<View style={styles.emptyIconContainer}>
|
|
69
|
+
<AtomicIcon
|
|
70
|
+
svgPath="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm0-14c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 18c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
|
|
71
|
+
customSize={48}
|
|
72
|
+
customColor={tokens.colors.secondary}
|
|
73
|
+
/>
|
|
74
|
+
</View>
|
|
75
|
+
<AtomicText type="bodyLarge" style={styles.emptyTitle}>{translations.emptyTitle}</AtomicText>
|
|
76
|
+
<AtomicText type="bodySmall" style={styles.emptyDescription}>{translations.emptyDescription}</AtomicText>
|
|
77
|
+
</View>
|
|
78
|
+
), [translations.emptyTitle, translations.emptyDescription, tokens.colors]);
|
|
79
|
+
|
|
80
|
+
const renderItem = useCallback(({ item }: { item: Reminder }) => (
|
|
81
|
+
<ReminderItem
|
|
82
|
+
reminder={item}
|
|
83
|
+
translations={{
|
|
84
|
+
frequencyOnce: translations.frequencyOnce,
|
|
85
|
+
frequencyDaily: translations.frequencyDaily,
|
|
86
|
+
frequencyWeekly: translations.frequencyWeekly,
|
|
87
|
+
frequencyMonthly: translations.frequencyMonthly,
|
|
88
|
+
}}
|
|
89
|
+
onToggle={handleToggle}
|
|
90
|
+
onEdit={onEditPress}
|
|
91
|
+
onDelete={handleDelete}
|
|
92
|
+
/>
|
|
93
|
+
), [translations, handleToggle, onEditPress, handleDelete]);
|
|
94
|
+
|
|
95
|
+
const keyExtractor = useCallback((item: Reminder) => item.id, []);
|
|
61
96
|
|
|
62
97
|
if (isLoading) {
|
|
63
98
|
return (
|
|
@@ -68,32 +103,20 @@ export const ReminderListScreen: React.FC<ReminderListScreenProps> = ({
|
|
|
68
103
|
}
|
|
69
104
|
|
|
70
105
|
return (
|
|
71
|
-
<ScreenLayout footer={fab}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
translations={{
|
|
86
|
-
frequencyOnce: translations.frequencyOnce,
|
|
87
|
-
frequencyDaily: translations.frequencyDaily,
|
|
88
|
-
frequencyWeekly: translations.frequencyWeekly,
|
|
89
|
-
frequencyMonthly: translations.frequencyMonthly,
|
|
90
|
-
}}
|
|
91
|
-
onToggle={handleToggle}
|
|
92
|
-
onEdit={onEditPress}
|
|
93
|
-
onDelete={handleDelete}
|
|
94
|
-
/>
|
|
95
|
-
))
|
|
96
|
-
)}
|
|
106
|
+
<ScreenLayout footer={fab} scrollable={false}>
|
|
107
|
+
<FlatList
|
|
108
|
+
data={reminders}
|
|
109
|
+
renderItem={renderItem}
|
|
110
|
+
keyExtractor={keyExtractor}
|
|
111
|
+
ListEmptyComponent={renderEmptyState}
|
|
112
|
+
contentContainerStyle={reminders.length === 0 ? styles.listEmptyContent : styles.listContent}
|
|
113
|
+
showsVerticalScrollIndicator={false}
|
|
114
|
+
removeClippedSubviews={true}
|
|
115
|
+
maxToRenderPerBatch={10}
|
|
116
|
+
updateCellsBatchingPeriod={50}
|
|
117
|
+
initialNumToRender={8}
|
|
118
|
+
windowSize={5}
|
|
119
|
+
/>
|
|
97
120
|
</ScreenLayout>
|
|
98
121
|
);
|
|
99
122
|
};
|
|
@@ -101,6 +124,7 @@ export const ReminderListScreen: React.FC<ReminderListScreenProps> = ({
|
|
|
101
124
|
const createStyles = (tokens: ReturnType<typeof useAppDesignTokens>) =>
|
|
102
125
|
StyleSheet.create({
|
|
103
126
|
listContent: { padding: 16, flexGrow: 1 },
|
|
127
|
+
listEmptyContent: { flexGrow: 1 },
|
|
104
128
|
emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingHorizontal: 32, paddingTop: 100 },
|
|
105
129
|
emptyIconContainer: {
|
|
106
130
|
width: 80,
|