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.
+
+ -
+ Tap the share button in Safari.
+
+ -
+ Scroll down and tap “Add to Home Screen”
+ .
+
+ -
+ Tap “Add”.
+
+ - Give this link a name and tap the new icon on your home screen
+
+ - Come back to this screen and enable notifications.
+ -
+ Tap “Allow” when prompted.
+
+
+
+);
+
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;
+};