proagents 1.6.17 → 1.6.18

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 (168) hide show
  1. package/.claude/settings.local.json +169 -0
  2. package/COMMANDS.md +595 -0
  3. package/README.md +13 -23
  4. package/package.json +2 -7
  5. package/.proagents/ai-models/README.md +0 -141
  6. package/.proagents/ai-models/cost-management.md +0 -362
  7. package/.proagents/ai-models/fallbacks.md +0 -342
  8. package/.proagents/ai-models/model-config.md +0 -318
  9. package/.proagents/ai-models/task-routing.md +0 -503
  10. package/.proagents/ai-training/README.md +0 -155
  11. package/.proagents/ai-training/continuous-learning.md +0 -413
  12. package/.proagents/ai-training/domain-knowledge.md +0 -378
  13. package/.proagents/ai-training/pattern-learning.md +0 -455
  14. package/.proagents/ai-training/training-data.md +0 -337
  15. package/.proagents/ai-training/user-preferences.md +0 -346
  16. package/.proagents/approval-workflows/README.md +0 -146
  17. package/.proagents/approval-workflows/approval-config.md +0 -332
  18. package/.proagents/approval-workflows/approval-stages.md +0 -503
  19. package/.proagents/approval-workflows/emergency-bypass.md +0 -351
  20. package/.proagents/approval-workflows/examples.md +0 -859
  21. package/.proagents/approval-workflows/notifications.md +0 -320
  22. package/.proagents/compliance/README.md +0 -206
  23. package/.proagents/compliance/access-control.md +0 -310
  24. package/.proagents/compliance/audit-logging.md +0 -444
  25. package/.proagents/compliance/compliance-frameworks.md +0 -429
  26. package/.proagents/compliance/reports.md +0 -491
  27. package/.proagents/compliance/retention-policies.md +0 -454
  28. package/.proagents/config-versioning/README.md +0 -120
  29. package/.proagents/config-versioning/changelog.md +0 -300
  30. package/.proagents/config-versioning/rollback.md +0 -283
  31. package/.proagents/config-versioning/versioning.md +0 -330
  32. package/.proagents/contract-testing/README.md +0 -223
  33. package/.proagents/contract-testing/contract-testing.md +0 -614
  34. package/.proagents/contract-testing/pact-integration.md +0 -507
  35. package/.proagents/contract-testing/schema-validation.md +0 -565
  36. package/.proagents/dependency-management/README.md +0 -140
  37. package/.proagents/dependency-management/automation.md +0 -363
  38. package/.proagents/dependency-management/compatibility.md +0 -319
  39. package/.proagents/dependency-management/security-scanning.md +0 -413
  40. package/.proagents/dependency-management/update-policies.md +0 -374
  41. package/.proagents/disaster-recovery/README.md +0 -247
  42. package/.proagents/disaster-recovery/automation.md +0 -366
  43. package/.proagents/disaster-recovery/backup-recovery.md +0 -571
  44. package/.proagents/disaster-recovery/incident-response.md +0 -565
  45. package/.proagents/disaster-recovery/rollback-procedures.md +0 -499
  46. package/.proagents/disaster-recovery/runbooks.md +0 -603
  47. package/.proagents/disaster-recovery/scenarios.md +0 -892
  48. package/.proagents/disaster-recovery/testing.md +0 -438
  49. package/.proagents/environments/README.md +0 -244
  50. package/.proagents/environments/configuration.md +0 -437
  51. package/.proagents/environments/promotion.md +0 -434
  52. package/.proagents/environments/setup.md +0 -420
  53. package/.proagents/examples/README.md +0 -55
  54. package/.proagents/examples/backend-nodejs/README.md +0 -188
  55. package/.proagents/examples/backend-nodejs/complete-conversation.md +0 -601
  56. package/.proagents/examples/backend-nodejs/proagents.config.yaml +0 -415
  57. package/.proagents/examples/backend-nodejs/workflow-example.md +0 -909
  58. package/.proagents/examples/fullstack-nextjs/README.md +0 -155
  59. package/.proagents/examples/fullstack-nextjs/complete-conversation.md +0 -604
  60. package/.proagents/examples/fullstack-nextjs/proagents.config.yaml +0 -287
  61. package/.proagents/examples/fullstack-nextjs/workflow-example.md +0 -553
  62. package/.proagents/examples/mobile-react-native/README.md +0 -171
  63. package/.proagents/examples/mobile-react-native/complete-conversation.md +0 -825
  64. package/.proagents/examples/mobile-react-native/proagents.config.yaml +0 -330
  65. package/.proagents/examples/mobile-react-native/workflow-example.md +0 -723
  66. package/.proagents/examples/web-frontend-react/README.md +0 -125
  67. package/.proagents/examples/web-frontend-react/complete-conversation.md +0 -556
  68. package/.proagents/examples/web-frontend-react/proagents.config.yaml +0 -183
  69. package/.proagents/examples/web-frontend-react/workflow-example.md +0 -603
  70. package/.proagents/existing-projects/README.md +0 -65
  71. package/.proagents/existing-projects/challenges.md +0 -861
  72. package/.proagents/existing-projects/coexistence-mode.md +0 -483
  73. package/.proagents/existing-projects/compatibility-assessment.md +0 -541
  74. package/.proagents/existing-projects/gradual-adoption.md +0 -515
  75. package/.proagents/existing-projects/migration-strategies.md +0 -788
  76. package/.proagents/existing-projects/pattern-reconciliation.md +0 -489
  77. package/.proagents/existing-projects/team-onboarding.md +0 -617
  78. package/.proagents/existing-projects/technical-debt-handling.md +0 -644
  79. package/.proagents/feature-flags/README.md +0 -263
  80. package/.proagents/feature-flags/ab-testing.md +0 -413
  81. package/.proagents/feature-flags/configuration.md +0 -420
  82. package/.proagents/feature-flags/kill-switches.md +0 -444
  83. package/.proagents/feature-flags/rollout-strategies.md +0 -392
  84. package/.proagents/history.log +0 -12
  85. package/.proagents/i18n/README.md +0 -133
  86. package/.proagents/i18n/extraction.md +0 -433
  87. package/.proagents/i18n/tms-integration.md +0 -332
  88. package/.proagents/i18n/translation-workflow.md +0 -413
  89. package/.proagents/i18n/validation.md +0 -355
  90. package/.proagents/logging/README.md +0 -276
  91. package/.proagents/logging/aggregation.md +0 -475
  92. package/.proagents/logging/log-levels.md +0 -376
  93. package/.proagents/logging/sensitive-data.md +0 -423
  94. package/.proagents/logging/structured-logging.md +0 -406
  95. package/.proagents/metrics/README.md +0 -69
  96. package/.proagents/metrics/code-quality-kpis.md +0 -461
  97. package/.proagents/metrics/deployment-metrics.md +0 -517
  98. package/.proagents/metrics/developer-productivity.md +0 -368
  99. package/.proagents/metrics/learning-effectiveness.md +0 -478
  100. package/.proagents/migrations/README.md +0 -77
  101. package/.proagents/migrations/from-claude-projects.md +0 -313
  102. package/.proagents/migrations/from-cursor-rules.md +0 -345
  103. package/.proagents/migrations/from-custom-workflows.md +0 -410
  104. package/.proagents/monitoring/README.md +0 -308
  105. package/.proagents/monitoring/alerting.md +0 -449
  106. package/.proagents/monitoring/dashboards.md +0 -454
  107. package/.proagents/monitoring/health-checks.md +0 -436
  108. package/.proagents/monitoring/metrics.md +0 -434
  109. package/.proagents/multi-project/README.md +0 -170
  110. package/.proagents/multi-project/coordinated-deploy.md +0 -510
  111. package/.proagents/multi-project/cross-project-deps.md +0 -395
  112. package/.proagents/multi-project/unified-changelog.md +0 -477
  113. package/.proagents/multi-project/walkthroughs/monorepo-setup.md +0 -787
  114. package/.proagents/multi-project/workspace-config.md +0 -408
  115. package/.proagents/notifications/README.md +0 -151
  116. package/.proagents/notifications/channels.md +0 -457
  117. package/.proagents/notifications/preferences.md +0 -415
  118. package/.proagents/notifications/routing.md +0 -449
  119. package/.proagents/notifications/scheduling.md +0 -425
  120. package/.proagents/notifications/templates.md +0 -446
  121. package/.proagents/offline-mode/README.md +0 -145
  122. package/.proagents/offline-mode/caching.md +0 -344
  123. package/.proagents/offline-mode/offline-operations.md +0 -312
  124. package/.proagents/offline-mode/queue-specifications.md +0 -679
  125. package/.proagents/offline-mode/sync.md +0 -475
  126. package/.proagents/parallel-features/README.md +0 -85
  127. package/.proagents/parallel-features/conflict-detection.md +0 -226
  128. package/.proagents/parallel-features/dependency-management.md +0 -392
  129. package/.proagents/parallel-features/merge-coordination.md +0 -506
  130. package/.proagents/parallel-features/tracking-system.md +0 -416
  131. package/.proagents/performance/README.md +0 -59
  132. package/.proagents/performance/bundle-analysis.md +0 -375
  133. package/.proagents/performance/load-testing.md +0 -563
  134. package/.proagents/performance/runtime-metrics.md +0 -489
  135. package/.proagents/performance/web-vitals.md +0 -425
  136. package/.proagents/plugins/README.md +0 -139
  137. package/.proagents/plugins/creating-plugins.md +0 -504
  138. package/.proagents/plugins/plugin-api.md +0 -467
  139. package/.proagents/plugins/plugin-registry.md +0 -276
  140. package/.proagents/reporting/README.md +0 -158
  141. package/.proagents/reporting/dashboards.md +0 -366
  142. package/.proagents/reporting/exports.md +0 -524
  143. package/.proagents/reporting/quality-metrics.md +0 -385
  144. package/.proagents/reporting/templates/README.md +0 -56
  145. package/.proagents/reporting/templates/dashboard-config.json +0 -187
  146. package/.proagents/reporting/templates/metrics-queries.md +0 -427
  147. package/.proagents/reporting/templates/react-dashboard.tsx +0 -544
  148. package/.proagents/reporting/templates/widgets.md +0 -451
  149. package/.proagents/reporting/velocity-metrics.md +0 -340
  150. package/.proagents/reverse-engineering/README.md +0 -151
  151. package/.proagents/reverse-engineering/architecture-extraction.md +0 -325
  152. package/.proagents/reverse-engineering/code-analysis.md +0 -377
  153. package/.proagents/reverse-engineering/dependency-mapping.md +0 -567
  154. package/.proagents/reverse-engineering/diagram-generation.md +0 -586
  155. package/.proagents/reverse-engineering/documentation-generation.md +0 -468
  156. package/.proagents/reverse-engineering/pattern-detection.md +0 -569
  157. package/.proagents/reverse-engineering/quality-assessment.md +0 -733
  158. package/.proagents/secrets/README.md +0 -278
  159. package/.proagents/secrets/access-control.md +0 -443
  160. package/.proagents/secrets/rotation.md +0 -403
  161. package/.proagents/secrets/scanning.md +0 -487
  162. package/.proagents/secrets/storage.md +0 -394
  163. package/.proagents/webhooks/README.md +0 -126
  164. package/.proagents/webhooks/endpoints.md +0 -298
  165. package/.proagents/webhooks/events.md +0 -316
  166. package/.proagents/webhooks/payloads.md +0 -325
  167. package/.proagents/webhooks/reliability.md +0 -363
  168. package/.proagents/webhooks/security.md +0 -380
