1
0
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:
Alexander Tseung 2018-10-25 17:21:41 +08:00 committed by GitHub
parent 315028ec53
commit 554f79c0e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 230 additions and 147 deletions

View File

@ -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)

View File

@ -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'

View File

@ -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

View File

@ -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 {

View File

@ -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')

View File

@ -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')

View File

@ -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)
}

View 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)}
/>
)
}
}

View 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)

View File

@ -0,0 +1 @@
export { default } from './identicon.container'

View File

@ -0,0 +1,7 @@
.identicon {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
overflow: hidden;
}

View File

@ -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')
})
})

View File

@ -16,6 +16,8 @@
@import './export-text-container/index';
@import './identicon/index';
@import './info-box/index';
@import './menu-bar/index';

View File

@ -0,0 +1 @@
export { default } from './jazzicon.component'

View 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}
/>
)
}
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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')

View File

@ -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')

View File

@ -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;
}
}

View File

@ -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')