mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Update token cell to show inline stale balance warning (#8259)
The token cell how shows a warning inline for the case where the token balance failed to update. It displays a warning icon next to the balance, with a tooltip that contains the same contents as was shown on the token list previously.
This commit is contained in:
parent
4f80ff5b01
commit
a554353ef3
@ -4,14 +4,15 @@ import React, { Component } from 'react'
|
|||||||
import Identicon from '../../ui/identicon'
|
import Identicon from '../../ui/identicon'
|
||||||
import { conversionUtil, multiplyCurrencies } from '../../../helpers/utils/conversion-util'
|
import { conversionUtil, multiplyCurrencies } from '../../../helpers/utils/conversion-util'
|
||||||
import TokenMenuDropdown from '../dropdowns/token-menu-dropdown.js'
|
import TokenMenuDropdown from '../dropdowns/token-menu-dropdown.js'
|
||||||
|
import Tooltip from '../../ui/tooltip-v2'
|
||||||
|
import { I18nContext } from '../../../contexts/i18n'
|
||||||
|
|
||||||
export default class TokenCell extends Component {
|
export default class TokenCell extends Component {
|
||||||
static contextTypes = {
|
static contextType = I18nContext
|
||||||
metricsEvent: PropTypes.func,
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
address: PropTypes.string,
|
address: PropTypes.string,
|
||||||
|
outdatedBalance: PropTypes.bool,
|
||||||
symbol: PropTypes.string,
|
symbol: PropTypes.string,
|
||||||
string: PropTypes.string,
|
string: PropTypes.string,
|
||||||
selectedTokenAddress: PropTypes.string,
|
selectedTokenAddress: PropTypes.string,
|
||||||
@ -20,6 +21,11 @@ export default class TokenCell extends Component {
|
|||||||
currentCurrency: PropTypes.string,
|
currentCurrency: PropTypes.string,
|
||||||
image: PropTypes.string,
|
image: PropTypes.string,
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
|
userAddress: PropTypes.string.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
outdatedBalance: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -27,6 +33,7 @@ export default class TokenCell extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
const t = this.context
|
||||||
const { tokenMenuOpen } = this.state
|
const { tokenMenuOpen } = this.state
|
||||||
const {
|
const {
|
||||||
address,
|
address,
|
||||||
@ -38,6 +45,8 @@ export default class TokenCell extends Component {
|
|||||||
onClick,
|
onClick,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
image,
|
image,
|
||||||
|
outdatedBalance,
|
||||||
|
userAddress,
|
||||||
} = this.props
|
} = this.props
|
||||||
let currentTokenToFiatRate
|
let currentTokenToFiatRate
|
||||||
let currentTokenInFiat
|
let currentTokenInFiat
|
||||||
@ -66,6 +75,7 @@ export default class TokenCell extends Component {
|
|||||||
<div
|
<div
|
||||||
className={classnames('token-cell', {
|
className={classnames('token-cell', {
|
||||||
'token-cell--active': selectedTokenAddress === address,
|
'token-cell--active': selectedTokenAddress === address,
|
||||||
|
'token-cell--outdated': outdatedBalance,
|
||||||
})}
|
})}
|
||||||
onClick={onClick.bind(null, address)}
|
onClick={onClick.bind(null, address)}
|
||||||
>
|
>
|
||||||
@ -85,6 +95,32 @@ export default class TokenCell extends Component {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
outdatedBalance && (
|
||||||
|
<Tooltip
|
||||||
|
interactive
|
||||||
|
position="bottom"
|
||||||
|
html={(
|
||||||
|
<div className="token-cell__outdated-tooltip">
|
||||||
|
{ t('troubleTokenBalances') }
|
||||||
|
<a
|
||||||
|
href={`https://ethplorer.io/address/${userAddress}`}
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
style={{ color: '#F7861C' }}
|
||||||
|
>
|
||||||
|
{ t('here') }
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<i className={classnames(['fa', 'fa-exclamation-circle', 'token-cell__outdated-icon'])} />
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
<div>
|
||||||
<i
|
<i
|
||||||
className="fa fa-ellipsis-h fa-lg token-cell__ellipsis cursor-pointer"
|
className="fa fa-ellipsis-h fa-lg token-cell__ellipsis cursor-pointer"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import TokenCell from './token-cell.component'
|
import TokenCell from './token-cell.component'
|
||||||
|
import { getSelectedAddress } from '../../../selectors/selectors'
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
return {
|
return {
|
||||||
@ -7,6 +8,7 @@ function mapStateToProps (state) {
|
|||||||
conversionRate: state.metamask.conversionRate,
|
conversionRate: state.metamask.conversionRate,
|
||||||
currentCurrency: state.metamask.currentCurrency,
|
currentCurrency: state.metamask.currentCurrency,
|
||||||
selectedTokenAddress: state.metamask.selectedTokenAddress,
|
selectedTokenAddress: state.metamask.selectedTokenAddress,
|
||||||
|
userAddress: getSelectedAddress(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,10 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--outdated > &__identicon {
|
||||||
|
opacity: 0.5
|
||||||
|
}
|
||||||
|
|
||||||
&__balance-ellipsis {
|
&__balance-ellipsis {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -68,9 +72,12 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--outdated > &__balance-ellipsis {
|
||||||
|
opacity: 0.5
|
||||||
|
}
|
||||||
|
|
||||||
&__ellipsis {
|
&__ellipsis {
|
||||||
line-height: 45px;
|
line-height: 45px;
|
||||||
margin-left: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__balance-wrapper {
|
&__balance-wrapper {
|
||||||
@ -79,6 +86,16 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (
|
|||||||
display: flex;
|
display: flex;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__outdated-icon {
|
||||||
|
color: $warning-yellow;
|
||||||
|
display: block;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__outdated-tooltip {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.token-menu-dropdown {
|
.token-menu-dropdown {
|
||||||
|
@ -110,7 +110,7 @@ class TokenList extends Component {
|
|||||||
render () {
|
render () {
|
||||||
const t = this.context
|
const t = this.context
|
||||||
const { error, tokensLoading, tokensWithBalances } = this.state
|
const { error, tokensLoading, tokensWithBalances } = this.state
|
||||||
const { assetImages, network, onTokenClick, userAddress } = this.props
|
const { assetImages, network, onTokenClick } = this.props
|
||||||
if (network === 'loading' || tokensLoading) {
|
if (network === 'loading' || tokensLoading) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -127,39 +127,17 @@ class TokenList extends Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="hotFix"
|
|
||||||
style={{
|
|
||||||
padding: '80px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('troubleTokenBalances')}
|
|
||||||
<span
|
|
||||||
className="hotFix"
|
|
||||||
style={{
|
|
||||||
color: 'rgba(247, 134, 28, 1)',
|
|
||||||
cursor: 'pointer',
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
global.platform.openWindow({
|
|
||||||
url: `https://ethplorer.io/address/${userAddress}`,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('here')}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{tokensWithBalances.map((tokenData, index) => {
|
{tokensWithBalances.map((tokenData, index) => {
|
||||||
tokenData.image = assetImages[tokenData.address]
|
tokenData.image = assetImages[tokenData.address]
|
||||||
return (
|
return (
|
||||||
<TokenCell key={index} {...tokenData} onClick={onTokenClick} />
|
<TokenCell
|
||||||
|
key={index}
|
||||||
|
{...tokenData}
|
||||||
|
outdatedBalance={Boolean(error)}
|
||||||
|
onClick={onTokenClick}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user