@umituz/react-native-settings 4.20.56 → 4.20.58
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/README.md +146 -4
- package/package.json +1 -2
- package/src/__tests__/setup.ts +1 -4
- package/src/application/README.md +322 -0
- package/src/domains/about/README.md +452 -0
- package/src/domains/about/presentation/hooks/README.md +350 -0
- package/src/domains/appearance/README.md +596 -0
- package/src/domains/appearance/hooks/README.md +366 -0
- package/src/domains/appearance/infrastructure/services/README.md +455 -0
- package/src/domains/appearance/presentation/components/README.md +493 -0
- package/src/domains/cloud-sync/README.md +451 -0
- package/src/domains/cloud-sync/presentation/components/README.md +493 -0
- package/src/domains/dev/README.md +477 -0
- package/src/domains/disclaimer/README.md +421 -0
- package/src/domains/disclaimer/presentation/components/README.md +394 -0
- package/src/domains/faqs/README.md +586 -0
- package/src/domains/feedback/README.md +565 -0
- package/src/domains/feedback/presentation/hooks/README.md +428 -0
- package/src/domains/legal/README.md +549 -0
- package/src/domains/rating/README.md +452 -0
- package/src/domains/rating/presentation/components/README.md +475 -0
- package/src/domains/video-tutorials/README.md +482 -0
- package/src/domains/video-tutorials/presentation/components/README.md +433 -0
- package/src/infrastructure/README.md +509 -0
- package/src/infrastructure/repositories/README.md +475 -0
- package/src/infrastructure/services/README.md +510 -0
- package/src/presentation/components/README.md +482 -0
- package/src/presentation/components/SettingsErrorBoundary/README.md +455 -0
- package/src/presentation/components/SettingsFooter/README.md +446 -0
- package/src/presentation/components/SettingsItemCard/README.md +457 -0
- package/src/presentation/components/SettingsSection/README.md +421 -0
- package/src/presentation/hooks/README.md +413 -0
- package/src/presentation/hooks/mutations/README.md +430 -0
- package/src/presentation/hooks/queries/README.md +441 -0
- package/src/presentation/navigation/README.md +532 -0
- package/src/presentation/navigation/components/README.md +330 -0
- package/src/presentation/navigation/hooks/README.md +399 -0
- package/src/presentation/navigation/utils/README.md +442 -0
- package/src/presentation/screens/README.md +525 -0
- package/src/presentation/screens/components/SettingsContent/README.md +404 -0
- package/src/presentation/screens/components/SettingsHeader/README.md +322 -0
- package/src/presentation/screens/components/sections/CustomSettingsList/README.md +388 -0
- package/src/presentation/screens/components/sections/FeatureSettingsSection/README.md +232 -0
- package/src/presentation/screens/components/sections/IdentitySettingsSection/README.md +325 -0
- package/src/presentation/screens/components/sections/ProfileSectionLoader/README.md +480 -0
- package/src/presentation/screens/components/sections/SupportSettingsSection/README.md +391 -0
- package/src/presentation/screens/hooks/README.md +383 -0
- package/src/presentation/screens/types/README.md +439 -0
- package/src/presentation/screens/utils/README.md +288 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# Presentation Hooks
|
|
2
|
+
|
|
3
|
+
Custom React hooks for managing settings state, queries, and mutations in the presentation layer.
|
|
4
|
+
|
|
5
|
+
## Hooks
|
|
6
|
+
|
|
7
|
+
### useSettings
|
|
8
|
+
|
|
9
|
+
Primary hook for accessing and managing user settings with TanStack Query integration.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { useSettings } from '@umituz/react-native-settings';
|
|
13
|
+
|
|
14
|
+
function SettingsComponent() {
|
|
15
|
+
const { settings, loading, error, updateSettings, resetSettings } = useSettings('user123');
|
|
16
|
+
|
|
17
|
+
if (loading) return <LoadingSpinner />;
|
|
18
|
+
if (error) return <ErrorMessage message={error} />;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<View>
|
|
22
|
+
<Text>Theme: {settings?.theme}</Text>
|
|
23
|
+
<Button
|
|
24
|
+
title="Toggle Dark Mode"
|
|
25
|
+
onPress={() => updateSettings({ theme: 'dark' })}
|
|
26
|
+
/>
|
|
27
|
+
</View>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
#### Return Value
|
|
33
|
+
|
|
34
|
+
| Property | Type | Description |
|
|
35
|
+
|----------|------|-------------|
|
|
36
|
+
| `settings` | `UserSettings \| null` | Current user settings |
|
|
37
|
+
| `loading` | `boolean` | Loading state |
|
|
38
|
+
| `error` | `string \| null` | Error message |
|
|
39
|
+
| `updateSettings` | `(updates) => Promise<void>` | Update settings function |
|
|
40
|
+
| `resetSettings` | `() => Promise<void>` | Reset to defaults function |
|
|
41
|
+
|
|
42
|
+
#### Example
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
function ThemeToggle() {
|
|
46
|
+
const { settings, updateSettings } = useSettings(userId);
|
|
47
|
+
|
|
48
|
+
const toggleTheme = () => {
|
|
49
|
+
const newTheme = settings?.theme === 'light' ? 'dark' : 'light';
|
|
50
|
+
updateSettings({ theme: newTheme });
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Switch
|
|
55
|
+
value={settings?.theme === 'dark'}
|
|
56
|
+
onValueChange={toggleTheme}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### useSettingsQuery
|
|
63
|
+
|
|
64
|
+
Hook for querying user settings with TanStack Query.
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { useSettingsQuery } from '@umituz/react-native-settings';
|
|
68
|
+
|
|
69
|
+
function SettingsData() {
|
|
70
|
+
const { data, isLoading, error } = useSettingsQuery('user123');
|
|
71
|
+
|
|
72
|
+
if (isLoading) return <Text>Loading...</Text>;
|
|
73
|
+
if (error) return <Text>Error loading settings</Text>;
|
|
74
|
+
|
|
75
|
+
return <Text>Language: {data.language}</Text>;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### useUpdateSettingsMutation
|
|
80
|
+
|
|
81
|
+
Hook for updating settings with TanStack Query mutation.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { useUpdateSettingsMutation } from '@umituz/react-native-settings';
|
|
85
|
+
|
|
86
|
+
function UpdateSettings() {
|
|
87
|
+
const mutation = useUpdateSettingsMutation('user123');
|
|
88
|
+
|
|
89
|
+
const handleUpdate = async () => {
|
|
90
|
+
await mutation.mutateAsync({ theme: 'dark' });
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return <Button onPress={handleUpdate} title="Update Settings" />;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### useResetSettingsMutation
|
|
98
|
+
|
|
99
|
+
Hook for resetting settings to defaults.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { useResetSettingsMutation } from '@umituz/react-native-settings';
|
|
103
|
+
|
|
104
|
+
function ResetButton() {
|
|
105
|
+
const mutation = useResetSettingsMutation('user123');
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<Button
|
|
109
|
+
onPress={() => mutation.mutateAsync()}
|
|
110
|
+
title="Reset to Defaults"
|
|
111
|
+
/>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Usage Examples
|
|
117
|
+
|
|
118
|
+
### Complete Settings Management
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import { useSettings } from '@umituz/react-native-settings';
|
|
122
|
+
|
|
123
|
+
function SettingsManager() {
|
|
124
|
+
const { settings, loading, error, updateSettings, resetSettings } = useSettings(userId);
|
|
125
|
+
|
|
126
|
+
const handleThemeChange = (theme: 'light' | 'dark') => {
|
|
127
|
+
updateSettings({ theme });
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const handleLanguageChange = (language: string) => {
|
|
131
|
+
updateSettings({ language });
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const handleNotificationsToggle = () => {
|
|
135
|
+
updateSettings({
|
|
136
|
+
notificationsEnabled: !settings?.notificationsEnabled,
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const handleReset = async () => {
|
|
141
|
+
Alert.alert(
|
|
142
|
+
'Reset Settings',
|
|
143
|
+
'Are you sure you want to reset all settings?',
|
|
144
|
+
[
|
|
145
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
146
|
+
{
|
|
147
|
+
text: 'Reset',
|
|
148
|
+
style: 'destructive',
|
|
149
|
+
onPress: async () => {
|
|
150
|
+
await resetSettings();
|
|
151
|
+
Alert.alert('Success', 'Settings have been reset');
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
if (loading) return <LoadingScreen />;
|
|
159
|
+
if (error) return <ErrorScreen message={error} />;
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<ScreenLayout>
|
|
163
|
+
<SettingsSection title="APPEARANCE">
|
|
164
|
+
<SettingsItemCard
|
|
165
|
+
icon="moon-outline"
|
|
166
|
+
title="Dark Mode"
|
|
167
|
+
showSwitch={true}
|
|
168
|
+
switchValue={settings?.theme === 'dark'}
|
|
169
|
+
onSwitchChange={() => handleThemeChange('dark')}
|
|
170
|
+
/>
|
|
171
|
+
<SettingsItemCard
|
|
172
|
+
icon="globe-outline"
|
|
173
|
+
title="Language"
|
|
174
|
+
description={settings?.language}
|
|
175
|
+
onPress={() => setShowLanguageSelector(true)}
|
|
176
|
+
/>
|
|
177
|
+
</SettingsSection>
|
|
178
|
+
|
|
179
|
+
<SettingsSection title="NOTIFICATIONS">
|
|
180
|
+
<SettingsItemCard
|
|
181
|
+
icon="notifications-outline"
|
|
182
|
+
title="Enable Notifications"
|
|
183
|
+
showSwitch={true}
|
|
184
|
+
switchValue={settings?.notificationsEnabled}
|
|
185
|
+
onSwitchChange={handleNotificationsToggle}
|
|
186
|
+
/>
|
|
187
|
+
</SettingsSection>
|
|
188
|
+
|
|
189
|
+
<SettingsSection title="DANGER ZONE">
|
|
190
|
+
<SettingsItemCard
|
|
191
|
+
icon="refresh-outline"
|
|
192
|
+
title="Reset Settings"
|
|
193
|
+
description="Reset all settings to defaults"
|
|
194
|
+
onPress={handleReset}
|
|
195
|
+
iconColor="#DC2626"
|
|
196
|
+
/>
|
|
197
|
+
</SettingsSection>
|
|
198
|
+
</ScreenLayout>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Multiple Settings Updates
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
function BulkUpdate() {
|
|
207
|
+
const { updateSettings, settings } = useSettings(userId);
|
|
208
|
+
|
|
209
|
+
const enableAllFeatures = async () => {
|
|
210
|
+
await updateSettings({
|
|
211
|
+
notificationsEnabled: true,
|
|
212
|
+
soundEnabled: true,
|
|
213
|
+
vibrationEnabled: true,
|
|
214
|
+
emailNotifications: true,
|
|
215
|
+
pushNotifications: true,
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const disableAllFeatures = async () => {
|
|
220
|
+
await updateSettings({
|
|
221
|
+
notificationsEnabled: false,
|
|
222
|
+
soundEnabled: false,
|
|
223
|
+
vibrationEnabled: false,
|
|
224
|
+
emailNotifications: false,
|
|
225
|
+
pushNotifications: false,
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<View>
|
|
231
|
+
<Button title="Enable All" onPress={enableAllFeatures} />
|
|
232
|
+
<Button title="Disable All" onPress={disableAllFeatures} />
|
|
233
|
+
</View>
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Optimistic Updates
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
function OptimisticThemeToggle() {
|
|
242
|
+
const { settings, updateSettings } = useSettings(userId);
|
|
243
|
+
const [localTheme, setLocalTheme] = useState(settings?.theme);
|
|
244
|
+
|
|
245
|
+
const handleToggle = async () => {
|
|
246
|
+
const newTheme = localTheme === 'light' ? 'dark' : 'light';
|
|
247
|
+
|
|
248
|
+
// Optimistic update
|
|
249
|
+
setLocalTheme(newTheme);
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
await updateSettings({ theme: newTheme });
|
|
253
|
+
} catch (error) {
|
|
254
|
+
// Revert on error
|
|
255
|
+
setLocalTheme(settings?.theme);
|
|
256
|
+
Alert.alert('Error', 'Failed to update theme');
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<Switch
|
|
262
|
+
value={localTheme === 'dark'}
|
|
263
|
+
onValueChange={handleToggle}
|
|
264
|
+
/>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Error Handling
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
function SettingsWithErrorHandling() {
|
|
273
|
+
const { settings, updateSettings, error } = useSettings(userId);
|
|
274
|
+
|
|
275
|
+
const handleUpdate = async () => {
|
|
276
|
+
try {
|
|
277
|
+
await updateSettings({ theme: 'dark' });
|
|
278
|
+
Alert.alert('Success', 'Settings updated');
|
|
279
|
+
} catch (err) {
|
|
280
|
+
Alert.alert('Error', 'Failed to update settings');
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
if (error) {
|
|
286
|
+
Alert.alert('Settings Error', error);
|
|
287
|
+
}
|
|
288
|
+
}, [error]);
|
|
289
|
+
|
|
290
|
+
return (
|
|
291
|
+
<Button
|
|
292
|
+
title="Update Theme"
|
|
293
|
+
onPress={handleUpdate}
|
|
294
|
+
disabled={!settings}
|
|
295
|
+
/>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Loading States
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
function SettingsWithLoadingStates() {
|
|
304
|
+
const { settings, loading, updateSettings } = useSettings(userId);
|
|
305
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
|
306
|
+
|
|
307
|
+
const handleUpdate = async () => {
|
|
308
|
+
setIsUpdating(true);
|
|
309
|
+
try {
|
|
310
|
+
await updateSettings({ theme: 'dark' });
|
|
311
|
+
} finally {
|
|
312
|
+
setIsUpdating(false);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
if (loading) {
|
|
317
|
+
return (
|
|
318
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
319
|
+
<ActivityIndicator size="large" />
|
|
320
|
+
<Text style={{ marginTop: 16 }}>Loading settings...</Text>
|
|
321
|
+
</View>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<Button
|
|
327
|
+
title={isUpdating ? 'Updating...' : 'Update Theme'}
|
|
328
|
+
onPress={handleUpdate}
|
|
329
|
+
disabled={loading || isUpdating}
|
|
330
|
+
/>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Hook Dependencies
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
presentation/hooks/
|
|
339
|
+
├── useSettings.ts # Main settings hook
|
|
340
|
+
├── queries/
|
|
341
|
+
│ └── useSettingsQuery.ts # TanStack Query integration
|
|
342
|
+
└── mutations/
|
|
343
|
+
└── useSettingsMutations.ts # Mutation hooks
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Integration with TanStack Query
|
|
347
|
+
|
|
348
|
+
These hooks use TanStack Query for:
|
|
349
|
+
|
|
350
|
+
- **Caching**: Automatic caching of settings data
|
|
351
|
+
- **Background Updates**: Automatic refetching
|
|
352
|
+
- **Optimistic Updates**: UI updates before server confirmation
|
|
353
|
+
- **Error Handling**: Built-in error management
|
|
354
|
+
- **Loading States**: Automatic loading state management
|
|
355
|
+
|
|
356
|
+
## Best Practices
|
|
357
|
+
|
|
358
|
+
1. **Use useSettings**: Prefer the main hook for most use cases
|
|
359
|
+
2. **Handle Loading**: Always handle loading state
|
|
360
|
+
3. **Error Handling**: Implement proper error handling
|
|
361
|
+
4. **Optimistic Updates**: Use optimistic updates for better UX
|
|
362
|
+
5. **Partial Updates**: Use partial updates to only change needed fields
|
|
363
|
+
6. **Reset Confirmation**: Always confirm before resetting settings
|
|
364
|
+
|
|
365
|
+
## Testing
|
|
366
|
+
|
|
367
|
+
```tsx
|
|
368
|
+
import { renderHook, act, waitFor } from '@testing-library/react-native';
|
|
369
|
+
import { useSettings } from '@umituz/react-native-settings';
|
|
370
|
+
|
|
371
|
+
describe('useSettings', () => {
|
|
372
|
+
it('loads settings for user', async () => {
|
|
373
|
+
const { result } = renderHook(() => useSettings('user123'));
|
|
374
|
+
|
|
375
|
+
expect(result.current.loading).toBe(true);
|
|
376
|
+
|
|
377
|
+
await waitFor(() => {
|
|
378
|
+
expect(result.current.loading).toBe(false);
|
|
379
|
+
expect(result.current.settings).toBeDefined();
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('updates settings', async () => {
|
|
384
|
+
const { result } = renderHook(() => useSettings('user123'));
|
|
385
|
+
|
|
386
|
+
await act(async () => {
|
|
387
|
+
await result.current.updateSettings({ theme: 'dark' });
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
expect(result.current.settings?.theme).toBe('dark');
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('resets settings', async () => {
|
|
394
|
+
const { result } = renderHook(() => useSettings('user123'));
|
|
395
|
+
|
|
396
|
+
await act(async () => {
|
|
397
|
+
await result.current.resetSettings();
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
expect(result.current.settings?.theme).toBe('auto');
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Related
|
|
406
|
+
|
|
407
|
+
- **Application Layer**: Repository interfaces and types
|
|
408
|
+
- **Infrastructure**: Storage implementation
|
|
409
|
+
- **Presentation Components**: UI components
|
|
410
|
+
|
|
411
|
+
## License
|
|
412
|
+
|
|
413
|
+
MIT
|