@umituz/react-native-settings 5.2.19 → 5.2.20

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 (46) hide show
  1. package/package.json +1 -1
  2. package/src/domains/about/presentation/hooks/useAboutInfo.ts +63 -98
  3. package/src/domains/feedback/presentation/components/SupportSection.tsx +2 -1
  4. package/src/domains/localization/infrastructure/hooks/useTranslation.ts +0 -3
  5. package/src/domains/localization/infrastructure/storage/LanguageInitializer.ts +0 -4
  6. package/src/domains/localization/infrastructure/storage/localizationStoreUtils.ts +6 -7
  7. package/src/domains/localization/presentation/components/LanguageItem.tsx +0 -2
  8. package/src/domains/localization/presentation/providers/LocalizationManager.tsx +2 -1
  9. package/src/domains/notifications/index.ts +7 -6
  10. package/src/domains/notifications/infrastructure/services/NotificationBadgeManager.ts +1 -1
  11. package/src/domains/notifications/infrastructure/services/NotificationManager.ts +1 -1
  12. package/src/domains/notifications/infrastructure/services/NotificationPermissions.ts +1 -1
  13. package/src/domains/notifications/infrastructure/storage/UnifiedNotificationStore.ts +223 -0
  14. package/src/domains/notifications/presentation/hooks/useNotificationSettingsUI.ts +2 -2
  15. package/src/domains/notifications/presentation/screens/NotificationSettingsScreen.tsx +1 -1
  16. package/src/domains/notifications/quietHours/infrastructure/hooks/useQuietHoursActions.ts +6 -6
  17. package/src/domains/notifications/reminders/infrastructure/hooks/useReminderActions.ts +5 -5
  18. package/src/domains/notifications/reminders/presentation/screens/ReminderListScreen.tsx +1 -1
  19. package/src/domains/rating/presentation/hooks/useAppRating.tsx +2 -1
  20. package/src/infrastructure/storage/storeConfig.ts +114 -0
  21. package/src/infrastructure/utils/async/core.ts +3 -2
  22. package/src/infrastructure/utils/errorHandlers.ts +4 -2
  23. package/src/infrastructure/utils/index.ts +1 -1
  24. package/src/presentation/components/SettingsNavigationItem.tsx +109 -0
  25. package/src/presentation/navigation/utils/index.ts +8 -1
  26. package/src/presentation/navigation/utils/navigationHelpers.ts +118 -0
  27. package/src/presentation/screens/components/SettingsContent.tsx +21 -11
  28. package/src/presentation/screens/components/sections/SupportSettingsSection.tsx +4 -2
  29. package/src/presentation/screens/types/UserFeatureConfig.ts +5 -4
  30. package/src/presentation/utils/config-creators/feature-configs.ts +3 -2
  31. package/src/presentation/utils/settingsConfigFactory.ts +2 -1
  32. package/src/utils/appUtils.ts +0 -6
  33. package/src/utils/errorUtils.ts +54 -0
  34. package/src/utils/hooks/index.ts +6 -0
  35. package/src/utils/hooks/useAsyncStateUpdate.ts +114 -0
  36. package/src/utils/hooks/useMountSafety.ts +30 -0
  37. package/src/utils/index.ts +2 -0
  38. package/src/domains/about/presentation/hooks/useAboutInfo.utils.ts +0 -167
  39. package/src/domains/notifications/infrastructure/storage/NotificationsStore.ts +0 -45
  40. package/src/domains/notifications/infrastructure/utils/dev.ts +0 -22
  41. package/src/domains/notifications/reminders/infrastructure/storage/RemindersStore.ts +0 -152
  42. package/src/infrastructure/utils/styleUtils.ts +0 -7
  43. package/src/presentation/screens/components/GamificationSettingsItem.tsx +0 -55
  44. package/src/presentation/screens/components/SubscriptionSettingsItem.tsx +0 -38
  45. package/src/presentation/screens/components/VideoTutorialSettingsItem.tsx +0 -51
  46. package/src/presentation/screens/components/WalletSettingsItem.tsx +0 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-settings",
