diff --git a/frontend/src/metabase/dashboard/containers/DashboardApp.jsx b/frontend/src/metabase/dashboard/containers/DashboardApp.jsx index 188e6cd26572674b8ed0e5f8117b495fb1471b48..6595edce5b37bf2531254a73069bf531e2cf34df 100644 --- a/frontend/src/metabase/dashboard/containers/DashboardApp.jsx +++ b/frontend/src/metabase/dashboard/containers/DashboardApp.jsx @@ -106,7 +106,7 @@ const DashboardApp = props => { const [isShowingToaster, setIsShowingToaster] = useState(false); const onTimeout = useCallback(() => { - if (Notification.permission === "default") { + if ("Notification" in window && Notification.permission === "default") { setIsShowingToaster(true); } }, []); @@ -123,7 +123,11 @@ const DashboardApp = props => { useEffect(() => { if (isLoadingComplete) { setIsShowingToaster(false); - if (Notification.permission === "granted" && document.hidden) { + if ( + "Notification" in window && + Notification.permission === "granted" && + document.hidden + ) { showNotification( t`All Set! ${dashboard?.name} is ready.`, t`All questions loaded`, diff --git a/frontend/src/metabase/hooks/use-web-notification.ts b/frontend/src/metabase/hooks/use-web-notification.ts index 5afad1cf9685459f92b4d5d724fceaefd22e9f18..52f70665780fc6b083c3ae378129ad9bc44edb6a 100644 --- a/frontend/src/metabase/hooks/use-web-notification.ts +++ b/frontend/src/metabase/hooks/use-web-notification.ts @@ -1,12 +1,21 @@ -import React, { useCallback } from "react"; +import { useCallback } from "react"; + +const hasNotificationAPI = "Notification" in window; export function useWebNotification() { const requestPermission = useCallback(async () => { + if (!hasNotificationAPI) { + return "denied"; + } const permission = await Notification.requestPermission(); return permission; }, []); const showNotification = useCallback((title: string, body: string) => { + if (!hasNotificationAPI) { + return; + } + const notification = new Notification(title, { body, icon: "app/assets/img/favicon-32x32.png", diff --git a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx index 2488c3eeff6d677d27b870e7f39393096e02d6fa..5d7b99d8bcdfbdd5210cd895e4162b1f7b0114dd 100644 --- a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx +++ b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx @@ -373,7 +373,7 @@ function QueryBuilder(props) { const { isRunning } = uiControls; const onTimeout = useCallback(() => { - if (Notification.permission === "default") { + if ("Notification" in window && Notification.permission === "default") { setIsShowingToaster(true); } }, []); @@ -389,7 +389,11 @@ function QueryBuilder(props) { if (isLoadingComplete) { setIsShowingToaster(false); - if (Notification.permission === "granted" && document.hidden) { + if ( + "Notification" in window && + Notification.permission === "granted" && + document.hidden + ) { showNotification( t`All Set! Your question is ready.`, t`${card.name} is loaded.`,