mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-26 12:29:06 +01:00
Merge pull request #5992 from MetaMask/i5140-accounts
Add scrolling button to account list
This commit is contained in:
commit
9b0b2f32f7
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 |
@ -34,7 +34,7 @@ const NoticeScreen = require('./components/pages/notice')
|
|||||||
const Loading = require('./components/loading-screen')
|
const Loading = require('./components/loading-screen')
|
||||||
const LoadingNetwork = require('./components/loading-network-screen').default
|
const LoadingNetwork = require('./components/loading-network-screen').default
|
||||||
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
|
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
|
||||||
const AccountMenu = require('./components/account-menu')
|
import AccountMenu from './components/account-menu'
|
||||||
|
|
||||||
// Global Modals
|
// Global Modals
|
||||||
const Modal = require('./components/modals/index').Modal
|
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
|
export { default } from './account-menu.container'
|
||||||
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 }
|
|
||||||
}
|
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: 240px;
|
max-height: 256px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
|
|
||||||
@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 575px) {
|
@media screen and (max-width: 575px) {
|
||||||
max-height: 215px;
|
max-height: 228px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.keyring-label {
|
.keyring-label {
|
||||||
@ -150,4 +150,28 @@
|
|||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
cursor: pointer;
|
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 './add-token-button/index';
|
||||||
|
|
||||||
|
@import './app-header/index';
|
||||||
|
|
||||||
@import './button-group/index';
|
@import './button-group/index';
|
||||||
|
|
||||||
@import './card/index';
|
@import './card/index';
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
@import './currency-display.scss';
|
@import './currency-display.scss';
|
||||||
|
|
||||||
@import './account-menu.scss';
|
|
||||||
|
|
||||||
@import './menu.scss';
|
@import './menu.scss';
|
||||||
|
|
||||||
@import './gas-slider.scss';
|
@import './gas-slider.scss';
|
||||||
|
Loading…
Reference in New Issue
Block a user