diff --git a/web/components/modals/BrowserNotifyModal/BrowserNotifyModal.tsx b/web/components/modals/BrowserNotifyModal/BrowserNotifyModal.tsx index 90d50f113..4c7eef07c 100644 --- a/web/components/modals/BrowserNotifyModal/BrowserNotifyModal.tsx +++ b/web/components/modals/BrowserNotifyModal/BrowserNotifyModal.tsx @@ -1,5 +1,7 @@ import { Row, Spin, Typography, Button } from 'antd'; import React, { FC, useState } from 'react'; +import UploadOutlined from '@ant-design/icons/lib/icons/UploadOutlined'; +import PlusSquareOutlined from '@ant-design/icons/lib/icons/PlusSquareOutlined'; import { useRecoilValue } from 'recoil'; import { ErrorBoundary } from 'react-error-boundary'; import { accessTokenAtom, clientConfigStateAtom } from '../../stores/ClientConfigStore'; @@ -8,9 +10,11 @@ import { saveNotificationRegistration, } from '../../../services/notifications-service'; import styles from './BrowserNotifyModal.module.scss'; -import isPushNotificationSupported from '../../../utils/browserPushNotifications'; import { ComponentError } from '../../ui/ComponentError/ComponentError'; +import { isMobileSafariHomeScreenApp, isMobileSafariIos } from '../../../utils/helpers'; +import { arePushNotificationSupported } from '../../../utils/browserPushNotifications'; + const { Title } = Typography; const NotificationsNotSupported = () => ( @@ -21,6 +25,31 @@ const NotificationsNotSupportedLocal = () => (
Browser notifications are not supported for local servers.
); +const MobileSafariInstructions = () => ( +
+ Get notified on iOS + It takes a couple extra steps to make sure you get notified when your favorite streams go live. +
    +
  1. + Tap the share button in Safari. +
  2. +
  3. + Scroll down and tap “Add to Home Screen” + . +
  4. +
  5. + Tap “Add”. +
  6. +
  7. Give this link a name and tap the new icon on your home screen
  8. + +
  9. Come back to this screen and enable notifications.
  10. +
  11. + Tap “Allow” when prompted. +
  12. +
+
+); + export type PermissionPopupPreviewProps = { start: () => void; }; @@ -78,22 +107,27 @@ export const BrowserNotifyModal = () => { const [browserPushPermissionsPending, setBrowserPushPermissionsPending] = useState(false); const notificationsPermitted = - isPushNotificationSupported() && Notification.permission !== 'default'; + arePushNotificationSupported() && Notification.permission !== 'default'; const { notifications } = config; const { browser } = notifications; const { publicKey } = browser; - const browserPushSupported = browser.enabled && isPushNotificationSupported(); + const browserPushSupported = + browser.enabled && (arePushNotificationSupported() || isMobileSafariHomeScreenApp()); // If notification permissions are granted, show user info how to disable them if (notificationsPermitted) { return ; } + if (isMobileSafariIos() && !isMobileSafariHomeScreenApp()) { + return ; + } + const startBrowserPushRegistration = async () => { // If notification permissions are already denied or granted, don't do anything. - if (isPushNotificationSupported() && Notification.permission !== 'default') { + if (arePushNotificationSupported() && Notification.permission !== 'default') { return; } diff --git a/web/components/ui/Content/Content.tsx b/web/components/ui/Content/Content.tsx index 5bb6e5eaa..e26df480b 100644 --- a/web/components/ui/Content/Content.tsx +++ b/web/components/ui/Content/Content.tsx @@ -6,7 +6,7 @@ import dynamic from 'next/dynamic'; import classnames from 'classnames'; import ActionButtons from './ActionButtons'; import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage'; -import isPushNotificationSupported from '../../../utils/browserPushNotifications'; +import { canPushNotificationsBeSupported } from '../../../utils/browserPushNotifications'; import { clientConfigStateAtom, @@ -179,7 +179,9 @@ export const Content: FC = () => { useEffect(() => { // isPushNotificationSupported relies on `navigator` so that needs to be // fired from this useEffect. - setSupportsBrowserNotifications(isPushNotificationSupported() && browserNotificationsEnabled); + setSupportsBrowserNotifications( + canPushNotificationsBeSupported() && browserNotificationsEnabled, + ); }, [browserNotificationsEnabled]); const showChat = isChatAvailable && !chatDisabled && isChatVisible; @@ -238,7 +240,7 @@ export const Content: FC = () => { { + try { + const ua = navigator.userAgent; + const uaParser = new UAParser(ua); + const browser = uaParser.getBrowser(); + const device = uaParser.getDevice(); + + if (device.vendor !== 'Apple') { + return false; + } + + if (device.type !== 'mobile' && device.type !== 'tablet') { + return false; + } + + return browser.name === 'Mobile Safari' || browser.name === 'Safari'; + } catch (e) { + return false; + } +}; + +export const isMobileSafariHomeScreenApp = () => { + if (!isMobileSafariIos()) { + return false; + } + + return 'standalone' in window.navigator && window.navigator.standalone; +};