mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Add switch to connected account alert (#8532)
Add alert suggesting that the user switch to a connected account. This alert is displayed when the popup is opened over an active tab that is connected to some account, but not the current selected account. The user can choose to switch to a connected account, or dismiss the alert. This alert is only shown once per account switch. So if the user repeatedly opens the popup on a dapp without switching accounts, it'll only be shown the first time. The alert also won't be shown if the user has just dismissed an "Unconnected account" alert on this same dapp and account, as that would be redundant. The alert has a "Don't show me this again" checkbox that allows the user to disable the alert. It can be re-enabled again on the Alerts settings page.
This commit is contained in:
parent
6868688a03
commit
53ec42d95f
@ -154,6 +154,12 @@
|
||||
"alertsSettingsDescription": {
|
||||
"message": "Enable or disable each alert"
|
||||
},
|
||||
"alertSettingsSwitchToConnected": {
|
||||
"message": "Opening popup with an unconnected account selected"
|
||||
},
|
||||
"alertSettingsSwitchToConnectedDescription": {
|
||||
"message": "This alert is shown when you open the popup with an unconnected account selected."
|
||||
},
|
||||
"alertSettingsUnconnectedAccount": {
|
||||
"message": "Switching to an unconnected account"
|
||||
},
|
||||
@ -953,6 +959,9 @@
|
||||
"noAlreadyHaveSeed": {
|
||||
"message": "No, I already have a seed phrase"
|
||||
},
|
||||
"notConnected": {
|
||||
"message": "Not connected"
|
||||
},
|
||||
"protectYourKeys": {
|
||||
"message": "Protect Your Keys!"
|
||||
},
|
||||
@ -1412,6 +1421,16 @@
|
||||
"supportCenter": {
|
||||
"message": "Visit our Support Center"
|
||||
},
|
||||
"switchAccounts": {
|
||||
"message": "Switch accounts"
|
||||
},
|
||||
"switchToConnectedAlertMultipleAccountsDescription": {
|
||||
"message": "This account is not connected. Switch to a connected account?"
|
||||
},
|
||||
"switchToConnectedAlertSingleAccountDescription": {
|
||||
"message": "This account is not connected. Switch to a connected account ($1)?",
|
||||
"description": "$1 will be replaced by the name of the connected account"
|
||||
},
|
||||
"symbol": {
|
||||
"message": "Symbol"
|
||||
},
|
||||
@ -1549,9 +1568,6 @@
|
||||
"unapproved": {
|
||||
"message": "Unapproved"
|
||||
},
|
||||
"unconnectedAccountAlertTitle": {
|
||||
"message": "Not connected"
|
||||
},
|
||||
"unconnectedAccountAlertDescription": {
|
||||
"message": "This account is not connected to this site."
|
||||
},
|
||||
|
@ -12,6 +12,7 @@ import ObservableStore from 'obs-store'
|
||||
*/
|
||||
|
||||
export const ALERT_TYPES = {
|
||||
switchToConnected: 'switchToConnected',
|
||||
unconnectedAccount: 'unconnectedAccount',
|
||||
}
|
||||
|
||||
@ -24,6 +25,7 @@ const defaultState = {
|
||||
},
|
||||
{}
|
||||
),
|
||||
switchToConnectedAlertShown: {},
|
||||
}
|
||||
|
||||
/**
|
||||
@ -36,13 +38,27 @@ export default class AlertController {
|
||||
* @param {AlertControllerOptions} [opts] - Controller configuration parameters
|
||||
*/
|
||||
constructor (opts = {}) {
|
||||
const { initState } = opts
|
||||
const { initState, preferencesStore } = opts
|
||||
const state = Object.assign(
|
||||
{},
|
||||
defaultState,
|
||||
initState,
|
||||
{
|
||||
switchToConnectedAlertShown: {},
|
||||
}
|
||||
)
|
||||
this.store = new ObservableStore(state)
|
||||
|
||||
const { selectedAddress } = preferencesStore.getState()
|
||||
this.selectedAddress = selectedAddress
|
||||
|
||||
preferencesStore.subscribe(({ selectedAddress }) => {
|
||||
const currentState = this.store.getState()
|
||||
if (currentState.switchToConnectedAlertShown && this.selectedAddress !== selectedAddress) {
|
||||
this.selectedAddress = selectedAddress
|
||||
this.store.updateState({ switchToConnectedAlertShown: {} })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setAlertEnabledness (alertId, enabledness) {
|
||||
@ -51,4 +67,15 @@ export default class AlertController {
|
||||
alertEnabledness[alertId] = enabledness
|
||||
this.store.updateState({ alertEnabledness })
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the "switch to connected" alert as shown for the given origin
|
||||
* @param {string} origin - The origin the alert has been shown for
|
||||
*/
|
||||
setSwitchToConnectedAlertShown (origin) {
|
||||
let { switchToConnectedAlertShown } = this.store.getState()
|
||||
switchToConnectedAlertShown = { ...switchToConnectedAlertShown }
|
||||
switchToConnectedAlertShown[origin] = true
|
||||
this.store.updateState({ switchToConnectedAlertShown })
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
|
||||
this.addressBookController = new AddressBookController(undefined, initState.AddressBookController)
|
||||
|
||||
this.alertController = new AlertController({ initState: initState.AlertController })
|
||||
this.alertController = new AlertController({
|
||||
initState: initState.AlertController,
|
||||
preferencesStore: this.preferencesController.store,
|
||||
})
|
||||
|
||||
this.threeBoxController = new ThreeBoxController({
|
||||
preferencesController: this.preferencesController,
|
||||
@ -564,6 +567,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
|
||||
// alert controller
|
||||
setAlertEnabledness: nodeify(alertController.setAlertEnabledness, alertController),
|
||||
setSwitchToConnectedAlertShown: nodeify(this.alertController.setSwitchToConnectedAlertShown, this.alertController),
|
||||
|
||||
// 3Box
|
||||
setThreeBoxSyncingPermission: nodeify(threeBoxController.setThreeBoxSyncingPermission, threeBoxController),
|
||||
|
@ -522,6 +522,9 @@
|
||||
"priceAndTimeEstimatesLastRetrieved": 1541527901281,
|
||||
"errors": {}
|
||||
},
|
||||
"switchToConnected": {
|
||||
"state": "CLOSED"
|
||||
},
|
||||
"unconnectedAccount": {
|
||||
"state": "CLOSED"
|
||||
}
|
||||
|
@ -473,6 +473,9 @@
|
||||
"priceAndTimeEstimatesLastRetrieved": 1541527901281,
|
||||
"errors": {}
|
||||
},
|
||||
"switchToConnected": {
|
||||
"state": "CLOSED"
|
||||
},
|
||||
"unconnectedAccount": {
|
||||
"state": "CLOSED"
|
||||
}
|
||||
|
@ -1278,6 +1278,9 @@
|
||||
"errors": {}
|
||||
},
|
||||
"confirmTransaction": {},
|
||||
"switchToConnected": {
|
||||
"state": "CLOSED"
|
||||
},
|
||||
"unconnectedAccount": {
|
||||
"state": "CLOSED"
|
||||
}
|
||||
|
@ -980,7 +980,7 @@ describe('Actions', function () {
|
||||
it('#showAccountDetail', async function () {
|
||||
setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress')
|
||||
.callsArgWith(1, null)
|
||||
const store = mockStore({ metamask: { alertEnabledness: {}, selectedAddress: '0x123' } })
|
||||
const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' } })
|
||||
|
||||
await store.dispatch(actions.showAccountDetail())
|
||||
assert(setSelectedAddressSpy.calledOnce)
|
||||
@ -989,7 +989,7 @@ describe('Actions', function () {
|
||||
it('displays warning if setSelectedAddress throws', async function () {
|
||||
setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress')
|
||||
.callsArgWith(1, new Error('error'))
|
||||
const store = mockStore({ metamask: { alertEnabledness: {}, selectedAddress: '0x123' } })
|
||||
const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' } })
|
||||
const expectedActions = [
|
||||
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
|
||||
{ type: 'HIDE_LOADING_INDICATION' },
|
||||
|
@ -2,15 +2,22 @@ import React from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
import UnconnectedAccountAlert from './unconnected-account-alert'
|
||||
import SwitchToConnectedAlert from './switch-to-connected-alert'
|
||||
import { alertIsOpen as unconnectedAccountAlertIsOpen } from '../../../ducks/alerts/unconnected-account'
|
||||
import { alertIsOpen as switchToConnectedAlertIsOpen } from '../../../ducks/alerts/switch-to-connected'
|
||||
|
||||
const Alerts = () => {
|
||||
const _unconnectedAccountAlertIsOpen = useSelector(unconnectedAccountAlertIsOpen)
|
||||
const _switchToConnectedAlertIsOpen = useSelector(switchToConnectedAlertIsOpen)
|
||||
|
||||
if (_unconnectedAccountAlertIsOpen) {
|
||||
return (
|
||||
<UnconnectedAccountAlert />
|
||||
)
|
||||
} else if (_switchToConnectedAlertIsOpen) {
|
||||
return (
|
||||
<SwitchToConnectedAlert />
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
|
@ -1 +1,3 @@
|
||||
@import './unconnected-account-alert/unconnected-account-alert.scss';
|
||||
|
||||
@import './switch-to-connected-alert/switch-to-connected-alert.scss';
|
||||
|
@ -0,0 +1 @@
|
||||
export { default } from './switch-to-connected-alert'
|
@ -0,0 +1,121 @@
|
||||
import React, { useContext, useState } from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
|
||||
import {
|
||||
ALERT_STATE,
|
||||
switchToAccount,
|
||||
dismissAlert,
|
||||
dismissAndDisableAlert,
|
||||
getAlertState,
|
||||
} from '../../../../ducks/alerts/switch-to-connected'
|
||||
import { getPermittedIdentitiesForCurrentTab } from '../../../../selectors'
|
||||
import { I18nContext } from '../../../../contexts/i18n'
|
||||
import Popover from '../../../ui/popover'
|
||||
import Button from '../../../ui/button'
|
||||
import Dropdown from '../../../ui/dropdown'
|
||||
import Checkbox from '../../../ui/check-box'
|
||||
import Tooltip from '../../../ui/tooltip-v2'
|
||||
|
||||
const {
|
||||
ERROR,
|
||||
LOADING,
|
||||
} = ALERT_STATE
|
||||
|
||||
const SwitchToUnconnectedAccountAlert = () => {
|
||||
const t = useContext(I18nContext)
|
||||
const dispatch = useDispatch()
|
||||
const alertState = useSelector(getAlertState)
|
||||
const connectedAccounts = useSelector(getPermittedIdentitiesForCurrentTab)
|
||||
const [accountToSwitchTo, setAccountToSwitchTo] = useState(connectedAccounts[0].address)
|
||||
const [dontShowThisAgain, setDontShowThisAgain] = useState(false)
|
||||
|
||||
const onClose = async () => {
|
||||
return dontShowThisAgain
|
||||
? await dispatch(dismissAndDisableAlert())
|
||||
: dispatch(dismissAlert())
|
||||
}
|
||||
|
||||
const options = connectedAccounts.map((account) => {
|
||||
return { name: account.name, value: account.address }
|
||||
})
|
||||
|
||||
return (
|
||||
<Popover
|
||||
contentClassName="switch-to-connected-alert__content"
|
||||
footer={(
|
||||
<>
|
||||
{
|
||||
alertState === ERROR
|
||||
? (
|
||||
<div className="switch-to-connected-alert__error">
|
||||
{ t('failureMessage') }
|
||||
</div>
|
||||
)
|
||||
: null
|
||||
}
|
||||
<div className="switch-to-connected-alert__footer-buttons">
|
||||
<Button
|
||||
disabled={alertState === LOADING}
|
||||
onClick={onClose}
|
||||
type="secondary"
|
||||
>
|
||||
{ t('dismiss') }
|
||||
</Button>
|
||||
<Button
|
||||
disabled={alertState === LOADING || alertState === ERROR || dontShowThisAgain}
|
||||
onClick={() => dispatch(switchToAccount(accountToSwitchTo))}
|
||||
type="primary"
|
||||
>
|
||||
{ t('switchAccounts') }
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
footerClassName="switch-to-connected-alert__footer"
|
||||
onClose={onClose}
|
||||
subtitle={
|
||||
connectedAccounts.length > 1
|
||||
? t('switchToConnectedAlertMultipleAccountsDescription')
|
||||
: t('switchToConnectedAlertSingleAccountDescription', [connectedAccounts[0].name])
|
||||
}
|
||||
title={t('notConnected')}
|
||||
>
|
||||
{
|
||||
connectedAccounts.length > 1
|
||||
? (
|
||||
<Dropdown
|
||||
className="switch-to-connected-alert__dropdown"
|
||||
title="Switch to account"
|
||||
onChange={(address) => setAccountToSwitchTo(address)}
|
||||
options={options}
|
||||
selectedOption={accountToSwitchTo}
|
||||
/>
|
||||
)
|
||||
: null
|
||||
}
|
||||
<div className="switch-to-connected-alert__checkbox-wrapper">
|
||||
<Checkbox
|
||||
id="switchToConnected_dontShowThisAgain"
|
||||
checked={dontShowThisAgain}
|
||||
className="switch-to-connected-alert__checkbox"
|
||||
onClick={() => setDontShowThisAgain((checked) => !checked)}
|
||||
/>
|
||||
<label
|
||||
className="switch-to-connected-alert__checkbox-label"
|
||||
htmlFor="switchToConnected_dontShowThisAgain"
|
||||
>
|
||||
{ t('dontShowThisAgain') }
|
||||
<Tooltip
|
||||
position="top"
|
||||
title={t('unconnectedAccountAlertDisableTooltip')}
|
||||
wrapperClassName="switch-to-connected-alert__checkbox-label-tooltip"
|
||||
>
|
||||
<i className="fa fa-info-circle" />
|
||||
</Tooltip>
|
||||
</label>
|
||||
</div>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
export default SwitchToUnconnectedAccountAlert
|
@ -0,0 +1,66 @@
|
||||
.switch-to-connected-alert {
|
||||
&__footer {
|
||||
flex-direction: column;
|
||||
|
||||
:only-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
button:first-child {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
font-size: 14px;
|
||||
border: 1px solid #D73A49;
|
||||
background: #F8EAE8;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&__content {
|
||||
align-items: center;
|
||||
padding: 0 24px 24px 24px;
|
||||
}
|
||||
|
||||
&__dropdown {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
&__checkbox-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
&__checkbox-label {
|
||||
font-size: 14px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
color: $Grey-500;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__checkbox-label-tooltip {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ const SwitchToUnconnectedAccountAlert = () => {
|
||||
return (
|
||||
<Popover
|
||||
contentClassName="unconnected-account-alert__content"
|
||||
title={t('unconnectedAccountAlertTitle')}
|
||||
title={t('notConnected')}
|
||||
subtitle={t('unconnectedAccountAlertDescription')}
|
||||
onClose={onClose}
|
||||
footer={(
|
||||
|
@ -1 +1,2 @@
|
||||
export { default as switchToConnected } from './switch-to-connected'
|
||||
export { default as unconnectedAccount } from './unconnected-account'
|
||||
|
111
ui/app/ducks/alerts/switch-to-connected.js
Normal file
111
ui/app/ducks/alerts/switch-to-connected.js
Normal file
@ -0,0 +1,111 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
import { captureException } from '@sentry/browser'
|
||||
|
||||
import { ALERT_TYPES } from '../../../../app/scripts/controllers/alert'
|
||||
import * as actionConstants from '../../store/actionConstants'
|
||||
import { setAlertEnabledness, setSelectedAddress } from '../../store/actions'
|
||||
|
||||
// Constants
|
||||
|
||||
export const ALERT_STATE = {
|
||||
CLOSED: 'CLOSED',
|
||||
ERROR: 'ERROR',
|
||||
LOADING: 'LOADING',
|
||||
OPEN: 'OPEN',
|
||||
}
|
||||
|
||||
const name = ALERT_TYPES.switchToConnected
|
||||
|
||||
const initialState = {
|
||||
state: ALERT_STATE.CLOSED,
|
||||
}
|
||||
|
||||
// Slice (reducer plus auto-generated actions and action creators)
|
||||
|
||||
const slice = createSlice({
|
||||
name,
|
||||
initialState,
|
||||
reducers: {
|
||||
disableAlertFailed: (state) => {
|
||||
state.state = ALERT_STATE.ERROR
|
||||
},
|
||||
disableAlertRequested: (state) => {
|
||||
state.state = ALERT_STATE.LOADING
|
||||
},
|
||||
disableAlertSucceeded: (state) => {
|
||||
state.state = ALERT_STATE.CLOSED
|
||||
},
|
||||
dismissAlert: (state) => {
|
||||
state.state = ALERT_STATE.CLOSED
|
||||
},
|
||||
switchAccountFailed: (state) => {
|
||||
state.state = ALERT_STATE.ERROR
|
||||
},
|
||||
switchAccountRequested: (state) => {
|
||||
state.state = ALERT_STATE.LOADING
|
||||
},
|
||||
switchAccountSucceeded: (state) => {
|
||||
state.state = ALERT_STATE.CLOSED
|
||||
},
|
||||
},
|
||||
extraReducers: {
|
||||
[actionConstants.SELECTED_ADDRESS_CHANGED]: (state) => {
|
||||
// close the alert if the account is switched while it's open
|
||||
if (state.state === ALERT_STATE.OPEN) {
|
||||
state.state = ALERT_STATE.CLOSED
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { actions, reducer } = slice
|
||||
|
||||
export default reducer
|
||||
|
||||
// Selectors
|
||||
|
||||
export const getAlertState = (state) => state[name].state
|
||||
|
||||
export const alertIsOpen = (state) => state[name].state !== ALERT_STATE.CLOSED
|
||||
|
||||
// Actions / action-creators
|
||||
|
||||
const {
|
||||
disableAlertFailed,
|
||||
disableAlertRequested,
|
||||
disableAlertSucceeded,
|
||||
dismissAlert,
|
||||
switchAccountFailed,
|
||||
switchAccountRequested,
|
||||
switchAccountSucceeded,
|
||||
} = actions
|
||||
|
||||
export { dismissAlert }
|
||||
|
||||
export const dismissAndDisableAlert = () => {
|
||||
return async (dispatch) => {
|
||||
try {
|
||||
await dispatch(disableAlertRequested())
|
||||
await dispatch(setAlertEnabledness(name, false))
|
||||
await dispatch(disableAlertSucceeded())
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
captureException(error)
|
||||
await dispatch(disableAlertFailed())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const switchToAccount = (address) => {
|
||||
return async (dispatch) => {
|
||||
try {
|
||||
await dispatch(switchAccountRequested())
|
||||
await dispatch(setSelectedAddress(address))
|
||||
await dispatch(switchAccountSucceeded())
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
captureException(error)
|
||||
await dispatch(switchAccountFailed())
|
||||
}
|
||||
}
|
||||
}
|
@ -5,10 +5,11 @@ import sendReducer from './send/send.duck'
|
||||
import appStateReducer from './app/app'
|
||||
import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck'
|
||||
import gasReducer from './gas/gas.duck'
|
||||
import { unconnectedAccount } from './alerts'
|
||||
import { switchToConnected, unconnectedAccount } from './alerts'
|
||||
import { ALERT_TYPES } from '../../../app/scripts/controllers/alert'
|
||||
|
||||
export default combineReducers({
|
||||
[ALERT_TYPES.switchToConnected]: switchToConnected,
|
||||
[ALERT_TYPES.unconnectedAccount]: unconnectedAccount,
|
||||
activeTab: (s) => (s === undefined ? null : s),
|
||||
metamask: metamaskReducer,
|
||||
|
@ -371,4 +371,8 @@ export const getCurrentLocale = (state) => state.metamask.currentLocale
|
||||
|
||||
export const getAlertEnabledness = (state) => state.metamask.alertEnabledness
|
||||
|
||||
export const getSwitchToConnectedAlertEnabledness = (state) => getAlertEnabledness(state)[ALERT_TYPES.switchToConnected]
|
||||
|
||||
export const getUnconnectedAccountAlertEnabledness = (state) => getAlertEnabledness(state)[ALERT_TYPES.unconnectedAccount]
|
||||
|
||||
export const getSwitchToConnectedAlertShown = (state) => state.metamask.switchToConnectedAlertShown
|
||||
|
@ -184,6 +184,7 @@ export default class Routes extends Component {
|
||||
render () {
|
||||
const {
|
||||
isLoading,
|
||||
isUnlocked,
|
||||
alertMessage,
|
||||
textDirection,
|
||||
loadingMessage,
|
||||
@ -252,7 +253,13 @@ export default class Routes extends Component {
|
||||
{ !isLoading && isLoadingNetwork && <LoadingNetwork /> }
|
||||
{ this.renderRoutes() }
|
||||
</div>
|
||||
{
|
||||
isUnlocked
|
||||
? (
|
||||
<Alerts />
|
||||
)
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -46,6 +46,10 @@ const AlertsTab = () => {
|
||||
const t = useContext(I18nContext)
|
||||
|
||||
const alertConfig = {
|
||||
[ALERT_TYPES.switchToConnected]: {
|
||||
title: t('alertSettingsSwitchToConnected'),
|
||||
description: t('alertSettingsSwitchToConnectedDescription'),
|
||||
},
|
||||
[ALERT_TYPES.unconnectedAccount]: {
|
||||
title: t('alertSettingsUnconnectedAccount'),
|
||||
description: t('alertSettingsUnconnectedAccountDescription'),
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { forOwn } from 'lodash'
|
||||
import { getOriginOfCurrentTab } from './selectors'
|
||||
import { getMetaMaskIdentities, getOriginOfCurrentTab } from './selectors'
|
||||
import {
|
||||
CAVEAT_NAMES,
|
||||
} from '../../../app/scripts/controllers/permissions/enums'
|
||||
@ -117,6 +117,12 @@ export function getConnectedDomainsForSelectedAddress (state) {
|
||||
return connectedDomains
|
||||
}
|
||||
|
||||
export function getPermittedIdentitiesForCurrentTab (state) {
|
||||
const permittedAccounts = getPermittedAccountsForCurrentTab(state)
|
||||
const identities = getMetaMaskIdentities(state)
|
||||
return permittedAccounts.map((address) => identities[address])
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object mapping addresses to objects mapping origins to connected
|
||||
* domain info. Domain info objects have the following properties:
|
||||
|
@ -1188,6 +1188,7 @@ export function showAccountDetail (address) {
|
||||
|
||||
const state = getState()
|
||||
const unconnectedAccountAlertIsEnabled = getUnconnectedAccountAlertEnabledness(state)
|
||||
const activeTabOrigin = state.activeTab.origin
|
||||
const selectedAddress = getSelectedAddress(state)
|
||||
const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(state)
|
||||
const currentTabIsConnectedToPreviousAddress = permittedAccountsForCurrentTab.includes(selectedAddress)
|
||||
@ -1206,10 +1207,11 @@ export function showAccountDetail (address) {
|
||||
type: actionConstants.SHOW_ACCOUNT_DETAIL,
|
||||
value: address,
|
||||
})
|
||||
dispatch(setSelectedToken())
|
||||
if (unconnectedAccountAlertIsEnabled && switchingToUnconnectedAddress) {
|
||||
dispatch(switchedToUnconnectedAccount())
|
||||
await setSwitchToConnectedAlertShown(activeTabOrigin)
|
||||
}
|
||||
dispatch(setSelectedToken())
|
||||
}
|
||||
}
|
||||
|
||||
@ -2162,6 +2164,10 @@ export function setAlertEnabledness (alertId, enabledness) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function setSwitchToConnectedAlertShown (origin) {
|
||||
await promisifiedBackground.setSwitchToConnectedAlertShown(origin)
|
||||
}
|
||||
|
||||
export function loadingMethodDataStarted () {
|
||||
return {
|
||||
type: actionConstants.LOADING_METHOD_DATA_STARTED,
|
||||
|
34
ui/index.js
34
ui/index.js
@ -7,8 +7,17 @@ import Root from './app/pages'
|
||||
import * as actions from './app/store/actions'
|
||||
import configureStore from './app/store/store'
|
||||
import txHelper from './lib/tx-helper'
|
||||
import { getEnvironmentType } from '../app/scripts/lib/util'
|
||||
import { ALERT_TYPES } from '../app/scripts/controllers/alert'
|
||||
import { ENVIRONMENT_TYPE_POPUP } from '../app/scripts/lib/enums'
|
||||
import { fetchLocale } from './app/helpers/utils/i18n-helper'
|
||||
import switchDirection from './app/helpers/utils/switch-direction'
|
||||
import { getPermittedAccountsForCurrentTab, getSelectedAddress } from './app/selectors'
|
||||
import { ALERT_STATE } from './app/ducks/alerts/switch-to-connected'
|
||||
import {
|
||||
getSwitchToConnectedAlertEnabledness,
|
||||
getSwitchToConnectedAlertShown,
|
||||
} from './app/ducks/metamask/metamask'
|
||||
|
||||
log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn')
|
||||
|
||||
@ -43,7 +52,7 @@ async function startApp (metamaskState, backgroundConnection, opts) {
|
||||
await switchDirection('rtl')
|
||||
}
|
||||
|
||||
const store = configureStore({
|
||||
const draftInitialState = {
|
||||
activeTab: opts.activeTab,
|
||||
|
||||
// metamaskState represents the cross-tab state
|
||||
@ -56,7 +65,28 @@ async function startApp (metamaskState, backgroundConnection, opts) {
|
||||
current: currentLocaleMessages,
|
||||
en: enLocaleMessages,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) {
|
||||
const origin = draftInitialState.activeTab.origin
|
||||
const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(draftInitialState)
|
||||
const selectedAddress = getSelectedAddress(draftInitialState)
|
||||
const switchToConnectedAlertShown = getSwitchToConnectedAlertShown(draftInitialState)
|
||||
const switchToConnectedAlertIsEnabled = getSwitchToConnectedAlertEnabledness(draftInitialState)
|
||||
|
||||
if (
|
||||
origin &&
|
||||
switchToConnectedAlertIsEnabled &&
|
||||
!switchToConnectedAlertShown[origin] &&
|
||||
permittedAccountsForCurrentTab.length > 0 &&
|
||||
!permittedAccountsForCurrentTab.includes(selectedAddress)
|
||||
) {
|
||||
draftInitialState[ALERT_TYPES.switchToConnected] = { state: ALERT_STATE.OPEN }
|
||||
actions.setSwitchToConnectedAlertShown(origin)
|
||||
}
|
||||
}
|
||||
|
||||
const store = configureStore(draftInitialState)
|
||||
|
||||
// if unconfirmed txs, start on txConf page
|
||||
const unapprovedTxsAll = txHelper(
|
||||
|
Loading…
Reference in New Issue
Block a user