diff options
author | Chi Kei Chan <chikeichan@gmail.com> | 2017-09-06 18:17:49 +0800 |
---|---|---|
committer | Chi Kei Chan <chikeichan@gmail.com> | 2017-09-06 18:17:49 +0800 |
commit | f1fb9e10a06d1811d97f61b6369684979b7ecf70 (patch) | |
tree | 674886d99e6be7ea30b83f8f3811643beb792f07 /ui/app/components | |
parent | 690ddf5ed75967537aa5513986146c262012832a (diff) | |
download | tangerine-wallet-browser-f1fb9e10a06d1811d97f61b6369684979b7ecf70.tar tangerine-wallet-browser-f1fb9e10a06d1811d97f61b6369684979b7ecf70.tar.gz tangerine-wallet-browser-f1fb9e10a06d1811d97f61b6369684979b7ecf70.tar.bz2 tangerine-wallet-browser-f1fb9e10a06d1811d97f61b6369684979b7ecf70.tar.lz tangerine-wallet-browser-f1fb9e10a06d1811d97f61b6369684979b7ecf70.tar.xz tangerine-wallet-browser-f1fb9e10a06d1811d97f61b6369684979b7ecf70.tar.zst tangerine-wallet-browser-f1fb9e10a06d1811d97f61b6369684979b7ecf70.zip |
Adding Token transaction detail screen
Diffstat (limited to 'ui/app/components')
-rw-r--r-- | ui/app/components/balance-component.js | 28 | ||||
-rw-r--r-- | ui/app/components/token-balance.js | 104 | ||||
-rw-r--r-- | ui/app/components/token-cell.js | 25 | ||||
-rw-r--r-- | ui/app/components/token-list.js | 10 | ||||
-rw-r--r-- | ui/app/components/tx-view.js | 75 | ||||
-rw-r--r-- | ui/app/components/wallet-view.js | 48 |
6 files changed, 213 insertions, 77 deletions
diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 48efc7b6a..6b997944f 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -2,13 +2,19 @@ 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 { formatBalance, generateBalanceObject } = require('../util') module.exports = connect(mapStateToProps)(BalanceComponent) function mapStateToProps (state) { + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const account = accounts[selectedAddress] + return { + account, conversionRate: state.metamask.conversionRate, currentCurrency: state.metamask.currentCurrency, } @@ -21,9 +27,8 @@ function BalanceComponent () { BalanceComponent.prototype.render = function () { const props = this.props - const { balanceValue } = props - const needsParse = 'needsParse' in props ? props.needsParse : true - const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...' + // const { balanceValue } = props + const { token } = props return h('div.balance-container', {}, [ @@ -33,13 +38,24 @@ BalanceComponent.prototype.render = function () { style: {}, }), - this.renderBalance(formattedBalance), + token ? this.renderTokenBalance() : this.renderBalance(), ]) } -BalanceComponent.prototype.renderBalance = function (formattedBalance) { +BalanceComponent.prototype.renderTokenBalance = function () { + const { token } = this.props + + return h('div.flex-column.balance-display', [ + h('div.token-amount', [ h(TokenBalance, { token }) ]), + ]) +} + +BalanceComponent.prototype.renderBalance = function () { const props = this.props - const { shorten } = props + const { shorten, account } = props + const balanceValue = account && account.balance + const needsParse = 'needsParse' in props ? props.needsParse : true + const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...' const showFiat = 'showFiat' in props ? props.showFiat : true if (formattedBalance === 'None' || formattedBalance === '...') { diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js new file mode 100644 index 000000000..0757cc65c --- /dev/null +++ b/ui/app/components/token-balance.js @@ -0,0 +1,104 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const TokenTracker = require('eth-token-tracker') +const connect = require('react-redux').connect +const selectors = require('../selectors') + +function mapStateToProps (state) { + return { + userAddress: selectors.getSelectedAddress(state), + } +} + +module.exports = connect(mapStateToProps)(TokenBalance) + + +inherits(TokenBalance, Component) +function TokenBalance () { + this.state = { + balance: '', + isLoading: true, + error: null, + } + Component.call(this) +} + +TokenBalance.prototype.render = function () { + const state = this.state + const { balance, isLoading } = state + + return isLoading + ? h('span', '') + : h('span', balance) +} + +TokenBalance.prototype.componentDidMount = function () { + this.createFreshTokenTracker() +} + +TokenBalance.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 + const { userAddress, token } = this.props + + this.tracker = new TokenTracker({ + userAddress, + provider: global.ethereumProvider, + tokens: [token], + pollingInterval: 8000, + }) + + + // Set up listener instances for cleaning up + this.balanceUpdater = this.updateBalance.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.updateBalance(this.tracker.serialize()) + }) + .catch((reason) => { + log.error(`Problem updating balances`, reason) + this.setState({ isLoading: false }) + }) +} + +TokenBalance.prototype.componentDidUpdate = function (nextProps) { + const { + userAddress: oldAddress, + } = this.props + const { + userAddress: newAddress, + } = nextProps + + if (!oldAddress || !newAddress) return + if (oldAddress === newAddress) return + + this.setState({ isLoading: true }) + this.createFreshTokenTracker() +} + +TokenBalance.prototype.updateBalance = function (tokens = []) { + const [{ string }] = tokens + this.setState({ + balance: string, + isLoading: false, + }) +} + +TokenBalance.prototype.componentWillUnmount = function () { + if (!this.tracker) return + this.tracker.stop() +} + diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index a24e4e1ac..7fae67de6 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -1,10 +1,27 @@ 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') const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') +const selectors = require('../selectors') +const actions = require('../actions') -module.exports = TokenCell +function mapStateToProps (state) { + return { + network: state.metamask.network, + selectedTokenAddress: state.metamask.selectedTokenAddress, + userAddress: selectors.getSelectedAddress(state), + } +} + +function mapDispatchToProps (dispatch) { + return { + setSelectedToken: address => dispatch(actions.setSelectedToken(address)), + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(TokenCell) inherits(TokenCell, Component) function TokenCell () { @@ -18,13 +35,17 @@ TokenCell.prototype.render = function () { symbol, string, network, + setSelectedToken, + selectedTokenAddress, // userAddress, } = props return ( h('div.token-list-item', { - style: { cursor: network === '1' ? 'pointer' : 'default' }, + className: `token-list-item ${selectedTokenAddress ? 'token-list-item--active' : ''}`, + // style: { cursor: network === '1' ? 'pointer' : 'default' }, // onClick: this.view.bind(this, address, userAddress, network), + onClick: () => setSelectedToken(address), }, [ h(Identicon, { diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index fea87a733..2d1dd0ea7 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -8,7 +8,6 @@ const connect = require('react-redux').connect const selectors = require('../selectors') function mapStateToProps (state) { - return { network: state.metamask.network, tokens: state.metamask.tokens, @@ -42,7 +41,6 @@ function TokenList () { TokenList.prototype.render = function () { const state = this.state const { tokens, isLoading, error } = state - const { userAddress, network } = this.props if (isLoading) { return this.message('Loading Tokens...') @@ -53,13 +51,7 @@ TokenList.prototype.render = function () { return this.message('There was a problem loading your token balances.') } - const tokenViews = tokens.map((tokenData) => { - tokenData.network = network - tokenData.userAddress = userAddress - return h(TokenCell, tokenData) - }) - - return h('div', tokenViews) + return h('div', tokens.map((tokenData) => h(TokenCell, tokenData))) } TokenList.prototype.message = function (body) { diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 9f75f7b31..d7e4a5b4b 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -4,10 +4,12 @@ const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits const actions = require('../actions') +const selectors = require('../selectors') const BalanceComponent = require('./balance-component') const TxList = require('./tx-list') const Identicon = require('./identicon') +const TokenBalance = require('./token-balance') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) @@ -16,6 +18,7 @@ function mapStateToProps (state) { const identities = state.metamask.identities const accounts = state.metamask.accounts + const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) const identity = identities[selectedAddress] @@ -25,6 +28,8 @@ function mapStateToProps (state) { sidebarOpen, selectedAddress, checksumAddress, + selectedTokenAddress, + selectedToken: selectors.getSelectedToken(state), identity, account, } @@ -44,9 +49,41 @@ function TxView () { Component.call(this) } +TxView.prototype.renderHeroBalance = function () { + const {account, selectedToken, showModal, showSendPage } = this.props + + return h('div.hero-balance', {}, [ + + h(BalanceComponent, { + balanceValue: account && account.balance, + token: selectedToken, + }), + + h('div.flex-row.flex-center.hero-balance-buttons', {}, [ + h('button.btn-clear', { + style: { + textAlign: 'center', + }, + onClick: () => showModal({ + name: 'BUY', + }), + }, 'BUY'), + + h('button.btn-clear', { + style: { + textAlign: 'center', + marginLeft: '0.8em', + }, + onClick: showSendPage, + }, 'SEND'), + + ]), + ]) +} + TxView.prototype.render = function () { - const { selectedAddress, identity, account } = this.props + const { selectedAddress, identity } = this.props return h('div.tx-view.flex-column', { style: {}, @@ -87,41 +124,7 @@ TxView.prototype.render = function () { ]), - h('div.hero-balance', { - style: {}, - }, [ - - h(BalanceComponent, { - balanceValue: account && account.balance, - style: {}, - }), - - h('div.flex-row.flex-center.hero-balance-buttons', { - style: {}, - }, [ - h('button.btn-clear', { - style: { - textAlign: 'center', - }, - onClick: () => { - this.props.showModal({ - name: 'BUY', - }) - }, - }, 'BUY'), - - h('button.btn-clear', { - style: { - textAlign: 'center', - marginLeft: '0.8em', - }, - onClick: () => { - this.props.showSendPage() - }, - }, 'SEND'), - - ]), - ]), + this.renderHeroBalance(), h(TxList, {}), diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 304b5daba..f9710ea4c 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -22,6 +22,7 @@ function mapStateToProps (state) { selectedAddress: selectors.getSelectedAddress(state), selectedIdentity: selectors.getSelectedIdentity(state), selectedAccount: selectors.getSelectedAccount(state), + selectedTokenAddress: state.metamask.selectedTokenAddress, } } @@ -29,6 +30,7 @@ function mapDispatchToProps (dispatch) { return { showSendPage: () => { dispatch(actions.showSendPage()) }, hideSidebar: () => { dispatch(actions.hideSidebar()) }, + unsetSelectedToken: () => dispatch(actions.setSelectedToken()), } } @@ -37,15 +39,26 @@ function WalletView () { Component.call(this) } -WalletView.prototype.renderTokenBalances = function () { - // const { tokens = [] } = this.props - // return tokens.map(({ address, decimals, symbol }) => ( - // h(BalanceComponent, { - // balanceValue: 0, - // style: {}, - // }) - // )) - return h(TokenList) +WalletView.prototype.renderWalletBalance = function () { + const { selectedTokenAddress, selectedAccount, unsetSelectedToken } = this.props + const selectedClass = selectedTokenAddress + ? '' + : 'wallet-balance-wrapper--active' + const className = `flex-column wallet-balance-wrapper ${selectedClass}` + + return h('div', { className }, [ + h('div.wallet-balance', + { + onClick: () => unsetSelectedToken(), + }, + [ + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + ] + ), + ]) } WalletView.prototype.render = function () { @@ -139,22 +152,9 @@ WalletView.prototype.render = function () { ]), ]), - // Wallet Balances - h('div.flex-column.wallet-balance-wrapper.wallet-balance-wrapper-active', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - - ]), + this.renderWalletBalance(), - this.renderTokenBalances(), + h(TokenList), ]) } |