diff --git a/src/Modals.tsx b/src/Modals.tsx index 3d8b0403..ea91f84b 100644 --- a/src/Modals.tsx +++ b/src/Modals.tsx @@ -1,10 +1,11 @@ -import { useContext, useEffect, useMemo } from 'react' +import { useContext, useEffect } from 'react' import { useWeb3Modal } from '@web3modal/wagmi/react' import { AnimatePresence } from 'framer-motion' import { PreferencesModal } from '@/components/notifications/NotificationsLayout/PreferencesModal' import { UnsubscribeModal } from '@/components/notifications/NotificationsLayout/UnsubscribeModal' +import ChangeBrowserModal from '@/components/utils/ChangeBrowserModal' import NotificationPwaModal from '@/components/utils/NotificationPwaModal' import PwaModal from '@/components/utils/PwaModal' import W3iContext from '@/contexts/W3iContext/context' @@ -15,7 +16,7 @@ import { checkIfNotificationModalClosed, notificationsEnabledInBrowser } from '@/utils/notifications' -import { isMobileButNotInstalledOnHomeScreen } from '@/utils/pwa' +import { isAppleMobile, isMobileButNotInstalledOnHomeScreen, isNonSafari } from '@/utils/pwa' import { notificationPwaModalService, signatureModalService } from '@/utils/store' import { isMobile } from '@/utils/ui' @@ -34,15 +35,21 @@ export const Modals = () => { const notificationModalClosed = checkIfNotificationModalClosed() const explicitlyDeniedOnDesktop = !isMobile() && window.Notification?.permission === 'denied' + const shouldShowChangeBrowserModal = isAppleMobile ? isNonSafari : false + const shouldShowPWAModal = isMobileButNotInstalledOnHomeScreen && !shouldShowChangeBrowserModal + const shouldShowSignatureModal = isSignatureModalOpen && !shouldShowChangeBrowserModal + const shouldShowUnsubscribeModalOpen = isUnsubscribeModalOpen && !shouldShowChangeBrowserModal + const shouldShowPreferencesModalOpen = isPreferencesModalOpen && !shouldShowChangeBrowserModal const shouldShowNotificationModal = notificationsEnabledInBrowser() && !explicitlyDeniedOnDesktop && - !isMobileButNotInstalledOnHomeScreen() && + !isMobileButNotInstalledOnHomeScreen && !notificationsEnabled && Boolean(notifyRegisteredKey) && !isSignatureModalOpen && - !notificationModalClosed + !notificationModalClosed && + !shouldShowChangeBrowserModal useEffect(() => { const notifySignatureRequired = Boolean(notifyRegisterMessage) && !notifyRegisteredKey @@ -67,17 +74,19 @@ export const Modals = () => { return ( - {isUnsubscribeModalOpen && } + {shouldShowUnsubscribeModalOpen && } - {isPreferencesModalOpen && } + {shouldShowPreferencesModalOpen && } - {isSignatureModalOpen && ( + {shouldShowSignatureModal && ( )} - {isMobileButNotInstalledOnHomeScreen() && } + {shouldShowPWAModal && } {isNotificationPwaModalOpen && } + + {shouldShowChangeBrowserModal && } ) } diff --git a/src/components/utils/ChangeBrowserModal/ChangeBrowserModal.scss b/src/components/utils/ChangeBrowserModal/ChangeBrowserModal.scss new file mode 100644 index 00000000..ee627eb7 --- /dev/null +++ b/src/components/utils/ChangeBrowserModal/ChangeBrowserModal.scss @@ -0,0 +1,54 @@ +.ChangeBrowserModal { + padding: 3em; + display: flex; + flex-direction: column; + text-align: center; + align-items: center; + gap: 2em; + position: relative; + + &__close-button { + svg { + color: var(--fg-color-3); + } + } + + &__header { + display: flex; + justify-content: flex-end; + width: 100%; + align-items: center; + } + + &__background { + position: absolute; + z-index: -999; + top: -50%; + left: -50%; + } + + &__icon { + display: block; + width: 3em; + background: white; + width: 4em; + height: 4em; + display: grid; + place-items: center; + padding: 0.75em; + border-radius: 13px; + box-shadow: 0px 8px 32px 17.5px hsla(0, 0%, 0%, 0.12); + } + + &__warning { + color: var(--error-color-1); + } + + &__content { + display: flex; + flex-direction: column; + gap: 1em; + align-items: center; + text-align: center; + } +} diff --git a/src/components/utils/ChangeBrowserModal/index.tsx b/src/components/utils/ChangeBrowserModal/index.tsx new file mode 100644 index 00000000..07e4ea7a --- /dev/null +++ b/src/components/utils/ChangeBrowserModal/index.tsx @@ -0,0 +1,34 @@ +import React from 'react' + +import BackgroundImage from '@/assets/IntroBackground.png' +import { Modal } from '@/components/general/Modal/Modal' +import Text from '@/components/general/Text' +import { pwaModalService } from '@/utils/store' + +import './ChangeBrowserModal.scss' + +export const ChangeBrowserModal: React.FC = () => { + return ( + +
+
+ +
+
+ Web3Inbox icon +
+ Change Browser +
+ + To install the app, you need to add this to your home screen. + + + Please open app.web3inbox.com in Safari and follow the instructions. + +
+
+
+ ) +} + +export default ChangeBrowserModal diff --git a/src/components/utils/PwaModal/index.tsx b/src/components/utils/PwaModal/index.tsx index 7c7b02b6..bfbb4f42 100644 --- a/src/components/utils/PwaModal/index.tsx +++ b/src/components/utils/PwaModal/index.tsx @@ -58,7 +58,7 @@ export const PwaModal: React.FC = () => { Web3Inbox icon
- Install Web3Inbox + Install PWA
diff --git a/src/utils/pwa.ts b/src/utils/pwa.ts index 1d2c8e7f..cd7abfdb 100644 --- a/src/utils/pwa.ts +++ b/src/utils/pwa.ts @@ -1,12 +1,15 @@ -export const isInstalledOnHomescreen = () => { - // on Android and iOS, display mode is set to - // standalone when the app is opened from home screen - const displayIsStandalone = window.matchMedia('(display-mode: standalone)').matches +export const isInstalledOnHomeScreen = window.matchMedia('(display-mode: standalone)').matches - return displayIsStandalone -} +export const isMobileBrowser = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) -export const isMobileBrowser = () => /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) +export const isAppleMobile = /iPhone|iPad|iPod/i.test(navigator.userAgent) -export const isMobileButNotInstalledOnHomeScreen = () => - isMobileBrowser() && !isInstalledOnHomescreen() +/** + * WARN: Browser check can be tricky and not reliable at some cases. + * Some non-Safari browsers can return the same `userAgent` value as Safari, so it might not be quite possible to detect if the browser is Safari or not. + * There are several fields like `vendor` (deprecated), `userAgent`, `userAgentData`. Some of these are deprecated and some are returning similar values across different browsers like `userAgent`. + * So be aware that is not perfect solution. + */ +export const isNonSafari = /CriOS|FxiOS/i.test(navigator.userAgent) + +export const isMobileButNotInstalledOnHomeScreen = isMobileBrowser && !isInstalledOnHomeScreen