@umituz/react-native-settings 4.20.56 → 4.20.57

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.
Files changed (47) hide show
  1. package/README.md +145 -3
  2. package/package.json +1 -2
  3. package/src/application/README.md +322 -0
  4. package/src/domains/about/README.md +452 -0
  5. package/src/domains/about/presentation/hooks/README.md +350 -0
  6. package/src/domains/appearance/README.md +596 -0
  7. package/src/domains/appearance/hooks/README.md +366 -0
  8. package/src/domains/appearance/infrastructure/services/README.md +455 -0
  9. package/src/domains/cloud-sync/README.md +451 -0
  10. package/src/domains/cloud-sync/presentation/components/README.md +493 -0
  11. package/src/domains/dev/README.md +477 -0
  12. package/src/domains/disclaimer/README.md +421 -0
  13. package/src/domains/disclaimer/presentation/components/README.md +394 -0
  14. package/src/domains/faqs/README.md +586 -0
  15. package/src/domains/feedback/README.md +565 -0
  16. package/src/domains/feedback/presentation/hooks/README.md +428 -0
  17. package/src/domains/legal/README.md +549 -0
  18. package/src/domains/rating/README.md +452 -0
  19. package/src/domains/rating/presentation/components/README.md +475 -0
  20. package/src/domains/video-tutorials/README.md +482 -0
  21. package/src/domains/video-tutorials/presentation/components/README.md +433 -0
  22. package/src/infrastructure/README.md +509 -0
  23. package/src/infrastructure/repositories/README.md +475 -0
  24. package/src/infrastructure/services/README.md +510 -0
  25. package/src/presentation/components/README.md +482 -0
  26. package/src/presentation/components/SettingsErrorBoundary/README.md +461 -0
  27. package/src/presentation/components/SettingsFooter/README.md +446 -0
  28. package/src/presentation/components/SettingsItemCard/README.md +457 -0
  29. package/src/presentation/components/SettingsSection/README.md +421 -0
  30. package/src/presentation/hooks/README.md +413 -0
  31. package/src/presentation/hooks/mutations/README.md +430 -0
  32. package/src/presentation/hooks/queries/README.md +441 -0
  33. package/src/presentation/navigation/README.md +532 -0
  34. package/src/presentation/navigation/components/README.md +330 -0
  35. package/src/presentation/navigation/hooks/README.md +399 -0
  36. package/src/presentation/navigation/utils/README.md +442 -0
  37. package/src/presentation/screens/README.md +525 -0
  38. package/src/presentation/screens/components/SettingsContent/README.md +404 -0
  39. package/src/presentation/screens/components/SettingsHeader/README.md +322 -0
  40. package/src/presentation/screens/components/sections/CustomSettingsList/README.md +388 -0
  41. package/src/presentation/screens/components/sections/FeatureSettingsSection/README.md +232 -0
  42. package/src/presentation/screens/components/sections/IdentitySettingsSection/README.md +325 -0
  43. package/src/presentation/screens/components/sections/ProfileSectionLoader/README.md +480 -0
  44. package/src/presentation/screens/components/sections/SupportSettingsSection/README.md +391 -0
  45. package/src/presentation/screens/hooks/README.md +383 -0
  46. package/src/presentation/screens/types/README.md +439 -0
  47. package/src/presentation/screens/utils/README.md +288 -0
