fix: web notifications to show in foreground + duplicates prevented

Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
Heikki Hellgren
2024-04-21 21:42:15 +03:00
parent 4bfb02ed70
commit 1bc3b86858
7 changed files with 37 additions and 17 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications': patch
---
Fix to show web notifications even when browser is on foreground. Fix duplicate notifications with multiple tabs.
+2 -1
View File
@@ -175,8 +175,9 @@ export function useTitleCounter(): {
};
// @public (undocumented)
export function useWebNotifications(): {
export function useWebNotifications(enabled: boolean): {
sendWebNotification: (options: {
id: string;
title: string;
description: string;
link?: string;
+3 -1
View File
@@ -20,9 +20,11 @@ import {
notificationsPlugin,
NotificationsSidebarItem,
} from '../src';
import { signalsPlugin } from '@backstage/plugin-signals';
createDevApp()
.registerPlugin(notificationsPlugin)
.registerPlugin(signalsPlugin)
.addPage({
element: (
<NotificationsPage
@@ -32,5 +34,5 @@ createDevApp()
),
path: '/notifications',
})
.addSidebarItem(<NotificationsSidebarItem />)
.addSidebarItem(<NotificationsSidebarItem webNotificationsEnabled />)
.render();
+1
View File
@@ -50,6 +50,7 @@
"@backstage/cli": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/dev-utils": "workspace:^",
"@backstage/plugin-signals": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^15.0.0",
@@ -51,7 +51,7 @@ export const NotificationsSidebarItem = (props?: {
const notificationsRoute = useRouteRef(rootRouteRef);
// TODO: Do we want to add long polling in case signals are not available
const { lastSignal } = useSignal<NotificationSignal>('notifications');
const { sendWebNotification } = useWebNotifications();
const { sendWebNotification } = useWebNotifications(webNotificationsEnabled);
const [refresh, setRefresh] = React.useState(false);
const { setNotificationCount } = useTitleCounter();
@@ -75,6 +75,7 @@ export const NotificationsSidebarItem = (props?: {
return;
}
sendWebNotification({
id: notification.id,
title: notification.payload.title,
description: notification.payload.description ?? '',
link: notification.payload.link,
@@ -14,49 +14,58 @@
* limitations under the License.
*/
import { useCallback, useEffect, useState } from 'react';
import { rootRouteRef } from '../routes';
import { useRouteRef } from '@backstage/core-plugin-api';
import { useNavigate } from 'react-router-dom';
/** @public */
export function useWebNotifications() {
export function useWebNotifications(enabled: boolean) {
const [webNotificationPermission, setWebNotificationPermission] =
useState('default');
const [webNotifications, setWebNotifications] = useState<Notification[]>([]);
const notificationsRoute = useRouteRef(rootRouteRef);
const navigate = useNavigate();
useEffect(() => {
if ('Notification' in window && webNotificationPermission === 'default') {
if (
enabled &&
'Notification' in window &&
webNotificationPermission === 'default'
) {
window.Notification.requestPermission().then(permission => {
setWebNotificationPermission(permission);
});
}
}, [webNotificationPermission]);
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
webNotifications.forEach(n => n.close());
setWebNotifications([]);
}
});
}, [enabled, webNotificationPermission]);
const sendWebNotification = useCallback(
(options: { title: string; description: string; link?: string }) => {
(options: {
id: string;
title: string;
description: string;
link?: string;
}) => {
if (webNotificationPermission !== 'granted') {
return null;
}
const notification = new Notification(options.title, {
body: options.description,
tag: options.id, // Prevent duplicates from multiple tabs
});
notification.onclick = event => {
event.preventDefault();
notification.close();
if (options.link) {
window.open(options.link, '_blank');
} else {
navigate(notificationsRoute());
}
notification.close();
};
return notification;
},
[webNotificationPermission],
[webNotificationPermission, navigate, notificationsRoute],
);
return { sendWebNotification };
+1
View File
@@ -6057,6 +6057,7 @@ __metadata:
"@backstage/dev-utils": "workspace:^"
"@backstage/errors": "workspace:^"
"@backstage/plugin-notifications-common": "workspace:^"
"@backstage/plugin-signals": "workspace:^"
"@backstage/plugin-signals-react": "workspace:^"
"@backstage/test-utils": "workspace:^"
"@backstage/theme": "workspace:^"