@umituz/react-native-settings 4.20.58 → 4.20.59

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 (64) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +51 -0
  2. package/.github/ISSUE_TEMPLATE/documentation.md +52 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +63 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +84 -0
  5. package/AI_AGENT_GUIDELINES.md +367 -0
  6. package/ARCHITECTURE.md +246 -0
  7. package/CHANGELOG.md +67 -0
  8. package/CODE_OF_CONDUCT.md +75 -0
  9. package/CONTRIBUTING.md +107 -0
  10. package/DOCUMENTATION_MIGRATION.md +319 -0
  11. package/DOCUMENTATION_TEMPLATE.md +155 -0
  12. package/LICENSE +21 -0
  13. package/README.md +321 -498
  14. package/SECURITY.md +98 -0
  15. package/SETTINGS_SCREEN_GUIDE.md +185 -0
  16. package/TESTING.md +358 -0
  17. package/package.json +13 -2
  18. package/src/application/README.md +85 -271
  19. package/src/domains/about/README.md +85 -440
  20. package/src/domains/about/presentation/hooks/README.md +93 -348
  21. package/src/domains/appearance/README.md +95 -584
  22. package/src/domains/appearance/hooks/README.md +95 -303
  23. package/src/domains/appearance/infrastructure/services/README.md +83 -397
  24. package/src/domains/appearance/presentation/components/README.md +95 -489
  25. package/src/domains/cloud-sync/README.md +73 -439
  26. package/src/domains/cloud-sync/presentation/components/README.md +95 -493
  27. package/src/domains/dev/README.md +71 -457
  28. package/src/domains/disclaimer/README.md +77 -411
  29. package/src/domains/disclaimer/presentation/components/README.md +95 -392
  30. package/src/domains/faqs/README.md +86 -574
  31. package/src/domains/feedback/README.md +79 -553
  32. package/src/domains/feedback/presentation/hooks/README.md +93 -426
  33. package/src/domains/legal/README.md +88 -537
  34. package/src/domains/rating/README.md +73 -440
  35. package/src/domains/rating/presentation/components/README.md +95 -475
  36. package/src/domains/video-tutorials/README.md +77 -470
  37. package/src/domains/video-tutorials/presentation/components/README.md +95 -431
  38. package/src/infrastructure/README.md +78 -425
  39. package/src/infrastructure/repositories/README.md +88 -420
  40. package/src/infrastructure/services/README.md +74 -460
  41. package/src/presentation/components/README.md +97 -480
  42. package/src/presentation/components/SettingsErrorBoundary/README.md +48 -436
  43. package/src/presentation/components/SettingsFooter/README.md +48 -427
  44. package/src/presentation/components/SettingsItemCard/README.md +152 -391
  45. package/src/presentation/components/SettingsItemCard/STRATEGY.md +164 -0
  46. package/src/presentation/components/SettingsSection/README.md +47 -401
  47. package/src/presentation/hooks/README.md +95 -389
  48. package/src/presentation/hooks/mutations/README.md +99 -376
  49. package/src/presentation/hooks/queries/README.md +111 -353
  50. package/src/presentation/navigation/README.md +70 -502
  51. package/src/presentation/navigation/components/README.md +70 -295
  52. package/src/presentation/navigation/hooks/README.md +75 -367
  53. package/src/presentation/navigation/utils/README.md +100 -380
  54. package/src/presentation/screens/README.md +53 -504
  55. package/src/presentation/screens/components/SettingsContent/README.md +53 -382
  56. package/src/presentation/screens/components/SettingsHeader/README.md +48 -303
  57. package/src/presentation/screens/components/sections/CustomSettingsList/README.md +47 -359
  58. package/src/presentation/screens/components/sections/FeatureSettingsSection/README.md +81 -176
  59. package/src/presentation/screens/components/sections/IdentitySettingsSection/README.md +40 -297
  60. package/src/presentation/screens/components/sections/ProfileSectionLoader/README.md +47 -451
  61. package/src/presentation/screens/components/sections/SupportSettingsSection/README.md +45 -361
  62. package/src/presentation/screens/hooks/README.md +64 -354
  63. package/src/presentation/screens/types/README.md +79 -409
  64. package/src/presentation/screens/utils/README.md +65 -255
