diff --git a/src/components/settings/PushNotifications/PushNotificationsBanner/index.tsx b/src/components/settings/PushNotifications/PushNotificationsBanner/index.tsx index baa7df4ad5..c1fdd57963 100644 --- a/src/components/settings/PushNotifications/PushNotificationsBanner/index.tsx +++ b/src/components/settings/PushNotifications/PushNotificationsBanner/index.tsx @@ -1,19 +1,19 @@ +import { useEffect, useRef, type ReactElement } from 'react' import { Button, Chip, Grid, SvgIcon, Typography, IconButton } from '@mui/material' import Link from 'next/link' import { useRouter } from 'next/router' -import { useCallback, useEffect, useRef } from 'react' -import type { ReactElement } from 'react' import { CustomTooltip } from '@/components/common/CustomTooltip' import { AppRoutes } from '@/config/routes' import { useAppSelector } from '@/store' -import { selectAddedSafes, selectAllAddedSafes, selectTotalAdded } from '@/store/addedSafesSlice' +import { selectAddedSafes, selectAllAddedSafes } from '@/store/addedSafesSlice' import PushNotificationIcon from '@/public/images/notifications/push-notification.svg' import useLocalStorage from '@/services/local-storage/useLocalStorage' import { useNotificationRegistrations } from '../hooks/useNotificationRegistrations' import { PUSH_NOTIFICATION_EVENTS } from '@/services/analytics/events/push-notifications' import { trackEvent } from '@/services/analytics' import useSafeInfo from '@/hooks/useSafeInfo' +import useChainId from '@/hooks/useChainId' import CheckWallet from '@/components/common/CheckWallet' import CloseIcon from '@/public/images/common/close.svg' import { useNotificationPreferences } from '../hooks/useNotificationPreferences' @@ -22,6 +22,7 @@ import useOnboard from '@/hooks/wallets/useOnboard' import { assertWalletChain } from '@/services/tx/tx-sender/sdk' import { useCurrentChain, useHasFeature } from '@/hooks/useChains' import { FEATURES } from '@/utils/chains' +import useWallet from '@/hooks/wallets/useWallet' import type { AddedSafesOnChain } from '@/store/addedSafesSlice' import type { PushNotificationPreferences } from '@/services/push-notifications/preferences' import type { NotifiableSafes } from '../logic' @@ -86,69 +87,146 @@ export const _getSafesToRegister = ( return { [chainId]: newlyAddedSafes } } -const TrackBanner = (): null => { - const hasTracked = useRef(false) +type BannerProps = { + children: ReactElement + onDismiss?: () => void + onCustomize?: () => void + onEnableAll?: () => void +} - useEffect(() => { - if (hasTracked.current) { - return - } +const Banner = ({ children, onDismiss, onEnableAll, onCustomize }: BannerProps) => { + const { chainName = '' } = useCurrentChain() || {} + const { query } = useRouter() - trackEvent(PUSH_NOTIFICATION_EVENTS.SHOW_BANNER) - hasTracked.current = true - }, []) + return ( + + + + + - return null + + + Enable push notifications + + + + + + + + Get notified about pending signatures, incoming and outgoing transactions for all Safe Accounts on{' '} + {chainName} when {`Safe{Wallet}`} is in the background or closed. + + + {/* Cannot wrap singular button as it causes style inconsistencies */} + + {(isOk) => ( + + + Enable all + + + + + Customize + + + + )} + + + + } + open + > + {children} + + ) } -export const PushNotificationsBanner = ({ children }: { children: ReactElement }): ReactElement => { - const isNotificationFeatureEnabled = useHasFeature(FEATURES.PUSH_NOTIFICATIONS) - const chain = useCurrentChain() - const totalAddedSafes = useAppSelector(selectTotalAdded) - const { safe, safeAddress } = useSafeInfo() - const addedSafesOnChain = useAppSelector((state) => selectAddedSafes(state, safe.chainId)) - const { query } = useRouter() +const useEnableAll = (addedSafes: AddedSafesOnChain | undefined) => { + const chainId = useChainId() const onboard = useOnboard() + const { getAllPreferences } = useNotificationPreferences() + const { registerNotifications } = useNotificationRegistrations() + + return async () => { + if (!onboard || !addedSafes) return + + const allPreferences = getAllPreferences() + const safesToRegister = _getSafesToRegister(chainId, addedSafes, allPreferences) + + await assertWalletChain(onboard, chainId) + await registerNotifications(safesToRegister) + } +} - const { getPreferences, getAllPreferences } = useNotificationPreferences() - const { dismissPushNotificationBanner, isPushNotificationBannerDismissed } = useDismissPushNotificationsBanner() +const useShowBanner = (addedSafes: AddedSafesOnChain | undefined): boolean => { + const isNotificationFeatureEnabled = useHasFeature(FEATURES.PUSH_NOTIFICATIONS) + const { safe, safeAddress } = useSafeInfo() + const wallet = useWallet() + const { getPreferences } = useNotificationPreferences() + const { isPushNotificationBannerDismissed } = useDismissPushNotificationsBanner() - const isSafeAdded = !!addedSafesOnChain?.[safeAddress] + const isSafeAdded = !!addedSafes?.[safeAddress] const isSafeRegistered = getPreferences(safe.chainId, safeAddress) + const shouldShowBanner = - isNotificationFeatureEnabled && !isPushNotificationBannerDismissed && isSafeAdded && !isSafeRegistered + isNotificationFeatureEnabled && !isPushNotificationBannerDismissed && isSafeAdded && !isSafeRegistered && !!wallet - const { registerNotifications } = useNotificationRegistrations() + return shouldShowBanner +} - const dismissBanner = useCallback(() => { - trackEvent(PUSH_NOTIFICATION_EVENTS.DISMISS_BANNER) - dismissPushNotificationBanner(safe.chainId) - }, [dismissPushNotificationBanner, safe.chainId]) +export const PushNotificationsBanner = ({ children }: { children: ReactElement }): ReactElement => { + const chainId = useChainId() + const addedSafesOnChain = useAppSelector((state) => selectAddedSafes(state, chainId)) + const { dismissPushNotificationBanner } = useDismissPushNotificationsBanner() + const hasTracked = useRef(false) + const enableAll = useEnableAll(addedSafesOnChain) + const shouldShowBanner = useShowBanner(addedSafesOnChain) - const onEnableAll = async () => { - if (!onboard || !addedSafesOnChain) { - return - } + // Track the banner impression + useEffect(() => { + if (!shouldShowBanner || hasTracked.current) return + trackEvent(PUSH_NOTIFICATION_EVENTS.SHOW_BANNER) + hasTracked.current = true + }, [shouldShowBanner]) - trackEvent(PUSH_NOTIFICATION_EVENTS.ENABLE_ALL) + // Dismiss the banner + const dismissBanner = () => { + dismissPushNotificationBanner(chainId) + } - const allPreferences = getAllPreferences() - const safesToRegister = _getSafesToRegister(safe.chainId, addedSafesOnChain, allPreferences) + // On dismiss, track the event and dismiss the banner + const onDismiss = () => { + trackEvent(PUSH_NOTIFICATION_EVENTS.DISMISS_BANNER) + dismissBanner + } + // On enable all, track the event and enable all notifications + const onEnableAll = async () => { + trackEvent(PUSH_NOTIFICATION_EVENTS.ENABLE_ALL) try { - await assertWalletChain(onboard, safe.chainId) + await enableAll() } catch { return } - - await registerNotifications(safesToRegister) - dismissBanner() } + // On customize, track the event and navigate to the settings page const onCustomize = () => { trackEvent(PUSH_NOTIFICATION_EVENTS.CUSTOMIZE_SETTINGS) - dismissBanner() } @@ -157,60 +235,8 @@ export const PushNotificationsBanner = ({ children }: { children: ReactElement } } return ( - <> - - - - - - - - - Enable push notifications - - - - - - Get notified about pending signatures, incoming and outgoing transactions for all Safe Accounts on{' '} - {chain?.chainName} when Safe - {`{Wallet}`} is in the background or closed. - - {/* Cannot wrap singular button as it causes style inconsistencies */} - - {(isOk) => ( - - {totalAddedSafes > 0 && ( - - Enable all - - )} - {safe && ( - - - Customize - - - )} - - )} - - - - } - open - > - {children} - - > + + {children} + ) }