fix: web notifications to show in foreground + duplicates prevented
Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
@@ -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.
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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",
|
||||
|
||||
+2
-1
@@ -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 };
|
||||
|
||||
@@ -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:^"
|
||||
|
||||
Reference in New Issue
Block a user