@@ -1,143 +1,109 @@
1
1
  # Infrastructure Layer
2
2
 
3
- The infrastructure layer provides concrete implementations of the interfaces defined in the application layer, handling data persistence and external service integrations.
3
+ Provides concrete implementations of the interfaces defined in the application layer, handling data persistence and external service integrations.
4
4
 
5
- ## Architecture
5
+ ## Purpose
6
+
7
+ The infrastructure layer is responsible for all external interactions including storage, network calls, and third-party integrations. It implements the interfaces defined in the application layer and provides concrete implementations for data persistence and retrieval.
8
+
9
+ ## File Paths
6
10
 
7
11
  ```
8
- infrastructure/
12
+ src/infrastructure/
9
13
  ├── repositories/
10
14
  │ └── SettingsRepository.ts # Settings storage implementation
11
15
  └── services/
12
16
  └── SettingsService.ts # Settings business logic service
13
17
  ```
14
18
 
15
- ## Components
19
+ ## Strategy
16
20
 
17
- ### SettingsRepository
21
+ 1. **Interface Implementation**: Implement all interfaces defined in the application layer
22
+ 2. **Dependency Injection**: Accept dependencies through constructors for testability
23
+ 3. **Error Transformation**: Convert external errors into domain-specific error types
24
+ 4. **Default Management**: Automatically create and apply default values for new users
25
+ 5. **Storage Abstraction**: Use abstract storage interfaces to remain implementation-agnostic
18
26
 
19
- Concrete implementation of `ISettingsRepository` using `@umituz/react-native-storage` for data persistence.
27
+ ## Restrictions
20
28
 
21
- #### Features
29
+ ### DO NOT
22
30
 
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
31
+ - DO NOT include business logic that belongs in the application layer
32
+ - DO NOT expose storage-specific details to upper layers
33
+ - DO NOT directly access React Native components
34
+ - DO NOT make network calls without proper error handling
35
+ - ❌ DO NOT store raw exceptions; transform to domain errors
27
36
 
28
- #### Usage
37
+ ### NEVER
29
38
 
30
- ```typescript
31
- import { SettingsRepository } from '@umituz/react-native-settings';
39
+ - ❌ NEVER bypass validation rules when saving data
40
+ - NEVER expose internal storage format to external layers
41
+ - ❌ EVER couple to specific storage implementations without abstraction
42
+ - ❌ EVER assume data always exists; handle null/undefined cases
32
43
 
33
- const repository = new SettingsRepository();
44
+ ### AVOID
34
45
 
35
- // Get settings
36
- const result = await repository.getSettings('user123');
37
- if (result.success) {
38
- console.log(result.data?.theme); // 'auto'
39
- }
46
+ - AVOID hardcoding storage keys or paths
47
+ - AVOID synchronous operations that could block the UI
48
+ - AVOID caching without proper invalidation strategies
49
+ - AVOID exposing implementation details in error messages
40
50
 
41
- // Save settings
42
- await repository.saveSettings({
43
- userId: 'user123',
44
- theme: 'dark',
45
- language: 'en-US',
46
- // ... other settings
47
- });
51
+ ## Rules
48
52
 
49
- // Delete settings
50
- await repository.deleteSettings('user123');
51
- ```
53
+ ### ALWAYS
52
54
 
53
- #### Implementation Details
55
+ - ALWAYS implement interfaces from the application layer
56
+ - ✅ ALWAYS return Results with proper error handling
57
+ - ✅ ALWAYS provide default values for missing data
58
+ - ✅ ALWAYS use dependency injection for external services
59
+ - ✅ ALWAYS handle storage errors gracefully
54
60
 
55
- **getSettings(userId):**
61
+ ### MUST
56
62
 
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
63
+ - MUST validate data before persistence
64
+ - MUST transform storage errors to domain errors
65
+ - MUST use async/await for all I/O operations
66
+ - MUST ensure thread safety for concurrent operations
62
67
 
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);
68
+ ### SHOULD
67
69
 
68
- if (!result.success) {
69
- await this.saveSettings(defaults);
70
- return { success: true, data: defaults };
71
- }
70
+ - SHOULD cache frequently accessed data
71
+ - ✅ SHOULD provide retry logic for transient failures
72
+ - SHOULD log all storage operations for debugging
73
+ - ✅ SHOULD handle schema migrations gracefully
72
74
 