@@ -1,825 +0,0 @@
1
- # Complete Conversation: React Native Notification Settings
2
-
3
- A full walkthrough of building a notification settings screen in a React Native application.
4
-
5
- ---
6
-
7
- ## Feature Request
8
-
9
- **User:** I need to add a notification settings screen where users can control push notifications, in-app alerts, and notification sounds. It should work on both iOS and Android.
10
-
11
- ---
12
-
13
- ## Phase 0: Initialization
14
-
15
- **AI:** I'll help you build a notification settings feature for your React Native app. Let me analyze your codebase first.
16
-
17
- ```
18
- Starting ProAgents workflow...
19
- Mode: Full Workflow
20
- Feature: Notification Settings Screen
21
- Branch: feature/notification-settings
22
- Platform: iOS + Android
23
- ```
24
-
25
- ---
26
-
27
- ## Phase 1: Codebase Analysis
28
-
29
- **AI:** I've analyzed your React Native project. Here's what I found:
30
-
31
- ### Project Structure
32
- ```
33
- src/
34
- ├── screens/
35
- │ ├── HomeScreen.tsx
36
- │ ├── ProfileScreen.tsx
37
- │ └── SettingsScreen.tsx
38
- ├── components/
39
- │ ├── ui/
40
- │ │ ├── Button.tsx
41
- │ │ ├── Switch.tsx
42
- │ │ └── Card.tsx
43
- │ └── common/
44
- ├── navigation/
45
- │ ├── RootNavigator.tsx
46
- │ └── types.ts
47
- ├── hooks/
48
- │ ├── useAuth.ts
49
- │ └── useStorage.ts
50
- ├── services/
51
- │ ├── api.ts
52
- │ └── notifications.ts
53
- ├── stores/
54
- │ └── userStore.ts
55
- └── utils/
56
- └── platform.ts
57
- ```
58
-
59
- ### Patterns Detected
60
- - **Framework:** React Native 0.72 (Expo managed)
61
- - **Navigation:** React Navigation 6
62
- - **State:** Zustand for global state
63
- - **Storage:** AsyncStorage for persistence
64
- - **Styling:** StyleSheet with custom theme
65
- - **Testing:** Jest + React Native Testing Library
66
-
67
- ### Existing Conventions
68
- - Functional components with TypeScript
69
- - Custom hooks for reusable logic
70
- - Platform-specific code uses `Platform.select()`
71
- - All screens follow consistent layout pattern
72
-
73
- **Checkpoint: Analysis Complete**
74
- Proceed with these patterns? [Yes/Modify]
75
-
76
- **User:** Yes, proceed.
77
-
78
- ---
79
-
80
- ## Phase 2: Requirements
81
-
82
- **AI:** Let me clarify the notification settings requirements.
83
-
84
- ### Feature Requirements
85
-
86
- **1. Push Notifications**
87
- - Master toggle for all push notifications
88
- - Category toggles (messages, updates, promotions)
89
- - Quiet hours configuration
90
-
91
- **2. In-App Alerts**
92
- - Badge count toggle
93
- - In-app banner toggle
94
- - Vibration toggle
95
-
96
- **3. Sound Settings**
97
- - Notification sound toggle
98
- - Sound selection (platform native picker)
99
- - Volume control
100
-
101
- **4. Platform Considerations**
102
- - iOS: Request notification permissions
103
- - Android: Channel management
104
- - Both: Deep link to system settings
105
-
106
- ### Technical Requirements
107
- - Persist settings locally with AsyncStorage
108
- - Sync settings with backend API
109
- - Handle permission states gracefully
110
- - Support offline mode
111
-
112
- **User:** Perfect, that covers everything I need.
113
-
114
- ---
115
-
116
- ## Phase 3: Design
117
-
118
- **AI:** Based on your existing UI patterns, here's the design:
119
-
120
- ### Screen Layout
121
- ```
122
- ┌─────────────────────────────┐
123
- │ ← Notification Settings │
124
- ├─────────────────────────────┤
125
- │ │
126
- │ ┌─────────────────────────┐ │
127
- │ │ Push Notifications │ │
128
- │ │ ─────────────────────── │ │
129
- │ │ Enable All [===] │ │
130
- │ │ Messages [===] │ │
131
- │ │ Updates [===] │ │
132
- │ │ Promotions [ = ] │ │
133
- │ └─────────────────────────┘ │
134
- │ │
135
- │ ┌─────────────────────────┐ │
136
- │ │ In-App Alerts │ │
137
- │ │ ─────────────────────── │ │
138
- │ │ Show Badges [===] │ │
139
- │ │ Show Banners [===] │ │
140
- │ │ Vibration [===] │ │
141
- │ └─────────────────────────┘ │
142
- │ │
143
- │ ┌─────────────────────────┐ │
144
- │ │ Sounds │ │
145
- │ │ ─────────────────────── │ │
146
- │ │ Enable Sound [===] │ │
147
- │ │ Sound: Default [>] │ │
148
- │ └─────────────────────────┘ │
149
- │ │
150
- │ [Open System Settings] │
151
- │ │
152
- └─────────────────────────────┘
153
- ```
154
-
155
- ### Component Hierarchy
156
- ```tsx
157
- <NotificationSettingsScreen>
158
- <ScrollView>
159
- <SettingsSection title="Push Notifications">
160
- <SettingsToggle />
161
- <SettingsToggle />
162
- </SettingsSection>
163
- <SettingsSection title="In-App Alerts">
164
- <SettingsToggle />
165
- </SettingsSection>
166
- <SettingsSection title="Sounds">
167
- <SettingsToggle />
168
- <SettingsLink />
169
- </SettingsSection>
170
- <SystemSettingsButton />
171
- </ScrollView>
172
- </NotificationSettingsScreen>
173
- ```
174
-
175
- **Checkpoint: Design Complete**
176
- Ready to implement? [Yes/Modify]
177
-
178
- **User:** Yes.
179
-
180
- ---
181
-
182
- ## Phase 4: Implementation Plan
183
-
184
- **AI:** Here's the implementation plan:
185
-
186
- ### Files to Create
187
- 1. `src/screens/NotificationSettingsScreen.tsx`
188
- 2. `src/components/settings/SettingsSection.tsx`
189
- 3. `src/components/settings/SettingsToggle.tsx`
190
- 4. `src/components/settings/SettingsLink.tsx`
191
- 5. `src/hooks/useNotificationSettings.ts`
192
- 6. `src/services/notificationSettings.ts`
193
- 7. `src/types/notifications.ts`
194
- 8. `__tests__/screens/NotificationSettingsScreen.test.tsx`
195
- 9. `__tests__/hooks/useNotificationSettings.test.ts`
196
-
197
- ### Files to Modify
198
- 1. `src/navigation/RootNavigator.tsx` - Add new screen
199
- 2. `src/navigation/types.ts` - Add route types
200
- 3. `src/screens/SettingsScreen.tsx` - Add navigation link
201
-
202
- ### Implementation Order
203
- 1. Types and interfaces
204
- 2. Service layer (API + storage)
205
- 3. Custom hook
206
- 4. UI components
207
- 5. Main screen
208
- 6. Navigation integration
209
- 7. Tests
210
-
211
- ---
212
-
213
- ## Phase 5: Implementation
214
-
215
- **AI:** Starting implementation.
216
-
217
- ### Step 1: Types
218
-
219
- ```typescript
220
- // src/types/notifications.ts
221
- export interface NotificationSettings {
222
- // Push notifications
223
- pushEnabled: boolean;
224
- pushMessages: boolean;
225
- pushUpdates: boolean;
226
- pushPromotions: boolean;
227
-
228
- // In-app
229
- showBadges: boolean;
230
- showBanners: boolean;
231
- vibrationEnabled: boolean;
232
-
233
- // Sounds
234
- soundEnabled: boolean;
235
- soundName: string;
236
- }
237
-
238
- export const defaultNotificationSettings: NotificationSettings = {
239
- pushEnabled: true,
240
- pushMessages: true,
241
- pushUpdates: true,
242
- pushPromotions: false,
243
- showBadges: true,
244
- showBanners: true,
245
- vibrationEnabled: true,
246
- soundEnabled: true,
247
- soundName: 'default',
248
- };
249
- ```
250
-
251
- ### Step 2: Service Layer
252
-
253
- ```typescript
254
- // src/services/notificationSettings.ts
255
- import AsyncStorage from '@react-native-async-storage/async-storage';
256
- import { NotificationSettings, defaultNotificationSettings } from '@/types/notifications';
257
- import { api } from './api';
258
-
259
- const STORAGE_KEY = '@notification_settings';
260
-
261
- export const notificationSettingsService = {
262
- async getLocal(): Promise<NotificationSettings> {
263
- try {
264
- const stored = await AsyncStorage.getItem(STORAGE_KEY);
265
- if (stored) {
266
- return { ...defaultNotificationSettings, ...JSON.parse(stored) };
267
- }
268
- return defaultNotificationSettings;
269
- } catch (error) {
270
- console.error('Failed to get notification settings:', error);
271
- return defaultNotificationSettings;
272
- }
273
- },
274
-
275
- async saveLocal(settings: NotificationSettings): Promise<void> {
276
- try {
277
- await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
278
- } catch (error) {
279
- console.error('Failed to save notification settings:', error);
280
- throw error;
281
- }
282
- },
283
-
284
- async syncWithServer(settings: NotificationSettings): Promise<void> {
285
- try {
286
- await api.patch('/user/notification-settings', settings);
287
- } catch (error) {
288
- console.error('Failed to sync with server:', error);
289
- // Don't throw - offline support
290
- }
291
- },
292
-
293
- async fetchFromServer(): Promise<NotificationSettings | null> {
294
- try {
295
- const response = await api.get('/user/notification-settings');
296
- return response.data;
297
- } catch (error) {
298
- console.error('Failed to fetch from server:', error);
299
- return null;
300
- }
301
- },
302
- };
303
- ```
304
-
305
- ### Step 3: Custom Hook
306
-
307
- ```typescript
308
- // src/hooks/useNotificationSettings.ts
309
- import { useState, useEffect, useCallback } from 'react';
310
- import { Platform, Linking } from 'react-native';
311
- import * as Notifications from 'expo-notifications';
312
- import { NotificationSettings, defaultNotificationSettings } from '@/types/notifications';
313
- import { notificationSettingsService } from '@/services/notificationSettings';
314
-
315
- export function useNotificationSettings() {
316
- const [settings, setSettings] = useState<NotificationSettings>(defaultNotificationSettings);
317
- const [loading, setLoading] = useState(true);
318
- const [permissionStatus, setPermissionStatus] = useState<string>('undetermined');
319
-
320
- // Load settings on mount
321
- useEffect(() => {
322
- loadSettings();
323
- checkPermissions();
324
- }, []);
325
-
326
- const loadSettings = async () => {
327
- setLoading(true);
328
- try {
329
- // Try server first, fall back to local
330
- const serverSettings = await notificationSettingsService.fetchFromServer();
331
- if (serverSettings) {
332
- setSettings(serverSettings);
333
- await notificationSettingsService.saveLocal(serverSettings);
334
- } else {
335
- const localSettings = await notificationSettingsService.getLocal();
336
- setSettings(localSettings);
337
- }
338
- } finally {
339
- setLoading(false);
340
- }
341
- };
342
-
343
- const checkPermissions = async () => {
344
- const { status } = await Notifications.getPermissionsAsync();
345
- setPermissionStatus(status);
346
- };
347
-
348
- const requestPermissions = async () => {
349
- const { status } = await Notifications.requestPermissionsAsync();
350
- setPermissionStatus(status);
351
- return status === 'granted';
352
- };
353
-
354
- const updateSetting = useCallback(async <K extends keyof NotificationSettings>(
355
- key: K,
356
- value: NotificationSettings[K]
357
- ) => {
358
- const newSettings = { ...settings, [key]: value };
359
- setSettings(newSettings);
360
-
361
- // Save locally immediately
362
- await notificationSettingsService.saveLocal(newSettings);
363
-
364
- // Sync with server in background
365
- notificationSettingsService.syncWithServer(newSettings);
366
- }, [settings]);
367
-
368
- const openSystemSettings = useCallback(() => {
369
- if (Platform.OS === 'ios') {
370
- Linking.openURL('app-settings:');
371
- } else {
372
- Linking.openSettings();
373
- }
374
- }, []);
375
-
376
- return {
377
- settings,
378
- loading,
379
- permissionStatus,
380
- updateSetting,
381
- requestPermissions,
382
- openSystemSettings,
383
- refresh: loadSettings,
384
- };
385
- }
386
- ```
387
-
388
- ### Step 4: UI Components
389
-
390
- ```tsx
391
- // src/components/settings/SettingsSection.tsx
392
- import React from 'react';
393
- import { View, Text, StyleSheet } from 'react-native';
394
-
395
- interface SettingsSectionProps {
396
- title: string;
397
- children: React.ReactNode;
398
- }
399
-
400
- export function SettingsSection({ title, children }: SettingsSectionProps) {
401
- return (
402
- <View style={styles.container}>
403
- <Text style={styles.title}>{title}</Text>
404
- <View style={styles.content}>{children}</View>
405
- </View>
406
- );
407
- }
408
-
409
- const styles = StyleSheet.create({
410
- container: {
411
- marginBottom: 24,
412
- },
413
- title: {
414
- fontSize: 14,
415
- fontWeight: '600',
416
- color: '#666',
417
- marginBottom: 8,
418
- paddingHorizontal: 16,
419
- textTransform: 'uppercase',
420
- },
421
- content: {
422
- backgroundColor: '#fff',
423
- borderRadius: 12,
424
- overflow: 'hidden',
425
- },
426
- });
427
- ```
428
-
429
- ```tsx
430
- // src/components/settings/SettingsToggle.tsx
431
- import React from 'react';
432
- import { View, Text, Switch, StyleSheet } from 'react-native';
433
-
434
- interface SettingsToggleProps {
435
- label: string;
436
- description?: string;
437
- value: boolean;
438
- onValueChange: (value: boolean) => void;
439
- disabled?: boolean;
440
- }
441
-
442
- export function SettingsToggle({
443
- label,
444
- description,
445
- value,
446
- onValueChange,
447
- disabled = false,
448
- }: SettingsToggleProps) {
449
- return (
450
- <View style={[styles.container, disabled && styles.disabled]}>
451
- <View style={styles.textContainer}>
452
- <Text style={styles.label}>{label}</Text>
453
- {description && <Text style={styles.description}>{description}</Text>}
454
- </View>
455
- <Switch
456
- value={value}
457
- onValueChange={onValueChange}
458
- disabled={disabled}
459
- trackColor={{ false: '#e0e0e0', true: '#4CAF50' }}
460
- thumbColor="#fff"
461
- />
462
- </View>
463
- );
464
- }
465
-
466
- const styles = StyleSheet.create({
467
- container: {
468
- flexDirection: 'row',
469
- alignItems: 'center',
470
- justifyContent: 'space-between',
471
- padding: 16,
472
- borderBottomWidth: StyleSheet.hairlineWidth,
473
- borderBottomColor: '#e0e0e0',
474
- },
475
- disabled: {
476
- opacity: 0.5,
477
- },
478
- textContainer: {
479
- flex: 1,
480
- marginRight: 16,
481
- },
482
- label: {
483
- fontSize: 16,
484
- color: '#333',
485
- },
486
- description: {
487
- fontSize: 13,
488
- color: '#666',
489
- marginTop: 2,
490
- },
491
- });
492
- ```
493
-
494
- ### Step 5: Main Screen
495
-
496
- ```tsx
497
- // src/screens/NotificationSettingsScreen.tsx
498
- import React from 'react';
499
- import { ScrollView, StyleSheet, Alert } from 'react-native';
500
- import { SettingsSection } from '@/components/settings/SettingsSection';
501
- import { SettingsToggle } from '@/components/settings/SettingsToggle';
502
- import { SettingsLink } from '@/components/settings/SettingsLink';
503
- import { Button } from '@/components/ui/Button';
504
- import { useNotificationSettings } from '@/hooks/useNotificationSettings';
505
- import { LoadingScreen } from '@/components/common/LoadingScreen';
506
-
507
- export function NotificationSettingsScreen() {
508
- const {
509
- settings,
510
- loading,
511
- permissionStatus,
512
- updateSetting,
513
- requestPermissions,
514
- openSystemSettings,
515
- } = useNotificationSettings();
516
-
517
- if (loading) {
518
- return <LoadingScreen />;
519
- }
520
-
521
- const handlePushToggle = async (value: boolean) => {
522
- if (value && permissionStatus !== 'granted') {
523
- const granted = await requestPermissions();
524
- if (!granted) {
525
- Alert.alert(
526
- 'Permission Required',
527
- 'Please enable notifications in your device settings.',
528
- [
529
- { text: 'Cancel', style: 'cancel' },
530
- { text: 'Open Settings', onPress: openSystemSettings },
531
- ]
532
- );
533
- return;
534
- }
535
- }
536
- updateSetting('pushEnabled', value);
537
- };
538
-
539
- return (
540
- <ScrollView style={styles.container}>
541
- <SettingsSection title="Push Notifications">
542
- <SettingsToggle
543
- label="Enable Push Notifications"
544
- description="Receive notifications when the app is closed"
545
- value={settings.pushEnabled}
546
- onValueChange={handlePushToggle}
547
- />
548
- <SettingsToggle
549
- label="Messages"
550
- description="New messages and replies"
551
- value={settings.pushMessages}
552
- onValueChange={(v) => updateSetting('pushMessages', v)}
553
- disabled={!settings.pushEnabled}
554
- />
555
- <SettingsToggle
556
- label="Updates"
557
- description="App updates and new features"
558
- value={settings.pushUpdates}
559
- onValueChange={(v) => updateSetting('pushUpdates', v)}
560
- disabled={!settings.pushEnabled}
561
- />
562
- <SettingsToggle
563
- label="Promotions"
564
- description="Special offers and discounts"
565
- value={settings.pushPromotions}
566
- onValueChange={(v) => updateSetting('pushPromotions', v)}
567
- disabled={!settings.pushEnabled}
568
- />
569
- </SettingsSection>
570
-
571
- <SettingsSection title="In-App Alerts">
572
- <SettingsToggle
573
- label="Show Badge Count"
574
- description="Display unread count on app icon"
575
- value={settings.showBadges}
576
- onValueChange={(v) => updateSetting('showBadges', v)}
577
- />
578
- <SettingsToggle
579
- label="Show Banners"
580
- description="Display in-app notification banners"
581
- value={settings.showBanners}
582
- onValueChange={(v) => updateSetting('showBanners', v)}
583
- />
584
- <SettingsToggle
585
- label="Vibration"
586
- description="Vibrate on notifications"
587
- value={settings.vibrationEnabled}
588
- onValueChange={(v) => updateSetting('vibrationEnabled', v)}
589
- />
590
- </SettingsSection>
591
-
592
- <SettingsSection title="Sounds">
593
- <SettingsToggle
594
- label="Notification Sound"
595
- description="Play sound for notifications"
596
- value={settings.soundEnabled}
597
- onValueChange={(v) => updateSetting('soundEnabled', v)}
598
- />
599
- <SettingsLink
600
- label="Sound"
601
- value={settings.soundName}
602
- onPress={() => {/* Open sound picker */}}
603
- disabled={!settings.soundEnabled}
604
- />
605
- </SettingsSection>
606
-
607
- <Button
608
- title="Open System Settings"
609
- variant="outline"
610
- onPress={openSystemSettings}
611
- style={styles.systemButton}
612
- />
613
- </ScrollView>
614
- );
615
- }
616
-
617
- const styles = StyleSheet.create({
618
- container: {
619
- flex: 1,
620
- backgroundColor: '#f5f5f5',
621
- padding: 16,
622
- },
623
- systemButton: {
624
- marginTop: 8,
625
- marginBottom: 32,
626
- },
627
- });
628
- ```
629
-
630
- ---
631
-
632
- ## Phase 6: Testing
633
-
634
- **AI:** Creating comprehensive tests.
635
-
636
- ### Hook Tests
637
-
638
- ```typescript
639
- // __tests__/hooks/useNotificationSettings.test.ts
640
- import { renderHook, act, waitFor } from '@testing-library/react-native';
641
- import { useNotificationSettings } from '@/hooks/useNotificationSettings';
642
- import { notificationSettingsService } from '@/services/notificationSettings';
643
-
644
- jest.mock('@/services/notificationSettings');
645
- jest.mock('expo-notifications', () => ({
646
- getPermissionsAsync: jest.fn().mockResolvedValue({ status: 'granted' }),
647
- requestPermissionsAsync: jest.fn().mockResolvedValue({ status: 'granted' }),
648
- }));
649
-
650
- describe('useNotificationSettings', () => {
651
- beforeEach(() => {
652
- jest.clearAllMocks();
653
- });
654
-
655
- it('loads settings on mount', async () => {
656
- const mockSettings = {
657
- pushEnabled: true,
658
- pushMessages: false,
659
- };
660
-
661
- (notificationSettingsService.fetchFromServer as jest.Mock)
662
- .mockResolvedValue(mockSettings);
663
-
664
- const { result } = renderHook(() => useNotificationSettings());
665
-
666
- await waitFor(() => {
667
- expect(result.current.loading).toBe(false);
668
- });
669
-
670
- expect(result.current.settings.pushMessages).toBe(false);
671
- });
672
-
673
- it('updates setting and saves locally', async () => {
674
- (notificationSettingsService.fetchFromServer as jest.Mock)
675
- .mockResolvedValue(null);
676
- (notificationSettingsService.getLocal as jest.Mock)
677
- .mockResolvedValue({ pushEnabled: true });
678
-
679
- const { result } = renderHook(() => useNotificationSettings());
680
-
681
- await waitFor(() => {
682
- expect(result.current.loading).toBe(false);
683
- });
684
-
685
- await act(async () => {
686
- await result.current.updateSetting('pushEnabled', false);
687
- });
688
-
689
- expect(notificationSettingsService.saveLocal).toHaveBeenCalledWith(
690
- expect.objectContaining({ pushEnabled: false })
691
- );
692
- });
693
- });
694
- ```
695
-
696
- ### Screen Tests
697
-
698
- ```typescript
699
- // __tests__/screens/NotificationSettingsScreen.test.tsx
700
- import React from 'react';
701
- import { render, fireEvent, waitFor } from '@testing-library/react-native';
702
- import { NotificationSettingsScreen } from '@/screens/NotificationSettingsScreen';
703
-
704
- jest.mock('@/hooks/useNotificationSettings', () => ({
705
- useNotificationSettings: () => ({
706
- settings: {
707
- pushEnabled: true,
708
- pushMessages: true,
709
- pushUpdates: true,
710
- pushPromotions: false,
711
- showBadges: true,
712
- showBanners: true,
713
- vibrationEnabled: true,
714
- soundEnabled: true,
715
- soundName: 'default',
716
- },
717
- loading: false,
718
- permissionStatus: 'granted',
719
- updateSetting: jest.fn(),
720
- requestPermissions: jest.fn(),
721
- openSystemSettings: jest.fn(),
722
- }),
723
- }));
724
-
725
- describe('NotificationSettingsScreen', () => {
726
- it('renders all settings sections', () => {
727
- const { getByText } = render(<NotificationSettingsScreen />);
728
-
729
- expect(getByText('Push Notifications')).toBeTruthy();
730
- expect(getByText('In-App Alerts')).toBeTruthy();
731
- expect(getByText('Sounds')).toBeTruthy();
732
- });
733
-
734
- it('disables child toggles when push is disabled', () => {
735
- // Test that Messages, Updates, Promotions toggles are disabled
736
- // when pushEnabled is false
737
- });
738
-
739
- it('handles permission request when enabling push', async () => {
740
- const mockRequestPermissions = jest.fn().mockResolvedValue(true);
741
-
742
- jest.mock('@/hooks/useNotificationSettings', () => ({
743
- useNotificationSettings: () => ({
744
- settings: { pushEnabled: false },
745
- permissionStatus: 'undetermined',
746
- requestPermissions: mockRequestPermissions,
747
- }),
748
- }));
749
-
750
- // Test permission flow
751
- });
752
- });
753
- ```
754
-
755
- **Test Results:**
756
- ```
757
- ✓ Hook tests: 8 passed
758
- ✓ Component tests: 12 passed
759
- ✓ Screen tests: 6 passed
760
- Coverage: 85%
761
- ```
762
-
763
- ---
764
-
765
- ## Phase 7: Documentation
766
-
767
- **AI:** Feature documentation created.
768
-
769
- ### Usage Guide
770
-
771
- ```markdown
772
- ## Notification Settings
773
-
774
- Navigate to Settings > Notifications to configure:
775
-
776
- ### Push Notifications
777
- Control which push notifications you receive:
778
- - Messages: New messages and replies
779
- - Updates: App updates and features
780
- - Promotions: Special offers (off by default)
781
-
782
- ### In-App Alerts
783
- - Badge Count: Show unread count on app icon
784
- - Banners: Show notification banners in-app
785
- - Vibration: Vibrate for notifications
786
-
787
- ### Sounds
788
- - Enable/disable notification sounds
789
- - Select custom notification sound
790
-
791
- ### System Settings
792
- Tap "Open System Settings" for advanced OS-level notification configuration.
793
- ```
794
-
795
- ---
796
-
797
- ## Phase 8: Deployment Preparation
798
-
799
- **AI:** Pre-deployment checklist:
800
-
801
- - [x] All tests passing
802
- - [x] iOS permissions handled
803
- - [x] Android channels configured
804
- - [x] Offline mode working
805
- - [x] Settings persist correctly
806
- - [x] Both platforms tested
807
-
808
- **Ready for deployment.**
809
-
810
- ---
811
-
812
- ## Summary
813
-
814
- **Feature Complete:** Notification Settings Screen
815
-
816
- **Files Created:** 9
817
- **Files Modified:** 3
818
- **Tests Added:** 26
819
- **Coverage:** 85%
820
-
821
- **Platforms Tested:**
822
- - iOS Simulator (iPhone 14)
823
- - Android Emulator (Pixel 6)
824
-
825
- **PR Ready:** `feature/notification-settings` → `main`