forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNotificationContext.tsx
More file actions
96 lines (84 loc) · 3.07 KB
/
Copy pathNotificationContext.tsx
File metadata and controls
96 lines (84 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
'use client';
import { createContext, useContext, useState, useCallback, useEffect, useMemo, ReactNode } from 'react';
import { useNotifications, UseNotificationsReturn } from '@/hooks/useNotifications';
import { getInstalledApps, type App } from '@/lib/api';
import type { OmiNotification } from '@/types/notification';
interface NotificationContextType extends UseNotificationsReturn {
// Panel state
isOpen: boolean;
openNotificationCenter: () => void;
closeNotificationCenter: () => void;
toggleNotificationCenter: () => void;
// App image lookup for plugin notifications
getAppImage: (appId: string | undefined) => string | undefined;
}
const NotificationContext = createContext<NotificationContextType | null>(null);
interface NotificationProviderProps {
children: ReactNode;
}
export function NotificationProvider({ children }: NotificationProviderProps) {
const [isOpen, setIsOpen] = useState(false);
const [installedApps, setInstalledApps] = useState<Map<string, App>>(new Map());
const notificationHook = useNotifications();
// Load installed apps on mount for image lookup
useEffect(() => {
async function loadApps() {
try {
const response = await getInstalledApps();
const appsMap = new Map<string, App>();
response.data.forEach((app) => {
appsMap.set(app.id, app);
});
setInstalledApps(appsMap);
} catch (error) {
console.error('Failed to load installed apps for notifications:', error);
}
}
loadApps();
}, []);
const openNotificationCenter = useCallback(() => setIsOpen(true), []);
const closeNotificationCenter = useCallback(() => setIsOpen(false), []);
const toggleNotificationCenter = useCallback(() => setIsOpen((prev) => !prev), []);
// Get app image for plugin notifications
const getAppImage = useCallback(
(appId: string | undefined): string | undefined => {
if (!appId) return undefined;
const app = installedApps.get(appId);
return app?.image || undefined;
},
[installedApps]
);
// Override navigateToNotification to also close the panel
const navigateToNotification = useCallback(
(notification: OmiNotification) => {
notificationHook.navigateToNotification(notification);
setIsOpen(false);
},
[notificationHook]
);
// Memoize context value to prevent cascading re-renders of all consumers
const value = useMemo(
() => ({
...notificationHook,
navigateToNotification,
isOpen,
openNotificationCenter,
closeNotificationCenter,
toggleNotificationCenter,
getAppImage,
}),
[notificationHook, navigateToNotification, isOpen, openNotificationCenter, closeNotificationCenter, toggleNotificationCenter, getAppImage]
);
return (
<NotificationContext.Provider value={value}>
{children}
</NotificationContext.Provider>
);
}
export function useNotificationContext() {
const context = useContext(NotificationContext);
if (!context) {
throw new Error('useNotificationContext must be used within a NotificationProvider');
}
return context;
}