3
- "version": "5.2.19",
3
+ "version": "5.2.20",
4
4
  "description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -1,135 +1,103 @@
1
1
  /**
2
2
  * Hook for managing About information
3
3
  * Provides reactive state management for About data
4
- * Optimized for performance and memory safety
4
+ * Refactored to use useAsyncStateUpdate for clean async state management
5
5
  */
6
6
  import { useState, useCallback, useRef, useEffect } from 'react';
7
7
  import type { AppInfo, AboutConfig } from '../../domain/entities/AppInfo';
8
8
  import { AboutRepository } from '../../infrastructure/repositories/AboutRepository';
9
+ import { useAsyncStateUpdate } from '../../../../utils/hooks/useAsyncStateUpdate';
10
+ import { createDefaultAppInfo } from '../../utils/AppInfoFactory';
9
11
  import type { UseAboutInfoOptions, UseAboutInfoReturn } from './useAboutInfo.types';
10
- import {
11
- setErrorIfMounted,
12
- initializeAppInfo,
13
- updateAppInfoConfig,
14
- updateAppInfoPartial,
15
- refreshAppInfo,
16
- } from './useAboutInfo.utils';
17
12
 
18
13
  export const useAboutInfo = (
19
14
  options: UseAboutInfoOptions = {}
20
15
  ): UseAboutInfoReturn => {
21
16
  const { initialConfig, autoInit } = options;
22
17
  const [repository] = useState(() => new AboutRepository());
23
- const [appInfo, setAppInfo] = useState<AppInfo | null>(null);
24
- const [loading, setLoading] = useState(false);
25
- const [error, setError] = useState<string | null>(null);
26
-
27
18
  const isInitializedRef = useRef(false);
28
- const isMountedRef = useRef(true);
29
19
 
20
+ // Use the new useAsyncStateUpdate hook for clean async state management
21
+ const { data: appInfo, loading, error, execute, setData: setAppInfo, setError } = useAsyncStateUpdate<AppInfo>({
22
+ initialData: null,
23
+ });
24
+
25
+ /**
26
+ * Initialize app info with config
27
+ */
30
28
  const initialize = useCallback(
31
- (config: AboutConfig) => initializeAppInfo(
32
- config,
33
- repository,
34
- isMountedRef,
35
- isInitializedRef,
36
- setAppInfo,
37
- setError,
38
- setLoading
39
- ),
40
- [repository]
29
+ async (config: AboutConfig) => {
30
+ if (isInitializedRef.current) {
31
+ return;
32
+ }
33
+
34
+ await execute(async () => {
35
+ const defaultAppInfo = createDefaultAppInfo(config);
36
+ await repository.saveAppInfo(defaultAppInfo);
37
+ isInitializedRef.current = true;
38
+ return defaultAppInfo;
39
+ });
40
+ },
41
+ [repository, execute]
41
42
  );
42
43
 
44
+ /**
45
+ * Update app info with new config
46
+ */
43
47
  const update = useCallback(
44
- (config: AboutConfig) => updateAppInfoConfig(
45
- config,
46
- repository,
47
- isMountedRef,
48
- setAppInfo,
49
- setError,
50
- setLoading
51
- ),
52
- [repository]
48
+ async (config: AboutConfig) => {
49
+ await execute(async () => {
50
+ const updatedAppInfo = createDefaultAppInfo(config);
51
+ await repository.saveAppInfo(updatedAppInfo);
52
+ return updatedAppInfo;
53
+ });
54
+ },
55
+ [repository, execute]
53
56
  );
54
57
 
58
+ /**
59
+ * Update app info with partial updates
60
+ */
55
61
  const updateAppInfoCallback = useCallback(
56
- (updates: Partial<AppInfo>) => {
62
+ async (updates: Partial<AppInfo>) => {
57
63
  if (!appInfo) {
58
- setErrorIfMounted(isMountedRef, setError, 'App info not initialized');
59
- return Promise.resolve();
64
+ setError('App info not initialized');
65
+ return;
60
66
  }
61
- return updateAppInfoPartial(
62
- updates,
63
- repository,
64
- isMountedRef,
65
- setAppInfo,
66
- setError,
67
- setLoading
68
- );
67
+
68
+ await execute(async () => {
69
+ return await repository.updateAppInfo(updates);
70
+ });
69
71
  },
70
- [repository, appInfo]
72
+ [repository, appInfo, execute, setError]
71
73
  );
72
74
 
75
+ /**
76
+ * Refresh app info from repository
77
+ */
73
78
  const refresh = useCallback(
74
- () => refreshAppInfo(
75
- repository,
76
- isMountedRef,
77
- setAppInfo,
78
- setError,
79
- setLoading
80
- ),
81
- [repository]
79
+ async () => {
80
+ await execute(async () => {
81
+ return await repository.getAppInfo();
82
+ });
83
+ },
84
+ [repository, execute]
82
85
  );
83
86
 
87
+ /**
88
+ * Reset to initial state
89
+ */
84
90
  const reset = useCallback(() => {
85
- if (!isMountedRef.current) {
86
- return;
87
- }
88
-
89
91
  setAppInfo(null);
90
92
  setError(null);
91
- setLoading(false);
92
93
  isInitializedRef.current = false;
93
- }, []);
94
-
95
- // Cleanup on unmount
96
- useEffect(() => {
97
- return () => {
98
- isMountedRef.current = false;
99
-
100
- if (repository && typeof repository.destroy === 'function') {
101
- try {
102
- repository.destroy();
103
- } catch (error) {
104
- // Log cleanup error but don't throw
105
- }
106
- }
107
- };
108
- }, [repository]);
94
+ }, [setAppInfo, setError]);
109
95
 