@@ -0,0 +1,509 @@
1
+ # Infrastructure Layer
2
+
3
+ The infrastructure layer provides concrete implementations of the interfaces defined in the application layer, handling data persistence and external service integrations.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ infrastructure/
9
+ ├── repositories/
10
+ │ └── SettingsRepository.ts # Settings storage implementation
11
+ └── services/
12
+ └── SettingsService.ts # Settings business logic service
13
+ ```
14
+
15
+ ## Components
16
+
17
+ ### SettingsRepository
18
+
19
+ Concrete implementation of `ISettingsRepository` using `@umituz/react-native-storage` for data persistence.
20
+
21
+ #### Features
22
+
23
+ - **Automatic Defaults**: Creates default settings for new users
24
+ - **Type Safety**: Full TypeScript support
25
+ - **Error Handling**: Comprehensive error catching and reporting
26
+ - **Storage Integration**: Uses storage repository for persistence
27
+
28
+ #### Usage
29
+
30
+ ```typescript
31
+ import { SettingsRepository } from '@umituz/react-native-settings';
32
+
33
+ const repository = new SettingsRepository();
34
+
35
+ // Get settings
36
+ const result = await repository.getSettings('user123');
37
+ if (result.success) {
38
+ console.log(result.data?.theme); // 'auto'
39
+ }
40
+
41
+ // Save settings
42
+ await repository.saveSettings({
43
+ userId: 'user123',
44
+ theme: 'dark',
45
+ language: 'en-US',
46
+ // ... other settings
47
+ });
48
+
49
+ // Delete settings
50
+ await repository.deleteSettings('user123');
51
+ ```
52
+
53
+ #### Implementation Details
54
+
55
+ **getSettings(userId):**
56
+
57
+ 1. Creates storage key from user ID
58
+ 2. Attempts to retrieve from storage
59
+ 3. Returns defaults if not found
60
+ 4. Saves defaults for next time
61
+ 5. Returns error on failure
62
+
63
+ ```typescript
64
+ const storageKey = createUserKey(StorageKey.USER_PREFERENCES, userId);
65
+ const defaults = this.defaultSettings(userId);
66
+ const result = await storageRepository.getItem<UserSettings>(storageKey, defaults);
67
+
68
+ if (!result.success) {
69
+ await this.saveSettings(defaults);
70
+ return { success: true, data: defaults };
71
+ }
72
+
73
+ return { success: true, data: result.data || defaults };
74
+ ```
75
+
76
+ **saveSettings(settings):**
77
+
78
+ 1. Creates storage key from user ID
79
+ 2. Saves settings to storage
80
+ 3. Returns success or error
81
+
82
+ ```typescript
83
+ const storageKey = createUserKey(StorageKey.USER_PREFERENCES, settings.userId);
84
+ const result = await storageRepository.setItem(storageKey, settings);
85
+
86
+ if (!result.success) {
87
+ return {
88
+ success: false,
89
+ error: {
90
+ code: 'SAVE_SETTINGS_FAILED',
91
+ message: 'Failed to save settings to storage',
92
+ },
93
+ };
94
+ }
95
+
96
+ return { success: true };
97
+ ```
98
+
99
+ **deleteSettings(userId):**
100
+
101
+ 1. Creates storage key from user ID
102
+ 2. Removes from storage
103
+ 3. Returns success or error
104
+
105
+ ```typescript
106
+ const storageKey = createUserKey(StorageKey.USER_PREFERENCES, userId);
107
+ const result = await storageRepository.removeItem(storageKey);
108
+
109
+ return result.success
110
+ ? { success: true }
111
+ : {
112
+ success: false,
113
+ error: {
114
+ code: 'DELETE_SETTINGS_FAILED',
115
+ message: 'Failed to delete settings',
116
+ },
117
+ };
118
+ ```
119
+
120
+ ### SettingsService
121
+
122
+ Business logic service for high-level settings operations.
123
+
124
+ #### Usage
125
+
126
+ ```typescript
127
+ import { SettingsService } from '@umituz/react-native-settings';
128
+
129
+ const service = new SettingsService(repository);
130
+
131
+ // Initialize settings for new user
132
+ await service.initializeUser('user123');
133
+
134
+ // Update specific settings
135
+ await service.updateTheme('user123', 'dark');
136
+ await service.updateLanguage('user123', 'tr-TR');
137
+
138
+ // Reset to defaults
139
+ await service.resetToDefaults('user123');
140
+ ```
141
+
142
+ ## Storage Integration
143
+
144
+ ### Storage Keys
145
+
146
+ The repository uses the following storage keys:
147
+
148
+ ```typescript
149
+ enum StorageKey {
150
+ USER_PREFERENCES = 'user_preferences', // Main settings storage
151
+ }
152
+ ```
153
+
154
+ ### Storage Format
155
+
156
+ Settings are stored as JSON:
157
+
158
+ ```json
159
+ {
160
+ "userId": "user123",
161
+ "theme": "dark",
162
+ "language": "en-US",
163
+ "notificationsEnabled": true,
164
+ "emailNotifications": true,
165
+ "pushNotifications": false,
166
+ "soundEnabled": true,
167
+ "vibrationEnabled": false,
168
+ "privacyMode": false,
169
+ "disclaimerAccepted": true,
170
+ "updatedAt": "2025-01-08T10:30:00.000Z"
171
+ }
172
+ ```
173
+
174
+ ## Default Settings
175
+
176
+ When creating new settings, these defaults are used:
177
+
178
+ | Setting | Default Value | Description |
179
+ |---------|---------------|-------------|
180
+ | `theme` | `'auto'` | Follow system theme |
181
+ | `language` | `'en-US'` | English (United States) |
182
+ | `notificationsEnabled` | `true` | Notifications enabled |
183
+ | `emailNotifications` | `true` | Email notifications enabled |
184
+ | `pushNotifications` | `true` | Push notifications enabled |
185
+ | `soundEnabled` | `true` | Sound effects enabled |
186
+ | `vibrationEnabled` | `true` | Haptic feedback enabled |
187
+ | `privacyMode` | `false` | Privacy mode disabled |
188
+ | `disclaimerAccepted` | `false` | Disclaimer not accepted |
189
+
190
+ ## Error Handling
191
+
192
+ All repository methods return `SettingsResult<T>`:
193
+
194
+ ```typescript
195
+ // Success case
196
+ { success: true, data: settings }
197
+
198
+ // Error case
199
+ {
200
+ success: false,
201
+ error: {
202
+ code: 'GET_SETTINGS_FAILED',
203
+ message: 'Detailed error message'
204
+ }
205
+ }
206
+ ```
207
+
208
+ ### Error Codes
209
+
210
+ | Code | Description |
211
+ |------|-------------|
212
+ | `GET_SETTINGS_FAILED` | Failed to retrieve settings |
213
+ | `SAVE_SETTINGS_FAILED` | Failed to save settings |
214
+ | `DELETE_SETTINGS_FAILED` | Failed to delete settings |
215
+
216
+ ## Examples
217
+
218
+ ### Custom Repository Implementation
219
+
220
+ ```typescript
221
+ import type { ISettingsRepository, UserSettings, SettingsResult } from '@umituz/react-native-settings';
222
+
223
+ class AsyncStorageRepository implements ISettingsRepository {
224
+ async getSettings(userId: string): Promise<SettingsResult<UserSettings>> {
225
+ try {
226
+ const key = `settings_${userId}`;
227
+ const json = await AsyncStorage.getItem(key);
228
+
229
+ if (!json) {
230
+ return {
231
+ success: false,
232
+ error: { code: 'NOT_FOUND', message: 'Settings not found' },
233
+ };
234
+ }
235
+
236
+ const data = JSON.parse(json);
237
+ return { success: true, data };
238
+ } catch (error) {
239
+ return {
240
+ success: false,
241
+ error: {
242
+ code: 'GET_SETTINGS_FAILED',
243
+ message: error.message,
244
+ },
245
+ };
246
+ }
247
+ }
248
+
249
+ async saveSettings(settings: UserSettings): Promise<SettingsResult<void>> {
250
+ try {
251
+ const key = `settings_${settings.userId}`;
252
+ const json = JSON.stringify(settings);
253
+ await AsyncStorage.setItem(key, json);
254
+ return { success: true };
255
+ } catch (error) {
256
+ return {
257
+ success: false,
258
+ error: {
259
+ code: 'SAVE_SETTINGS_FAILED',
260
+ message: error.message,
261
+ },
262
+ };
263
+ }
264
+ }
265
+
266
+ async deleteSettings(userId: string): Promise<SettingsResult<void>> {
267
+ try {
268
+ const key = `settings_${userId}`;
269
+ await AsyncStorage.removeItem(key);
270
+ return { success: true };
271
+ } catch (error) {
272
+ return {
273
+ success: false,
274
+ error: {
275
+ code: 'DELETE_SETTINGS_FAILED',
276
+ message: error.message,
277
+ },
278
+ };
279
+ }
280
+ }
281
+ }
282
+ ```
283
+
284
+ ### Using Custom Repository
285
+
286
+ ```typescript
287
+ import { useSettings } from '@umituz/react-native-settings';
288
+
289
+ // Provide custom repository to your app
290
+ const customRepository = new AsyncStorageRepository();
291
+
292
+ function App() {
293
+ return (
294
+ <SettingsProvider repository={customRepository}>
295
+ <MyApp />
296
+ </SettingsProvider>
297
+ );
298
+ }
299
+ ```
300
+
301
+ ### Migration Handler
302
+
303
+ ```typescript
304
+ class MigrationSettingsRepository implements ISettingsRepository {
305
+ constructor(private baseRepository: ISettingsRepository) {}
306
+
307
+ async getSettings(userId: string): Promise<SettingsResult<UserSettings>> {
308
+ const result = await this.baseRepository.getSettings(userId);
309
+
310
+ if (result.success && result.data) {
311
+ // Migration: Add new fields
312
+ const migrated = this.migrateSettings(result.data);
313
+ if (migrated !== result.data) {
314
+ await this.saveSettings(migrated);
315
+ return { success: true, data: migrated };
316
+ }
317
+ }
318
+
319
+ return result;
320
+ }
321
+
322
+ private migrateSettings(settings: UserSettings): UserSettings {
323
+ // Add new field with default
324
+ if (!('newField' in settings)) {
325
+ return { ...settings, newField: defaultValue };
326
+ }
327
+ return settings;
328
+ }
329
+
330
+ // Delegate other methods
331
+ async saveSettings(settings: UserSettings) {
332
+ return this.baseRepository.saveSettings(settings);
333
+ }
334
+
335
+ async deleteSettings(userId: string) {
336
+ return this.baseRepository.deleteSettings(userId);
337
+ }
338
+ }
339
+ ```
340
+
341
+ ### Encrypted Storage
342
+
343
+ ```typescript
344
+ import * as SecureStore from 'expo-secure-store';
345
+
346
+ class SecureSettingsRepository implements ISettingsRepository {
347
+ async getSettings(userId: string): Promise<SettingsResult<UserSettings>> {
348
+ try {
349
+ const key = `secure_settings_${userId}`;
350
+ const json = await SecureStore.getItemAsync(key);
351
+
352
+ if (!json) {
353
+ return { success: false, error: { code: 'NOT_FOUND', message: 'Not found' } };
354
+ }
355
+
356
+ const data = JSON.parse(json);
357
+ return { success: true, data };
358
+ } catch (error) {
359
+ return {
360
+ success: false,
361
+ error: { code: 'GET_SETTINGS_FAILED', message: error.message },
362
+ };
363
+ }
364
+ }
365
+
366
+ async saveSettings(settings: UserSettings): Promise<SettingsResult<void>> {
367
+ try {
368
+ const key = `secure_settings_${settings.userId}`;
369
+ const json = JSON.stringify(settings);
370
+ await SecureStore.setItemAsync(key, json);
371
+ return { success: true };
372
+ } catch (error) {
373
+ return {
374
+ success: false,
375
+ error: { code: 'SAVE_SETTINGS_FAILED', message: error.message },
376
+ };
377
+ }
378
+ }
379
+
380
+ async deleteSettings(userId: string): Promise<SettingsResult<void>> {
381
+ try {
382
+ const key = `secure_settings_${userId}`;
383
+ await SecureStore.deleteItemAsync(key);
384
+ return { success: true };
385
+ } catch (error) {
386
+ return {
387
+ success: false,
388
+ error: { code: 'DELETE_SETTINGS_FAILED', message: error.message },
389
+ };
390
+ }
391
+ }
392
+ }
393
+ ```
394
+
395
+ ## Testing
396
+
397
+ ### Mock Repository
398
+
399
+ ```typescript
400
+ class MockSettingsRepository implements ISettingsRepository {
401
+ private storage: Map<string, UserSettings> = new Map();
402
+
403
+ async getSettings(userId: string): Promise<SettingsResult<UserSettings>> {
404
+ const settings = this.storage.get(userId);
405
+ return settings
406
+ ? { success: true, data: settings }
407
+ : { success: false, error: { code: 'NOT_FOUND', message: 'Not found' } };
408
+ }
409
+
410
+ async saveSettings(settings: UserSettings): Promise<SettingsResult<void>> {
411
+ this.storage.set(settings.userId, settings);
412
+ return { success: true };
413
+ }
414
+
415
+ async deleteSettings(userId: string): Promise<SettingsResult<void>> {
416
+ this.storage.delete(userId);
417
+ return { success: true };
418
+ }
419
+
420
+ // Test helper methods
421
+ clear() {
422
+ this.storage.clear();
423
+ }
424
+
425
+ hasSettings(userId: string): boolean {
426
+ return this.storage.has(userId);
427
+ }
428
+ }
429
+ ```
430
+
431
+ ### Test Example
432
+
433
+ ```typescript
434
+ import { SettingsRepository } from '@umituz/react-native-settings';
435
+
436
+ describe('SettingsRepository', () => {
437
+ let repository: SettingsRepository;
438
+
439
+ beforeEach(() => {
440
+ repository = new SettingsRepository();
441
+ });
442
+
443
+ it('should save and retrieve settings', async () => {
444
+ const settings: UserSettings = {
445
+ userId: 'test123',
446
+ theme: 'dark',
447
+ language: 'en-US',
448
+ notificationsEnabled: true,
449
+ emailNotifications: true,
450
+ pushNotifications: false,
451
+ soundEnabled: true,
452
+ vibrationEnabled: false,
453
+ privacyMode: false,
454
+ disclaimerAccepted: true,
455
+ updatedAt: new Date(),
456
+ };
457
+
458
+ const saveResult = await repository.saveSettings(settings);
459
+ expect(saveResult.success).toBe(true);
460
+
461
+ const getResult = await repository.getSettings('test123');
462
+ expect(getResult.success).toBe(true);
463
+ expect(getResult.data?.theme).toBe('dark');
464
+ });
465
+
466
+ it('should return defaults for new user', async () => {
467
+ const result = await repository.getSettings('newuser');
468
+
469
+ expect(result.success).toBe(true);
470
+ expect(result.data?.theme).toBe('auto');
471
+ expect(result.data?.language).toBe('en-US');
472
+ });
473
+
474
+ it('should delete settings', async () => {
475
+ await repository.saveSettings({
476
+ userId: 'deleteMe',
477
+ theme: 'light',
478
+ // ... other required fields
479
+ } as any);
480
+
481
+ const deleteResult = await repository.deleteSettings('deleteMe');
482
+ expect(deleteResult.success).toBe(true);
483
+
484
+ const getResult = await repository.getSettings('deleteMe');
485
+ expect(getResult.data?.theme).toBe('auto'); // Returns defaults
486
+ });
487
+ });
488
+ ```
489
+
490
+ ## Best Practices
491
+
492
+ 1. **Use Repository Interface**: Program to `ISettingsRepository`, not concrete implementation
493
+ 2. **Handle Errors**: Always check `success` flag
494
+ 3. **Type Safety**: Use TypeScript types for all operations
495
+ 4. **Validation**: Validate data before saving
496
+ 5. **Default Values**: Always provide sensible defaults
497
+ 6. **Error Messages**: Include detailed, helpful error messages
498
+ 7. **Testing**: Use mock repositories in tests
499
+ 8. **Migration**: Handle schema migrations gracefully
500
+
501
+ ## Related
502
+
503
+ - **Application Layer**: Repository interfaces and types
504
+ - **Presentation Hooks**: React hooks for UI integration
505
+ - **Storage Package**: `@umituz/react-native-storage`
506
+
507
+ ## License
508
+
509
+ MIT