Fix blockies icons overriding contract map icons. Refactor Identicon component (#5599)
parent
315028ec53
commit
554f79c0e2
@ -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) |
||||
} |
@ -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)} |
||||
/> |
||||
) |
||||
} |
||||
} |
@ -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) |
@ -0,0 +1 @@ |
||||
export { default } from './identicon.container' |
@ -0,0 +1,7 @@ |
||||
.identicon { |
||||
display: flex; |
||||
flex-shrink: 0; |
||||
align-items: center; |
||||
justify-content: center; |
||||
overflow: hidden; |
||||
} |
@ -0,0 +1 @@ |
||||
export { default } from './jazzicon.component' |
@ -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} |
||||
/> |
||||
) |
||||
} |
||||
} |
Loading…
Reference in new issue