110
- // Initialize with default config if provided
96
+ /**
97
+ * Auto-initialize if config provided
98
+ */
111
99
  useEffect(() => {
112
- if (
113
- initialConfig &&
114
- autoInit !== false &&
115
- isMountedRef.current &&
116
- !isInitializedRef.current
117
- ) {
118
- // Dynamic import to avoid require issues
119
- import('../../utils/AppInfoFactory').then(({ createDefaultAppInfo }) => {
120
- if (isMountedRef.current) {
121
- const defaultAppInfo = createDefaultAppInfo(initialConfig);
122
- setAppInfo(defaultAppInfo);
123
- isInitializedRef.current = true;
124
- }
125
- }).catch((_error) => {
126
- });
127
- }
128
- }, [initialConfig, autoInit]);
129
-
130
- // Auto-initialize if autoInit is true
131
- useEffect(() => {
132
- if (autoInit === true && initialConfig && isMountedRef.current) {
100
+ if (autoInit && initialConfig && !isInitializedRef.current) {
133
101
  initialize(initialConfig);
134
102
  }
135
103
  }, [autoInit, initialConfig, initialize]);
@@ -145,6 +113,3 @@ export const useAboutInfo = (
145
113
  reset,
146
114
  };
147
115
  };
148
-
149
- // Re-export types for convenience
150
- export type { UseAboutInfoOptions, UseAboutInfoReturn } from './useAboutInfo.types';
@@ -8,6 +8,7 @@ import React, { useState, useCallback } from "react";
8
8
  import { Linking } from "react-native";
9
9
  import { FeedbackModal } from "./FeedbackModal";
10
10
  import type { FeedbackType } from "../../domain/entities/FeedbackEntity";
11
+ import { isDev } from "../../../../utils/devUtils";
11
12
 
