Send Token screen partial UI

This commit is contained in:
Chi Kei Chan 2017-09-07 04:24:03 -07:00
parent 983fa2a117
commit 8b919758e5
7 changed files with 283 additions and 3 deletions

View File

@ -95,6 +95,8 @@ var actions = {
// account detail screen // account detail screen
SHOW_SEND_PAGE: 'SHOW_SEND_PAGE', SHOW_SEND_PAGE: 'SHOW_SEND_PAGE',
showSendPage: showSendPage, showSendPage: showSendPage,
SHOW_SEND_TOKEN_PAGE: 'SHOW_SEND_TOKEN_PAGE',
showSendTokenPage,
ADD_TO_ADDRESS_BOOK: 'ADD_TO_ADDRESS_BOOK', ADD_TO_ADDRESS_BOOK: 'ADD_TO_ADDRESS_BOOK',
addToAddressBook: addToAddressBook, addToAddressBook: addToAddressBook,
REQUEST_ACCOUNT_EXPORT: 'REQUEST_ACCOUNT_EXPORT', REQUEST_ACCOUNT_EXPORT: 'REQUEST_ACCOUNT_EXPORT',
@ -928,6 +930,12 @@ function showSendPage () {
} }
} }
function showSendTokenPage () {
return {
type: actions.SHOW_SEND_TOKEN_PAGE,
}
}
function buyEth (opts) { function buyEth (opts) {
return (dispatch) => { return (dispatch) => {
const url = getBuyEthUrl(opts) const url = getBuyEthUrl(opts)

View File

@ -9,6 +9,7 @@ const NewKeyChainScreen = require('./new-keychain')
// accounts // accounts
const MainContainer = require('./main-container') const MainContainer = require('./main-container')
const SendTransactionScreen = require('./send') const SendTransactionScreen = require('./send')
const SendTokenScreen = require('./components/send-token')
const ConfirmTxScreen = require('./conf-tx') const ConfirmTxScreen = require('./conf-tx')
// notice // notice
const NoticeScreen = require('./components/notice') const NoticeScreen = require('./components/notice')
@ -327,6 +328,10 @@ App.prototype.renderPrimary = function () {
log.debug('rendering send tx screen') log.debug('rendering send tx screen')
return h(SendTransactionScreen, {key: 'send-transaction'}) return h(SendTransactionScreen, {key: 'send-transaction'})
case 'sendToken':
log.debug('rendering send token screen')
return h(SendTokenScreen, {key: 'sendToken'})
case 'newKeychain': case 'newKeychain':
log.debug('rendering new keychain screen') log.debug('rendering new keychain screen')
return h(NewKeyChainScreen, {key: 'new-keychain'}) return h(NewKeyChainScreen, {key: 'new-keychain'})

View File

@ -0,0 +1,213 @@
const Component = require('react').Component
const connect = require('react-redux').connect
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 Identicon = require('../identicon')
const TokenBalance = require('../token-balance')
const CurrencyToggle = require('../send/currency-toggle')
const GasTooltip = require('../send/gas-tooltip')
const GasFeeDisplay = require('../send/gas-fee-display')
module.exports = connect(mapStateToProps, mapDispatchToProps)(SendTokenScreen)
function mapStateToProps (state) {
// const sidebarOpen = state.appState.sidebarOpen
const identities = state.metamask.identities
const addressBook = state.metamask.addressBook
const conversionRate = state.metamask.conversionRate
const currentBlockGasLimit = state.metamask.currentBlockGasLimit
// const accounts = state.metamask.accounts
// const network = state.metamask.network
const selectedTokenAddress = state.metamask.selectedTokenAddress
// const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
// const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress)
// const identity = identities[selectedAddress]
return {
// sidebarOpen,
// selectedAddress,
// checksumAddress,
selectedTokenAddress,
identities,
addressBook,
conversionRate,
currentBlockGasLimit,
selectedToken: selectors.getSelectedToken(state),
// selectedToken: selectors.getSelectedToken(state),
// identity,
// network,
}
}
function mapDispatchToProps (dispatch) {
return {
// showSidebar: () => { dispatch(actions.showSidebar()) },
// hideSidebar: () => { dispatch(actions.hideSidebar()) },
// showModal: (payload) => { dispatch(actions.showModal(payload)) },
// showSendPage: () => { dispatch(actions.showSendPage()) },
// showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) },
}
}
inherits(SendTokenScreen, Component)
function SendTokenScreen () {
Component.call(this)
this.state = {
to: '',
selectedCurrency: 'USD',
isGasTooltipOpen: false,
gasPrice: '0x5d21dba00',
gasLimit: '0x7b0d',
}
}
SendTokenScreen.prototype.renderToAddressInput = function () {
const {
identities,
addressBook,
} = this.props
const {
to,
} = this.state
return h('div.send-screen-input-wrapper', {}, [
h('div', ['To:']),
h('input.large-input.send-screen-input', {
name: 'address',
list: 'addresses',
placeholder: 'Address',
value: to,
onChange: e => this.setState({ to: e.target.value }),
}),
h('datalist#addresses', [
// Corresponds to the addresses owned.
Object.entries(identities).map(([key, { address, name }]) => {
return h('option', {
value: address,
label: name,
key: address,
})
}),
addressBook.map(({ address, name }) => {
return h('option', {
value: address,
label: name,
key: address,
})
}),
]),
])
}
SendTokenScreen.prototype.renderAmountInput = function () {
const {
selectedCurrency,
} = this.state
const {
selectedToken: {symbol},
} = this.props
return h('div.send-screen-input-wrapper', {}, [
h('div.send-screen-amount-labels', [
h('span', ['Amount']),
h(CurrencyToggle, {
selectedCurrency,
onClick: currency => this.setState({ selectedCurrency: currency }),
}),
]),
h('input.large-input.send-screen-input', {
placeholder: `0 ${symbol}`,
type: 'number',
onChange: e => this.setState({ amount: e.target.value }),
}),
])
}
SendTokenScreen.prototype.renderGasInput = function () {
const {
isGasTooltipOpen,
gasPrice,
gasLimit,
selectedCurrency,
} = this.state
const {
conversionRate,
currentBlockGasLimit,
} = this.props
return h('div.send-screen-input-wrapper', [
isGasTooltipOpen && h(GasTooltip, {
className: 'send-tooltip',
gasPrice,
gasLimit,
onClose: () => this.setState({ isGasTooltipOpen: false }),
onFeeChange: ({ gasLimit, gasPrice }) => {
this.setState({ gasLimit, gasPrice })
},
}),
h('div.send-screen-gas-labels', {}, [
h('span', [ h('i.fa.fa-bolt'), 'Gas fee:']),
h('span', ['What\'s this?']),
]),
h('div.large-input.send-screen-gas-input', [
h(GasFeeDisplay, {
conversionRate,
gasPrice,
currentCurrency: selectedCurrency,
gas: gasLimit,
blockGasLimit: currentBlockGasLimit,
}),
h(
'div.send-screen-gas-input-customize',
{ onClick: () => this.setState({ isGasTooltipOpen: !isGasTooltipOpen }) },
['Customize']
),
]),
])
}
SendTokenScreen.prototype.renderMemoInput = function () {
return h('div.send-screen-input-wrapper', {}, [
h('div', {}, ['Transaction memo (optional)']),
h(
'input.large-input.send-screen-input',
{ onChange: e => this.setState({ memo: e.target.value }) }
),
])
}
SendTokenScreen.prototype.render = function () {
const {
selectedTokenAddress,
selectedToken,
} = this.props
return h('div.send-token', [
h(Identicon, {
diameter: 75,
address: selectedTokenAddress,
}),
h('div.send-token__title', ['Send Tokens']),
h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']),
h('div.send-token__balance-text', ['Your Token Balance is:']),
h('div.send-token__token-balance', [
h(TokenBalance, { token: selectedToken, balanceOnly: true }),
]),
h('div.send-token__token-symbol', [selectedToken.symbol]),
this.renderToAddressInput(),
this.renderAmountInput(),
this.renderGasInput(),
this.renderMemoInput(),
])
}

View File

@ -93,8 +93,10 @@ TokenBalance.prototype.componentDidUpdate = function (nextProps) {
TokenBalance.prototype.updateBalance = function (tokens = []) { TokenBalance.prototype.updateBalance = function (tokens = []) {
const [{ string, symbol }] = tokens const [{ string, symbol }] = tokens
const { balanceOnly } = this.props
this.setState({ this.setState({
balance: `${string} ${symbol}`, balance: balanceOnly ? string : `${string} ${symbol}`,
isLoading: false, isLoading: false,
}) })
} }

View File

@ -40,6 +40,7 @@ function mapDispatchToProps (dispatch) {
hideSidebar: () => { dispatch(actions.hideSidebar()) }, hideSidebar: () => { dispatch(actions.hideSidebar()) },
showModal: (payload) => { dispatch(actions.showModal(payload)) }, showModal: (payload) => { dispatch(actions.showModal(payload)) },
showSendPage: () => { dispatch(actions.showSendPage()) }, showSendPage: () => { dispatch(actions.showSendPage()) },
showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) },
} }
} }
@ -60,7 +61,7 @@ TxView.prototype.renderHeroBalance = function () {
} }
TxView.prototype.renderButtons = function () { TxView.prototype.renderButtons = function () {
const {selectedToken, showModal, showSendPage } = this.props const {selectedToken, showModal, showSendPage, showSendTokenPage } = this.props
return !selectedToken return !selectedToken
? ( ? (
@ -90,7 +91,7 @@ TxView.prototype.renderButtons = function () {
textAlign: 'center', textAlign: 'center',
marginLeft: '0.8em', marginLeft: '0.8em',
}, },
onClick: showSendPage, onClick: showSendTokenPage,
}, 'SEND'), }, 'SEND'),
]) ])
) )

