aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilip Š <filip.stamcar@hotmail.com>2019-01-10 21:27:21 +0800
committerFilip Š <filip.stamcar@hotmail.com>2019-01-10 21:27:21 +0800
commit7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554 (patch)
tree2c3b47607f45e214652bd9082052c02e0e3510b2
parentdc2d16ca47841a7e69304bde7b7c2f932eb3d990 (diff)
parentcef4caeb61f2564e1ed871c12449f1e5c8d66427 (diff)
downloadtangerine-wallet-browser-7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554.tar
tangerine-wallet-browser-7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554.tar.gz
tangerine-wallet-browser-7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554.tar.bz2
tangerine-wallet-browser-7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554.tar.lz
tangerine-wallet-browser-7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554.tar.xz
tangerine-wallet-browser-7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554.tar.zst
tangerine-wallet-browser-7ff8d6c6b160ce2a032b53e5cf6ea5b3e4a83554.zip
Merge branch 'develop' of https://github.com/MetaMask/metamask-extension into patch-1
-rw-r--r--CHANGELOG.md9
-rw-r--r--app/_locales/en/messages.json2
-rw-r--r--app/_locales/fr/messages.json12
-rw-r--r--app/images/icons/down-arrow.svg4
-rw-r--r--app/manifest.json2
-rw-r--r--app/phishing.html2
-rw-r--r--app/scripts/platforms/extension.js2
-rwxr-xr-xtest/e2e/beta/run-drizzle.sh33
-rw-r--r--ui/app/app.js2
-rw-r--r--ui/app/components/account-menu/account-menu.component.js301
-rw-r--r--ui/app/components/account-menu/account-menu.container.js62
-rw-r--r--ui/app/components/account-menu/index.js250
-rw-r--r--ui/app/components/account-menu/index.scss (renamed from ui/app/css/itcss/components/account-menu.scss)28
-rw-r--r--ui/app/components/index.scss4
-rw-r--r--ui/app/components/token-currency-display/token-currency-display.component.js2
-rw-r--r--ui/app/components/token-list.js6
-rw-r--r--ui/app/css/itcss/components/index.scss2
17 files changed, 445 insertions, 278 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7fc182db0..becbae3e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@
## Current Develop Branch
+## 5.3.0 Wed Jan 02 2019
+
+- [#5978](https://github.com/MetaMask/metamask-extension/pull/5978): Fix etherscan links on notifications
+- [#5980](https://github.com/MetaMask/metamask-extension/pull/5980): Fix drizzle tests
+- [#5922](https://github.com/MetaMask/metamask-extension/pull/5922): Prevent users from changing the From field in the send screen
+- [#5932](https://github.com/MetaMask/metamask-extension/pull/5932): Fix displayed time and date in the activity log. Remove vreme library, add luxon library.
+- [#5924](https://github.com/MetaMask/metamask-extension/pull/5924): transactions - throw an error if a transaction is generated while the network is loading
+- [#5893](https://github.com/MetaMask/metamask-extension/pull/5893): Add loading network screen
+
## 5.2.2 Wed Dec 12 2018
- [#5925](https://github.com/MetaMask/metamask-extension/pull/5925): Fix speed up button not showing for transactions with the lowest nonce
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 5f42ac437..34415232a 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -102,7 +102,7 @@
"message": "Amount + TX Fee"
},
"appDescription": {
- "message": "Ethereum Browser Extension",
+ "message": "An Ethereum Wallet in your Browser",
"description": "The description of the application"
},
"appName": {
diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json
index e60aa3218..9018ef578 100644
--- a/app/_locales/fr/messages.json
+++ b/app/_locales/fr/messages.json
@@ -204,22 +204,22 @@
"message": "Connecter"
},
"connecting": {
- "message": "Connection..."
+ "message": "Connexion..."
},
"connectingToKovan": {
- "message": "Connection au réseau de test Kovan"
+ "message": "Connexion au réseau de test Kovan"
},
"connectingToMainnet": {
- "message": "Connection au réseau principal Ethereum"
+ "message": "Connexion au réseau principal Ethereum"
},
"connectingToRopsten": {
- "message": "Connection au réseau de test Ropsten"
+ "message": "Connexion au réseau de test Ropsten"
},
"connectingToRinkeby": {
- "message": "Connection au réseau de test Rinkeby"
+ "message": "Connexion au réseau de test Rinkeby"
},
"connectingToUnknown": {
- "message": "Connection à un réseau inconnu"
+ "message": "Connexion à un réseau inconnu"
},
"connectToLedger": {
"message": "Connecter un Ledger"
diff --git a/app/images/icons/down-arrow.svg b/app/images/icons/down-arrow.svg
new file mode 100644
index 000000000..6cfb4a38b
--- /dev/null
+++ b/app/images/icons/down-arrow.svg
@@ -0,0 +1,4 @@
+<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="13.5" cy="13.5" r="13" fill="white" fill-opacity="0.25" stroke="#DCDDE6"/>
+<path d="M19.2 14.1L18.5 13.4L14.1 17.8V7H13.1V17.8L8.7 13.4L8 14.1L13.1 19.2L13.6 19.7L14.1 19.2L19.2 14.1Z" fill="#DCDDE6"/>
+</svg>
diff --git a/app/manifest.json b/app/manifest.json
index 4f4598a18..6c35c6989 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -1,7 +1,7 @@
{
"name": "__MSG_appName__",
"short_name": "__MSG_appName__",
- "version": "5.2.2",
+ "version": "5.3.0",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "__MSG_appDescription__",
diff --git a/app/phishing.html b/app/phishing.html
index 284d0fcac..207489a12 100644
--- a/app/phishing.html
+++ b/app/phishing.html
@@ -3,7 +3,7 @@
<html>
<head>
- <title>Ethereum Phishing Detection - MetMask</title>
+ <title>Ethereum Phishing Detection - MetaMask</title>
<style>
body {
diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js
index 3f1cb0f27..e8779739c 100644
--- a/app/scripts/platforms/extension.js
+++ b/app/scripts/platforms/extension.js
@@ -111,7 +111,7 @@ class ExtensionPlatform {
_viewOnEtherScan (txId) {
if (txId.startsWith('http://')) {
- global.metamaskController.platform.openWindow({ url: txId })
+ extension.tabs.create({ url: txId })
}
}
}
diff --git a/test/e2e/beta/run-drizzle.sh b/test/e2e/beta/run-drizzle.sh
index 609f2765e..0799b5a65 100755
--- a/test/e2e/beta/run-drizzle.sh
+++ b/test/e2e/beta/run-drizzle.sh
@@ -1,16 +1,31 @@
#!/usr/bin/env bash
-export PATH="$PATH:./node_modules/.bin"
+set -e
+set -u
+set -o pipefail
npm run ganache:start -- -b 2 >> /dev/null 2>&1 &
+npm_run_ganache_start_pid=$!
sleep 5
-cd test/e2e/beta/
-rm -rf drizzle-test
-mkdir drizzle-test && cd drizzle-test
-sudo npm install -g truffle
-truffle unbox drizzle
+
+pushd "$(mktemp -d)"
+npm install --no-package-lock truffle
+truffle="$(npm bin)/truffle"
+$truffle unbox drizzle
echo "Deploying contracts for Drizzle test..."
-truffle compile && truffle migrate
+$truffle compile
+$truffle migrate
+
BROWSER=none npm start >> /dev/null 2>&1 &
-cd ../../../../
-mocha test/e2e/beta/drizzle.spec
+npm_start_pid=$!
+
+popd
+if ! mocha test/e2e/beta/drizzle.spec
+then
+ test_status=1
+fi
+
+! kill -15 $npm_run_ganache_start_pid
+! kill -15 $npm_start_pid
+! wait $npm_run_ganache_start_pid $npm_start_pid
+exit ${test_status:-}
diff --git a/ui/app/app.js b/ui/app/app.js
index 14b199b8e..f320ced0a 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -34,7 +34,7 @@ const NoticeScreen = require('./components/pages/notice')
const Loading = require('./components/loading-screen')
const LoadingNetwork = require('./components/loading-network-screen').default
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
-const AccountMenu = require('./components/account-menu')
+import AccountMenu from './components/account-menu'
// Global Modals
const Modal = require('./components/modals/index').Modal
diff --git a/ui/app/components/account-menu/account-menu.component.js b/ui/app/components/account-menu/account-menu.component.js
new file mode 100644
index 000000000..b2fec647a
--- /dev/null
+++ b/ui/app/components/account-menu/account-menu.component.js
@@ -0,0 +1,301 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import debounce from 'lodash.debounce'
+import { Menu, Item, Divider, CloseArea } from '../dropdowns/components/menu'
+import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums'
+import { getEnvironmentType } from '../../../../app/scripts/lib/util'
+import Tooltip from '../tooltip'
+import Identicon from '../identicon'
+import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'
+import { PRIMARY } from '../../constants/common'
+import {
+ SETTINGS_ROUTE,
+ INFO_ROUTE,
+ NEW_ACCOUNT_ROUTE,
+ IMPORT_ACCOUNT_ROUTE,
+ CONNECT_HARDWARE_ROUTE,
+ DEFAULT_ROUTE,
+} from '../../routes'
+
+export default class AccountMenu extends PureComponent {
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ static propTypes = {
+ accounts: PropTypes.object,
+ history: PropTypes.object,
+ identities: PropTypes.object,
+ isAccountMenuOpen: PropTypes.bool,
+ keyrings: PropTypes.array,
+ lockMetamask: PropTypes.func,
+ selectedAddress: PropTypes.string,
+ showAccountDetail: PropTypes.func,
+ showRemoveAccountConfirmationModal: PropTypes.func,
+ toggleAccountMenu: PropTypes.func,
+ }
+
+ state = {
+ atAccountListBottom: false,
+ }
+
+ componentDidUpdate (prevProps) {
+ const { prevIsAccountMenuOpen } = prevProps
+ const { isAccountMenuOpen } = this.props
+
+ if (!prevIsAccountMenuOpen && isAccountMenuOpen) {
+ this.setAtAccountListBottom()
+ }
+ }
+
+ renderAccounts () {
+ const {
+ identities,
+ accounts,
+ selectedAddress,
+ keyrings,
+ showAccountDetail,
+ } = this.props
+
+ const accountOrder = keyrings.reduce((list, keyring) => list.concat(keyring.accounts), [])
+
+ return accountOrder.filter(address => !!identities[address]).map(address => {
+ const identity = identities[address]
+ const isSelected = identity.address === selectedAddress
+
+ const balanceValue = accounts[address] ? accounts[address].balance : ''
+ const simpleAddress = identity.address.substring(2).toLowerCase()
+
+ const keyring = keyrings.find(kr => {
+ return kr.accounts.includes(simpleAddress) || kr.accounts.includes(identity.address)
+ })
+
+ return (
+ <div
+ className="account-menu__account menu__item--clickable"
+ onClick={() => showAccountDetail(identity.address)}
+ key={identity.address}
+ >
+ <div className="account-menu__check-mark">
+ { isSelected && <div className="account-menu__check-mark-icon" /> }
+ </div>
+ <Identicon
+ address={identity.address}
+ diameter={24}
+ />
+ <div className="account-menu__account-info">
+ <div className="account-menu__name">
+ { identity.name || '' }
+ </div>
+ <UserPreferencedCurrencyDisplay
+ className="account-menu__balance"
+ value={balanceValue}
+ type={PRIMARY}
+ />
+ </div>
+ { this.renderKeyringType(keyring) }
+ { this.renderRemoveAccount(keyring, identity) }
+ </div>
+ )
+ })
+ }
+
+ renderRemoveAccount (keyring, identity) {
+ const { t } = this.context
+ // Any account that's not from the HD wallet Keyring can be removed
+ const { type } = keyring
+ const isRemovable = type !== 'HD Key Tree'
+
+ return isRemovable && (
+ <Tooltip
+ title={t('removeAccount')}
+ position="bottom"
+ >
+ <a
+ className="remove-account-icon"
+ onClick={e => this.removeAccount(e, identity)}
+ />
+ </Tooltip>
+ )
+ }
+
+ removeAccount (e, identity) {
+ e.preventDefault()
+ e.stopPropagation()
+ const { showRemoveAccountConfirmationModal } = this.props
+ showRemoveAccountConfirmationModal(identity)
+ }
+
+ renderKeyringType (keyring) {
+ const { t } = this.context
+
+ // Sometimes keyrings aren't loaded yet
+ if (!keyring) {
+ return null
+ }
+
+ const { type } = keyring
+ let label
+
+ switch (type) {
+ case 'Trezor Hardware':
+ case 'Ledger Hardware':
+ label = t('hardware')
+ break
+ case 'Simple Key Pair':
+ label = t('imported')
+ break
+ }
+
+ return label && (
+ <div className="keyring-label allcaps">
+ { label }
+ </div>
+ )
+ }
+
+ setAtAccountListBottom = () => {
+ const target = document.querySelector('.account-menu__accounts')
+ const { scrollTop, offsetHeight, scrollHeight } = target
+ const atAccountListBottom = scrollTop + offsetHeight >= scrollHeight
+ this.setState({ atAccountListBottom })
+ }
+
+ onScroll = debounce(this.setAtAccountListBottom, 25)
+
+ handleScrollDown = e => {
+ e.stopPropagation()
+ const target = document.querySelector('.account-menu__accounts')
+ const { scrollHeight } = target
+ target.scroll({ left: 0, top: scrollHeight, behavior: 'smooth' })
+ this.setAtAccountListBottom()
+ }
+
+ renderScrollButton () {
+ const { accounts } = this.props
+ const { atAccountListBottom } = this.state
+
+ return !atAccountListBottom && Object.keys(accounts).length > 3 && (
+ <div
+ className="account-menu__scroll-button"
+ onClick={this.handleScrollDown}
+ >
+ <img
+ src="./images/icons/down-arrow.svg"
+ width={28}
+ height={28}
+ />
+ </div>
+ )
+ }
+
+ render () {
+ const { t } = this.context
+ const {
+ isAccountMenuOpen,
+ toggleAccountMenu,
+ lockMetamask,
+ history,
+ } = this.props
+
+ return (
+ <Menu
+ className="account-menu"
+ isShowing={isAccountMenuOpen}
+ >
+ <CloseArea onClick={toggleAccountMenu} />
+ <Item className="account-menu__header">
+ { t('myAccounts') }
+ <button
+ className="account-menu__logout-button"
+ onClick={() => {
+ lockMetamask()
+ history.push(DEFAULT_ROUTE)
+ }}
+ >
+ { t('logout') }
+ </button>
+ </Item>
+ <Divider />
+ <div className="account-menu__accounts-container">
+ <div
+ className="account-menu__accounts"
+ onScroll={this.onScroll}
+ >
+ { this.renderAccounts() }
+ </div>
+ { this.renderScrollButton() }
+ </div>
+ <Divider />
+ <Item
+ onClick={() => {
+ toggleAccountMenu()
+ history.push(NEW_ACCOUNT_ROUTE)
+ }}
+ icon={
+ <img
+ className="account-menu__item-icon"
+ src="images/plus-btn-white.svg"
+ />
+ }
+ text={t('createAccount')}
+ />
+ <Item
+ onClick={() => {
+ toggleAccountMenu()
+ history.push(IMPORT_ACCOUNT_ROUTE)
+ }}
+ icon={
+ <img
+ className="account-menu__item-icon"
+ src="images/import-account.svg"
+ />
+ }
+ text={t('importAccount')}
+ />
+ <Item
+ onClick={() => {
+ toggleAccountMenu()
+
+ if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
+ global.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE)
+ } else {
+ history.push(CONNECT_HARDWARE_ROUTE)
+ }
+ }}
+ icon={
+ <img
+ className="account-menu__item-icon"
+ src="images/connect-icon.svg"
+ />
+ }
+ text={t('connectHardwareWallet')}
+ />
+ <Divider />
+ <Item
+ onClick={() => {
+ toggleAccountMenu()
+ history.push(INFO_ROUTE)
+ }}
+ icon={
+ <img src="images/mm-info-icon.svg" />
+ }
+ text={t('infoHelp')}
+ />
+ <Item
+ onClick={() => {
+ toggleAccountMenu()
+ history.push(SETTINGS_ROUTE)
+ }}
+ icon={
+ <img
+ className="account-menu__item-icon"
+ src="images/settings.svg"
+ />
+ }
+ text={t('settings')}
+ />
+ </Menu>
+ )
+ }
+}
diff --git a/ui/app/components/account-menu/account-menu.container.js b/ui/app/components/account-menu/account-menu.container.js
new file mode 100644
index 000000000..93246ec72
--- /dev/null
+++ b/ui/app/components/account-menu/account-menu.container.js
@@ -0,0 +1,62 @@
+import { connect } from 'react-redux'
+import { compose } from 'recompose'
+import { withRouter } from 'react-router-dom'
+import {
+ toggleAccountMenu,
+ showAccountDetail,
+ hideSidebar,
+ lockMetamask,
+ hideWarning,
+ showConfigPage,
+ showInfoPage,
+ showModal,
+} from '../../actions'
+import { getMetaMaskAccounts } from '../../selectors'
+import AccountMenu from './account-menu.component'
+
+function mapStateToProps (state) {
+ const { metamask: { selectedAddress, isAccountMenuOpen, keyrings, identities } } = state
+
+ return {
+ selectedAddress,
+ isAccountMenuOpen,
+ keyrings,
+ identities,
+ accounts: getMetaMaskAccounts(state),
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ toggleAccountMenu: () => dispatch(toggleAccountMenu()),
+ showAccountDetail: address => {
+ dispatch(showAccountDetail(address))
+ dispatch(hideSidebar())
+ dispatch(toggleAccountMenu())
+ },
+ lockMetamask: () => {
+ dispatch(lockMetamask())
+ dispatch(hideWarning())
+ dispatch(hideSidebar())
+ dispatch(toggleAccountMenu())
+ },
+ showConfigPage: () => {
+ dispatch(showConfigPage())
+ dispatch(hideSidebar())
+ dispatch(toggleAccountMenu())
+ },
+ showInfoPage: () => {
+ dispatch(showInfoPage())
+ dispatch(hideSidebar())
+ dispatch(toggleAccountMenu())
+ },
+ showRemoveAccountConfirmationModal: identity => {
+ return dispatch(showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity }))
+ },
+ }
+}
+
+export default compose(
+ withRouter,
+ connect(mapStateToProps, mapDispatchToProps)
+)(AccountMenu)
diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js
index e88389096..b2b4e4c6f 100644
--- a/ui/app/components/account-menu/index.js
+++ b/ui/app/components/account-menu/index.js
@@ -1,249 +1 @@
-const inherits = require('util').inherits
-const Component = require('react').Component
-const connect = require('react-redux').connect
-const { compose } = require('recompose')
-const { withRouter } = require('react-router-dom')
-const PropTypes = require('prop-types')
-const h = require('react-hyperscript')
-const actions = require('../../actions')
-const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
-const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums')
-const { getEnvironmentType } = require('../../../../app/scripts/lib/util')
-const Tooltip = require('../tooltip')
-import Identicon from '../identicon'
-import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'
-import { PRIMARY } from '../../constants/common'
-import { getMetaMaskAccounts } from '../../selectors'
-
-const {
- SETTINGS_ROUTE,
- INFO_ROUTE,
- NEW_ACCOUNT_ROUTE,
- IMPORT_ACCOUNT_ROUTE,
- CONNECT_HARDWARE_ROUTE,
- DEFAULT_ROUTE,
-} = require('../../routes')
-
-module.exports = compose(
- withRouter,
- connect(mapStateToProps, mapDispatchToProps)
-)(AccountMenu)
-
-AccountMenu.contextTypes = {
- t: PropTypes.func,
-}
-
-inherits(AccountMenu, Component)
-function AccountMenu () { Component.call(this) }
-
-function mapStateToProps (state) {
- return {
- selectedAddress: state.metamask.selectedAddress,
- isAccountMenuOpen: state.metamask.isAccountMenuOpen,
- keyrings: state.metamask.keyrings,
- identities: state.metamask.identities,
- accounts: getMetaMaskAccounts(state),
- }
-}
-
-function mapDispatchToProps (dispatch) {
- return {
- toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
- showAccountDetail: address => {
- dispatch(actions.showAccountDetail(address))
- dispatch(actions.hideSidebar())
- dispatch(actions.toggleAccountMenu())
- },
- lockMetamask: () => {
- dispatch(actions.lockMetamask())
- dispatch(actions.hideWarning())
- dispatch(actions.hideSidebar())
- dispatch(actions.toggleAccountMenu())
- },
- showConfigPage: () => {
- dispatch(actions.showConfigPage())
- dispatch(actions.hideSidebar())
- dispatch(actions.toggleAccountMenu())
- },
- showInfoPage: () => {
- dispatch(actions.showInfoPage())
- dispatch(actions.hideSidebar())
- dispatch(actions.toggleAccountMenu())
- },
- showRemoveAccountConfirmationModal: (identity) => {
- return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity }))
- },
- }
-}
-
-AccountMenu.prototype.render = function () {
- const {
- isAccountMenuOpen,
- toggleAccountMenu,
- lockMetamask,
- history,
- } = this.props
-
- return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [
- h(CloseArea, { onClick: toggleAccountMenu }),
- h(Item, {
- className: 'account-menu__header',
- }, [
- this.context.t('myAccounts'),
- h('button.account-menu__logout-button', {
- onClick: () => {
- lockMetamask()
- history.push(DEFAULT_ROUTE)
- },
- }, this.context.t('logout')),
- ]),
- h(Divider),
- h('div.account-menu__accounts', this.renderAccounts()),
- h(Divider),
- h(Item, {
- onClick: () => {
- toggleAccountMenu()
- history.push(NEW_ACCOUNT_ROUTE)
- },
- icon: h('img.account-menu__item-icon', { src: 'images/plus-btn-white.svg' }),
- text: this.context.t('createAccount'),
- }),
- h(Item, {
- onClick: () => {
- toggleAccountMenu()
- history.push(IMPORT_ACCOUNT_ROUTE)
- },
- icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }),
- text: this.context.t('importAccount'),
- }),
- h(Item, {
- onClick: () => {
- toggleAccountMenu()
- if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
- global.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE)
- } else {
- history.push(CONNECT_HARDWARE_ROUTE)
- }
- },
- icon: h('img.account-menu__item-icon', { src: 'images/connect-icon.svg' }),
- text: this.context.t('connectHardwareWallet'),
- }),
- h(Divider),
- h(Item, {
- onClick: () => {
- toggleAccountMenu()
- history.push(INFO_ROUTE)
- },
- icon: h('img', { src: 'images/mm-info-icon.svg' }),
- text: this.context.t('infoHelp'),
- }),
- h(Item, {
- onClick: () => {
- toggleAccountMenu()
- history.push(SETTINGS_ROUTE)
- },
- icon: h('img.account-menu__item-icon', { src: 'images/settings.svg' }),
- text: this.context.t('settings'),
- }),
- ])
-}
-
-AccountMenu.prototype.renderAccounts = function () {
- const {
- identities,
- accounts,
- selectedAddress,
- keyrings,
- showAccountDetail,
- } = this.props
-
- const accountOrder = keyrings.reduce((list, keyring) => list.concat(keyring.accounts), [])
- return accountOrder.filter(address => !!identities[address]).map((address) => {
-
- const identity = identities[address]
- const isSelected = identity.address === selectedAddress
-
- const balanceValue = accounts[address] ? accounts[address].balance : ''
- const simpleAddress = identity.address.substring(2).toLowerCase()
-
- const keyring = keyrings.find((kr) => {
- return kr.accounts.includes(simpleAddress) ||
- kr.accounts.includes(identity.address)
- })
-
- return h(
- 'div.account-menu__account.menu__item--clickable',
- { onClick: () => showAccountDetail(identity.address) },
- [
- h('div.account-menu__check-mark', [
- isSelected ? h('div.account-menu__check-mark-icon') : null,
- ]),
-
- h(
- Identicon,
- {
- address: identity.address,
- diameter: 24,
- },
- ),
-
- h('div.account-menu__account-info', [
- h('div.account-menu__name', identity.name || ''),
- h(UserPreferencedCurrencyDisplay, {
- className: 'account-menu__balance',
- value: balanceValue,
- type: PRIMARY,
- }),
- ]),
-
- this.renderKeyringType(keyring),
- this.renderRemoveAccount(keyring, identity),
- ],
- )
- })
-}
-
-AccountMenu.prototype.renderRemoveAccount = function (keyring, identity) {
- // Any account that's not from the HD wallet Keyring can be removed
- const type = keyring.type
- const isRemovable = type !== 'HD Key Tree'
- if (isRemovable) {
- return h(Tooltip, {
- title: this.context.t('removeAccount'),
- position: 'bottom',
- }, [
- h('a.remove-account-icon', {
- onClick: (e) => this.removeAccount(e, identity),
- }, ''),
- ])
- }
- return null
-}
-
-AccountMenu.prototype.removeAccount = function (e, identity) {
- e.preventDefault()
- e.stopPropagation()
- const { showRemoveAccountConfirmationModal } = this.props
- showRemoveAccountConfirmationModal(identity)
-}
-
-AccountMenu.prototype.renderKeyringType = function (keyring) {
- try { // Sometimes keyrings aren't loaded yet:
- const type = keyring.type
- let label
- switch (type) {
- case 'Trezor Hardware':
- case 'Ledger Hardware':
- label = this.context.t('hardware')
- break
- case 'Simple Key Pair':
- label = this.context.t('imported')
- break
- default:
- label = ''
- }
-
- return label !== '' ? h('.keyring-label.allcaps', label) : null
-
- } catch (e) { return }
-}
+export { default } from './account-menu.container'
diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/components/account-menu/index.scss
index b14753e23..9a61bf887 100644
--- a/ui/app/css/itcss/components/account-menu.scss
+++ b/ui/app/components/account-menu/index.scss
@@ -55,7 +55,7 @@
display: flex;
flex-flow: column nowrap;
overflow-y: auto;
- max-height: 240px;
+ max-height: 256px;
position: relative;
z-index: 200;
@@ -64,7 +64,7 @@
}
@media screen and (max-width: 575px) {
- max-height: 215px;
+ max-height: 228px;
}
.keyring-label {
@@ -150,4 +150,28 @@
line-height: 18px;
cursor: pointer;
}
+
+ &__accounts-container {
+ position: relative;
+ }
+
+ &__scroll-button {
+ position: absolute;
+ bottom: 12px;
+ right: 12px;
+ height: 28px;
+ width: 28px;
+ border-radius: 14px;
+ background: #3f3f3f;
+ z-index: 201;
+ cursor: pointer;
+ opacity: .8;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
}
diff --git a/ui/app/components/index.scss b/ui/app/components/index.scss
index 78c1216f7..f1ecbbc3d 100644
--- a/ui/app/components/index.scss
+++ b/ui/app/components/index.scss
@@ -1,7 +1,9 @@
-@import './app-header/index';
+@import './account-menu/index';
@import './add-token-button/index';
+@import './app-header/index';
+
@import './button-group/index';
@import './card/index';
diff --git a/ui/app/components/token-currency-display/token-currency-display.component.js b/ui/app/components/token-currency-display/token-currency-display.component.js
index 6e9a65300..f49846449 100644
--- a/ui/app/components/token-currency-display/token-currency-display.component.js
+++ b/ui/app/components/token-currency-display/token-currency-display.component.js
@@ -35,7 +35,7 @@ export default class TokenCurrencyDisplay extends PureComponent {
let displayValue
- if (tokenData.params && tokenData.params.length) {
+ if (tokenData && tokenData.params && tokenData.params.length) {
const tokenValue = getTokenValue(tokenData.params)
displayValue = calcTokenAmount(tokenValue, decimals).toString()
}
diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js
index 6a88f30bf..258abde72 100644
--- a/ui/app/components/token-list.js
+++ b/ui/app/components/token-list.js
@@ -134,17 +134,17 @@ TokenList.prototype.createFreshTokenTracker = function () {
})
}
-TokenList.prototype.componentDidUpdate = function (nextProps) {
+TokenList.prototype.componentDidUpdate = function (prevProps) {
const {
network: oldNet,
userAddress: oldAddress,
tokens,
- } = this.props
+ } = prevProps
const {
network: newNet,
userAddress: newAddress,
tokens: newTokens,
- } = nextProps
+ } = this.props
const isLoading = newNet === 'loading'
const missingInfo = !oldNet || !newNet || !oldAddress || !newAddress
diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss
index 63aa62eb3..b11b76f35 100644
--- a/ui/app/css/itcss/components/index.scss
+++ b/ui/app/css/itcss/components/index.scss
@@ -30,8 +30,6 @@
@import './currency-display.scss';
-@import './account-menu.scss';
-
@import './menu.scss';
@import './gas-slider.scss';