Skip to content
This repository has been archived by the owner on Nov 10, 2023. It is now read-only.

refactor: cleanup notifications system #3926

Merged
merged 5 commits into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"@openzeppelin/contracts": "4.4.2",
"@sentry/react": "^6.10.0",
"@sentry/tracing": "^6.10.0",
"@truffle/hdwallet-provider": "^2.0.8",
"@unstoppabledomains/resolution": "^1.17.0",
"abi-decoder": "^2.4.0",
"axios": "0.21.4",
Expand All @@ -110,7 +111,7 @@
"immutable": "4.0.0-rc.12",
"js-cookie": "^3.0.0",
"lodash": "^4.17.21",
"notistack": "https://github.com/gnosis/notistack.git#v0.9.5",
"notistack": "1.0.10",
"object-hash": "^2.1.1",
"qrcode.react": "1.0.1",
"query-string": "7.0.1",
Expand Down Expand Up @@ -138,8 +139,7 @@
"web3": "1.7.0",
"web3-core": "^1.7.0",
"web3-eth-contract": "^1.7.0",
"web3-utils": "^1.7.0",
"@truffle/hdwallet-provider": "^2.0.8"
"web3-utils": "^1.7.0"
},
"devDependencies": {
"@gnosis.pm/safe-core-sdk-types": "1.0.0",
Expand Down
5 changes: 0 additions & 5 deletions src/components/Notifier/actions.ts

This file was deleted.

72 changes: 0 additions & 72 deletions src/components/Notifier/index.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/components/Notifier/selector.ts

This file was deleted.

57 changes: 44 additions & 13 deletions src/components/Providers/SnackbarProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import AlertIcon from 'src/assets/icons/alert.svg'
import CheckIcon from 'src/assets/icons/check.svg'
import ErrorIcon from 'src/assets/icons/error.svg'
import InfoIcon from 'src/assets/icons/info.svg'
import Notifier from 'src/components/Notifier'
import useNotifier from 'src/logic/hooks/useNotifier'
import { fontColor, secondaryText, sm } from 'src/theme/variables'

type SnackBarProviderProps = {
children: ReactNode
}

const notificationStyles = {
const useStyles = makeStyles({
containerRoot: {
top: '50px',
},
root: {
width: '340px',
},
success: {
background: '#fff',
},
Expand All @@ -26,17 +29,47 @@ const notificationStyles = {
info: {
background: '#fff',
},
}
snackbar: {
borderRadius: `${sm}`,
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
flexWrap: 'nowrap',
padding: '20px',
alignItems: 'space-between',
'& div:first-child': {
color: fontColor,
padding: '0 10px 0 0',
alignItems: 'stretch',
overflowY: 'auto',
maxHeight: '160px',
'& > img': {
marginRight: '13px',
},
},
'& div:last-child': {
paddingLeft: '0',
'& > button': {
color: secondaryText,
},
},
},
})

const useStyles = makeStyles(notificationStyles)
// Hook must be inside the provider
const Notifier = (): null => {
useNotifier()
return null
}

const CustomSnackBarProvider = ({ children }: SnackBarProviderProps): React.ReactElement => {
const CustomSnackBarProvider = ({ children }: { children: ReactNode }): React.ReactElement => {
const classes = useStyles()

return (
<SnackbarProvider
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
className={classes.snackbar}
classes={{
containerRoot: classes.containerRoot,
root: classes.root,
variantSuccess: classes.success,
variantError: classes.error,
variantWarning: classes.warning,
Expand All @@ -50,10 +83,8 @@ const CustomSnackBarProvider = ({ children }: SnackBarProviderProps): React.Reac
}}
maxSnack={5}
>
<>
{children}
<Notifier />
</>
{children}
<Notifier />
</SnackbarProvider>
)
}
Expand Down
34 changes: 14 additions & 20 deletions src/logic/addressBook/store/middleware/index.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
import { ADDRESS_BOOK_ACTIONS } from 'src/logic/addressBook/store/actions'
import { enhanceSnackbarForAction, getNotificationsFromTxType } from 'src/logic/notifications'
import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar'
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
import { showNotification } from 'src/logic/notifications/store/notifications'
import { NOTIFICATIONS } from 'src/logic/notifications'
import { AppReduxState } from 'src/store'
import { ThunkMiddleware } from 'redux-thunk'

const watchedActions = Object.values(ADDRESS_BOOK_ACTIONS)
export const addressBookMiddleware: ThunkMiddleware<AppReduxState> =
({ dispatch }) =>
(next) =>
(action) => {
const handledAction = next(action)

export const addressBookMiddleware = (store) => (next) => async (action) => {
const handledAction = next(action)
if (watchedActions.includes(action.type)) {
const { dispatch } = store
switch (action.type) {
case ADDRESS_BOOK_ACTIONS.ADD_OR_UPDATE: {
const { shouldAvoidUpdatesNotifications } = action.payload
if (!shouldAvoidUpdatesNotifications) {
const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.ADDRESS_BOOK_NEW_ENTRY)
dispatch(enqueueSnackbar(enhanceSnackbarForAction(notification.afterExecution.noMoreConfirmationsNeeded)))
}
dispatch(showNotification(NOTIFICATIONS.ADDRESS_BOOK_NEW_ENTRY_SUCCESS))
break
}
case ADDRESS_BOOK_ACTIONS.REMOVE: {
const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.ADDRESS_BOOK_DELETE_ENTRY)
dispatch(enqueueSnackbar(enhanceSnackbarForAction(notification.afterExecution.noMoreConfirmationsNeeded)))
dispatch(showNotification(NOTIFICATIONS.ADDRESS_BOOK_DELETE_ENTRY_SUCCESS))
break
}
case ADDRESS_BOOK_ACTIONS.IMPORT: {
const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.ADDRESS_BOOK_IMPORT_ENTRIES)
dispatch(enqueueSnackbar(enhanceSnackbarForAction(notification.afterExecution.noMoreConfirmationsNeeded)))
dispatch(showNotification(NOTIFICATIONS.ADDRESS_BOOK_IMPORT_ENTRIES_SUCCESS))
break
}
default:
break
}
}

return handledAction
}
return handledAction
}
50 changes: 50 additions & 0 deletions src/logic/hooks/useNotifier.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { SnackbarKey, useSnackbar } from 'notistack'
import { IconButton } from '@material-ui/core'
import CloseIcon from '@material-ui/icons/Close'