View File

@ -203,3 +203,44 @@
font-size: .8em; font-size: .8em;
padding: 1px 4px; padding: 1px 4px;
} }
.send-token {
width: 498px;
height: 605px;
background-color: #fff;
display: flex;
flex-flow: column nowrap;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .08);
padding: 46px 40.5px 26px;
position: relative;
top: -26px;
z-index: 25;
align-items: center;
font-family: "Montserrat Light";
.identicon {
position: absolute;
top: -35px;
z-index: 25;
}
&__title {
color: $scorpion;
font-size: 20px;
line-height: 29px;
}
&__description,
&__balance-text,
&__token-symbol {
margin-top: 10px;
font-size: 16px;
line-height: 24px;
}
&__token-balance {
font-size: 43px;
line-height: 40px;
margin-top: 13px;
}
}

View File

@ -219,6 +219,16 @@ function reduceApp (state, action) {
warning: null, warning: null,
}) })
case actions.SHOW_SEND_TOKEN_PAGE:
return extend(appState, {
currentView: {
name: 'sendToken',
context: appState.currentView.context,
},
transForward: true,
warning: null,
})
case actions.SHOW_NEW_KEYCHAIN: case actions.SHOW_NEW_KEYCHAIN:
return extend(appState, { return extend(appState, {
currentView: { currentView: {