12
13
  export interface FeedbackConfig {
13
14
  enabled?: boolean;
@@ -75,7 +76,7 @@ export const SupportSection: React.FC<SupportSectionProps> = ({
75
76
  setModalVisible(false);
76
77
  } catch (error) {
77
78
  // If the passed onSubmit throws, we log it.
78
- if (__DEV__) {
79
+ if (isDev()) {
79
80
  console.error('[SupportSection] Failed to submit feedback:', error);
80
81
  }
81
82
  // Optionally keep modal open? Or close it?
@@ -81,9 +81,6 @@ export const useTranslationFunction = () => {
81
81
  }
82
82
  }
83
83
 
84
- if (__DEV__ && !translationFound) {
85
- }
86
-
87
84
  return finalResult;
88
85
  }, [i18nextT, ready]);
89
86
 
@@ -7,8 +7,6 @@
7
7
  * - i18n setup
8
8
  */
9
9
 
10
- declare const __DEV__: boolean;
11
-
12
10
  import { storageRepository } from '@umituz/react-native-design-system';
13
11
  import i18n from '../config/i18n';
14
12
  import { languageRepository } from '../repository/LanguageRepository';
@@ -33,8 +31,6 @@ export class LanguageInitializer {
33
31
 
34
32
  return finalLanguage;
35
33
  } catch {
36
- if (typeof __DEV__ !== "undefined" && __DEV__) {
37
- }
38
34
  return await this.setupFallbackLanguage();
39
35
  }
40
36
  }
@@ -6,8 +6,7 @@
6
6
  import { LanguageInitializer } from "./LanguageInitializer";
7
7
  import { LanguageSwitcher } from "./LanguageSwitcher";
8
8
  import { languageRepository } from "../repository/LanguageRepository";
9
-
10
- declare const __DEV__: boolean;
9
+ import { isDev } from "../../../../utils/devUtils";
11
10
 
12
11
  export const LANGUAGE_SWITCH_DEBOUNCE_MS = 300;
13
12
 
@@ -45,7 +44,7 @@ export class InitializationManager {
45
44
  });
