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.
feature/default_network_editable
Mark Stacey 5 years ago committed by GitHub
parent 6868688a03
commit 53ec42d95f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      app/_locales/en/messages.json
  2. 29
      app/scripts/controllers/alert.js
  3. 6
      app/scripts/metamask-controller.js
  4. 3
      development/states/confirm-sig-requests.json
  5. 3
      development/states/currency-localization.json
  6. 3
      development/states/tx-list-items.json
  7. 4
      test/unit/ui/app/actions.spec.js
  8. 7
      ui/app/components/app/alerts/alerts.js
  9. 2
      ui/app/components/app/alerts/alerts.scss
  10. 1
      ui/app/components/app/alerts/switch-to-connected-alert/index.js
  11. 121
      ui/app/components/app/alerts/switch-to-connected-alert/switch-to-connected-alert.js
  12. 66
      ui/app/components/app/alerts/switch-to-connected-alert/switch-to-connected-alert.scss
  13. 2
      ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js
  14. 1
      ui/app/ducks/alerts/index.js
  15. 111
      ui/app/ducks/alerts/switch-to-connected.js
  16. 3
      ui/app/ducks/index.js
  17. 4
      ui/app/ducks/metamask/metamask.js
  18. 7
      ui/app/pages/routes/routes.component.js
  19. 4
      ui/app/pages/settings/alerts-tab/alerts-tab.js
  20. 8
      ui/app/selectors/permissions.js
  21. 8
      ui/app/store/actions.js
  22. 34
      ui/index.js

