2024-09-20 04:29:34 -07:00
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
import { useSettings } from '../state/settingsSlice';
|
|
|
|
import { NotificationsContext } from '../state/useNotifications';
|
|
|
|
import { Notification, NotificationsResult } from "../api/responseTypes/notifications";
|
|
|
|
import { useAPIQuery } from '../api/api';
|
2024-09-27 06:58:41 -07:00
|
|
|
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
2024-09-20 04:29:34 -07:00
|
|
|
|
|
|
|
export const NotificationsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
|
|
const { pathPrefix } = useSettings();
|
|
|
|
const [notifications, setNotifications] = useState<Notification[]>([]);
|
|
|
|
const [isConnectionError, setIsConnectionError] = useState(false);
|
|
|
|
const [shouldFetchFromAPI, setShouldFetchFromAPI] = useState(false);
|
|
|
|
|
|
|
|
const { data, isError } = useAPIQuery<NotificationsResult>({
|
|
|
|
path: '/notifications',
|
|
|
|
enabled: shouldFetchFromAPI,
|
|
|
|
refetchInterval: 10000,
|
|
|
|
});
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (data && data.data) {
|
|
|
|
setNotifications(data.data);
|
|
|
|
}
|
|
|
|
setIsConnectionError(isError);
|
|
|
|
}, [data, isError]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
2024-09-27 06:58:41 -07:00
|
|
|
const controller = new AbortController();
|
|
|
|
fetchEventSource(`${pathPrefix}/api/v1/notifications/live`, {
|
|
|
|
signal: controller.signal,
|
|
|
|
async onopen(response) {
|
|
|
|
if (response.ok) {
|
|
|
|
if (response.status === 200) {
|
|
|
|
setNotifications([]);
|
|
|
|
setIsConnectionError(false);
|
|
|
|
} else if (response.status === 204) {
|
|
|
|
controller.abort();
|
|
|
|
setShouldFetchFromAPI(true);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
setIsConnectionError(true);
|
|
|
|
throw new Error(`Unexpected response: ${response.status} ${response.statusText}`);
|
2024-09-20 04:29:34 -07:00
|
|
|
}
|
2024-09-27 06:58:41 -07:00
|
|
|
},
|
|
|
|
onmessage(event) {
|
|
|
|
const notification: Notification = JSON.parse(event.data);
|
2024-09-20 04:29:34 -07:00
|
|
|
|
2024-09-27 06:58:41 -07:00
|
|
|
setNotifications((prev: Notification[]) => {
|
|
|
|
const updatedNotifications = [...prev.filter((n: Notification) => n.text !== notification.text)];
|
2024-09-20 04:29:34 -07:00
|
|
|
|
2024-09-27 06:58:41 -07:00
|
|
|
if (notification.active) {
|
|
|
|
updatedNotifications.push(notification);
|
|
|
|
}
|
|
|
|
|
|
|
|
return updatedNotifications;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
onclose() {
|
|
|
|
throw new Error("Server closed the connection");
|
|
|
|
},
|
|
|
|
onerror() {
|
|
|
|
setIsConnectionError(true);
|
|
|
|
return 5000;
|
|
|
|
},
|
|
|
|
});
|
2024-09-20 04:29:34 -07:00
|
|
|
|
|
|
|
return () => {
|
2024-09-27 06:58:41 -07:00
|
|
|
controller.abort();
|
2024-09-20 04:29:34 -07:00
|
|
|
};
|
|
|
|
}, [pathPrefix]);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<NotificationsContext.Provider value={{ notifications, isConnectionError }}>
|
|
|
|
{children}
|
|
|
|
</NotificationsContext.Provider>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default NotificationsProvider;
|