-
Notifications
You must be signed in to change notification settings - Fork 5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Alert user upon switching to unconnected account
An alert is now shown when the user switches from an account that is connected to the active tab to an account that is not connected. The alert prompts the user to dismiss the alert or connect the account they're switching to. The "loading" state is handled by disabling the buttons, and the error state is handled by displaying a generic error message and disabling the connect button. The new reducer for this alert has been created with `createSlice` from the Redux Toolkit. This utility is recommended by the Redux team, and represents a new style of writing reducers that I hope we will use more in the future (or at least something similar). `createSlice` constructs a reducer, actions, and action creators automatically. The reducer is constructed using their `createReducer` helper, which uses Immer to allow directly mutating the state in the reducer but exposing these changes as immutable.
- Loading branch information
Showing
19 changed files
with
282 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from 'react' | ||
import { useSelector } from 'react-redux' | ||
|
||
import UnconnectedAccountAlert from './unconnected-account-alert' | ||
import { alertIsOpen as unconnectedAccountAlertIsOpen } from '../../../ducks/alerts/unconnected-account' | ||
|
||
const Alerts = () => { | ||
const _unconnectedAccountAlertIsOpen = useSelector(unconnectedAccountAlertIsOpen) | ||
|
||
if (_unconnectedAccountAlertIsOpen) { | ||
return ( | ||
<UnconnectedAccountAlert /> | ||
) | ||
} | ||
|
||
return null | ||
} | ||
|
||
export default Alerts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
@import './unconnected-account-alert/unconnected-account-alert.scss'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './alerts' |
1 change: 1 addition & 0 deletions
1
ui/app/components/app/alerts/unconnected-account-alert/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './unconnected-account-alert' |
63 changes: 63 additions & 0 deletions
63
ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import React, { useContext } from 'react' | ||
import { useDispatch, useSelector } from 'react-redux' | ||
|
||
import { | ||
ALERT_STATE, | ||
connectAccount, | ||
dismissAlert, | ||
getAlertState, | ||
} from '../../../../ducks/alerts/unconnected-account' | ||
import { I18nContext } from '../../../../contexts/i18n' | ||
import Popover from '../../../ui/popover' | ||
import Button from '../../../ui/button' | ||
|
||
const { | ||
ERROR, | ||
LOADING, | ||
} = ALERT_STATE | ||
|
||
const SwitchToUnconnectedAccountAlert = () => { | ||
const t = useContext(I18nContext) | ||
const dispatch = useDispatch() | ||
const alertState = useSelector(getAlertState) | ||
|
||
return ( | ||
<Popover | ||
title={t('unconnectedAccountAlertTitle')} | ||
subtitle={t('unconnectedAccountAlertDescription')} | ||
onClose={() => dispatch(dismissAlert())} | ||
footer={( | ||
<> | ||
{ | ||
alertState === ERROR | ||
? ( | ||
<div className="unconnected-account-alert__error"> | ||
{ t('failureMessage') } | ||
</div> | ||
) | ||
: null | ||
} | ||
<div className="unconnected-account-alert__footer-buttons"> | ||
<Button | ||
disabled={alertState === LOADING} | ||
onClick={() => dispatch(dismissAlert())} | ||
type="secondary" | ||
> | ||
{ t('dismiss') } | ||
</Button> | ||
<Button | ||
disabled={alertState === LOADING || alertState === ERROR} | ||
onClick={() => dispatch(connectAccount())} | ||
type="primary" | ||
> | ||
{ t('connect') } | ||
</Button> | ||
</div> | ||
</> | ||
)} | ||
footerClassName="unconnected-account-alert__footer" | ||
/> | ||
) | ||
} | ||
|
||
export default SwitchToUnconnectedAccountAlert |
27 changes: 27 additions & 0 deletions
27
ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.unconnected-account-alert { | ||
&__footer { | ||
flex-direction: column; | ||
|
||
:only-child { | ||
margin: 0; | ||
} | ||
} | ||
|
||
&__footer-buttons { | ||
display: flex; | ||
flex-direction: row; | ||
|
||
button:first-child { | ||
margin-right: 24px; | ||
} | ||
} | ||
|
||
&__error { | ||
margin-bottom: 16px; | ||
padding: 16px; | ||
font-size: 14px; | ||
border: 1px solid #D73A49; | ||
background: #F8EAE8; | ||
border-radius: 3px; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import unconnectedAccount from './unconnected-account' | ||
|
||
export default { | ||
unconnectedAccount, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { createSlice } from '@reduxjs/toolkit' | ||
import { captureException } from '@sentry/browser' | ||
|
||
import actionConstants from '../../store/actionConstants' | ||
import { addPermittedAccount } from '../../store/actions' | ||
import { getOriginOfCurrentTab } from '../../selectors/selectors' | ||
|
||
// Constants | ||
|
||
export const ALERT_STATE = { | ||
CLOSED: 'CLOSED', | ||
ERROR: 'ERROR', | ||
LOADING: 'LOADING', | ||
OPEN: 'OPEN', | ||
} | ||
|
||
const name = 'unconnectedAccount' | ||
|
||
const initialState = { | ||
state: ALERT_STATE.CLOSED, | ||
address: null, | ||
} | ||
|
||
// Slice (reducer plus auto-generated actions and action creators) | ||
|
||
const slice = createSlice({ | ||
name, | ||
initialState, | ||
reducers: { | ||
connectAccountFailed: (state) => { | ||
state.state = ALERT_STATE.ERROR | ||
}, | ||
connectAccountRequested: (state) => { | ||
state.state = ALERT_STATE.LOADING | ||
}, | ||
connectAccountSucceeded: (state) => { | ||
state.state = ALERT_STATE.CLOSED | ||
state.address = null | ||
}, | ||
dismissAlert: (state) => { | ||
state.state = ALERT_STATE.CLOSED | ||
state.address = null | ||
}, | ||
switchedToUnconnectedAccount: (state, action) => { | ||
state.state = ALERT_STATE.OPEN | ||
state.address = action.payload | ||
}, | ||
}, | ||
extraReducers: { | ||
[actionConstants.UPDATE_METAMASK_STATE]: (state, action) => { | ||
// close the alert if the account is switched while it's open | ||
if ( | ||
state.state === ALERT_STATE.OPEN && | ||
state.address !== action.value.selectedAddress | ||
) { | ||
state.state = ALERT_STATE.CLOSED | ||
state.address = null | ||
} | ||
}, | ||
}, | ||
}) | ||
|
||
const { actions, reducer } = slice | ||
|
||
export default reducer | ||
|
||
// Selectors | ||
|
||
export const getAlertState = (state) => state[name].state | ||
|
||
export const getAlertAccountAddress = (state) => state[name].address | ||
|
||
export const alertIsOpen = (state) => state[name].state !== ALERT_STATE.CLOSED | ||
|
||
|
||
// Actions / action-creators | ||
|
||
export const { | ||
connectAccountFailed, | ||
connectAccountRequested, | ||
connectAccountSucceeded, | ||
dismissAlert, | ||
switchedToUnconnectedAccount, | ||
} = actions | ||
|
||
export const connectAccount = () => { | ||
return async (dispatch, getState) => { | ||
const state = getState() | ||
const address = getAlertAccountAddress(state) | ||
const origin = getOriginOfCurrentTab(state) | ||
try { | ||
await dispatch(connectAccountRequested()) | ||
await dispatch(addPermittedAccount(origin, address)) | ||
await dispatch(connectAccountSucceeded()) | ||
} catch (error) { | ||
console.error(error) | ||
captureException(error) | ||
await dispatch(connectAccountFailed()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.