Skip to content
This repository was archived by the owner on Dec 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions src/Modals.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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'

Expand All @@ -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
Expand All @@ -67,17 +74,19 @@ export const Modals = () => {

return (
<AnimatePresence mode="popLayout">
{isUnsubscribeModalOpen && <UnsubscribeModal />}
{shouldShowUnsubscribeModalOpen && <UnsubscribeModal />}

{isPreferencesModalOpen && <PreferencesModal />}
{shouldShowPreferencesModalOpen && <PreferencesModal />}

{isSignatureModalOpen && (
{shouldShowSignatureModal && (
<SignatureModal message={notifyRegisterMessage ?? ''} sender={'notify'} />
)}

{isMobileButNotInstalledOnHomeScreen() && <PwaModal />}
{shouldShowPWAModal && <PwaModal />}

{isNotificationPwaModalOpen && <NotificationPwaModal />}

{shouldShowChangeBrowserModal && <ChangeBrowserModal />}
</AnimatePresence>
)
}
54 changes: 54 additions & 0 deletions src/components/utils/ChangeBrowserModal/ChangeBrowserModal.scss
Original file line number Diff line number Diff line change
@@ -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;
}
}
34 changes: 34 additions & 0 deletions src/components/utils/ChangeBrowserModal/index.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Modal onCloseModal={pwaModalService.closeModal}>
<div className="ChangeBrowserModal">
<div className="ChangeBrowserModal__background">
<img src={BackgroundImage} />
</div>
<div className="ChangeBrowserModal__icon">
<img alt="Web3Inbox icon" className="wc-icon" src="/icon.png" />
</div>
<Text variant={'large-500'}>Change Browser</Text>
<div className="ChangeBrowserModal__content">
<Text variant="small-500">
To install the app, you need to add this to your home screen.
</Text>
<Text variant="small-500">
Please open <span>app.web3inbox.com</span> in Safari and follow the instructions.
</Text>
</div>
</div>
</Modal>
)
}

export default ChangeBrowserModal
2 changes: 1 addition & 1 deletion src/components/utils/PwaModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const PwaModal: React.FC = () => {
<img alt="Web3Inbox icon" className="wc-icon" src="/icon.png" />
</div>
<div className="PwaModal__header">
<Text variant={'large-500'}>Install Web3Inbox</Text>
<Text variant={'large-500'}>Install PWA</Text>
</div>
<div className="PwaModal__description">
<Text variant="small-500">
Expand Down
21 changes: 12 additions & 9 deletions src/utils/pwa.ts
Original file line number Diff line number Diff line change
@@ -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