diff options
Diffstat (limited to 'ui/app')
-rw-r--r-- | ui/app/account-detail.js | 100 | ||||
-rw-r--r-- | ui/app/accounts.js | 45 | ||||
-rw-r--r-- | ui/app/app.js | 37 | ||||
-rw-r--r-- | ui/app/components/account-panel.js | 2 | ||||
-rw-r--r-- | ui/app/components/identicon.js | 55 | ||||
-rw-r--r-- | ui/app/components/panel.js | 13 | ||||
-rw-r--r-- | ui/app/css/fonts.css | 46 | ||||
-rw-r--r-- | ui/app/css/index.css | 47 | ||||
-rw-r--r-- | ui/app/css/lib.css | 31 | ||||
-rw-r--r-- | ui/app/css/transitions.css | 48 |
10 files changed, 308 insertions, 116 deletions
diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js index 2775e24fb..a71e85da8 100644 --- a/ui/app/account-detail.js +++ b/ui/app/account-detail.js @@ -5,9 +5,12 @@ const h = require('react-hyperscript') const connect = require('react-redux').connect const copyToClipboard = require('copy-to-clipboard') const actions = require('./actions') +const addressSummary = require('./util').addressSummary +const formatBalance = require('./util').formatBalance const ReactCSSTransitionGroup = require('react-addons-css-transition-group') const AccountPanel = require('./components/account-panel') +const Identicon = require('./components/identicon') const transactionList = require('./components/transaction-list') const ExportAccountView = require('./components/account-export') @@ -41,49 +44,80 @@ AccountDetailScreen.prototype.render = function() { h('.account-detail-section.flex-column.flex-grow', { style: { - width: '330px', + width: 330, + 'margin-top': 28, }, }, [ - // subtitle and nav - h('.section-title.flex-row.flex-center', [ - h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { + h('.flex-row.flex-space-between', [ + + // invisible placeholder for later + h('i.fa.fa-users.fa-lg.color-orange', { + style: { + visibility: 'hidden', + }, + }), + + // large identicon + h('.identicon-wrapper.flex-column.flex-center.select-none', [ + h(Identicon, { + diameter: 62, + address: account.address + }), + ]), + + // small accounts nav + h('i.fa.fa-users.fa-lg.cursor-pointer.color-orange', { onClick: this.navigateToAccounts.bind(this), }), - h('h2.page-subtitle', 'Account Detail'), + ]), - // account summary, with embedded action buttons - h(AccountPanel, { - showFullAddress: true, - identity: identity, - account: account, - key: 'accountPanel' - }), + h('h2.font-medium.color-forest.flex-center', { + style: { + 'padding-top': 8, + 'margin-bottom': 32, + }, + }, identity && identity.name), - h('div', { + h('.flex-row.flex-space-between', { style: { - display: 'flex', - } + 'margin-bottom': 16, + }, }, [ - h('button', { - onClick: () => { - copyToClipboard(identity.address) + h('div', { + style: { + 'line-height': 16, }, - }, 'COPY ADDR'), + }, addressSummary(account.address)), - h('button', { - onClick: () => { - this.props.dispatch(actions.showSendPage()) + h('i.fa.fa-download.fa-md.cursor-pointer.color-orange', { + onClick: () => this.requestAccountExport(account.address), + }), + + h('i.fa.fa-qrcode.fa-md.cursor-disabled.color-orange', { + onClick: () => console.warn('QRCode not implented...'), + }), + + h('i.fa.fa-clipboard.fa-md.cursor-pointer.color-orange', { + onClick: () => copyToClipboard(account.address), + }), + + ]), + + h('.flex-row.flex-space-between', [ + + h('div', { + style: { + 'line-height': 50, }, - }, 'SEND'), + }, formatBalance(account.balance)), h('button', { - onClick: () => { - this.requestAccountExport(identity.address) - }, - }, 'EXPORT'), + onClick: () => this.props.dispatch(actions.showSendPage()), + }, 'SEND ETH'), + ]), h(ReactCSSTransitionGroup, { @@ -93,12 +127,7 @@ AccountDetailScreen.prototype.render = function() { }, [ this.subview(), ]), - // transaction table - /* - h('section.flex-column', [ - h('span', 'your transaction history will go here.'), - ]), - */ + ]) ) } @@ -127,8 +156,13 @@ AccountDetailScreen.prototype.transactionList = function() { var transactions = state.transactions return transactionList(transactions + // only transactions that have a hash + .filter(tx => tx.hash) + // only transactions that are from the current address .filter(tx => tx.txParams.from === state.address) + // only transactions that are on the current network .filter(tx => tx.txParams.metamaskNetworkId === state.networkVersion) + // sort by recency .sort((a, b) => b.time - a.time), state.networkVersion) } diff --git a/ui/app/accounts.js b/ui/app/accounts.js index 16f37dc67..18ba1e67d 100644 --- a/ui/app/accounts.js +++ b/ui/app/accounts.js @@ -3,9 +3,12 @@ const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect const extend = require('xtend') +const Identicon = require('./components/identicon') const actions = require('./actions') const AccountPanel = require('./components/account-panel') const valuesFor = require('./util').valuesFor +const addressSummary = require('./util').addressSummary +const formatBalance = require('./util').formatBalance module.exports = connect(mapStateToProps)(AccountsScreen) @@ -40,24 +43,14 @@ AccountsScreen.prototype.render = function() { // subtitle and nav h('.section-title.flex-column.flex-center', [ - h('h2.page-subtitle', 'Accounts'), + h('h2.page-subtitle', 'Select Account'), ]), - // current domain - /* AUDIT - * Temporarily removed - * since accounts are currently injected - * regardless of the current domain. - */ - h('.current-domain-panel.flex-center.font-small', [ - h('span', 'Selected address is visible to all sites you visit.'), - // h('span', state.currentDomain), - ]), + h('hr.horizontal-line'), // identity selection h('section.identity-section.flex-column', { style: { - maxHeight: '290px', overflowY: 'auto', overflowX: 'hidden', } @@ -94,7 +87,33 @@ AccountsScreen.prototype.render = function() { isSelected: false, isFauceting: isFauceting, }) - return h(AccountPanel, componentState) + + return ( + h('.accounts-list-option.flex-row.flex-space-between.cursor-pointer', { + style: { + flex: '1 0 auto', + background: isSelected ? 'white' : 'none', + }, + onClick: (event) => actions.onShowDetail(identity.address, event), + }, [ + + h('.identicon-wrapper.flex-column.flex-center.select-none', [ + h(Identicon, { + address: identity.address + }), + ]), + + // account address, balance + h('.identity-data.flex-column.flex-justify-center.flex-grow.select-none', [ + + h('span', identity.name), + h('span.font-small', addressSummary(identity.address)), + h('span.font-small', formatBalance(account.balance)), + + ]), + + ]) + ) } } diff --git a/ui/app/app.js b/ui/app/app.js index a4ce40881..388a067f0 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -73,9 +73,18 @@ App.prototype.render = function() { h(LoadingIndicator), // top row - h('.app-header.flex-column.flex-center', { + h('.app-header.flex-row.flex-space-between', { + style: { + alignItems: 'center', + } }, [ + h('img', { + height: 24, + width: 24, + src: '/images/icon-128.png', + }), h('h1', 'MetaMask'), + h('i.fa.fa-bars'), ]), // panel content @@ -115,19 +124,19 @@ App.prototype.render = function() { }, }), - // toggle - onOffToggle({ - toggleMetamaskActive: this.toggleMetamaskActive.bind(this), - isUnlocked: state.isUnlocked, - }), - - // help - h('i.fa.fa-question.fa-lg.cursor-pointer', { - style: { - opacity: state.isUnlocked ? '1.0' : '0.0', - }, - onClick() { state.dispatch(actions.showInfoPage()) } - }), + // // toggle + // onOffToggle({ + // toggleMetamaskActive: this.toggleMetamaskActive.bind(this), + // isUnlocked: state.isUnlocked, + // }), + + // // help + // h('i.fa.fa-question.fa-lg.cursor-pointer', { + // style: { + // opacity: state.isUnlocked ? '1.0' : '0.0', + // }, + // onClick() { state.dispatch(actions.showInfoPage()) } + // }), ]), ]) ) diff --git a/ui/app/components/account-panel.js b/ui/app/components/account-panel.js index c1450b516..6bae095d1 100644 --- a/ui/app/components/account-panel.js +++ b/ui/app/components/account-panel.js @@ -4,7 +4,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const addressSummary = require('../util').addressSummary const formatBalance = require('../util').formatBalance -const Identicon = require('identicon.js') +const Identicon = require('./identicon') const Panel = require('./panel') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js new file mode 100644 index 000000000..ef625cc62 --- /dev/null +++ b/ui/app/components/identicon.js @@ -0,0 +1,55 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const jazzicon = require('jazzicon') +const findDOMNode = require('react-dom').findDOMNode + +module.exports = IdenticonComponent + +inherits(IdenticonComponent, Component) +function IdenticonComponent() { + Component.call(this) + + this.defaultDiameter = 46 +} + +IdenticonComponent.prototype.render = function() { + var state = this.props + var diameter = state.diameter || this.defaultDiameter + return ( + h('div', { + key: 'identicon-' + this.props.address, + style: { + display: 'inline-block', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }) + ) +} + +IdenticonComponent.prototype.componentDidMount = function(){ + var state = this.props + var address = state.address + + if (!address) return + var numericRepresentation = jsNumberForAddress(address) + + var container = findDOMNode(this) + // jazzicon with hack to fix inline svg error + var diameter = state.diameter || this.defaultDiameter + var identicon = jazzicon(diameter, numericRepresentation) + var identiconSrc = identicon.innerHTML + var dataUri = 'data:image/svg+xml;charset=utf-8,'+encodeURIComponent(identiconSrc) + var img = document.createElement('img') + img.src = dataUri + container.appendChild(img) +} + +function jsNumberForAddress(address) { + var addr = address.slice(2, 10) + var seed = parseInt(addr, 16) + return seed +} diff --git a/ui/app/components/panel.js b/ui/app/components/panel.js index 25e6b7f0f..2f5a3715d 100644 --- a/ui/app/components/panel.js +++ b/ui/app/components/panel.js @@ -2,7 +2,7 @@ const inherits = require('util').inherits const ethUtil = require('ethereumjs-util') const Component = require('react').Component const h = require('react-hyperscript') -const Identicon = require('identicon.js') +const Identicon = require('./identicon') module.exports = Panel @@ -19,9 +19,6 @@ Panel.prototype.render = function() { var account = state.account || {} var isFauceting = state.isFauceting - var identicon = new Identicon(state.identiconKey, 46).toString() - var identiconSrc = `data:image/png;base64,${identicon}` - return ( h('.identity-panel.flex-row.flex-space-between', { style: { @@ -32,12 +29,8 @@ Panel.prototype.render = function() { // account identicon h('.identicon-wrapper.flex-column.select-none', [ - h('img.identicon', { - src: identiconSrc, - style: { - border: 'none', - borderRadius: '20px', - } + h(Identicon, { + address: state.identiconKey, }), h('span.font-small', state.identiconLabel), ]), diff --git a/ui/app/css/fonts.css b/ui/app/css/fonts.css index dd1a755fb..b528cb9ab 100644 --- a/ui/app/css/fonts.css +++ b/ui/app/css/fonts.css @@ -1,2 +1,46 @@ @import url(https://fonts.googleapis.com/css?family=Roboto:300,500); -@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css);
\ No newline at end of file +@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css); + +@font-face { + font-family: 'Transat Standard'; + src: url('/fonts/Transat Standard/transat_standard-webfont.eot'); + src: url('/fonts/Transat Standard/transat_standard-webfont.eot?#iefix') format('embedded-opentype'), + url('/fonts/Transat Standard/transat_standard-webfont.woff') format('woff'), + url('/fonts/Transat Standard/transat_standard-webfont.ttf') format('truetype'), + url('/fonts/Transat Standard/transat_standard-webfont.svg#ywftsvg') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Transat Black'; + src: url('/fonts/Transat Black/transat_black-webfont.eot'); + src: url('/fonts/Transat Black/transat_black-webfont.eot?#iefix') format('embedded-opentype'), + url('/fonts/Transat Black/transat_black-webfont.woff') format('woff'), + url('/fonts/Transat Black/transat_black-webfont.ttf') format('truetype'), + url('/fonts/Transat Black/transat_black-webfont.svg#ywftsvg') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Transat Medium'; + src: url('/fonts/Transat Medium/transat_medium-webfont.eot'); + src: url('/fonts/Transat Medium/transat_medium-webfont.eot?#iefix') format('embedded-opentype'), + url('/fonts/Transat Medium/transat_medium-webfont.woff') format('woff'), + url('/fonts/Transat Medium/transat_medium-webfont.ttf') format('truetype'), + url('/fonts/Transat Medium/transat_medium-webfont.svg#ywftsvg') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Transat Light'; + src: url('/fonts/Transat Light/transat_light-webfont.eot'); + src: url('/fonts/Transat Light/transat_light-webfont.eot?#iefix') format('embedded-opentype'), + url('/fonts/Transat Light/transat_light-webfont.woff') format('woff'), + url('/fonts/Transat Light/transat_light-webfont.ttf') format('truetype'), + url('/fonts/Transat Light/transat_light-webfont.svg#ywftsvg') format('svg'); + font-weight: normal; + font-style: normal; +} diff --git a/ui/app/css/index.css b/ui/app/css/index.css index 4871a650f..9dbfb6518 100644 --- a/ui/app/css/index.css +++ b/ui/app/css/index.css @@ -14,8 +14,7 @@ application specific styles } html, body { - /*font-family: 'Open Sans', Arial, sans-serif;*/ - font-family: 'Roboto', 'Noto', sans-serif; + font-family: 'Transat Standard', Arial; color: #4D4D4D; font-weight: 300; line-height: 1.4em; @@ -29,18 +28,18 @@ html, body { } button { + font-family: 'Transat Black'; outline: none; cursor: pointer; margin: 10px; - padding: 6px; + padding: 8px 12px; border: none; - border-radius: 3px; background: #F7861C; - font-weight: 500; color: white; transform-origin: center center; transition: transform 50ms ease-in; } + button:hover { transform: scale(1.1); } @@ -98,23 +97,25 @@ button.btn-thin { } .app-header { - padding-top: 20px; + padding: 6px 8px; } .app-header h1 { - font-size: 2em; - font-weight: 300; - height: 42px; + font-family: 'Transat Medium'; + text-transform: uppercase; + color: #AEAEAE; } h2.page-subtitle { + font-family: 'Transat Light'; + text-transform: uppercase; + color: #AEAEAE; font-size: 1em; - font-weight: 500; - height: 24px; - color: #F3C83E; + margin: 12px; } .app-primary { + background: #F7F7F7; } .app-footer { @@ -238,11 +239,24 @@ app sections /* accounts */ .accounts-section { - margin: 0 20px; + margin: 0 0px; +} + +.accounts-section .horizontal-line { + margin: 0px 18px; } -.current-domain-panel { - border: 1px solid #B7B7B7; +.accounts-list-option { + height: 120px; +} + +.accounts-list-option:hover { + background: pink; + transform: scale(1.1); +} + +.accounts-list-option .identicon-wrapper { + width: 100px; } .unconftx-link { @@ -289,8 +303,7 @@ app sections /* accounts screen */ .identity-section { - border: 2px solid #4D4D4D; - margin: 0; + } .identity-section .identity-panel { diff --git a/ui/app/css/lib.css b/ui/app/css/lib.css index b6b26402b..14ef272ad 100644 --- a/ui/app/css/lib.css +++ b/ui/app/css/lib.css @@ -1,3 +1,13 @@ +/* color */ + +.color-orange { + color: #F7861C; +} + +.color-forest { + color: #08525D; +} + /* lib */ .full-width { @@ -47,6 +57,10 @@ flex: none; } +.flex-basis-auto { + flex-basis: auto; +} + .flex-grow { flex: 1 1 auto; } @@ -105,6 +119,10 @@ transform: scale(0.95); } +.cursor-disabled { + cursor: not-allowed; +} + .margin-bottom-sml { margin-bottom: 20px; } @@ -125,6 +143,10 @@ font-size: 12px; } +.font-medium { + font-size: 1.2em; +} + /* Send Screen */ .send-screen { margin: 0 20px; @@ -141,3 +163,12 @@ .send-screen section input { width: 100%; } + +hr.horizontal-line { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; + margin: 1em 0; + padding: 0; +}
\ No newline at end of file diff --git a/ui/app/css/transitions.css b/ui/app/css/transitions.css index e2225a98d..393a944f9 100644 --- a/ui/app/css/transitions.css +++ b/ui/app/css/transitions.css @@ -1,48 +1,42 @@ -/* initial positions */ -.app-primary.from-right .main-enter { - transform: translateX(400px); +/* universal */ +.app-primary .main-enter { position: absolute; width: 100%; - transition: transform 300ms ease-in-out; -} -.app-primary.from-left .main-enter { - transform: translateX(-400px); - position: absolute; - width: 100%; - transition: transform 300ms ease-in-out; } /* center position */ -.app-primary .main-enter.main-enter-active, -.app-primary .main-leave { - transform: translateX(0px); - position: absolute; - width: 100%; - transition: transform 300ms ease-in-out; +.app-primary.from-right .main-enter-active, +.app-primary.from-left .main-enter-active { overflow-x: hidden; + transform: translateX(0px); + transition: transform 300ms ease-in; } -/* final positions */ +/* exited positions */ .app-primary.from-left .main-leave-active { - transform: translateX(400px); - position: absolute; - width: 100%; - transition: transform 300ms ease-in-out; + transform: translateX(360px); + transition: transform 300ms ease-in; } .app-primary.from-right .main-leave-active { - transform: translateX(-400px); - position: absolute; - width: 100%; - transition: transform 300ms ease-in-out; + transform: translateX(-360px); + transition: transform 300ms ease-in; } /* loader transitions */ .loader-enter, .loader-leave-active { opacity: 0.0; - transition: opacity 150 ease-in-out; + transition: opacity 150 ease-in; } .loader-enter-active, .loader-leave { opacity: 1.0; - transition: opacity 150 ease-in-out; + transition: opacity 150 ease-in; +} + +/* entering positions */ +.app-primary.from-right .main-enter:not(.main-enter-active) { + transform: translateX(360px); +} +.app-primary.from-left .main-enter:not(.main-enter-active) { + transform: translateX(-360px); } |