diff options
author | Chi Kei Chan <chikeichan@gmail.com> | 2017-09-20 12:18:36 +0800 |
---|---|---|
committer | Chi Kei Chan <chikeichan@gmail.com> | 2017-09-20 12:18:36 +0800 |
commit | 0204aa2001af25da01ba61aed32f36eac47079a1 (patch) | |
tree | 617053e69807f42bda05156855fca7e7236b7dc9 /ui/app | |
parent | e7f1fc44361829f05a713218f8b1837a8574c2f2 (diff) | |
download | tangerine-wallet-browser-0204aa2001af25da01ba61aed32f36eac47079a1.tar tangerine-wallet-browser-0204aa2001af25da01ba61aed32f36eac47079a1.tar.gz tangerine-wallet-browser-0204aa2001af25da01ba61aed32f36eac47079a1.tar.bz2 tangerine-wallet-browser-0204aa2001af25da01ba61aed32f36eac47079a1.tar.lz tangerine-wallet-browser-0204aa2001af25da01ba61aed32f36eac47079a1.tar.xz tangerine-wallet-browser-0204aa2001af25da01ba61aed32f36eac47079a1.tar.zst tangerine-wallet-browser-0204aa2001af25da01ba61aed32f36eac47079a1.zip |
Add Add Token UI; Add Fuzzy search for tokens
Diffstat (limited to 'ui/app')
-rw-r--r-- | ui/app/add-token.js | 348 | ||||
-rw-r--r-- | ui/app/css/itcss/components/add-token.scss | 173 | ||||
-rw-r--r-- | ui/app/css/itcss/components/index.scss | 2 |
3 files changed, 398 insertions, 125 deletions
diff --git a/ui/app/add-token.js b/ui/app/add-token.js index 4374ee586..dbba8e4f1 100644 --- a/ui/app/add-token.js +++ b/ui/app/add-token.js @@ -2,8 +2,20 @@ const inherits = require('util').inherits const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect -const actions = require('./actions') -const Tooltip = require('./components/tooltip.js') +const Fuse = require('fuse.js') +const contractMap = require('eth-contract-metadata') +const contractList = Object.entries(contractMap).map(([ _, tokenData]) => tokenData) +const fuse = new Fuse(contractList, { + shouldSort: true, + threshold: 0.3, + location: 0, + distance: 100, + maxPatternLength: 32, + minMatchCharLength: 1, + keys: ['address', 'name', 'symbol'], +}) +// const actions = require('./actions') +// const Tooltip = require('./components/tooltip.js') const ethUtil = require('ethereumjs-util') @@ -24,146 +36,232 @@ function mapStateToProps (state) { inherits(AddTokenScreen, Component) function AddTokenScreen () { this.state = { - warning: null, - address: null, - symbol: 'TOKEN', - decimals: 18, + // warning: null, + // address: null, + // symbol: 'TOKEN', + // decimals: 18, + searchQuery: '', + isCollapsed: true, } Component.call(this) } -AddTokenScreen.prototype.render = function () { - const state = this.state - const props = this.props - const { warning, symbol, decimals } = state - - return ( - h('.flex-column.flex-grow', [ - - // subtitle and nav - h('.section-title.flex-row.flex-center', [ - h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { - onClick: (event) => { - props.dispatch(actions.goHome()) - }, - }), - h('h2.page-subtitle', 'Add Token'), +AddTokenScreen.prototype.renderCustomForm = function () { + return !this.state.isCollapsed && ( + h('div.add-token__add-custom-form', [ + h('div.add-token__add-custom-field', [ + h('div.add-token__add-custom-label', 'Token Address'), + h('input.add-token__add-custom-input', { type: 'text' }), ]), + h('div.add-token__add-custom-field', [ + h('div.add-token__add-custom-label', 'Token Symbol'), + h('input.add-token__add-custom-input', { type: 'text', disabled: true }), + ]), + h('div.add-token__add-custom-field', [ + h('div.add-token__add-custom-label', 'Decimals of Precision'), + h('input.add-token__add-custom-input', { type: 'text', disabled: true }), + ]), + ]) + ) +} - h('.error', { - style: { - display: warning ? 'block' : 'none', - padding: '0 20px', - textAlign: 'center', - }, - }, warning), - - // conf view - h('.flex-column.flex-justify-center.flex-grow.select-none', [ - h('.flex-space-around', { - style: { - padding: '20px', - }, - }, [ - - h('div', [ - h(Tooltip, { - position: 'top', - title: 'The contract of the actual token contract. Click for more info.', - }, [ - h('a', { - style: { fontWeight: 'bold', paddingRight: '10px'}, - href: 'https://consensyssupport.happyfox.com/staff/kb/article/24-what-is-a-token-contract-address', - target: '_blank', - }, [ - h('span', 'Token Contract Address '), - h('i.fa.fa-question-circle'), - ]), - ]), - ]), - - h('section.flex-row.flex-center', [ - h('input#token-address', { - name: 'address', - placeholder: 'Token Contract Address', - onChange: this.tokenAddressDidChange.bind(this), - style: { - width: 'inherit', - flex: '1 0 auto', - height: '30px', - margin: '8px', - }, - }), - ]), - - h('div', [ - h('span', { - style: { fontWeight: 'bold', paddingRight: '10px'}, - }, 'Token Symbol'), - ]), - - h('div', { style: {display: 'flex'} }, [ - h('input#token_symbol', { - placeholder: `Like "ETH"`, - value: symbol, - style: { - width: 'inherit', - flex: '1 0 auto', - height: '30px', - margin: '8px', - }, - onChange: (event) => { - var element = event.target - var symbol = element.value - this.setState({ symbol }) - }, - }), +AddTokenScreen.prototype.renderTokenList = function () { + const { searchQuery = '' } = this.state + const results = searchQuery + ? fuse.search(searchQuery) || [] + : contractList + + return Array(6).fill(undefined) + .map((_, i) => { + const { logo, symbol, name } = results[i] || {} + console.log({ i, logo, symbol, name }) + return Boolean(logo || symbol || name) && ( + h('div.add-token__token-wrapper', [ + h('div.add-token__token-icon', { + style: { + backgroundImage: `url(images/contract/${logo})`, + }, + }), + h('div.add-token__token-data', [ + h('div.add-token__token-symbol', symbol), + h('div.add-token__token-name', name), ]), + ]) + ) + }) +} - h('div', [ - h('span', { - style: { fontWeight: 'bold', paddingRight: '10px'}, - }, 'Decimals of Precision'), - ]), +AddTokenScreen.prototype.render = function () { + const { isCollapsed } = this.state - h('div', { style: {display: 'flex'} }, [ - h('input#token_decimals', { - value: decimals, - type: 'number', - min: 0, - max: 36, - style: { - width: 'inherit', - flex: '1 0 auto', - height: '30px', - margin: '8px', - }, - onChange: (event) => { - var element = event.target - var decimals = element.value.trim() - this.setState({ decimals }) - }, + return ( + h('div.add-token', [ + h('div.add-token__wrapper', [ + h('div.add-token__title-container', [ + h('div.add-token__title', 'Add Token'), + h('div.add-token__description', 'Keep track of the tokens you’ve bought with your MetaMask account. If you bought tokens using a different account, those tokens will not appear here.'), + h('div.add-token__description', 'Search for tokens or select from our list of popular tokens.'), + ]), + h('div.add-token__content-container', [ + h('div.add-token__input-container', [ + h('input.add-token__input', { + type: 'text', + placeholder: 'Search', + onChange: e => this.setState({ searchQuery: e.target.value }), }), ]), - - h('button', { - style: { - alignSelf: 'center', - }, - onClick: (event) => { - const valid = this.validateInputs() - if (!valid) return - - const { address, symbol, decimals } = this.state - this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals)) - }, - }, 'Add'), + h( + 'div.add-token__token-icons-container', + this.renderTokenList(), + ), + ]), + h('div.add-token__footers', [ + h('div.add-token__add-custom', { + onClick: () => this.setState({ isCollapsed: !isCollapsed }), + }, 'Add custom token'), + this.renderCustomForm(), ]), ]), + h('div.add-token__buttons', [ + h('button.btn-secondary', 'Next'), + h('button.btn-tertiary', 'Cancel'), + ]), ]) ) } +// AddTokenScreen.prototype.render = function () { +// const state = this.state +// const props = this.props +// const { warning, symbol, decimals } = state + +// return ( +// h('.flex-column.flex-grow', [ + +// // subtitle and nav +// h('.section-title.flex-row.flex-center', [ +// h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { +// onClick: (event) => { +// props.dispatch(actions.goHome()) +// }, +// }), +// h('h2.page-subtitle', 'Add Token'), +// ]), + +// h('.error', { +// style: { +// display: warning ? 'block' : 'none', +// padding: '0 20px', +// textAlign: 'center', +// }, +// }, warning), + +// // conf view +// h('.flex-column.flex-justify-center.flex-grow.select-none', [ +// h('.flex-space-around', { +// style: { +// padding: '20px', +// }, +// }, [ + +// h('div', [ +// h(Tooltip, { +// position: 'top', +// title: 'The contract of the actual token contract. Click for more info.', +// }, [ +// h('a', { +// style: { fontWeight: 'bold', paddingRight: '10px'}, +// href: 'https://consensyssupport.happyfox.com/staff/kb/article/24-what-is-a-token-contract-address', +// target: '_blank', +// }, [ +// h('span', 'Token Contract Address '), +// h('i.fa.fa-question-circle'), +// ]), +// ]), +// ]), + +// h('section.flex-row.flex-center', [ +// h('input#token-address', { +// name: 'address', +// placeholder: 'Token Contract Address', +// onChange: this.tokenAddressDidChange.bind(this), +// style: { +// width: 'inherit', +// flex: '1 0 auto', +// height: '30px', +// margin: '8px', +// }, +// }), +// ]), + +// h('div', [ +// h('span', { +// style: { fontWeight: 'bold', paddingRight: '10px'}, +// }, 'Token Symbol'), +// ]), + +// h('div', { style: {display: 'flex'} }, [ +// h('input#token_symbol', { +// placeholder: `Like "ETH"`, +// value: symbol, +// style: { +// width: 'inherit', +// flex: '1 0 auto', +// height: '30px', +// margin: '8px', +// }, +// onChange: (event) => { +// var element = event.target +// var symbol = element.value +// this.setState({ symbol }) +// }, +// }), +// ]), + +// h('div', [ +// h('span', { +// style: { fontWeight: 'bold', paddingRight: '10px'}, +// }, 'Decimals of Precision'), +// ]), + +// h('div', { style: {display: 'flex'} }, [ +// h('input#token_decimals', { +// value: decimals, +// type: 'number', +// min: 0, +// max: 36, +// style: { +// width: 'inherit', +// flex: '1 0 auto', +// height: '30px', +// margin: '8px', +// }, +// onChange: (event) => { +// var element = event.target +// var decimals = element.value.trim() +// this.setState({ decimals }) +// }, +// }), +// ]), + +// h('button', { +// style: { +// alignSelf: 'center', +// }, +// onClick: (event) => { +// const valid = this.validateInputs() +// if (!valid) return + +// const { address, symbol, decimals } = this.state +// this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals)) +// }, +// }, 'Add'), +// ]), +// ]), +// ]) +// ) +// } + AddTokenScreen.prototype.componentWillMount = function () { if (typeof global.ethereumProvider === 'undefined') return diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss new file mode 100644 index 000000000..db1d0dc18 --- /dev/null +++ b/ui/app/css/itcss/components/add-token.scss @@ -0,0 +1,173 @@ +.add-token { + width: 498px; + display: flex; + flex-flow: column nowrap; + align-items: center; + position: relative; + top: -36px; + z-index: 12; + font-family: 'DIN Next Light'; + + @media screen and (max-width: $break-small) { + top: 0; + width: 100%; + + &__wrapper { + box-shadow: none !important; + } + + &__footers { + border-bottom: 1px solid $gallery; + } + } + + &__wrapper { + background-color: $white; + box-shadow: 0 2px 4px 0 rgba($black, .08); + display: flex; + flex-flow: column nowrap; + align-items: center; + flex: 0 0 auto; + } + + &__title-container { + display: flex; + flex-flow: column nowrap; + align-items: center; + padding: 30px 60px 12px; + border-bottom: 1px solid $gallery; + flex: 0 0 auto; + } + + &__title { + color: $scorpion; + font-size: 20px; + line-height: 26px; + text-align: center; + font-weight: 600; + margin-bottom: 12px; + } + + &__description { + text-align: center; + } + + &__description + &__description { + margin-top: 24px; + } + + &__content-container { + width: 100%; + border-bottom: 1px solid $gallery; + } + + &__input-container { + padding: 11px 0; + width: 263px; + margin: 0 auto; + } + + &__input { + width: 100%; + border: 2px solid $gallery; + border-radius: 4px; + padding: 5px 15px; + font-size: 14px; + line-height: 19px; + + &::placeholder { + color: $silver; + } + } + + &__footers { + width: 100%; + } + + &__add-custom { + color: $scorpion; + font-size: 18px; + line-height: 24px; + text-align: center; + padding: 11px 0 19px; + font-weight: 600; + cursor: pointer; + } + + &__add-custom-form { + display: flex; + flex-flow: column nowrap; + margin: 8px 0 51px; + } + + &__add-custom-field { + width: 290px; + margin: 0 auto; + } + + &__add-custom-label { + font-size: 16px; + line-height: 21px; + margin-bottom: 8px; + } + + &__add-custom-input { + width: 100%; + border: 1px solid $silver; + padding: 5px 15px; + font-size: 14px; + line-height: 19px; + + &::placeholder { + color: $silver; + } + } + + &__add-custom-field + &__add-custom-field { + margin-top: 21px; + } + + &__buttons { + display: flex; + flex-flow: column nowrap; + margin: 30px 0 51px; + flex: 0 0 auto; + } + + &__token-icons-container { + display: flex; + flex-flow: row wrap; + } + + &__token-wrapper { + display: flex; + flex-flow: row nowrap; + flex: 0 0 50%; + align-items: center; + padding: 24px 0 24px 24px; + } + + &__token-name { + font-size: 14px; + line-height: 19px; + } + + &__token-symbol { + font-size: 22px; + line-height: 29px; + font-weight: 600; + } + + &__token-icon { + width: 60px; + height: 60px; + background-repeat: no-repeat; + background-size: contain; + background-position: center; + border-radius: 50%; + background-color: $white; + box-shadow: 0 2px 4px 0 rgba($black, .24); + margin-right: 12px; + flex: 0 0 auto; + } +} diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 63ac8bd47..9b3690099 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -27,3 +27,5 @@ @import './sections.scss'; @import './token-list.scss'; + +@import './add-token.scss'; |