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 (
+
+
+
+
+
+
+
+
+
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 = () => {
- 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