mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Fix blockies icons overriding contract map icons. Refactor Identicon component (#5599)
This commit is contained in:
parent
315028ec53
commit
554f79c0e2
@ -6,10 +6,11 @@ const genAccountLink = require('etherscan-link').createAccountLink
|
||||
const connect = require('react-redux').connect
|
||||
const Dropdown = require('./dropdown').Dropdown
|
||||
const DropdownMenuItem = require('./dropdown').DropdownMenuItem
|
||||
const Identicon = require('./identicon')
|
||||
const copyToClipboard = require('copy-to-clipboard')
|
||||
const { checksumAddress } = require('../util')
|
||||
|
||||
import Identicon from './identicon'
|
||||
|
||||
class AccountDropdowns extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
@ -7,10 +7,10 @@ const PropTypes = require('prop-types')
|
||||
const h = require('react-hyperscript')
|
||||
const actions = require('../../actions')
|
||||
const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
|
||||
const Identicon = require('../identicon')
|
||||
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'
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
const inherits = require('util').inherits
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const Identicon = require('./identicon')
|
||||
import Identicon from './identicon'
|
||||
const formatBalance = require('../util').formatBalance
|
||||
const addressSummary = require('../util').addressSummary
|
||||
|
||||
|
@ -2,13 +2,13 @@ import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import { matchPath } from 'react-router-dom'
|
||||
import Identicon from '../identicon'
|
||||
|
||||
const {
|
||||
ENVIRONMENT_TYPE_NOTIFICATION,
|
||||
ENVIRONMENT_TYPE_POPUP,
|
||||
} = require('../../../../app/scripts/lib/enums')
|
||||
const { DEFAULT_ROUTE, INITIALIZE_ROUTE, CONFIRM_TRANSACTION_ROUTE } = require('../../routes')
|
||||
const Identicon = require('../identicon')
|
||||
const NetworkIndicator = require('../network')
|
||||
|
||||
export default class AppHeader extends PureComponent {
|
||||
|
@ -2,8 +2,8 @@ const Component = require('react').Component
|
||||
const connect = require('react-redux').connect
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const TokenBalance = require('./token-balance')
|
||||
const Identicon = require('./identicon')
|
||||
import TokenBalance from './token-balance'
|
||||
import Identicon from './identicon'
|
||||
import UserPreferencedCurrencyDisplay from './user-preferenced-currency-display'
|
||||
import { PRIMARY, SECONDARY } from '../constants/common'
|
||||
const { getAssetImages, conversionRateSelector, getCurrentCurrency} = require('../selectors')
|
||||
|
@ -6,7 +6,7 @@ const genAccountLink = require('../../../../lib/account-link.js')
|
||||
const connect = require('react-redux').connect
|
||||
const Dropdown = require('./dropdown').Dropdown
|
||||
const DropdownMenuItem = require('./dropdown').DropdownMenuItem
|
||||
const Identicon = require('../../identicon')
|
||||
import Identicon from '../../identicon'
|
||||
const { checksumAddress } = require('../../../util')
|
||||
const copyToClipboard = require('copy-to-clipboard')
|
||||
const { formatBalance } = require('../../../util')
|
||||
|
@ -1,124 +0,0 @@
|
||||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const connect = require('react-redux').connect
|
||||
const isNode = require('detect-node')
|
||||
const findDOMNode = require('react-dom').findDOMNode
|
||||
const jazzicon = require('jazzicon')
|
||||
const iconFactoryGen = require('../../lib/icon-factory')
|
||||
const iconFactory = iconFactoryGen(jazzicon)
|
||||
const { toDataUrl } = require('../../lib/blockies')
|
||||
|
||||
module.exports = connect(mapStateToProps)(IdenticonComponent)
|
||||
|
||||
inherits(IdenticonComponent, Component)
|
||||
function IdenticonComponent () {
|
||||
Component.call(this)
|
||||
|
||||
this.defaultDiameter = 46
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
useBlockie: state.metamask.useBlockie,
|
||||
}
|
||||
}
|
||||
|
||||
IdenticonComponent.prototype.render = function () {
|
||||
var props = this.props
|
||||
const { className = '', address, image } = props
|
||||
var diameter = props.diameter || this.defaultDiameter
|
||||
const style = {
|
||||
height: diameter,
|
||||
width: diameter,
|
||||
borderRadius: diameter / 2,
|
||||
}
|
||||
if (image) {
|
||||
return h('img', {
|
||||
className: `${className} identicon`,
|
||||
src: image,
|
||||
style: {
|
||||
...style,
|
||||
},
|
||||
})
|
||||
} else if (address) {
|
||||
return h('div', {
|
||||
className: `${className} identicon`,
|
||||
key: 'identicon-' + address,
|
||||
style: {
|
||||
display: 'flex',
|
||||
flexShrink: 0,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
...style,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
})
|
||||
} else {
|
||||
return h('img.balance-icon', {
|
||||
className,
|
||||
src: './images/eth_logo.svg',
|
||||
style: {
|
||||
...style,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
IdenticonComponent.prototype.componentDidMount = function () {
|
||||
var props = this.props
|
||||
const { address, useBlockie } = props
|
||||
|
||||
if (!address) return
|
||||
|
||||
if (!isNode) {
|
||||
// eslint-disable-next-line react/no-find-dom-node
|
||||
var container = findDOMNode(this)
|
||||
|
||||
const diameter = props.diameter || this.defaultDiameter
|
||||
|
||||
if (useBlockie) {
|
||||
_generateBlockie(container, address, diameter)
|
||||
} else {
|
||||
_generateJazzicon(container, address, diameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IdenticonComponent.prototype.componentDidUpdate = function () {
|
||||
var props = this.props
|
||||
const { address, useBlockie } = props
|
||||
|
||||
if (!address) return
|
||||
|
||||
if (!isNode) {
|
||||
// eslint-disable-next-line react/no-find-dom-node
|
||||
var container = findDOMNode(this)
|
||||
|
||||
var children = container.children
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
container.removeChild(children[i])
|
||||
}
|
||||
|
||||
const diameter = props.diameter || this.defaultDiameter
|
||||
|
||||
if (useBlockie) {
|
||||
_generateBlockie(container, address, diameter)
|
||||
} else {
|
||||
_generateJazzicon(container, address, diameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _generateBlockie (container, address, diameter) {
|
||||
const img = new Image()
|
||||
img.src = toDataUrl(address)
|
||||
img.height = diameter
|
||||
img.width = diameter
|
||||
container.appendChild(img)
|
||||
}
|
||||
|
||||
function _generateJazzicon (container, address, diameter) {
|
||||
const img = iconFactory.iconForAddress(address, diameter)
|
||||
container.appendChild(img)
|
||||
}
|
99
ui/app/components/identicon/identicon.component.js
Normal file
99
ui/app/components/identicon/identicon.component.js
Normal file
@ -0,0 +1,99 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import { toDataUrl } from '../../../lib/blockies'
|
||||
import contractMap from 'eth-contract-metadata'
|
||||
import { checksumAddress } from '../../../app/util'
|
||||
import Jazzicon from '../jazzicon'
|
||||
|
||||
const getStyles = diameter => (
|
||||
{
|
||||
height: diameter,
|
||||
width: diameter,
|
||||
borderRadius: diameter / 2,
|
||||
}
|
||||
)
|
||||
|
||||
export default class Identicon extends PureComponent {
|
||||
static propTypes = {
|
||||
address: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
diameter: PropTypes.number,
|
||||
image: PropTypes.string,
|
||||
useBlockie: PropTypes.bool,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
diameter: 46,
|
||||
}
|
||||
|
||||
renderImage () {
|
||||
const { className, diameter, image } = this.props
|
||||
|
||||
return (
|
||||
<img
|
||||
className={classnames('identicon', className)}
|
||||
src={image}
|
||||
style={getStyles(diameter)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderJazzicon () {
|
||||
const { address, className, diameter } = this.props
|
||||
|
||||
return (
|
||||
<Jazzicon
|
||||
address={address}
|
||||
diameter={diameter}
|
||||
className={classnames('identicon', className)}
|
||||
style={getStyles(diameter)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderBlockie () {
|
||||
const { address, className, diameter } = this.props
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames('identicon', className)}
|
||||
style={getStyles(diameter)}
|
||||
>
|
||||
<img
|
||||
src={toDataUrl(address)}
|
||||
height={diameter}
|
||||
width={diameter}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { className, address, image, diameter, useBlockie } = this.props
|
||||
|
||||
if (image) {
|
||||
return this.renderImage()
|
||||
}
|
||||
|
||||
if (address) {
|
||||
const checksummedAddress = checksumAddress(address)
|
||||
|
||||
if (contractMap[checksummedAddress] && contractMap[checksummedAddress].logo) {
|
||||
return this.renderJazzicon()
|
||||
}
|
||||
|
||||
return useBlockie
|
||||
? this.renderBlockie()
|
||||
: this.renderJazzicon()
|
||||
}
|
||||
|
||||
return (
|
||||
<img
|
||||
className={classnames('balance-icon', className)}
|
||||
src="./images/eth_logo.svg"
|
||||
style={getStyles(diameter)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
12
ui/app/components/identicon/identicon.container.js
Normal file
12
ui/app/components/identicon/identicon.container.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { connect } from 'react-redux'
|
||||
import Identicon from './identicon.component'
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const { metamask: { useBlockie } } = state
|
||||
|
||||
return {
|
||||
useBlockie,
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Identicon)
|
1
ui/app/components/identicon/index.js
Normal file
1
ui/app/components/identicon/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './identicon.container'
|
7
ui/app/components/identicon/index.scss
Normal file
7
ui/app/components/identicon/index.scss
Normal file
@ -0,0 +1,7 @@
|
||||
.identicon {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
@ -3,11 +3,9 @@ import assert from 'assert'
|
||||
import thunk from 'redux-thunk'
|
||||
import configureMockStore from 'redux-mock-store'
|
||||
import { mount } from 'enzyme'
|
||||
import Identicon from '../identicon.component'
|
||||
|
||||
import IdenticonComponent from '../../../../../ui/app/components/identicon'
|
||||
|
||||
describe('Identicon Component', () => {
|
||||
|
||||
describe('Identicon', () => {
|
||||
const state = {
|
||||
metamask: {
|
||||
useBlockie: false,
|
||||
@ -19,18 +17,35 @@ describe('Identicon Component', () => {
|
||||
const store = mockStore(state)
|
||||
|
||||
it('renders default eth_logo identicon with no props', () => {
|
||||
const wrapper = mount(<IdenticonComponent store={store}/>)
|
||||
const wrapper = mount(
|
||||
<Identicon store={store}/>
|
||||
)
|
||||
|
||||
assert.equal(wrapper.find('img.balance-icon').prop('src'), './images/eth_logo.svg')
|
||||
})
|
||||
|
||||
it('renders custom image and add className props', () => {
|
||||
const wrapper = mount(<IdenticonComponent store={store} className={'test-image'} image={'test-image'} />)
|
||||
assert.equal(wrapper.find('img.test-image').prop('className'), 'test-image identicon')
|
||||
const wrapper = mount(
|
||||
<Identicon
|
||||
store={store}
|
||||
className="test-image"
|
||||
image="test-image"
|
||||
/>
|
||||
)
|
||||
|
||||
assert.equal(wrapper.find('img.test-image').prop('className'), 'identicon test-image')
|
||||
assert.equal(wrapper.find('img.test-image').prop('src'), 'test-image')
|
||||
})
|
||||
|
||||
it('renders div with address prop', () => {
|
||||
const wrapper = mount(<IdenticonComponent store={store} className={'test-address'} address={'0xTest'} />)
|
||||
assert.equal(wrapper.find('div.test-address').prop('className'), 'test-address identicon')
|
||||
const wrapper = mount(
|
||||
<Identicon
|
||||
store={store}
|
||||
className="test-address"
|
||||
address="0xTest"
|
||||
/>
|
||||
)
|
||||
|
||||
assert.equal(wrapper.find('div.test-address').prop('className'), 'identicon test-address')
|
||||
})
|
||||
})
|
@ -16,6 +16,8 @@
|
||||
|
||||
@import './export-text-container/index';
|
||||
|
||||
@import './identicon/index';
|
||||
|
||||
@import './info-box/index';
|
||||
|
||||
@import './menu-bar/index';
|
||||
|
1
ui/app/components/jazzicon/index.js
Normal file
1
ui/app/components/jazzicon/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './jazzicon.component'
|
69
ui/app/components/jazzicon/jazzicon.component.js
Normal file
69
ui/app/components/jazzicon/jazzicon.component.js
Normal file
@ -0,0 +1,69 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import isNode from 'detect-node'
|
||||
import { findDOMNode } from 'react-dom'
|
||||
import jazzicon from 'jazzicon'
|
||||
import iconFactoryGenerator from '../../../lib/icon-factory'
|
||||
const iconFactory = iconFactoryGenerator(jazzicon)
|
||||
|
||||
/**
|
||||
* Wrapper around the jazzicon library to return a React component, as the library returns an
|
||||
* HTMLDivElement which needs to be appended.
|
||||
*/
|
||||
export default class Jazzicon extends PureComponent {
|
||||
static propTypes = {
|
||||
address: PropTypes.string.isRequired,
|
||||
className: PropTypes.string,
|
||||
diameter: PropTypes.number,
|
||||
style: PropTypes.object,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
diameter: 46,
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
if (!isNode) {
|
||||
this.appendJazzicon()
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
const { address: prevAddress } = prevProps
|
||||
const { address } = this.props
|
||||
|
||||
if (!isNode && address !== prevAddress) {
|
||||
this.removeExistingChildren()
|
||||
this.appendJazzicon()
|
||||
}
|
||||
}
|
||||
|
||||
removeExistingChildren () {
|
||||
// eslint-disable-next-line react/no-find-dom-node
|
||||
const container = findDOMNode(this)
|
||||
const { children } = container
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
container.removeChild(children[i])
|
||||
}
|
||||
}
|
||||
|
||||
appendJazzicon () {
|
||||
// eslint-disable-next-line react/no-find-dom-node
|
||||
const container = findDOMNode(this)
|
||||
const { address, diameter } = this.props
|
||||
const image = iconFactory.iconForAddress(address, diameter)
|
||||
container.appendChild(image)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { className, style } = this.props
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ const inherits = require('util').inherits
|
||||
const connect = require('react-redux').connect
|
||||
const actions = require('../../actions')
|
||||
const { getSelectedIdentity } = require('../../selectors')
|
||||
const Identicon = require('../identicon')
|
||||
import Identicon from '../identicon'
|
||||
|
||||
function mapStateToProps (state, ownProps) {
|
||||
return {
|
||||
|
@ -4,7 +4,7 @@ const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const connect = require('react-redux').connect
|
||||
const actions = require('../../actions')
|
||||
const Identicon = require('../identicon')
|
||||
import Identicon from '../identicon'
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
|
@ -2,7 +2,7 @@ const Component = require('react').Component
|
||||
const PropTypes = require('prop-types')
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const Identicon = require('./identicon')
|
||||
import Identicon from './identicon'
|
||||
const connect = require('react-redux').connect
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const classnames = require('classnames')
|
||||
|
@ -2,7 +2,7 @@ const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const connect = require('react-redux').connect
|
||||
const Identicon = require('./identicon')
|
||||
import Identicon from './identicon'
|
||||
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
|
||||
const selectors = require('../selectors')
|
||||
const actions = require('../actions')
|
||||
|
@ -23,7 +23,8 @@
|
||||
font-size: 1.5rem;
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
margin-bottom: 12px;
|
||||
margin: 12px 0;
|
||||
margin-left: 0;
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
@ -32,7 +33,6 @@
|
||||
font-size: 1.5rem;
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
margin-bottom: 12px;
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ const { compose } = require('recompose')
|
||||
const inherits = require('util').inherits
|
||||
const classnames = require('classnames')
|
||||
const { checksumAddress } = require('../util')
|
||||
const Identicon = require('./identicon')
|
||||
import Identicon from './identicon'
|
||||
// const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
|
||||
const Tooltip = require('./tooltip-v2.js').default
|
||||
const copyToClipboard = require('copy-to-clipboard')
|
||||
|
Loading…
Reference in New Issue
Block a user