@umituz/react-native-notifications 1.5.2 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-notifications",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "Offline-first local notifications system for React Native apps using expo-notifications",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -38,13 +38,14 @@
|
|
|
38
38
|
"react": ">=18.2.0",
|
|
39
39
|
"react-native": ">=0.74.0",
|
|
40
40
|
"react-native-safe-area-context": ">=4.0.0",
|
|
41
|
-
"
|
|
41
|
+
"@umituz/react-native-storage": "latest"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@react-native-async-storage/async-storage": "^2.1.0",
|
|
45
45
|
"@react-native-community/datetimepicker": "^8.2.0",
|
|
46
46
|
"@umituz/react-native-design-system": "latest",
|
|
47
47
|
"@umituz/react-native-haptics": "latest",
|
|
48
|
+
"@umituz/react-native-storage": "latest",
|
|
48
49
|
"expo-device": "~7.0.0",
|
|
49
50
|
"expo-haptics": "~14.0.0",
|
|
50
51
|
"expo-linear-gradient": "~14.0.0",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Manages reminder state with AsyncStorage persistence
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { createStore } from '@umituz/react-native-storage';
|
|
7
7
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
8
8
|
import type { Reminder, QuietHoursConfig, NotificationPreferences } from '../../../../infrastructure/services/types';
|
|
9
9
|
|
|
@@ -37,8 +37,6 @@ interface RemindersActions {
|
|
|
37
37
|
reset: () => Promise<void>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
type RemindersStore = RemindersState & RemindersActions;
|
|
41
|
-
|
|
42
40
|
// ============================================================================
|
|
43
41
|
// DEFAULT VALUES
|
|
44
42
|
// ============================================================================
|
|
@@ -56,108 +54,115 @@ const DEFAULT_PREFERENCES: NotificationPreferences = {
|
|
|
56
54
|
},
|
|
57
55
|
};
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
// STORE IMPLEMENTATION
|
|
61
|
-
// ============================================================================
|
|
62
|
-
|
|
63
|
-
export const useRemindersStore = create<RemindersStore>((set, get) => ({
|
|
57
|
+
const initialRemindersState: RemindersState = {
|
|
64
58
|
reminders: [],
|
|
65
59
|
preferences: DEFAULT_PREFERENCES,
|
|
66
60
|
isLoading: true,
|
|
67
61
|
isInitialized: false,
|
|
62
|
+
};
|
|
68
63
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
AsyncStorage.getItem(STORAGE_KEYS.REMINDERS),
|
|
73
|
-
AsyncStorage.getItem(STORAGE_KEYS.PREFERENCES)
|
|
74
|
-
]);
|
|
75
|
-
|
|
76
|
-
const reminders = remindersData ? JSON.parse(remindersData) : [];
|
|
77
|
-
let preferences = DEFAULT_PREFERENCES;
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// STORE IMPLEMENTATION
|
|
66
|
+
// ============================================================================
|
|
78
67
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
68
|
+
export const useRemindersStore = createStore<RemindersState, RemindersActions>({
|
|
69
|
+
name: 'reminders-store',
|
|
70
|
+
initialState: initialRemindersState,
|
|
71
|
+
persist: false, // Manual persistence via AsyncStorage
|
|
72
|
+
actions: (set, get) => ({
|
|
73
|
+
initialize: async () => {
|
|
74
|
+
try {
|
|
75
|
+
const [remindersData, preferencesData] = await Promise.all([
|
|
76
|
+
AsyncStorage.getItem(STORAGE_KEYS.REMINDERS),
|
|
77
|
+
AsyncStorage.getItem(STORAGE_KEYS.PREFERENCES)
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
const reminders = remindersData ? JSON.parse(remindersData) : [];
|
|
81
|
+
let preferences = DEFAULT_PREFERENCES;
|
|
82
|
+
|
|
83
|
+
if (preferencesData) {
|
|
84
|
+
const parsed = JSON.parse(preferencesData);
|
|
85
|
+
preferences = { ...DEFAULT_PREFERENCES, ...parsed };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
set({ reminders, preferences, isLoading: false, isInitialized: true });
|
|
89
|
+
} catch {
|
|
90
|
+
set({ reminders: [], preferences: DEFAULT_PREFERENCES, isLoading: false, isInitialized: true });
|
|
82
91
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
set({ reminders: [], preferences: DEFAULT_PREFERENCES });
|
|
158
|
-
await AsyncStorage.multiRemove([STORAGE_KEYS.REMINDERS, STORAGE_KEYS.PREFERENCES]);
|
|
159
|
-
},
|
|
160
|
-
}));
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
loadReminders: async () => {
|
|
95
|
+
try {
|
|
96
|
+
const data = await AsyncStorage.getItem(STORAGE_KEYS.REMINDERS);
|
|
97
|
+
const reminders = data ? JSON.parse(data) : [];
|
|
98
|
+
set({ reminders });
|
|
99
|
+
} catch {
|
|
100
|
+
set({ reminders: [] });
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
addReminder: async (reminder: Reminder) => {
|
|
105
|
+
const { reminders } = get();
|
|
106
|
+
const updated = [...reminders, reminder];
|
|
107
|
+
set({ reminders: updated });
|
|
108
|
+
await AsyncStorage.setItem(STORAGE_KEYS.REMINDERS, JSON.stringify(updated));
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
updateReminder: async (id: string, updates: Partial<Reminder>) => {
|
|
112
|
+
const { reminders } = get();
|
|
113
|
+
const updated = reminders.map(r =>
|
|
114
|
+
r.id === id ? { ...r, ...updates, updatedAt: new Date().toISOString() } : r
|
|
115
|
+
);
|
|
116
|
+
set({ reminders: updated });
|
|
117
|
+
await AsyncStorage.setItem(STORAGE_KEYS.REMINDERS, JSON.stringify(updated));
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
deleteReminder: async (id: string) => {
|
|
121
|
+
const { reminders } = get();
|
|
122
|
+
const updated = reminders.filter(r => r.id !== id);
|
|
123
|
+
set({ reminders: updated });
|
|
124
|
+
await AsyncStorage.setItem(STORAGE_KEYS.REMINDERS, JSON.stringify(updated));
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
toggleReminder: async (id: string) => {
|
|
128
|
+
const { reminders } = get();
|
|
129
|
+
const updated = reminders.map(r =>
|
|
130
|
+
r.id === id ? { ...r, enabled: !r.enabled, updatedAt: new Date().toISOString() } : r
|
|
131
|
+
);
|
|
132
|
+
set({ reminders: updated });
|
|
133
|
+
await AsyncStorage.setItem(STORAGE_KEYS.REMINDERS, JSON.stringify(updated));
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
loadPreferences: async () => {
|
|
137
|
+
try {
|
|
138
|
+
const data = await AsyncStorage.getItem(STORAGE_KEYS.PREFERENCES);
|
|
139
|
+
const preferences = data ? { ...DEFAULT_PREFERENCES, ...JSON.parse(data) } : DEFAULT_PREFERENCES;
|
|
140
|
+
set({ preferences });
|
|
141
|
+
} catch {
|
|
142
|
+
set({ preferences: DEFAULT_PREFERENCES });
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
updatePreferences: async (updates: Partial<NotificationPreferences>) => {
|
|
147
|
+
const { preferences } = get();
|
|
148
|
+
const updated = { ...preferences, ...updates };
|
|
149
|
+
set({ preferences: updated });
|
|
150
|
+
await AsyncStorage.setItem(STORAGE_KEYS.PREFERENCES, JSON.stringify(updated));
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
updateQuietHours: async (quietHours: QuietHoursConfig) => {
|
|
154
|
+
const { preferences } = get();
|
|
155
|
+
const updated = { ...preferences, quietHours };
|
|
156
|
+
set({ preferences: updated });
|
|
157
|
+
await AsyncStorage.setItem(STORAGE_KEYS.PREFERENCES, JSON.stringify(updated));
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
reset: async () => {
|
|
161
|
+
set({ reminders: [], preferences: DEFAULT_PREFERENCES });
|
|
162
|
+
await AsyncStorage.multiRemove([STORAGE_KEYS.REMINDERS, STORAGE_KEYS.PREFERENCES]);
|
|
163
|
+
},
|
|
164
|
+
}),
|
|
165
|
+
});
|
|
161
166
|
|
|
162
167
|
// ============================================================================
|
|
163
168
|
// SELECTOR HOOKS
|
|
@@ -4,25 +4,30 @@
|
|
|
4
4
|
* NO backend, NO user IDs, NO notification history
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { createStore } from '@umituz/react-native-storage';
|
|
8
8
|
|
|
9
|
-
interface
|
|
10
|
-
// State
|
|
9
|
+
interface NotificationsState {
|
|
11
10
|
hasPermissions: boolean;
|
|
12
11
|
isInitialized: boolean;
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
interface NotificationsActions {
|
|
15
15
|
setPermissions: (granted: boolean) => void;
|
|
16
16
|
setInitialized: (initialized: boolean) => void;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const useNotificationsStore =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
export const useNotificationsStore = createStore<NotificationsState, NotificationsActions>({
|
|
20
|
+
name: 'notifications-store',
|
|
21
|
+
initialState: {
|
|
22
|
+
hasPermissions: false,
|
|
23
|
+
isInitialized: false,
|
|
24
|
+
},
|
|
25
|
+
persist: false,
|
|
26
|
+
actions: (set) => ({
|
|
27
|
+
setPermissions: (granted) => set({ hasPermissions: granted }),
|
|
28
|
+
setInitialized: (initialized) => set({ isInitialized: initialized }),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
26
31
|
|
|
27
32
|
/**
|
|
28
33
|
* Hook for accessing notifications state
|