46
45
  } catch (error) {
47
46
  // Log and set fallback state
48
- if (typeof __DEV__ !== "undefined" && __DEV__) {
47
+ if (isDev()) {
49
48
  console.error("Localization initialization failed:", error);
50
49
  }
51
50
 
@@ -103,14 +102,14 @@ export class LanguageSwitchManager {
103
102
  this.pendingResolvers.push(pendingItem);
104
103
 
105
104
  this.timer = setTimeout(async () => {
106
- if (typeof __DEV__ !== "undefined" && __DEV__) {
105
+ if (isDev()) {
107
106
  console.log("[Localization] Switching language to:", languageCode);
108
107
  }
109
108
 
110
109
  try {
111
110
  const result = await LanguageSwitcher.switchLanguage(languageCode);
112
111
 
113
- if (typeof __DEV__ !== "undefined" && __DEV__) {
112
+ if (isDev()) {
114
113
  console.log("[Localization] Language switched successfully");
115
114
  }
116
115
 
@@ -121,7 +120,7 @@ export class LanguageSwitchManager {
121
120
 
122
121
  setState(stateUpdate);
123
122
 
124
- if (typeof __DEV__ !== "undefined" && __DEV__) {
123
+ if (isDev()) {
125
124
  console.log("[Localization] State updated:", stateUpdate);
126
125
  }
127
126
 
@@ -133,7 +132,7 @@ export class LanguageSwitchManager {
133
132
  const errorMessage =
134
133
  error instanceof Error ? error : new Error(String(error));
135
134
 
136
- if (typeof __DEV__ !== "undefined" && __DEV__) {
135
+ if (isDev()) {
137
136
  console.error("[Localization] Language switch failed:", errorMessage);
138
137
  }
139
138
 
@@ -70,8 +70,6 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
70
70
  customStyles?.languageItem,
71
71
  ]}
72
72
  onPress={() => {
73
- if (__DEV__) {
74
- }
75
73
  onSelect(item.code);
76
74
  }}
77
75
  activeOpacity={0.7}
@@ -6,6 +6,7 @@
6
6
  import React, { useEffect, useState } from "react";
7
7
  import { I18nInitializer } from "../../infrastructure/config/I18nInitializer";
8
8
  import { useLocalizationStore } from "../../infrastructure/storage/LocalizationStore";
9
+ import { isDev } from "../../../../utils/devUtils";
9
10
 
10
11
  interface LocalizationProviderProps {
11
12
  children: React.ReactNode;
@@ -32,7 +33,7 @@ export const LocalizationManager: React.FC<LocalizationProviderProps> = ({
32
33
  setIsI18nReady(true);
33
34
  }
34
35
  } catch (error) {
35
- if (__DEV__) {
36
+ if (isDev()) {
36
37
  console.error('[LocalizationManager] Initialization failed:', error);
37
38
  }
38
39
  if (isMounted) {
@@ -55,18 +55,19 @@ export { NotificationManager } from './infrastructure/services/NotificationManag
55
55
  // STORES
56
56
  // ============================================================================
57
57
 
58
- export { useNotificationsStore, useNotifications } from './infrastructure/storage/NotificationsStore';
59
58
  export {
60
- useRemindersStore,
61
- usePreferencesStore,
59
+ useNotificationStore,
60
+ useNotificationPermissions,
61
+ useNotificationInitialized,
62
+ useNotificationPreferences,
63
+ useQuietHours,
62
64
  useReminders,
63
65
  useEnabledReminders,
64
66
  useReminderById,
65
- useNotificationPreferences,
66
- useQuietHours,
67
67
  useRemindersLoading,
68
68
  useRemindersInitialized,
69
- } from './reminders/infrastructure/storage/RemindersStore';
69
+ useNotifications, // Legacy compatibility
70
+ } from './infrastructure/storage/UnifiedNotificationStore';
70
71
 
71
72
  // ============================================================================
72
73
  // HOOKS
@@ -1,6 +1,6 @@
1
1
  import * as Notifications from 'expo-notifications';
2
2
  import { Platform } from 'react-native';
3
- import { devError } from '../utils/dev';
3
+ import { devError } from '../../../../utils/devUtils';
4
4
 
5
5
  export class NotificationBadgeManager {
6
6
  async getBadgeCount(): Promise<number> {
@@ -9,7 +9,7 @@ import * as Notifications from 'expo-notifications';
9
9
  import { NotificationPermissions } from './NotificationPermissions';
10
10
  import { NotificationScheduler } from './NotificationScheduler';
11
11
  import { NotificationBadgeManager } from './NotificationBadgeManager';
12
- import { devLog, devError } from '../utils/dev';
12
+ import { devLog, devError } from '../../../../utils/devUtils';
13
13
  import type { ScheduleNotificationOptions, ScheduledNotification } from './types';
14
14
 
15
15
  export class NotificationManager {
@@ -1,7 +1,7 @@
1
1
  import * as Notifications from 'expo-notifications';
2
2
  import * as Device from 'expo-device';
3
3
  import { Platform } from 'react-native';
4
- import { devWarn, devError, devLog } from '../utils/dev';
4
+ import { devWarn, devError, devLog } from '../../../../utils/devUtils';
5
5
 
6
6
  export class NotificationPermissions {
7
7
  async requestPermissions(): Promise<boolean> {
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Unified Notification Store
3
+ * Consolidates NotificationsStore, RemindersStore, and PreferencesStore
4
+ *
5
+ * Production-ready implementation with:
6
+ * - Single source of truth for all notification state
7
+ * - Proper state partializing (transient vs persistent)
8
+ * - Type-safe actions and selectors
9
+ * - Data migration support
10
+ */
11
+
12
+ import { useMemo } from 'react';
13
+ import { createStore, storageService } from '@umituz/react-native-design-system';
14
+ import { excludeTransientState } from '../../../../infrastructure/storage/storeConfig';
15
+ import type { Reminder, QuietHoursConfig, NotificationPreferences } from '../services/types';
16
+
17
+ // ============================================================================
18
+ // STATE & ACTIONS TYPES
19
+ // ============================================================================
20
+
21
+ interface NotificationState {
22
+ // Runtime state (not persisted)
23
+ hasPermissions: boolean;
24
+ isInitialized: boolean;
25
+ isLoading: boolean;
26
+
27
+ // Persistent state
28
+ preferences: NotificationPreferences;
29
+ reminders: Reminder[];
30
+ }
31
+
32
+ interface NotificationActions {
33
+ // Permission actions
34
+ setPermissions: (granted: boolean) => void;
35
+ setInitialized: (initialized: boolean) => void;
36
+
37
+ // Preference actions
38
+ initialize: () => void;
39
+ updatePreferences: (updates: Partial<NotificationPreferences>) => void;
40
+ updateQuietHours: (quietHours: QuietHoursConfig) => void;
41
+
42
+ // Reminder actions
43
+ addReminder: (reminder: Reminder) => void;
44
+ updateReminder: (id: string, updates: Partial<Reminder>) => void;
45
+ deleteReminder: (id: string) => void;
46
+ toggleReminder: (id: string) => void;
47
+
48
+ // Reset actions
49
+ reset: () => void;
50
+ resetReminders: () => void;
51
+ }
52
+
53
+ // ============================================================================
54
+ // DEFAULT VALUES
55
+ // ============================================================================
56
+
57
+ const DEFAULT_PREFERENCES: NotificationPreferences = {
58
+ enabled: true,
59
+ sound: true,
60
+ vibration: true,
61
+ quietHours: {
62
+ enabled: false,
63
+ startHour: 22,
64
+ startMinute: 0,
65
+ endHour: 7,
66
+ endMinute: 0,
67
+ },
68
+ };
69
+
70
+ const DEFAULT_STATE: NotificationState = {
71
+ // Runtime state
72
+ hasPermissions: false,
73
+ isInitialized: false,
74
+ isLoading: true,
75
+
76
+ // Persistent state
77
+ preferences: DEFAULT_PREFERENCES,
78
+ reminders: [],
79
+ };
80
+
81
+ // ============================================================================
82
+ // UNIFIED NOTIFICATION STORE
83
+ // ============================================================================
84
+
85
+ export const useNotificationStore = createStore<NotificationState, NotificationActions>({
86
+ name: 'unified-notification-store',
87
+ version: 1,
88
+ persist: true,
89
+ storage: storageService,
90
+
91
+ // Only persist preferences and reminders (exclude runtime state)
92
+ partialize: (state) => ({
93
+ preferences: state.preferences,
94
+ reminders: state.reminders,
95
+ }),
96
+
97
+ initialState: DEFAULT_STATE,
98
+
99
+ actions: (set, get) => ({
100
+ // Permission actions
101
+ setPermissions: (granted) => set({ hasPermissions: granted }),
102
+ setInitialized: (initialized) => set({ isInitialized: initialized }),
103
+
104
+ // Preference actions
105
+ initialize: () => {
106
+ set({ isLoading: false, isInitialized: true });
107
+ },
108
+
109
+ updatePreferences: (updates) => {
110
+ const { preferences } = get();
111
+ set({ preferences: { ...preferences, ...updates } });
112
+ },
113
+
114
+ updateQuietHours: (quietHours) => {
115
+ const { preferences } = get();
116
+ set({ preferences: { ...preferences, quietHours } });
117
+ },
118
+
119
+ // Reminder actions
120
+ addReminder: (reminder) => {
121
+ const { reminders } = get();
122
+ set({ reminders: [...reminders, reminder] });
123
+ },
124
+
125
+ updateReminder: (id, updates) => {
126
+ const { reminders } = get();
127
+ set({
128
+ reminders: reminders.map(r =>
129
+ r.id === id ? { ...r, ...updates, updatedAt: new Date().toISOString() } : r
130
+ ),
131
+ });
132
+ },
133
+
134
+ deleteReminder: (id) => {
135
+ const { reminders } = get();
136
+ set({ reminders: reminders.filter(r => r.id !== id) });
137
+ },
138
+
139
+ toggleReminder: (id) => {
140
+ const { reminders } = get();
141
+ set({
142
+ reminders: reminders.map(r =>
143
+ r.id === id ? { ...r, enabled: !r.enabled, updatedAt: new Date().toISOString() } : r
144
+ ),
145
+ });
146
+ },
147
+
148
+ // Reset actions
149
+ reset: () => {
150
+ set({
151
+ preferences: DEFAULT_PREFERENCES,
152
+ reminders: [],
153
+ });
154
+ },
155
+
156
+ resetReminders: () => {
157
+ set({ reminders: [] });
158
+ },
159
+ }),
160
+ });
161
+
162
+ // ============================================================================
163
+ // SELECTOR HOOKS - Permissions & Initialization
164
+ // ============================================================================
165
+
166
+ export const useNotificationPermissions = () =>
167
+ useNotificationStore(state => state.hasPermissions);
168
+
169
+ export const useNotificationInitialized = () =>
170
+ useNotificationStore(state => state.isInitialized);
171
+
172
+ export const useRemindersLoading = () =>
173
+ useNotificationStore(state => state.isLoading);
174
+
175
+ export const useRemindersInitialized = () =>
176
+ useNotificationStore(state => state.isInitialized);
177
+
178
+ // ============================================================================
179
+ // SELECTOR HOOKS - Preferences
180
+ // ============================================================================
181
+
182
+ export const useNotificationPreferences = () =>
183
+ useNotificationStore(state => state.preferences);
184
+
185
+ export const useQuietHours = () =>
186
+ useNotificationStore(state => state.preferences.quietHours);
187
+
188
+ // ============================================================================
189
+ // SELECTOR HOOKS - Reminders
190
+ // ============================================================================
191
+
192
+ export const useReminders = () =>
193
+ useNotificationStore(state => state.reminders);
194
+
195
+ export const useEnabledReminders = () => {
196
+ const reminders = useNotificationStore(state => state.reminders);
197
+ return useMemo(() => reminders.filter(r => r.enabled), [reminders]);
198
+ };
199
+
200
+ export const useReminderById = (id: string) =>
201
+ useNotificationStore(state => state.reminders.find(r => r.id === id));
202
+
203
+ // ============================================================================
204
+ // LEGACY COMPATIBILITY HOOK (for smooth migration)
205
+ // ============================================================================
206
+
207
+ /**
208
+ * @deprecated Use useNotificationStore directly or specific selectors
209
+ * Kept temporarily for backward compatibility during migration
210
+ */
211
+ export const useNotifications = () => {
212
+ const hasPermissions = useNotificationPermissions();
213
+ const isInitialized = useNotificationInitialized();
214
+ const setPermissions = useNotificationStore(state => state.setPermissions);
215
+ const setInitialized = useNotificationStore(state => state.setInitialized);
216
+
217
+ return {
218
+ hasPermissions,
219
+ isInitialized,
220
+ setPermissions,
221
+ setInitialized,
222
+ };
223
+ };
@@ -4,13 +4,13 @@
4
4
  */
5
5
 
6
6
  import { useEffect, useCallback } from 'react';
7
- import { useNotificationPreferences, useQuietHours, usePreferencesStore, useRemindersLoading } from '../../reminders/infrastructure/storage/RemindersStore';
7
+ import { useNotificationPreferences, useQuietHours, useNotificationStore, useRemindersLoading } from '../../infrastructure/storage/UnifiedNotificationStore';
8
8
  import { notificationService } from '../../infrastructure/services/NotificationService';
9
9
 
10
10
  export const useNotificationSettingsUI = () => {
11
11
  const preferences = useNotificationPreferences();
12
12
  const quietHours = useQuietHours();
13
- const { initialize, updatePreferences, updateQuietHours } = usePreferencesStore();
13
+ const { initialize, updatePreferences, updateQuietHours } = useNotificationStore();
14
14
  const isLoading = useRemindersLoading();
15
15
 
16
16
  useEffect(() => {
@@ -18,7 +18,7 @@ import { SettingRow } from '../components/SettingRow';
18
18
  import { RemindersNavRow } from '../components/RemindersNavRow';
19
19
  import { useNotificationSettingsUI } from '../hooks/useNotificationSettingsUI';
20
20
  import { useTimePicker } from '../hooks/useTimePicker';
21
- import { useReminders } from '../../reminders/infrastructure/storage/RemindersStore';
21
+ import { useReminders } from '../../infrastructure/storage/UnifiedNotificationStore';
22
22
  import { useQuietHoursActions } from '../../quietHours/infrastructure/hooks/useQuietHoursActions';
23
23
  import type { NotificationSettingsTranslations, QuietHoursTranslations } from '../../infrastructure/services/types';
24
24
  import { createStyles } from './NotificationSettingsScreen.styles';