import { selectNotifications, closeNotification } from 'src/logic/notifications/store/notifications'

let onScreenKeys: SnackbarKey[] = []

const useNotifier = (): void => {
const notifications = useSelector(selectNotifications)
const { closeSnackbar, enqueueSnackbar } = useSnackbar()
const dispatch = useDispatch()

useEffect(() => {
for (const notification of notifications) {
// Unspecified keys are automatically generated in `enqueueSnackbar` thunk
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const key = notification.options!.key!

if (notification.dismissed) {
closeSnackbar(key)
continue
}

if (onScreenKeys.includes(key)) {
continue
}

enqueueSnackbar(notification.message, {
...notification.options,
onExited: () => {
// Cleanup store/cache when notification has unmounted
dispatch(closeNotification({ key }))
onScreenKeys = onScreenKeys.filter((onScreenKey) => onScreenKey !== key)
},
action: (
<IconButton onClick={() => dispatch(closeNotification({ key }))}>
<CloseIcon />
</IconButton>
),
})

onScreenKeys = [...onScreenKeys, key]
}
}, [notifications, closeSnackbar, enqueueSnackbar, dispatch])
}

export default useNotifier
2 changes: 1 addition & 1 deletion src/logic/notifications/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './notificationTypes'
export * from './notificationBuilder'
export * from './txNotificationBuilder'
Loading