73
- return { success: true, data: result.data || defaults };
74
- ```
75
+ ## AI Agent Guidelines
75
76
 
76
- **saveSettings(settings):**
77
+ 1. **When implementing repositories**: Always inject storage dependencies and implement the full interface
78
+ 2. **When handling errors**: Transform technical errors into user-friendly domain errors with actionable messages
79
+ 3. **When adding caching**: Implement proper cache invalidation and consider cache coherence
80
+ 4. **When dealing with defaults**: Provide sensible defaults that match the application's expected behavior
81
+ 5. **When creating migrations**: Ensure backward compatibility and provide migration paths for existing data
77
82
 
78
- 1. Creates storage key from user ID
79
- 2. Saves settings to storage
80
- 3. Returns success or error
83
+ ## Components Reference
81
84
 
82
- ```typescript
83
- const storageKey = createUserKey(StorageKey.USER_PREFERENCES, settings.userId);
84
- const result = await storageRepository.setItem(storageKey, settings);
85
+ ### SettingsRepository
85
86
 
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
- }
87
+ Concrete implementation of `ISettingsRepository` using storage abstraction for data persistence.
95
88
 
96
- return { success: true };
97
- ```
89
+ **Location**: `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/infrastructure/repositories/SettingsRepository.ts`
98
90
 
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
- ```
91
+ **Features**:
92
+ - Automatic defaults creation for new users
93
+ - Full TypeScript type safety
94
+ - Comprehensive error catching and reporting
95
+ - Storage repository integration
119
96
 
120
97
  ### SettingsService
121
98
 
122
99
  Business logic service for high-level settings operations.
123
100
 
124
- #### Usage
125
-
126
- ```typescript
127
- import { SettingsService } from '@umituz/react-native-settings';
101
+ **Location**: `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/infrastructure/services/SettingsService.ts`
128
102
 
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
- ```
103
+ **Features**:
104
+ - User initialization
105
+ - Partial setting updates
106
+ - Reset to defaults functionality
141
107
 
142
108
  ## Storage Integration
143
109
 
@@ -145,35 +111,13 @@ await service.resetToDefaults('user123');
145
111
 
146
112
  The repository uses the following storage keys:
147
113
 
148
- ```typescript
149
- enum StorageKey {
150
- USER_PREFERENCES = 'user_preferences', // Main settings storage
151
- }
152
- ```
114
+ - `USER_PREFERENCES` - Main settings storage key
153
115
 
154
116
  ### Storage Format
155
117
 
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
118
+ Settings are stored as JSON with all user preferences including theme, language, notifications, and timestamps.
175
119
 
176
- When creating new settings, these defaults are used:
120
+ ## Default Values
177
121
 
178
122
  | Setting | Default Value | Description |
179
123
  |---------|---------------|-------------|
@@ -191,19 +135,8 @@ When creating new settings, these defaults are used:
191
135
 
192
136
  All repository methods return `SettingsResult<T>`:
193
137
 
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
- ```
138
+ **Success case**: `{ success: true, data: settings }`
139
+ **Error case**: `{ success: false, error: { code: string, message: string } }`
207
140
 
208
141
  ### Error Codes
209
142
 
@@ -213,296 +146,16 @@ All repository methods return `SettingsResult<T>`:
213
146
  | `SAVE_SETTINGS_FAILED` | Failed to save settings |
214
147
  | `DELETE_SETTINGS_FAILED` | Failed to delete settings |
215
148
 
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
149
  ## Testing
396
150
 
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
151
+ ### Mock Repository Pattern
500
152
 
501
- ## Related
153
+ Create mock implementations for testing that implement `ISettingsRepository`:
502
154
 
503
- - **Application Layer**: Repository interfaces and types
504
- - **Presentation Hooks**: React hooks for UI integration
505
- - **Storage Package**: `@umituz/react-native-storage`
155
+ 1. Use in-memory storage (Map or object)
156
+ 2. Implement all interface methods
157
+ 3. Provide test helper methods (clear, hasSettings, etc.)
158
+ 4. Simulate errors for error handling tests
506
159
 
507
160
  ## License
508
161