mirror of
https://github.com/status-im/safe-react.git
synced 2025-02-19 13:14:22 +00:00
Add models, reducers, actions and selectors for notification handling
This commit is contained in:
parent
4335ec6c09
commit
d4ed0d7f4a
8
src/logic/notifications/store/actions/closeSnackbar.js
Normal file
8
src/logic/notifications/store/actions/closeSnackbar.js
Normal file
@ -0,0 +1,8 @@
|
||||
// @flow
|
||||
import { createAction } from 'redux-actions'
|
||||
|
||||
export const CLOSE_SNACKBAR = 'CLOSE_SNACKBAR'
|
||||
|
||||
const closeSnackbar = createAction<string, *>(CLOSE_SNACKBAR)
|
||||
|
||||
export default closeSnackbar
|
24
src/logic/notifications/store/actions/enqueueSnackbar.js
Normal file
24
src/logic/notifications/store/actions/enqueueSnackbar.js
Normal file
@ -0,0 +1,24 @@
|
||||
// @flow
|
||||
import { createAction } from 'redux-actions'
|
||||
import type { Dispatch as ReduxDispatch, GetState } from 'redux'
|
||||
import { type GlobalState } from '~/store'
|
||||
import { type NotificationProps } from '~/logic/notifications/store/models/notification'
|
||||
|
||||
export const ENQUEUE_SNACKBAR = 'ENQUEUE_SNACKBAR'
|
||||
|
||||
const addSnackbar = createAction<string, *, *>(ENQUEUE_SNACKBAR, (notification: NotificationProps): ActionReturn => ({
|
||||
notification,
|
||||
}))
|
||||
|
||||
const enqueueSnackbar = (notification: NotificationProps) => (
|
||||
dispatch: ReduxDispatch<GlobalState>,
|
||||
getState: GetState<GlobalState>,
|
||||
) => {
|
||||
const newNotification = {
|
||||
...notification,
|
||||
key: new Date().getTime() + Math.random(),
|
||||
}
|
||||
dispatch(addSnackbar(newNotification))
|
||||
}
|
||||
|
||||
export default enqueueSnackbar
|
8
src/logic/notifications/store/actions/removeSnackbar.js
Normal file
8
src/logic/notifications/store/actions/removeSnackbar.js
Normal file
@ -0,0 +1,8 @@
|
||||
// @flow
|
||||
import { createAction } from 'redux-actions'
|
||||
|
||||
export const REMOVE_SNACKBAR = 'REMOVE_SNACKBAR'
|
||||
|
||||
const removeSnackbar = createAction<string, *>(REMOVE_SNACKBAR)
|
||||
|
||||
export default removeSnackbar
|
17
src/logic/notifications/store/models/notification.js
Normal file
17
src/logic/notifications/store/models/notification.js
Normal file
@ -0,0 +1,17 @@
|
||||
// @flow
|
||||
import { Record } from 'immutable'
|
||||
import type { RecordFactory, RecordOf } from 'immutable'
|
||||
|
||||
export type NotificationProps = {
|
||||
message: string,
|
||||
options: Object,
|
||||
dismissed: boolean,
|
||||
}
|
||||
|
||||
export const makeNotification: RecordFactory<NotificationProps> = Record({
|
||||
message: '',
|
||||
options: {},
|
||||
dismissed: false,
|
||||
})
|
||||
|
||||
export type Notification = RecordOf<NotificationProps>
|
38
src/logic/notifications/store/reducer/notifications.js
Normal file
38
src/logic/notifications/store/reducer/notifications.js
Normal file
@ -0,0 +1,38 @@
|
||||
// @flow
|
||||
import { Map } from 'immutable'
|
||||
import { handleActions, type ActionType } from 'redux-actions'
|
||||
import { makeNotification, type NotificationProps } from '~/logic/notifications/store/models/notification'
|
||||
import { ENQUEUE_SNACKBAR } from '../actions/enqueueSnackbar'
|
||||
import { CLOSE_SNACKBAR } from '../actions/closeSnackbar'
|
||||
import { REMOVE_SNACKBAR } from '../actions/removeSnackbar'
|
||||
|
||||
export const NOTIFICATIONS_REDUCER_ID = 'notifications'
|
||||
|
||||
export type NotificationReducerState = Map<string, *>
|
||||
|
||||
export default handleActions<NotificationReducerState, *>(
|
||||
{
|
||||
[ENQUEUE_SNACKBAR]: (state: NotificationReducerState, action: ActionType<Function>): NotificationReducerState => {
|
||||
const { notification }: { notification: NotificationProps } = action.payload
|
||||
|
||||
if (state.hasIn(['notifications', notification.options.key])) {
|
||||
return state.updateIn(['notifications', notification.options.key], (prev) => prev.merge(notification))
|
||||
}
|
||||
return state.setIn(['notifications', notification.options.key], makeNotification(notification))
|
||||
},
|
||||
[CLOSE_SNACKBAR]: (state: NotificationReducerState, action: ActionType<Function>): NotificationReducerState => {
|
||||
const { notification }: { notification: NotificationProps } = action.payload
|
||||
notification.dismissed = true
|
||||
|
||||
return state.updateIn(['notifications', notification.key], (prev) => prev.merge(notification))
|
||||
},
|
||||
[REMOVE_SNACKBAR]: (state: NotificationReducerState, action: ActionType<Function>): NotificationReducerState => {
|
||||
const key = action.payload
|
||||
|
||||
return state.deleteIn(['notification', key])
|
||||
},
|
||||
},
|
||||
Map({
|
||||
notifications: Map(),
|
||||
}),
|
||||
)
|
15
src/logic/notifications/store/selectors/index.js
Normal file
15
src/logic/notifications/store/selectors/index.js
Normal file
@ -0,0 +1,15 @@
|
||||
// @flow
|
||||
import { List, Map } from 'immutable'
|
||||
import { createSelector, type Selector } from 'reselect'
|
||||
import { type GlobalState } from '~/store'
|
||||
import { NOTIFICATIONS_REDUCER_ID } from '~/logic/notifications/store/reducer/notifications'
|
||||
import { type Notification } from '~/logic/notifications/store/models/notification'
|
||||
|
||||
export const notificationsMapSelector = (
|
||||
state: GlobalState,
|
||||
): Map<string, Notification> => state[NOTIFICATIONS_REDUCER_ID]
|
||||
|
||||
export const notificationsListSelector: Selector<GlobalState, {}, List<Notification>> = createSelector(
|
||||
notificationsMapSelector,
|
||||
(notifications: Map<string, Notification>): List<Notification> => notifications.toList(),
|
||||
)
|
@ -4,6 +4,8 @@ import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3'
|
||||
import type { ProviderProps } from '~/logic/wallets/store/model/provider'
|
||||
import { makeProvider } from '~/logic/wallets/store/model/provider'
|
||||
import { NOTIFICATIONS } from '~/logic/notifications'
|
||||
import enqueueSnackbar from '~/logic/notifications/store/actions/enqueueSnackbar'
|
||||
import closeSnackbar from '~/logic/notifications/store/actions/closeSnackbar'
|
||||
import addProvider from './addProvider'
|
||||
|
||||
export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => {
|
||||
@ -22,7 +24,7 @@ export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: Pr
|
||||
dispatch(addProvider(walletRecord))
|
||||
}
|
||||
|
||||
const handleProviderNotification = (enqueueSnackbar: Function, closeSnackbar: Function, provider: ProviderProps) => {
|
||||
const handleProviderNotification = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => {
|
||||
const { loaded, available, network } = provider
|
||||
|
||||
if (!loaded) {
|
||||
@ -40,15 +42,26 @@ const handleProviderNotification = (enqueueSnackbar: Function, closeSnackbar: Fu
|
||||
enqueueSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG.description, NOTIFICATIONS.RINKEBY_VERSION_MSG.options)
|
||||
|
||||
if (available) {
|
||||
enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.description, NOTIFICATIONS.WALLET_CONNECTED_MSG.options)
|
||||
// NOTE:
|
||||
// if you want to be able to dispatch a `closeSnackbar` action later on,
|
||||
// you SHOULD pass your own `key` in the options. `key` can be any sequence
|
||||
// of number or characters, but it has to be unique to a given snackbar.
|
||||
dispatch(
|
||||
enqueueSnackbar({
|
||||
message: NOTIFICATIONS.WALLET_CONNECTED_MSG.description,
|
||||
options: {
|
||||
...NOTIFICATIONS.WALLET_CONNECTED_MSG.options,
|
||||
key: new Date().getTime() + Math.random(),
|
||||
},
|
||||
}),
|
||||
)
|
||||
// enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.description, NOTIFICATIONS.WALLET_CONNECTED_MSG.options)
|
||||
} else {
|
||||
enqueueSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG.description, NOTIFICATIONS.UNLOCK_WALLET_MSG.options)
|
||||
}
|
||||
}
|
||||
|
||||
export default (provider: ProviderProps, enqueueSnackbar: Function, closeSnackbar: Function) => (
|
||||
dispatch: ReduxDispatch<*>,
|
||||
) => {
|
||||
handleProviderNotification(enqueueSnackbar, closeSnackbar, provider)
|
||||
export default (provider: ProviderProps) => (dispatch: ReduxDispatch<*>) => {
|
||||
handleProviderNotification(dispatch, provider)
|
||||
processProviderResponse(dispatch, provider)
|
||||
}
|
||||
|
@ -5,14 +5,18 @@ import {
|
||||
combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store,
|
||||
} from 'redux'
|
||||
import thunk from 'redux-thunk'
|
||||
import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider'
|
||||
import safe, { SAFE_REDUCER_ID, type SafeReducerState as SafeState } from '~/routes/safe/store/reducer/safe'
|
||||
import safeStorage from '~/routes/safe/store/middleware/safeStorage'
|
||||
import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/logic/tokens/store/reducer/tokens'
|
||||
import transactions, {
|
||||
type State as TransactionsState,
|
||||
TRANSACTIONS_REDUCER_ID,
|
||||
} from '~/routes/safe/store/reducer/transactions'
|
||||
import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider'
|
||||
import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/logic/tokens/store/reducer/tokens'
|
||||
import notifications, {
|
||||
NOTIFICATIONS_REDUCER_ID,
|
||||
type State as NotificationsState,
|
||||
} from '~/logic/notifications/store/reducer/notifications'
|
||||
|
||||
export const history = createBrowserHistory()
|
||||
|
||||
@ -25,6 +29,7 @@ export type GlobalState = {
|
||||
safes: SafeState,
|
||||
tokens: TokensState,
|
||||
transactions: TransactionsState,
|
||||
notifications: NotificationsState,
|
||||
}
|
||||
|
||||
export type GetState = () => GlobalState
|
||||
@ -35,8 +40,13 @@ const reducers: Reducer<GlobalState> = combineReducers({
|
||||
[SAFE_REDUCER_ID]: safe,
|
||||
[TOKEN_REDUCER_ID]: tokens,
|
||||
[TRANSACTIONS_REDUCER_ID]: transactions,
|
||||
[NOTIFICATIONS_REDUCER_ID]: notifications,
|
||||
})
|
||||
|
||||
export const store: Store<GlobalState> = createStore(reducers, finalCreateStore)
|
||||
|
||||
export const aNewStore = (localState?: Object): Store<GlobalState> => createStore(reducers, localState, finalCreateStore)
|
||||
export const aNewStore = (localState?: Object): Store<GlobalState> => createStore(
|
||||
reducers,
|
||||
localState,
|
||||
finalCreateStore,
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user