mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'develop' of https://github.com/MetaMask/metamask-extension into patch-1
This commit is contained in:
commit
7ff8d6c6b1
@ -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
|
||||
|
@ -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": {
|
||||
|
@ -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"
|
||||
|
4
app/images/icons/down-arrow.svg
Normal file
4
app/images/icons/down-arrow.svg
Normal file
@ -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>
|
After Width: | Height: | Size: 317 B |
@ -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__",
|
||||
|
@ -3,7 +3,7 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Ethereum Phishing Detection - MetMask</title>
|
||||
<title>Ethereum Phishing Detection - MetaMask</title>
|
||||
|
||||
<style>
|
||||
body {
|
||||
|
@ -111,7 +111,7 @@ class ExtensionPlatform {
|
||||
|
||||
_viewOnEtherScan (txId) {
|
||||
if (txId.startsWith('http://')) {
|
||||
global.metamaskController.platform.openWindow({ url: txId })
|
||||
extension.tabs.create({ url: txId })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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:-}
|
||||
|
@ -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
|
||||
|
301
ui/app/components/account-menu/account-menu.component.js
Normal file
301
ui/app/components/account-menu/account-menu.component.js
Normal file
@ -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>
|
||||
)
|
||||
}
|
||||
}
|
62
ui/app/components/account-menu/account-menu.container.js
Normal file
62
ui/app/components/account-menu/account-menu.container.js
Normal file
@ -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)
|
@ -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'
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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';
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -30,8 +30,6 @@
|
||||
|
||||
@import './currency-display.scss';
|
||||
|
||||
@import './account-menu.scss';
|
||||
|
||||
@import './menu.scss';
|
||||
|
||||
@import './gas-slider.scss';
|
||||
|
Loading…
Reference in New Issue
Block a user