@umituz/react-native-notifications 1.1.7 → 1.3.1
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 +18 -40
- package/src/index.ts +84 -13
- package/src/infrastructure/config/reminderPresets.ts +120 -0
- package/src/infrastructure/hooks/useQuietHoursActions.ts +52 -0
- package/src/infrastructure/hooks/useReminderActions.ts +147 -0
- package/src/infrastructure/services/types.ts +137 -44
- package/src/infrastructure/storage/RemindersStore.ts +150 -0
- package/src/presentation/components/FormButton.tsx +66 -0
- package/src/presentation/components/FrequencySelector.tsx +72 -0
- package/src/presentation/components/NotificationsSection.tsx +95 -160
- package/src/presentation/components/QuietHoursCard.tsx +105 -0
- package/src/presentation/components/ReminderForm.tsx +165 -0
- package/src/presentation/components/ReminderItem.tsx +124 -0
- package/src/presentation/components/TimePresetSelector.tsx +100 -0
- package/src/presentation/components/WeekdaySelector.tsx +61 -0
- package/src/presentation/screens/NotificationSettingsScreen.tsx +210 -0
- package/src/presentation/screens/NotificationsScreen.tsx +1 -1
- package/src/presentation/screens/ReminderListScreen.tsx +138 -0
- package/src/types/global.d.ts +11 -8
- package/lib/index.d.ts +0 -16
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -23
- package/lib/index.js.map +0 -1
- package/lib/infrastructure/config/notificationsConfig.d.ts +0 -20
- package/lib/infrastructure/config/notificationsConfig.d.ts.map +0 -1
- package/lib/infrastructure/config/notificationsConfig.js +0 -81
- package/lib/infrastructure/config/notificationsConfig.js.map +0 -1
- package/lib/infrastructure/hooks/actions/useNotificationActions.d.ts +0 -7
- package/lib/infrastructure/hooks/actions/useNotificationActions.d.ts.map +0 -1
- package/lib/infrastructure/hooks/actions/useNotificationActions.js +0 -75
- package/lib/infrastructure/hooks/actions/useNotificationActions.js.map +0 -1
- package/lib/infrastructure/hooks/actions/useNotificationManagementActions.d.ts +0 -8
- package/lib/infrastructure/hooks/actions/useNotificationManagementActions.d.ts.map +0 -1
- package/lib/infrastructure/hooks/actions/useNotificationManagementActions.js +0 -78
- package/lib/infrastructure/hooks/actions/useNotificationManagementActions.js.map +0 -1
- package/lib/infrastructure/hooks/state/useNotificationsState.d.ts +0 -12
- package/lib/infrastructure/hooks/state/useNotificationsState.d.ts.map +0 -1
- package/lib/infrastructure/hooks/state/useNotificationsState.js +0 -30
- package/lib/infrastructure/hooks/state/useNotificationsState.js.map +0 -1
- package/lib/infrastructure/hooks/types.d.ts +0 -87
- package/lib/infrastructure/hooks/types.d.ts.map +0 -1
- package/lib/infrastructure/hooks/types.js +0 -8
- package/lib/infrastructure/hooks/types.js.map +0 -1
- package/lib/infrastructure/hooks/useNotificationSettings.d.ts +0 -10
- package/lib/infrastructure/hooks/useNotificationSettings.d.ts.map +0 -1
- package/lib/infrastructure/hooks/useNotificationSettings.js +0 -43
- package/lib/infrastructure/hooks/useNotificationSettings.js.map +0 -1
- package/lib/infrastructure/hooks/useNotifications.d.ts +0 -24
- package/lib/infrastructure/hooks/useNotifications.d.ts.map +0 -1
- package/lib/infrastructure/hooks/useNotifications.js +0 -72
- package/lib/infrastructure/hooks/useNotifications.js.map +0 -1
- package/lib/infrastructure/hooks/utils/useNotificationRefresh.d.ts +0 -8
- package/lib/infrastructure/hooks/utils/useNotificationRefresh.d.ts.map +0 -1
- package/lib/infrastructure/hooks/utils/useNotificationRefresh.js +0 -99
- package/lib/infrastructure/hooks/utils/useNotificationRefresh.js.map +0 -1
- package/lib/infrastructure/services/NotificationBadgeManager.d.ts +0 -5
- package/lib/infrastructure/services/NotificationBadgeManager.d.ts.map +0 -1
- package/lib/infrastructure/services/NotificationBadgeManager.js +0 -29
- package/lib/infrastructure/services/NotificationBadgeManager.js.map +0 -1
- package/lib/infrastructure/services/NotificationManager.d.ts +0 -59
- package/lib/infrastructure/services/NotificationManager.d.ts.map +0 -1
- package/lib/infrastructure/services/NotificationManager.js +0 -118
- package/lib/infrastructure/services/NotificationManager.js.map +0 -1
- package/lib/infrastructure/services/NotificationPermissions.d.ts +0 -6
- package/lib/infrastructure/services/NotificationPermissions.d.ts.map +0 -1
- package/lib/infrastructure/services/NotificationPermissions.js +0 -75
- package/lib/infrastructure/services/NotificationPermissions.js.map +0 -1
- package/lib/infrastructure/services/NotificationScheduler.d.ts +0 -8
- package/lib/infrastructure/services/NotificationScheduler.d.ts.map +0 -1
- package/lib/infrastructure/services/NotificationScheduler.js +0 -72
- package/lib/infrastructure/services/NotificationScheduler.js.map +0 -1
- package/lib/infrastructure/services/NotificationService.d.ts +0 -30
- package/lib/infrastructure/services/NotificationService.d.ts.map +0 -1
- package/lib/infrastructure/services/NotificationService.js +0 -41
- package/lib/infrastructure/services/NotificationService.js.map +0 -1
- package/lib/infrastructure/services/channels/ChannelManager.d.ts +0 -18
- package/lib/infrastructure/services/channels/ChannelManager.d.ts.map +0 -1
- package/lib/infrastructure/services/channels/ChannelManager.js +0 -87
- package/lib/infrastructure/services/channels/ChannelManager.js.map +0 -1
- package/lib/infrastructure/services/delivery/NotificationDelivery.d.ts +0 -10
- package/lib/infrastructure/services/delivery/NotificationDelivery.d.ts.map +0 -1
- package/lib/infrastructure/services/delivery/NotificationDelivery.js +0 -71
- package/lib/infrastructure/services/delivery/NotificationDelivery.js.map +0 -1
- package/lib/infrastructure/services/preferences/PreferencesManager.d.ts +0 -18
- package/lib/infrastructure/services/preferences/PreferencesManager.d.ts.map +0 -1
- package/lib/infrastructure/services/preferences/PreferencesManager.js +0 -65
- package/lib/infrastructure/services/preferences/PreferencesManager.js.map +0 -1
- package/lib/infrastructure/services/types.d.ts +0 -89
- package/lib/infrastructure/services/types.d.ts.map +0 -1
- package/lib/infrastructure/services/types.js +0 -7
- package/lib/infrastructure/services/types.js.map +0 -1
- package/lib/infrastructure/storage/NotificationsStore.d.ts +0 -23
- package/lib/infrastructure/storage/NotificationsStore.d.ts.map +0 -1
- package/lib/infrastructure/storage/NotificationsStore.js +0 -26
- package/lib/infrastructure/storage/NotificationsStore.js.map +0 -1
- package/lib/infrastructure/utils/dev.d.ts +0 -5
- package/lib/infrastructure/utils/dev.d.ts.map +0 -1
- package/lib/infrastructure/utils/dev.js +0 -24
- package/lib/infrastructure/utils/dev.js.map +0 -1
- package/lib/presentation/components/NotificationsSection.d.ts +0 -17
- package/lib/presentation/components/NotificationsSection.d.ts.map +0 -1
- package/lib/presentation/components/NotificationsSection.js +0 -133
- package/lib/presentation/components/NotificationsSection.js.map +0 -1
- package/lib/presentation/screens/NotificationsScreen.d.ts +0 -20
- package/lib/presentation/screens/NotificationsScreen.d.ts.map +0 -1
- package/lib/presentation/screens/NotificationsScreen.js +0 -74
- package/lib/presentation/screens/NotificationsScreen.js.map +0 -1
- package/src/__tests__/NotificationManager.test.ts +0 -215
- package/src/__tests__/useNotificationActions.test.ts +0 -189
- package/src/__tests__/useNotificationRefresh.test.ts +0 -213
- package/src/infrastructure/hooks/actions/useNotificationActions.ts +0 -131
- package/src/infrastructure/hooks/actions/useNotificationManagementActions.ts +0 -131
- package/src/infrastructure/hooks/state/useNotificationsState.ts +0 -46
- package/src/infrastructure/hooks/types.ts +0 -83
- package/src/infrastructure/hooks/useNotifications.ts +0 -96
- package/src/infrastructure/hooks/utils/useNotificationRefresh.ts +0 -131
- package/src/infrastructure/services/channels/ChannelManager.ts +0 -111
- package/src/infrastructure/services/delivery/NotificationDelivery.ts +0 -83
- package/src/infrastructure/services/preferences/PreferencesManager.ts +0 -77
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef } from 'react';
|
|
2
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
3
|
-
import type { Notification } from '../types';
|
|
4
|
-
import { ChannelManager } from '../../services/channels/ChannelManager';
|
|
5
|
-
import { PreferencesManager } from '../../services/preferences/PreferencesManager';
|
|
6
|
-
import { devLog, devError } from '../../utils/dev';
|
|
7
|
-
|
|
8
|
-
export const useNotificationRefresh = (pageSize: number, setters: any) => {
|
|
9
|
-
const {
|
|
10
|
-
setNotifications,
|
|
11
|
-
setUnreadCount,
|
|
12
|
-
setChannels,
|
|
13
|
-
setPreferences,
|
|
14
|
-
setLoading,
|
|
15
|
-
setError,
|
|
16
|
-
setHasMore,
|
|
17
|
-
} = setters;
|
|
18
|
-
|
|
19
|
-
const channelManager = useRef(new ChannelManager()).current;
|
|
20
|
-
const preferencesManager = useRef(new PreferencesManager()).current;
|
|
21
|
-
const abortController = useRef<AbortController | null>(null);
|
|
22
|
-
|
|
23
|
-
const cleanup = useCallback(() => {
|
|
24
|
-
if (abortController.current) {
|
|
25
|
-
abortController.current.abort();
|
|
26
|
-
abortController.current = null;
|
|
27
|
-
}
|
|
28
|
-
}, []);
|
|
29
|
-
|
|
30
|
-
const refreshNotifications = useCallback(async () => {
|
|
31
|
-
try {
|
|
32
|
-
cleanup();
|
|
33
|
-
abortController.current = new AbortController();
|
|
34
|
-
|
|
35
|
-
setLoading(true);
|
|
36
|
-
setError(null);
|
|
37
|
-
|
|
38
|
-
const data = await AsyncStorage.getItem('@notifications:list');
|
|
39
|
-
const allNotifications: Notification[] = data ? JSON.parse(data) : [];
|
|
40
|
-
|
|
41
|
-
const paginated = allNotifications.slice(0, pageSize);
|
|
42
|
-
const unread = allNotifications.filter((n) => !n.read).length;
|
|
43
|
-
|
|
44
|
-
setNotifications(paginated);
|
|
45
|
-
setUnreadCount(unread);
|
|
46
|
-
setHasMore(allNotifications.length > pageSize);
|
|
47
|
-
|
|
48
|
-
devLog('[useNotificationRefresh] Refreshed notifications:', paginated.length);
|
|
49
|
-
} catch (err) {
|
|
50
|
-
if (err instanceof Error && err.name === 'AbortError') {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
setError(
|
|
54
|
-
err instanceof Error ? err.message : 'Failed to load notifications'
|
|
55
|
-
);
|
|
56
|
-
} finally {
|
|
57
|
-
setLoading(false);
|
|
58
|
-
cleanup();
|
|
59
|
-
}
|
|
60
|
-
}, [pageSize, setNotifications, setUnreadCount, setHasMore, setLoading, setError, cleanup]);
|
|
61
|
-
|
|
62
|
-
const loadMoreNotifications = useCallback(
|
|
63
|
-
async (currentLength: number, hasMore: boolean, loading: boolean) => {
|
|
64
|
-
if (!hasMore || loading) return;
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
cleanup();
|
|
68
|
-
abortController.current = new AbortController();
|
|
69
|
-
|
|
70
|
-
setLoading(true);
|
|
71
|
-
setError(null);
|
|
72
|
-
|
|
73
|
-
const data = await AsyncStorage.getItem('@notifications:list');
|
|
74
|
-
const allNotifications: Notification[] = data ? JSON.parse(data) : [];
|
|
75
|
-
|
|
76
|
-
const moreNotifications = allNotifications.slice(
|
|
77
|
-
currentLength,
|
|
78
|
-
currentLength + pageSize
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
setNotifications((prev: any[]) => [...prev, ...moreNotifications]);
|
|
82
|
-
setHasMore(allNotifications.length > currentLength + pageSize);
|
|
83
|
-
|
|
84
|
-
devLog('[useNotificationRefresh] Loaded more notifications:', moreNotifications.length);
|
|
85
|
-
} catch (err) {
|
|
86
|
-
if (err instanceof Error && err.name === 'AbortError') {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
setError(
|
|
90
|
-
err instanceof Error
|
|
91
|
-
? err.message
|
|
92
|
-
: 'Failed to load more notifications'
|
|
93
|
-
);
|
|
94
|
-
} finally {
|
|
95
|
-
setLoading(false);
|
|
96
|
-
cleanup();
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
[pageSize, setNotifications, setHasMore, setLoading, setError, cleanup]
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
const refreshChannels = useCallback(async () => {
|
|
103
|
-
try {
|
|
104
|
-
const channelsData = await channelManager.getActiveChannels();
|
|
105
|
-
setChannels(channelsData);
|
|
106
|
-
|
|
107
|
-
devLog('[useNotificationRefresh] Refreshed channels:', channelsData.length);
|
|
108
|
-
} catch (err) {
|
|
109
|
-
devError('[useNotificationRefresh] Failed to refresh channels:', err);
|
|
110
|
-
}
|
|
111
|
-
}, [setChannels]);
|
|
112
|
-
|
|
113
|
-
const refreshPreferences = useCallback(async () => {
|
|
114
|
-
try {
|
|
115
|
-
const prefsData = await preferencesManager.get();
|
|
116
|
-
setPreferences(prefsData);
|
|
117
|
-
|
|
118
|
-
devLog('[useNotificationRefresh] Refreshed preferences');
|
|
119
|
-
} catch (err) {
|
|
120
|
-
devError('[useNotificationRefresh] Failed to refresh preferences:', err);
|
|
121
|
-
}
|
|
122
|
-
}, [setPreferences]);
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
refreshNotifications,
|
|
126
|
-
loadMoreNotifications,
|
|
127
|
-
refreshChannels,
|
|
128
|
-
refreshPreferences,
|
|
129
|
-
cleanup,
|
|
130
|
-
};
|
|
131
|
-
};
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
|
-
import * as Notifications from 'expo-notifications';
|
|
3
|
-
import type { NotificationChannel } from '../types';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* ChannelManager - Offline Notification Channel Management
|
|
7
|
-
*
|
|
8
|
-
* Manages push notification tokens and preferences in AsyncStorage.
|
|
9
|
-
* Only supports local push and in-app notifications.
|
|
10
|
-
*
|
|
11
|
-
* NO backend, NO email/SMS - pure offline.
|
|
12
|
-
*/
|
|
13
|
-
export class ChannelManager {
|
|
14
|
-
private static STORAGE_KEY = '@notifications:channels';
|
|
15
|
-
|
|
16
|
-
async register(
|
|
17
|
-
channelType: 'push' | 'in_app',
|
|
18
|
-
preferences: Record<string, any> = {}
|
|
19
|
-
): Promise<NotificationChannel | null> {
|
|
20
|
-
try {
|
|
21
|
-
// Get push token for local notifications
|
|
22
|
-
const token =
|
|
23
|
-
channelType === 'push'
|
|
24
|
-
? (await Notifications.getExpoPushTokenAsync()).data
|
|
25
|
-
: 'in_app';
|
|
26
|
-
|
|
27
|
-
const channel: NotificationChannel = {
|
|
28
|
-
id: `${channelType}_${Date.now()}`,
|
|
29
|
-
channel_type: channelType,
|
|
30
|
-
channel_address: token,
|
|
31
|
-
preferences,
|
|
32
|
-
is_verified: true, // Local channels always verified
|
|
33
|
-
is_active: true,
|
|
34
|
-
created_at: new Date().toISOString(),
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Store in AsyncStorage
|
|
38
|
-
const channels = await this.getAllChannels();
|
|
39
|
-
channels.push(channel);
|
|
40
|
-
await AsyncStorage.setItem(
|
|
41
|
-
ChannelManager.STORAGE_KEY,
|
|
42
|
-
JSON.stringify(channels)
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
return channel;
|
|
46
|
-
} catch (error) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async verify(channelId: string): Promise<boolean> {
|
|
52
|
-
try {
|
|
53
|
-
const channels = await this.getAllChannels();
|
|
54
|
-
const index = channels.findIndex((c) => c.id === channelId);
|
|
55
|
-
|
|
56
|
-
if (index !== -1) {
|
|
57
|
-
channels[index].is_verified = true;
|
|
58
|
-
await AsyncStorage.setItem(
|
|
59
|
-
ChannelManager.STORAGE_KEY,
|
|
60
|
-
JSON.stringify(channels)
|
|
61
|
-
);
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return false;
|
|
66
|
-
} catch (error) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async getActiveChannels(): Promise<NotificationChannel[]> {
|
|
72
|
-
try {
|
|
73
|
-
const channels = await this.getAllChannels();
|
|
74
|
-
return channels.filter((c) => c.is_active && c.is_verified);
|
|
75
|
-
} catch (error) {
|
|
76
|
-
return [];
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private async getAllChannels(): Promise<NotificationChannel[]> {
|
|
81
|
-
try {
|
|
82
|
-
const data = await AsyncStorage.getItem(ChannelManager.STORAGE_KEY);
|
|
83
|
-
return data ? JSON.parse(data) : [];
|
|
84
|
-
} catch (error) {
|
|
85
|
-
return [];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private async update(
|
|
90
|
-
channelId: string,
|
|
91
|
-
updates: Partial<NotificationChannel>
|
|
92
|
-
): Promise<NotificationChannel | null> {
|
|
93
|
-
try {
|
|
94
|
-
const channels = await this.getAllChannels();
|
|
95
|
-
const index = channels.findIndex((c) => c.id === channelId);
|
|
96
|
-
|
|
97
|
-
if (index !== -1) {
|
|
98
|
-
channels[index] = { ...channels[index], ...updates };
|
|
99
|
-
await AsyncStorage.setItem(
|
|
100
|
-
ChannelManager.STORAGE_KEY,
|
|
101
|
-
JSON.stringify(channels)
|
|
102
|
-
);
|
|
103
|
-
return channels[index];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return null;
|
|
107
|
-
} catch (error) {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import * as Notifications from 'expo-notifications';
|
|
2
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
3
|
-
import type { Notification } from '../types';
|
|
4
|
-
import { devLog, devError } from '../../utils/dev';
|
|
5
|
-
|
|
6
|
-
export class NotificationDelivery {
|
|
7
|
-
private static STORAGE_KEY = '@notifications:delivered';
|
|
8
|
-
|
|
9
|
-
async deliver(notification: Notification): Promise<void> {
|
|
10
|
-
try {
|
|
11
|
-
await Notifications.scheduleNotificationAsync({
|
|
12
|
-
content: {
|
|
13
|
-
title: notification.title,
|
|
14
|
-
body: notification.body,
|
|
15
|
-
data: { notificationId: notification.id },
|
|
16
|
-
},
|
|
17
|
-
trigger: notification.scheduled_for
|
|
18
|
-
? { date: new Date(notification.scheduled_for) }
|
|
19
|
-
: null,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
await this.updateStatus(notification.id, 'delivered');
|
|
23
|
-
|
|
24
|
-
devLog('[NotificationDelivery] Notification delivered:', notification.id);
|
|
25
|
-
} catch (error) {
|
|
26
|
-
await this.updateStatus(notification.id, 'failed');
|
|
27
|
-
|
|
28
|
-
devError('[NotificationDelivery] Delivery failed:', notification.id, error);
|
|
29
|
-
throw error;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
private async updateStatus(
|
|
34
|
-
notificationId: string,
|
|
35
|
-
status: 'delivered' | 'failed'
|
|
36
|
-
): Promise<void> {
|
|
37
|
-
try {
|
|
38
|
-
const delivered = await this.getDelivered();
|
|
39
|
-
delivered[notificationId] = {
|
|
40
|
-
status,
|
|
41
|
-
delivered_at: new Date().toISOString(),
|
|
42
|
-
};
|
|
43
|
-
await AsyncStorage.setItem(
|
|
44
|
-
NotificationDelivery.STORAGE_KEY,
|
|
45
|
-
JSON.stringify(delivered)
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
devLog('[NotificationDelivery] Status updated:', notificationId, status);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
devError('[NotificationDelivery] Status update failed:', notificationId, error);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
private async getDelivered(): Promise<Record<string, any>> {
|
|
55
|
-
try {
|
|
56
|
-
const data = await AsyncStorage.getItem(NotificationDelivery.STORAGE_KEY);
|
|
57
|
-
return data ? JSON.parse(data) : {};
|
|
58
|
-
} catch (error) {
|
|
59
|
-
devError('[NotificationDelivery] Failed to get delivered notifications:', error);
|
|
60
|
-
return {};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async getDeliveryStatus(notificationId: string): Promise<string | null> {
|
|
65
|
-
try {
|
|
66
|
-
const delivered = await this.getDelivered();
|
|
67
|
-
return delivered[notificationId]?.status || null;
|
|
68
|
-
} catch (error) {
|
|
69
|
-
devError('[NotificationDelivery] Failed to get delivery status:', notificationId, error);
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async clearDeliveryHistory(): Promise<void> {
|
|
75
|
-
try {
|
|
76
|
-
await AsyncStorage.removeItem(NotificationDelivery.STORAGE_KEY);
|
|
77
|
-
|
|
78
|
-
devLog('[NotificationDelivery] Delivery history cleared');
|
|
79
|
-
} catch (error) {
|
|
80
|
-
devError('[NotificationDelivery] Failed to clear delivery history:', error);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
|
-
import type { NotificationPreferences } from '../types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* PreferencesManager - Offline Notification Preferences
|
|
6
|
-
*
|
|
7
|
-
* Stores preferences in AsyncStorage (offline-capable).
|
|
8
|
-
* Only supports local push and in-app notifications.
|
|
9
|
-
*
|
|
10
|
-
* NO backend, NO email/SMS - pure offline.
|
|
11
|
-
*/
|
|
12
|
-
export class PreferencesManager {
|
|
13
|
-
private static STORAGE_KEY = '@notifications:preferences';
|
|
14
|
-
|
|
15
|
-
async get(): Promise<NotificationPreferences> {
|
|
16
|
-
try {
|
|
17
|
-
const data = await AsyncStorage.getItem(PreferencesManager.STORAGE_KEY);
|
|
18
|
-
return data ? JSON.parse(data) : this.getDefaults();
|
|
19
|
-
} catch (error) {
|
|
20
|
-
return this.getDefaults();
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async update(preferences: Partial<NotificationPreferences>): Promise<boolean> {
|
|
25
|
-
try {
|
|
26
|
-
const current = await this.get();
|
|
27
|
-
const updated = {
|
|
28
|
-
...current,
|
|
29
|
-
...preferences,
|
|
30
|
-
categories: { ...current.categories, ...preferences.categories },
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
await AsyncStorage.setItem(
|
|
34
|
-
PreferencesManager.STORAGE_KEY,
|
|
35
|
-
JSON.stringify(updated)
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
return true;
|
|
39
|
-
} catch (error) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
isChannelEnabled(
|
|
45
|
-
channelType: 'push' | 'in_app',
|
|
46
|
-
prefs: NotificationPreferences
|
|
47
|
-
): boolean {
|
|
48
|
-
if (channelType === 'in_app') return true;
|
|
49
|
-
return prefs.push_enabled ?? true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
isInQuietHours(quietHours: NotificationPreferences['quiet_hours']): boolean {
|
|
53
|
-
if (!quietHours.enabled) return false;
|
|
54
|
-
const currentTime = new Date().toTimeString().slice(0, 5);
|
|
55
|
-
return (
|
|
56
|
-
currentTime >= quietHours.start_time ||
|
|
57
|
-
currentTime <= quietHours.end_time
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private getDefaults(): NotificationPreferences {
|
|
62
|
-
return {
|
|
63
|
-
push_enabled: true,
|
|
64
|
-
quiet_hours: {
|
|
65
|
-
enabled: false,
|
|
66
|
-
start_time: '22:00',
|
|
67
|
-
end_time: '08:00',
|
|
68
|
-
timezone: 'UTC',
|
|
69
|
-
},
|
|
70
|
-
categories: {
|
|
71
|
-
reminders: { push: true, in_app: true },
|
|
72
|
-
updates: { push: true, in_app: true },
|
|
73
|
-
alerts: { push: true, in_app: true },
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
}
|