@ -154,6 +154,12 @@
"alertsSettingsDescription": { "alertsSettingsDescription": {
"message": "Enable or disable each alert" "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": { "alertSettingsUnconnectedAccount": {
"message": "Switching to an unconnected account" "message": "Switching to an unconnected account"
}, },
@ -953,6 +959,9 @@
"noAlreadyHaveSeed": { "noAlreadyHaveSeed": {
"message": "No, I already have a seed phrase" "message": "No, I already have a seed phrase"
}, },
"notConnected": {
"message": "Not connected"
},
"protectYourKeys": { "protectYourKeys": {
"message": "Protect Your Keys!" "message": "Protect Your Keys!"
}, },
@ -1412,6 +1421,16 @@
"supportCenter": { "supportCenter": {
"message": "Visit our Support Center" "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": { "symbol": {
"message": "Symbol" "message": "Symbol"
}, },
@ -1549,9 +1568,6 @@
"unapproved": { "unapproved": {
"message": "Unapproved" "message": "Unapproved"
}, },
"unconnectedAccountAlertTitle": {
"message": "Not connected"
},
"unconnectedAccountAlertDescription": { "unconnectedAccountAlertDescription": {
"message": "This account is not connected to this site." "message": "This account is not connected to this site."
}, },

@ -12,6 +12,7 @@ import ObservableStore from 'obs-store'
*/ */
export const ALERT_TYPES = { export const ALERT_TYPES = {
switchToConnected: 'switchToConnected',
unconnectedAccount: 'unconnectedAccount', unconnectedAccount: 'unconnectedAccount',
} }
@ -24,6 +25,7 @@ const defaultState = {
}, },
{} {}
), ),
switchToConnectedAlertShown: {},
} }
/** /**
@ -36,13 +38,27 @@ export default class AlertController {
* @param {AlertControllerOptions} [opts] - Controller configuration parameters * @param {AlertControllerOptions} [opts] - Controller configuration parameters
*/ */
constructor (opts = {}) { constructor (opts = {}) {
const { initState } = opts const { initState, preferencesStore } = opts
const state = Object.assign( const state = Object.assign(
{}, {},
defaultState, defaultState,
initState, initState,
{
switchToConnectedAlertShown: {},
}
) )
this.store = new ObservableStore(state) 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) { setAlertEnabledness (alertId, enabledness) {
@ -51,4 +67,15 @@ export default class AlertController {
alertEnabledness[alertId] = enabledness alertEnabledness[alertId] = enabledness
this.store.updateState({ alertEnabledness }) 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.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({ this.threeBoxController = new ThreeBoxController({
preferencesController: this.preferencesController, preferencesController: this.preferencesController,
@ -564,6 +567,7 @@ export default class MetamaskController extends EventEmitter {
// alert controller // alert controller
setAlertEnabledness: nodeify(alertController.setAlertEnabledness, alertController), setAlertEnabledness: nodeify(alertController.setAlertEnabledness, alertController),
setSwitchToConnectedAlertShown: nodeify(this.alertController.setSwitchToConnectedAlertShown, this.alertController),
// 3Box // 3Box
setThreeBoxSyncingPermission: nodeify(threeBoxController.setThreeBoxSyncingPermission, threeBoxController), setThreeBoxSyncingPermission: nodeify(threeBoxController.setThreeBoxSyncingPermission, threeBoxController),

@ -522,6 +522,9 @@
"priceAndTimeEstimatesLastRetrieved": 1541527901281, "priceAndTimeEstimatesLastRetrieved": 1541527901281,
"errors": {} "errors": {}
}, },
"switchToConnected": {
"state": "CLOSED"
},
"unconnectedAccount": { "unconnectedAccount": {
"state": "CLOSED" "state": "CLOSED"
} }

@ -473,6 +473,9 @@
"priceAndTimeEstimatesLastRetrieved": 1541527901281, "priceAndTimeEstimatesLastRetrieved": 1541527901281,
"errors": {} "errors": {}
}, },
"switchToConnected": {
"state": "CLOSED"
},
"unconnectedAccount": { "unconnectedAccount": {
"state": "CLOSED" "state": "CLOSED"
} }

@ -1278,6 +1278,9 @@
"errors": {} "errors": {}
}, },
"confirmTransaction": {}, "confirmTransaction": {},
"switchToConnected": {
"state": "CLOSED"
},
"unconnectedAccount": { "unconnectedAccount": {
"state": "CLOSED" "state": "CLOSED"
} }

@ -980,7 +980,7 @@ describe('Actions', function () {
it('#showAccountDetail', async function () { it('#showAccountDetail', async function () {
setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress') setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress')
.callsArgWith(1, null) .callsArgWith(1, null)
const store = mockStore({ metamask: { alertEnabledness: {}, selectedAddress: '0x123' } }) const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' } })
await store.dispatch(actions.showAccountDetail()) await store.dispatch(actions.showAccountDetail())
assert(setSelectedAddressSpy.calledOnce) assert(setSelectedAddressSpy.calledOnce)
@ -989,7 +989,7 @@ describe('Actions', function () {
it('displays warning if setSelectedAddress throws', async function () { it('displays warning if setSelectedAddress throws', async function () {
setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress') setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress')
.callsArgWith(1, new Error('error')) .callsArgWith(1, new Error('error'))
const store = mockStore({ metamask: { alertEnabledness: {}, selectedAddress: '0x123' } }) const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' } })
const expectedActions = [ const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'HIDE_LOADING_INDICATION' }, { type: 'HIDE_LOADING_INDICATION' },

@ -2,15 +2,22 @@ import React from 'react'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import UnconnectedAccountAlert from './unconnected-account-alert' 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 unconnectedAccountAlertIsOpen } from '../../../ducks/alerts/unconnected-account'
import { alertIsOpen as switchToConnectedAlertIsOpen } from '../../../ducks/alerts/switch-to-connected'
const Alerts = () => { const Alerts = () => {
const _unconnectedAccountAlertIsOpen = useSelector(unconnectedAccountAlertIsOpen) const _unconnectedAccountAlertIsOpen = useSelector(unconnectedAccountAlertIsOpen)
const _switchToConnectedAlertIsOpen = useSelector(switchToConnectedAlertIsOpen)
if (_unconnectedAccountAlertIsOpen) { if (_unconnectedAccountAlertIsOpen) {
return ( return (
<UnconnectedAccountAlert /> <UnconnectedAccountAlert />
) )
} else if (_switchToConnectedAlertIsOpen) {
return (
<SwitchToConnectedAlert />
)
} }
return null return null

@ -1 +1,3 @@
@import './unconnected-account-alert/unconnected-account-alert.scss'; @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 ( return (
<Popover <Popover
contentClassName="unconnected-account-alert__content" contentClassName="unconnected-account-alert__content"
title={t('unconnectedAccountAlertTitle')} title={t('notConnected')}
subtitle={t('unconnectedAccountAlertDescription')} subtitle={t('unconnectedAccountAlertDescription')}
onClose={onClose} onClose={onClose}
footer={( footer={(

@ -1 +1,2 @@
export { default as switchToConnected } from './switch-to-connected'
export { default as unconnectedAccount } from './unconnected-account' export { default as unconnectedAccount } from './unconnected-account'

@ -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 appStateReducer from './app/app'
import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck' import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck'
import gasReducer from './gas/gas.duck' import gasReducer from './gas/gas.duck'
import { unconnectedAccount } from './alerts' import { switchToConnected, unconnectedAccount } from './alerts'
import { ALERT_TYPES } from '../../../app/scripts/controllers/alert' import { ALERT_TYPES } from '../../../app/scripts/controllers/alert'
export default combineReducers({ export default combineReducers({
[ALERT_TYPES.switchToConnected]: switchToConnected,
[ALERT_TYPES.unconnectedAccount]: unconnectedAccount, [ALERT_TYPES.unconnectedAccount]: unconnectedAccount,
activeTab: (s) => (s === undefined ? null : s), activeTab: (s) => (s === undefined ? null : s),
metamask: metamaskReducer, metamask: metamaskReducer,

@ -371,4 +371,8 @@ export const getCurrentLocale = (state) => state.metamask.currentLocale
export const getAlertEnabledness = (state) => state.metamask.alertEnabledness 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 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 () { render () {
const { const {
isLoading, isLoading,
isUnlocked,
alertMessage, alertMessage,
textDirection, textDirection,
loadingMessage, loadingMessage,
@ -252,7 +253,13 @@ export default class Routes extends Component {
{ !isLoading && isLoadingNetwork && <LoadingNetwork /> } { !isLoading && isLoadingNetwork && <LoadingNetwork /> }
{ this.renderRoutes() } { this.renderRoutes() }
</div> </div>
{
isUnlocked
? (
<Alerts /> <Alerts />
)
: null
}
</div> </div>
) )
} }

@ -46,6 +46,10 @@ const AlertsTab = () => {
const t = useContext(I18nContext) const t = useContext(I18nContext)
const alertConfig = { const alertConfig = {
[ALERT_TYPES.switchToConnected]: {
title: t('alertSettingsSwitchToConnected'),
description: t('alertSettingsSwitchToConnectedDescription'),
},
[ALERT_TYPES.unconnectedAccount]: { [ALERT_TYPES.unconnectedAccount]: {
title: t('alertSettingsUnconnectedAccount'), title: t('alertSettingsUnconnectedAccount'),
description: t('alertSettingsUnconnectedAccountDescription'), description: t('alertSettingsUnconnectedAccountDescription'),

@ -1,5 +1,5 @@
import { forOwn } from 'lodash' import { forOwn } from 'lodash'
import { getOriginOfCurrentTab } from './selectors' import { getMetaMaskIdentities, getOriginOfCurrentTab } from './selectors'
import { import {
CAVEAT_NAMES, CAVEAT_NAMES,
} from '../../../app/scripts/controllers/permissions/enums' } from '../../../app/scripts/controllers/permissions/enums'
@ -117,6 +117,12 @@ export function getConnectedDomainsForSelectedAddress (state) {
return connectedDomains 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 * Returns an object mapping addresses to objects mapping origins to connected
* domain info. Domain info objects have the following properties: * domain info. Domain info objects have the following properties:

@ -1188,6 +1188,7 @@ export function showAccountDetail (address) {
const state = getState() const state = getState()
const unconnectedAccountAlertIsEnabled = getUnconnectedAccountAlertEnabledness(state) const unconnectedAccountAlertIsEnabled = getUnconnectedAccountAlertEnabledness(state)
const activeTabOrigin = state.activeTab.origin
const selectedAddress = getSelectedAddress(state) const selectedAddress = getSelectedAddress(state)
const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(state) const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(state)
const currentTabIsConnectedToPreviousAddress = permittedAccountsForCurrentTab.includes(selectedAddress) const currentTabIsConnectedToPreviousAddress = permittedAccountsForCurrentTab.includes(selectedAddress)
@ -1206,10 +1207,11 @@ export function showAccountDetail (address) {
type: actionConstants.SHOW_ACCOUNT_DETAIL, type: actionConstants.SHOW_ACCOUNT_DETAIL,
value: address, value: address,
}) })
dispatch(setSelectedToken())
if (unconnectedAccountAlertIsEnabled && switchingToUnconnectedAddress) { if (unconnectedAccountAlertIsEnabled && switchingToUnconnectedAddress) {
dispatch(switchedToUnconnectedAccount()) 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 () { export function loadingMethodDataStarted () {
return { return {
type: actionConstants.LOADING_METHOD_DATA_STARTED, type: actionConstants.LOADING_METHOD_DATA_STARTED,

@ -7,8 +7,17 @@ import Root from './app/pages'
import * as actions from './app/store/actions' import * as actions from './app/store/actions'
import configureStore from './app/store/store' import configureStore from './app/store/store'
import txHelper from './lib/tx-helper' 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 { fetchLocale } from './app/helpers/utils/i18n-helper'
import switchDirection from './app/helpers/utils/switch-direction' 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') log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn')
@ -43,7 +52,7 @@ async function startApp (metamaskState, backgroundConnection, opts) {
await switchDirection('rtl') await switchDirection('rtl')
} }
const store = configureStore({ const draftInitialState = {
activeTab: opts.activeTab, activeTab: opts.activeTab,
// metamaskState represents the cross-tab state // metamaskState represents the cross-tab state
@ -56,7 +65,28 @@ async function startApp (metamaskState, backgroundConnection, opts) {
current: currentLocaleMessages, current: currentLocaleMessages,
en: enLocaleMessages, 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 // if unconfirmed txs, start on txConf page
const unapprovedTxsAll = txHelper( const unapprovedTxsAll = txHelper(

Loading…
Cancel
Save