From 9bae32e78b230ede45ab159e0022da5728f0f267 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 20 Apr 2017 19:07:09 -0700 Subject: Add functional but ugly and hard-coded token list --- ui/app/components/account-export.js | 2 -- ui/app/components/token-cell.js | 22 +++++++++++++++ ui/app/components/token-list.js | 51 +++++++++++++++++++++++++++++++++++ ui/app/components/transaction-list.js | 11 -------- 4 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 ui/app/components/token-cell.js create mode 100644 ui/app/components/token-list.js (limited to 'ui/app/components') diff --git a/ui/app/components/account-export.js b/ui/app/components/account-export.js index 888196c5d..394d878f7 100644 --- a/ui/app/components/account-export.js +++ b/ui/app/components/account-export.js @@ -20,8 +20,6 @@ function mapStateToProps (state) { } ExportAccountView.prototype.render = function () { - console.log('EXPORT VIEW') - console.dir(this.props) var state = this.props var accountDetail = state.accountDetail diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js new file mode 100644 index 000000000..34a12733f --- /dev/null +++ b/ui/app/components/token-cell.js @@ -0,0 +1,22 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +module.exports = TokenCell + +inherits(TokenCell, Component) +function TokenCell () { + Component.call(this) +} + +TokenCell.prototype.render = function () { + const props = this.props + const { address, symbol, string } = props + log.info({ address, symbol, string }) + + return ( + h('li', [ + h('span', `${symbol}: ${string}`), + ]) + ) +} diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js new file mode 100644 index 000000000..35e79401b --- /dev/null +++ b/ui/app/components/token-list.js @@ -0,0 +1,51 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const TokenTracker = require('eth-token-tracker') +const TokenCell = require('./token-cell.js') + +module.exports = TokenList + +inherits(TokenList, Component) +function TokenList () { + + // Hard coded for development for now: + const tokens = [ + { address: '0x48c80F1f4D53D5951e5D5438B54Cba84f29F32a5', symbol: 'REP', balance: 'aa'}, + { address: '0xc66ea802717bfb9833400264dd12c2bceaa34a6d', symbol: 'MKR', balance: '1000', decimals: 18}, + { address: '0xa74476443119A942dE498590Fe1f2454d7D4aC0d', symbol: 'GOL', balance: 'ff'}, + { address: '0xaec2e87e0a235266d9c5adc9deb4b2e29b54d009', symbol: 'SNGLS', balance: '0' }, + ] + + this.state = { tokens } + Component.call(this) +} + +TokenList.prototype.render = function () { + const tokens = this.state.tokens + + return ( + h('ol', tokens.map((tokenData) => { + console.log('rendering token with', tokenData) + return h(TokenCell, tokenData) + })) + ) +} + +TokenList.prototype.componentDidMount = function () { + const { userAddress } = this.props + + this.tracker = new TokenTracker({ + userAddress, + provider: web3.currentProvider, + tokens: this.state.tokens, + }) + + this.setState({ tokens: this.tracker.serialize() }) + this.tracker.on('update', (tokenData) => this.setState({ tokens: tokenData })) + this.tracker.updateBalances() +} + +TokenList.prototype.componentWillUnmount = function () { + this.tracker.stop() +} diff --git a/ui/app/components/transaction-list.js b/ui/app/components/transaction-list.js index 3ae953637..4c25f3dd9 100644 --- a/ui/app/components/transaction-list.js +++ b/ui/app/components/transaction-list.js @@ -36,17 +36,6 @@ TransactionList.prototype.render = function () { } `), - h('h3.flex-center.text-transform-uppercase', { - style: { - background: '#EBEBEB', - color: '#AEAEAE', - paddingTop: '4px', - paddingBottom: '4px', - }, - }, [ - 'History', - ]), - h('.tx-list', { style: { overflowY: 'auto', -- cgit From 40e2450022488daa5e36d4c1b866e061bba7c5d2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 21 Apr 2017 09:01:51 -0700 Subject: Get token list looking ok --- ui/app/components/balance.js | 88 +++++++++++++++++++++++++++++++++++++++++ ui/app/components/identicon.js | 8 ++-- ui/app/components/token-cell.js | 11 +++++- ui/app/components/token-list.js | 23 +++++++++-- 4 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 ui/app/components/balance.js (limited to 'ui/app/components') diff --git a/ui/app/components/balance.js b/ui/app/components/balance.js new file mode 100644 index 000000000..3c5e24b65 --- /dev/null +++ b/ui/app/components/balance.js @@ -0,0 +1,88 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const formatBalance = require('../util').formatBalance const generateBalanceObject = require('../util').generateBalanceObject +const Tooltip = require('./tooltip.js') +const FiatValue = require('./fiat-value.js') + +module.exports = EthBalanceComponent + +inherits(EthBalanceComponent, Component) +function EthBalanceComponent () { + Component.call(this) +} + +EthBalanceComponent.prototype.render = function () { + var props = this.props + let { value } = props + var style = props.style + var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true + value = value ? formatBalance(value, 6, needsParse) : '...' + var width = props.width + + return ( + + h('.ether-balance.ether-balance-amount', { + style: style, + }, [ + h('div', { + style: { + display: 'inline', + width: width, + }, + }, this.renderBalance(value)), + ]) + + ) +} +EthBalanceComponent.prototype.renderBalance = function (value) { + var props = this.props + if (value === 'None') return value + if (value === '...') return value + var balanceObj = generateBalanceObject(value, props.shorten ? 1 : 3) + var balance + var splitBalance = value.split(' ') + var ethNumber = splitBalance[0] + var ethSuffix = splitBalance[1] + const showFiat = 'showFiat' in props ? props.showFiat : true + + if (props.shorten) { + balance = balanceObj.shortBalance + } else { + balance = balanceObj.balance + } + + var label = balanceObj.label + + return ( + h(Tooltip, { + position: 'bottom', + title: `${ethNumber} ${ethSuffix}`, + }, h('div.flex-column', [ + h('.flex-row', { + style: { + alignItems: 'flex-end', + lineHeight: '13px', + fontFamily: 'Montserrat Light', + textRendering: 'geometricPrecision', + }, + }, [ + h('div', { + style: { + width: '100%', + textAlign: 'right', + }, + }, this.props.incoming ? `+${balance}` : balance), + h('div', { + style: { + color: ' #AEAEAE', + fontSize: '12px', + marginLeft: '5px', + }, + }, label), + ]), + + showFiat ? h(FiatValue, { value: props.value }) : null, + ])) + ) +} diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 6d4871d02..1bb92301e 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -34,19 +34,19 @@ IdenticonComponent.prototype.render = function () { IdenticonComponent.prototype.componentDidMount = function () { var props = this.props - var address = props.address + const { address, network } = props if (!address) return var container = findDOMNode(this) var diameter = props.diameter || this.defaultDiameter - var img = iconFactory.iconForAddress(address, diameter, false) + var img = iconFactory.iconForAddress(address, diameter, false, network) container.appendChild(img) } IdenticonComponent.prototype.componentDidUpdate = function () { var props = this.props - var address = props.address + const { address, network } = props if (!address) return @@ -58,6 +58,6 @@ IdenticonComponent.prototype.componentDidUpdate = function () { } var diameter = props.diameter || this.defaultDiameter - var img = iconFactory.iconForAddress(address, diameter, false) + var img = iconFactory.iconForAddress(address, diameter, false, network) container.appendChild(img) } diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 34a12733f..81e92b301 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const Identicon = require('./identicon') module.exports = TokenCell @@ -15,8 +16,14 @@ TokenCell.prototype.render = function () { log.info({ address, symbol, string }) return ( - h('li', [ - h('span', `${symbol}: ${string}`), + h('li.token-cell', [ + + h(Identicon, { + diameter: 50, + address, + }), + + h('h3', `${string || 0} ${symbol}`), ]) ) } diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 35e79401b..c6a7d3552 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -24,11 +24,26 @@ function TokenList () { TokenList.prototype.render = function () { const tokens = this.state.tokens + const tokenViews = tokens.map((tokenData) => { + console.log('rendering token with', tokenData) + return h(TokenCell, tokenData) + }) + return ( - h('ol', tokens.map((tokenData) => { - console.log('rendering token with', tokenData) - return h(TokenCell, tokenData) - })) + h('ol', [h('style', ` + + li.token-cell { + display: flex; + flex-direction: row; + align-items: center; + padding: 10px; + } + + li.token-cell > h3 { + margin-left: 12px; + } + + `)].concat(tokenViews)) ) } -- cgit From bce4af2dcaeeab3bd931afbbcc6f17da675ce2b6 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 24 Apr 2017 13:55:19 -0700 Subject: Add placeholder etherscan token icons --- ui/app/components/token-cell.js | 4 +++- ui/app/components/token-list.js | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 81e92b301..879dc01d1 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -12,7 +12,7 @@ function TokenCell () { TokenCell.prototype.render = function () { const props = this.props - const { address, symbol, string } = props + const { address, symbol, string, network } = props log.info({ address, symbol, string }) return ( @@ -21,9 +21,11 @@ TokenCell.prototype.render = function () { h(Identicon, { diameter: 50, address, + network, }), h('h3', `${string || 0} ${symbol}`), ]) ) } + diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index c6a7d3552..6589dea62 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -23,9 +23,10 @@ function TokenList () { TokenList.prototype.render = function () { const tokens = this.state.tokens + const network = this.props.network const tokenViews = tokens.map((tokenData) => { - console.log('rendering token with', tokenData) + tokenData.network = network return h(TokenCell, tokenData) }) @@ -43,6 +44,11 @@ TokenList.prototype.render = function () { margin-left: 12px; } + li.token-cell:hover { + background: white; + cursor: pointer; + } + `)].concat(tokenViews)) ) } -- cgit From 108c4ab2c58074aa8148828fbbef8cbf3a4e23f5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 13 Jun 2017 17:47:56 -0700 Subject: Auto populate token list with popular token balances Half implements #175 Things to do: - Add ability to add tokens to the list. - Persist the token tab selection (so it is an implicit preference) - Check what's up with the token-tracker polling, it seems like it is not waiting the interval. --- ui/app/components/identicon.js | 6 +++-- ui/app/components/tab-bar.js | 1 + ui/app/components/token-cell.js | 22 +++++++++++++++--- ui/app/components/token-list.js | 49 +++++++++++++++++++++++++++++------------ 4 files changed, 59 insertions(+), 19 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 58bd2bdc4..c754bc6ba 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -23,7 +23,9 @@ IdenticonComponent.prototype.render = function () { h('div', { key: 'identicon-' + this.props.address, style: { - display: 'inline-block', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', height: diameter, width: diameter, borderRadius: diameter / 2, @@ -40,8 +42,8 @@ IdenticonComponent.prototype.componentDidMount = function () { if (!address) return var container = findDOMNode(this) - var diameter = props.diameter || this.defaultDiameter + var diameter = props.diameter || this.defaultDiameter if (!isNode) { var img = iconFactory.iconForAddress(address, diameter) container.appendChild(img) diff --git a/ui/app/components/tab-bar.js b/ui/app/components/tab-bar.js index 65078e0a4..6295e7dd9 100644 --- a/ui/app/components/tab-bar.js +++ b/ui/app/components/tab-bar.js @@ -33,3 +33,4 @@ TabBar.prototype.render = function () { })) ) } + diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 879dc01d1..ad7f55345 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -12,11 +12,19 @@ function TokenCell () { TokenCell.prototype.render = function () { const props = this.props - const { address, symbol, string, network } = props - log.info({ address, symbol, string }) + const { address, symbol, string, network, userAddress } = props + log.info({ address, symbol, string, network }) return ( - h('li.token-cell', [ + h('li.token-cell', { + style: { cursor: network === '1' ? 'pointer' : 'default' }, + onClick: (event) => { + const url = urlFor(address, userAddress, network) + if (url) { + navigateTo(url) + } + }, + }, [ h(Identicon, { diameter: 50, @@ -29,3 +37,11 @@ TokenCell.prototype.render = function () { ) } +function navigateTo (url) { + global.platform.openWindow({ url }) +} + +function urlFor (tokenAddress, address, network) { + return `https://etherscan.io/token/${tokenAddress}?a=${address}` +} + diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 6589dea62..b79fbccf3 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -3,35 +3,49 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const TokenTracker = require('eth-token-tracker') const TokenCell = require('./token-cell.js') +const contracts = require('eth-contract-metadata') +const Loading = require('./loading') + +const tokens = [] +for (let address in contracts) { + const contract = contracts[address] + if (contract.erc20) { + contract.address = address + tokens.push(contract) + } +} module.exports = TokenList inherits(TokenList, Component) function TokenList () { - - // Hard coded for development for now: - const tokens = [ - { address: '0x48c80F1f4D53D5951e5D5438B54Cba84f29F32a5', symbol: 'REP', balance: 'aa'}, - { address: '0xc66ea802717bfb9833400264dd12c2bceaa34a6d', symbol: 'MKR', balance: '1000', decimals: 18}, - { address: '0xa74476443119A942dE498590Fe1f2454d7D4aC0d', symbol: 'GOL', balance: 'ff'}, - { address: '0xaec2e87e0a235266d9c5adc9deb4b2e29b54d009', symbol: 'SNGLS', balance: '0' }, - ] - - this.state = { tokens } + this.state = { tokens, isLoading: true } Component.call(this) } TokenList.prototype.render = function () { - const tokens = this.state.tokens + const state = this.state + const { tokens, isLoading } = state + + const { userAddress } = this.props + + if (isLoading) return h(Loading, { isLoading }) + const network = this.props.network const tokenViews = tokens.map((tokenData) => { tokenData.network = network + tokenData.userAddress = userAddress return h(TokenCell, tokenData) }) return ( - h('ol', [h('style', ` + h('ol', { + style: { + height: '302px', + overflowY: 'auto', + }, + }, [h('style', ` li.token-cell { display: flex; @@ -54,19 +68,26 @@ TokenList.prototype.render = function () { } TokenList.prototype.componentDidMount = function () { + if (!global.ethereumProvider) return const { userAddress } = this.props this.tracker = new TokenTracker({ userAddress, - provider: web3.currentProvider, + provider: global.ethereumProvider, tokens: this.state.tokens, + pollingInterval: 8000, }) this.setState({ tokens: this.tracker.serialize() }) - this.tracker.on('update', (tokenData) => this.setState({ tokens: tokenData })) + this.tracker.on('update', (tokenData) => { + const heldTokens = tokenData.filter(token => token.balance !== '0' && token.string !== '0.000') + this.setState({ tokens: heldTokens, isLoading: false }) + }) this.tracker.updateBalances() } TokenList.prototype.componentWillUnmount = function () { + if (!this.tracker) return this.tracker.stop() } + -- cgit From b7b9e0c1ac203d39196753f39f17a1fe2f4751e5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 14:21:50 -0700 Subject: Persist selected account tab Also improve error handling with token balances. --- ui/app/components/token-list.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index b79fbccf3..66cbddeda 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -80,10 +80,21 @@ TokenList.prototype.componentDidMount = function () { this.setState({ tokens: this.tracker.serialize() }) this.tracker.on('update', (tokenData) => { - const heldTokens = tokenData.filter(token => token.balance !== '0' && token.string !== '0.000') - this.setState({ tokens: heldTokens, isLoading: false }) + this.updateBalances(tokenData) }) this.tracker.updateBalances() + .then(() => { + this.updateBalances(this.tracker.serialize()) + }) + .catch((reason) => { + log.error(`Problem updating balances`, reason) + this.setState({ isLoading: false }) + }) +} + +TokenList.prototype.updateBalances = function (tokenData) { + const heldTokens = tokenData.filter(token => token.balance !== '0' && token.string !== '0.000') + this.setState({ tokens: heldTokens, isLoading: false }) } TokenList.prototype.componentWillUnmount = function () { -- cgit From 6fda78cd2b850c7414d598227a0ef6b4235f241e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 15:17:46 -0700 Subject: Refresh token balance on network change --- ui/app/components/token-list.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 66cbddeda..90e7e876e 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -7,7 +7,7 @@ const contracts = require('eth-contract-metadata') const Loading = require('./loading') const tokens = [] -for (let address in contracts) { +for (const address in contracts) { const contract = contracts[address] if (contract.erc20) { contract.address = address @@ -19,7 +19,7 @@ module.exports = TokenList inherits(TokenList, Component) function TokenList () { - this.state = { tokens, isLoading: true } + this.state = { tokens, isLoading: true, network: null } Component.call(this) } @@ -68,17 +68,23 @@ TokenList.prototype.render = function () { } TokenList.prototype.componentDidMount = function () { + this.createFreshTokenTracker() +} + +TokenList.prototype.createFreshTokenTracker = function () { + if (this.tracker) { + this.tracker.stop() + } + if (!global.ethereumProvider) return const { userAddress } = this.props - this.tracker = new TokenTracker({ userAddress, provider: global.ethereumProvider, - tokens: this.state.tokens, + tokens: tokens, pollingInterval: 8000, }) - this.setState({ tokens: this.tracker.serialize() }) this.tracker.on('update', (tokenData) => { this.updateBalances(tokenData) }) @@ -92,6 +98,17 @@ TokenList.prototype.componentDidMount = function () { }) } +TokenList.prototype.componentWillUpdate = function (nextProps) { + if (nextProps.network === 'loading') return + const oldNet = this.props.network + const newNet = nextProps.network + + if (oldNet && newNet && newNet !== oldNet) { + this.setState({ isLoading: true }) + this.createFreshTokenTracker() + } +} + TokenList.prototype.updateBalances = function (tokenData) { const heldTokens = tokenData.filter(token => token.balance !== '0' && token.string !== '0.000') this.setState({ tokens: heldTokens, isLoading: false }) -- cgit From 96d416c486c4efd3698d41a38a02c6379fbb61b1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 15:30:03 -0700 Subject: Vertically center loading indication --- ui/app/components/token-list.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 90e7e876e..c9e86dd22 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -4,7 +4,6 @@ const inherits = require('util').inherits const TokenTracker = require('eth-token-tracker') const TokenCell = require('./token-cell.js') const contracts = require('eth-contract-metadata') -const Loading = require('./loading') const tokens = [] for (const address in contracts) { @@ -29,7 +28,16 @@ TokenList.prototype.render = function () { const { userAddress } = this.props - if (isLoading) return h(Loading, { isLoading }) + if (isLoading) { + return h('div', { + style: { + display: 'flex', + height: '250px', + alignItems: 'center', + justifyContent: 'center', + }, + }, 'Loading') + } const network = this.props.network -- cgit From 1814721e80c057dd5da6f89ece3f2d376ca59bc1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 18:08:03 -0700 Subject: Add no tokens message --- ui/app/components/token-list.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index c9e86dd22..c560a6072 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -29,14 +29,7 @@ TokenList.prototype.render = function () { const { userAddress } = this.props if (isLoading) { - return h('div', { - style: { - display: 'flex', - height: '250px', - alignItems: 'center', - justifyContent: 'center', - }, - }, 'Loading') + return this.message('Loading') } const network = this.props.network @@ -71,10 +64,21 @@ TokenList.prototype.render = function () { cursor: pointer; } - `)].concat(tokenViews)) + `)].concat(tokenViews.length ? tokenViews : this.message('No Tokens Found.'))) ) } +TokenList.prototype.message = function (body) { + return h('div', { + style: { + display: 'flex', + height: '250px', + alignItems: 'center', + justifyContent: 'center', + }, + }, body) +} + TokenList.prototype.componentDidMount = function () { this.createFreshTokenTracker() } -- cgit From 68389d5d496dc11a25ce07b5f95b0e10954e847f Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 18:12:41 -0700 Subject: Remove excessive log --- ui/app/components/token-cell.js | 1 - 1 file changed, 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index ad7f55345..d3a895d36 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -13,7 +13,6 @@ function TokenCell () { TokenCell.prototype.render = function () { const props = this.props const { address, symbol, string, network, userAddress } = props - log.info({ address, symbol, string, network }) return ( h('li.token-cell', { -- cgit From 1ed5804e4dd2f85549abcb8dfd8981dab3f6868c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 14 Jun 2017 19:15:50 -0700 Subject: Multiple loading style improvements - When seeking network, show a full screen loading indication + message. - Network menu is still accessible "over" this indication. - Top Menu-Droppo components now slide *under* the menu bar like they should. - Loading indication opacity increased to increase message legibility. --- ui/app/components/loading.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js index 88dc535df..87d6f5d20 100644 --- a/ui/app/components/loading.js +++ b/ui/app/components/loading.js @@ -26,18 +26,21 @@ LoadingIndicator.prototype.render = function () { style: { zIndex: 10, position: 'absolute', + flexDirection: 'column', display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%', width: '100%', - background: 'rgba(255, 255, 255, 0.5)', + background: 'rgba(255, 255, 255, 0.8)', }, }, [ h('img', { src: 'images/loading.svg', }), + h('br'), + showMessageIfAny(loadingMessage), ]) : null, ]) -- cgit From a2781df8b4ce8d1fc03080eb3361217a236ec82d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 19 Jun 2017 19:11:55 -0700 Subject: Add better event lifecycle management to token list. Token list now renders errors when a token lookup fails. Also now cleans up event listeners when re-initializing the token list. --- ui/app/components/token-list.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index c560a6072..633d3ccfe 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -24,7 +24,7 @@ function TokenList () { TokenList.prototype.render = function () { const state = this.state - const { tokens, isLoading } = state + const { tokens, isLoading, error } = state const { userAddress } = this.props @@ -32,6 +32,11 @@ TokenList.prototype.render = function () { return this.message('Loading') } + if (error) { + log.error(error) + return this.message('There was a problem loading your token balances.') + } + const network = this.props.network const tokenViews = tokens.map((tokenData) => { @@ -85,7 +90,10 @@ TokenList.prototype.componentDidMount = function () { TokenList.prototype.createFreshTokenTracker = function () { if (this.tracker) { + // Clean up old trackers when refreshing: this.tracker.stop() + this.tracker.removeListener('update', this.balanceUpdater) + this.tracker.removeListener('error', this.showError) } if (!global.ethereumProvider) return @@ -97,9 +105,15 @@ TokenList.prototype.createFreshTokenTracker = function () { pollingInterval: 8000, }) - this.tracker.on('update', (tokenData) => { - this.updateBalances(tokenData) - }) + + // Set up listener instances for cleaning up + this.balanceUpdater = this.updateBalances.bind(this) + this.showError = (error) => { + this.setState({ error, isLoading: false }) + } + this.tracker.on('update', this.balanceUpdater) + this.tracker.on('error', this.showError) + this.tracker.updateBalances() .then(() => { this.updateBalances(this.tracker.serialize()) -- cgit