aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app
diff options
context:
space:
mode:
authorAlexander Tseung <alextsg@gmail.com>2018-05-11 07:51:26 +0800
committerAlexander Tseung <alextsg@gmail.com>2018-05-12 03:49:17 +0800
commit2381c0e0f461304265279155176fa655e2eb97b4 (patch)
treec0053ef5a62ee246bf02bc2cf7cfe6dae50ed3c9 /ui/app
parent76ab5c04fae20dc0fd2798ad8a336a0364032aff (diff)
downloadtangerine-wallet-browser-2381c0e0f461304265279155176fa655e2eb97b4.tar
tangerine-wallet-browser-2381c0e0f461304265279155176fa655e2eb97b4.tar.gz
tangerine-wallet-browser-2381c0e0f461304265279155176fa655e2eb97b4.tar.bz2
tangerine-wallet-browser-2381c0e0f461304265279155176fa655e2eb97b4.tar.lz
tangerine-wallet-browser-2381c0e0f461304265279155176fa655e2eb97b4.tar.xz
tangerine-wallet-browser-2381c0e0f461304265279155176fa655e2eb97b4.tar.zst
tangerine-wallet-browser-2381c0e0f461304265279155176fa655e2eb97b4.zip
Add new unlock screen design
Diffstat (limited to 'ui/app')
-rw-r--r--ui/app/actions.js2
-rw-r--r--ui/app/app.js130
-rw-r--r--ui/app/components/app-header/app-header.component.js106
-rw-r--r--ui/app/components/app-header/app-header.container.js38
-rw-r--r--ui/app/components/app-header/index.js2
-rw-r--r--ui/app/components/export-text-container/export-text-container.scss2
-rw-r--r--ui/app/components/pages/unlock-page/index.js2
-rw-r--r--ui/app/components/pages/unlock-page/unlock-page.component.js182
-rw-r--r--ui/app/components/pages/unlock-page/unlock-page.container.js33
-rw-r--r--ui/app/components/pages/unlock-page/unlock-page.scss51
-rw-r--r--ui/app/components/pages/unlock.js194
-rw-r--r--ui/app/components/text-field/index.js2
-rw-r--r--ui/app/components/text-field/text-field.component.js54
-rw-r--r--ui/app/components/wallet-view.js6
-rw-r--r--ui/app/css/itcss/components/header.scss118
-rw-r--r--ui/app/css/itcss/components/pages/index.scss4
-rw-r--r--ui/app/css/itcss/components/pages/unlock.scss9
-rw-r--r--ui/app/css/itcss/components/sections.scss41
-rw-r--r--ui/app/css/itcss/components/settings.scss4
-rw-r--r--ui/app/css/itcss/generic/index.scss5
-rw-r--r--ui/app/main-container.js2
-rw-r--r--ui/app/unlock.js141
22 files changed, 559 insertions, 569 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js
index f060e40bd..9c4de9551 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -317,6 +317,7 @@ function tryUnlockMetamask (password) {
background.verifySeedPhrase(err => {
if (err) {
dispatch(actions.displayWarning(err.message))
+ return reject(err)
}
resolve()
@@ -330,6 +331,7 @@ function tryUnlockMetamask (password) {
.catch(err => {
dispatch(actions.unlockFailed(err.message))
dispatch(actions.hideLoadingIndication())
+ return Promise.reject(err)
})
}
}
diff --git a/ui/app/app.js b/ui/app/app.js
index c93a6314c..5bc571c64 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -1,7 +1,7 @@
const { Component } = require('react')
const PropTypes = require('prop-types')
const connect = require('react-redux').connect
-const { Route, Switch, withRouter } = require('react-router-dom')
+const { Route, Switch, withRouter, matchPath } = require('react-router-dom')
const { compose } = require('recompose')
const h = require('react-hyperscript')
const actions = require('./actions')
@@ -22,7 +22,7 @@ const Home = require('./components/pages/home')
const Authenticated = require('./components/pages/authenticated')
const Initialized = require('./components/pages/initialized')
const Settings = require('./components/pages/settings')
-const UnlockPage = require('./components/pages/unlock')
+const UnlockPage = require('./components/pages/unlock-page')
const RestoreVaultPage = require('./components/pages/keychains/restore-vault')
const RevealSeedConfirmation = require('./components/pages/keychains/reveal-seed')
const AddTokenPage = require('./components/pages/add-token')
@@ -30,8 +30,6 @@ const CreateAccountPage = require('./components/pages/create-account')
const NoticeScreen = require('./components/pages/notice')
const Loading = require('./components/loading-screen')
-const NetworkIndicator = require('./components/network')
-const Identicon = require('./components/identicon')
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
const AccountMenu = require('./components/account-menu')
@@ -39,6 +37,8 @@ const AccountMenu = require('./components/account-menu')
// Global Modals
const Modal = require('./components/modals/index').Modal
+const AppHeader = require('./components/app-header')
+
// Routes
const {
DEFAULT_ROUTE,
@@ -69,11 +69,11 @@ class App extends Component {
return (
h(Switch, [
h(Route, { path: INITIALIZE_ROUTE, component: InitializeScreen }),
- h(Initialized, { path: REVEAL_SEED_ROUTE, exact, component: RevealSeedConfirmation }),
h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }),
- h(Initialized, { path: SETTINGS_ROUTE, component: Settings }),
h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }),
- h(Initialized, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
+ h(Authenticated, { path: REVEAL_SEED_ROUTE, exact, component: RevealSeedConfirmation }),
+ h(Authenticated, { path: SETTINGS_ROUTE, component: Settings }),
+ h(Authenticated, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
h(Authenticated, { path: CONFIRM_TRANSACTION_ROUTE, component: ConfirmTxScreen }),
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }),
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
@@ -83,6 +83,15 @@ class App extends Component {
)
}
+ renderAppHeader () {
+ const { location } = this.props
+ const isInitializing = matchPath(location.pathname, {
+ path: INITIALIZE_ROUTE, exact: false,
+ })
+
+ return isInitializing ? null : h(AppHeader)
+ }
+
render () {
const {
isLoading,
@@ -119,8 +128,7 @@ class App extends Component {
// global modal
h(Modal, {}, []),
- // app bar
- this.renderAppBar(),
+ this.renderAppHeader(),
// sidebar
this.renderSidebar(),
@@ -197,110 +205,6 @@ class App extends Component {
])
}
- renderAppBar () {
- const {
- isUnlocked,
- network,
- provider,
- networkDropdownOpen,
- showNetworkDropdown,
- hideNetworkDropdown,
- isInitialized,
- welcomeScreenSeen,
- isPopup,
- betaUI,
- } = this.props
-
- if (window.METAMASK_UI_TYPE === 'notification') {
- return null
- }
-
- const props = this.props
- const {isMascara, isOnboarding} = props
-
- // Do not render header if user is in mascara onboarding
- if (isMascara && isOnboarding) {
- return null
- }
-
- // Do not render header if user is in mascara buy ether
- if (isMascara && props.currentView.name === 'buyEth') {
- return null
- }
-
- return (
-
- h('.full-width', {
- style: {},
- }, [
-
- (isInitialized || welcomeScreenSeen || isPopup || !betaUI) && h('.app-header.flex-row.flex-space-between', {
- className: classnames({
- 'app-header--initialized': !isOnboarding,
- }),
- }, [
- h('div.app-header-contents', {}, [
- h('div.left-menu-wrapper', {
- onClick: () => props.history.push(DEFAULT_ROUTE),
- }, [
- // mini logo
- h('img.metafox-icon', {
- height: 42,
- width: 42,
- src: '/images/metamask-fox.svg',
- }),
-
- // metamask name
- h('.flex-row', [
- h('h1', this.context.t('appName')),
- h('div.beta-label', this.context.t('beta')),
- ]),
-
- ]),
-
- betaUI && isInitialized && h('div.header__right-actions', [
- h('div.network-component-wrapper', {
- style: {},
- }, [
- // Network Indicator
- h(NetworkIndicator, {
- network,
- provider,
- disabled: this.props.location.pathname === CONFIRM_TRANSACTION_ROUTE,
- onClick: (event) => {
- event.preventDefault()
- event.stopPropagation()
- return networkDropdownOpen === false
- ? showNetworkDropdown()
- : hideNetworkDropdown()
- },
- }),
-
- ]),
-
- isUnlocked && h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
- h(Identicon, {
- address: this.props.selectedAddress,
- diameter: 32,
- }),
- ]),
- ]),
- ]),
- ]),
-
- !isInitialized && !isPopup && betaUI && h('.alpha-warning__container', {}, [
- h('h2', {
- className: classnames({
- 'alpha-warning': welcomeScreenSeen,
- 'alpha-warning-welcome-screen': !welcomeScreenSeen,
- }),
- }, 'Please be aware that this version is still under development'),
- ]),
-
- ])
- )
- }
-
toggleMetamaskActive () {
if (!this.props.isUnlocked) {
// currently inactive: redirect to password box
diff --git a/ui/app/components/app-header/app-header.component.js b/ui/app/components/app-header/app-header.component.js
new file mode 100644
index 000000000..cf36e0d79
--- /dev/null
+++ b/ui/app/components/app-header/app-header.component.js
@@ -0,0 +1,106 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import classnames from 'classnames'
+
+const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../../app/scripts/lib/enums')
+const { DEFAULT_ROUTE, CONFIRM_TRANSACTION_ROUTE } = require('../../routes')
+const Identicon = require('../identicon')
+const NetworkIndicator = require('../network')
+
+class AppHeader extends Component {
+ static propTypes = {
+ history: PropTypes.object,
+ location: PropTypes.object,
+ network: PropTypes.string,
+ provider: PropTypes.object,
+ networkDropdownOpen: PropTypes.bool,
+ showNetworkDropdown: PropTypes.func,
+ hideNetworkDropdown: PropTypes.func,
+ toggleAccountMenu: PropTypes.func,
+ selectedAddress: PropTypes.string,
+ isUnlocked: PropTypes.bool,
+ }
+
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ handleNetworkIndicatorClick (event) {
+ event.preventDefault()
+ event.stopPropagation()
+
+ const { networkDropdownOpen, showNetworkDropdown, hideNetworkDropdown } = this.props
+
+ return networkDropdownOpen === false
+ ? showNetworkDropdown()
+ : hideNetworkDropdown()
+ }
+
+ renderAccountMenu () {
+ const { isUnlocked, toggleAccountMenu, selectedAddress } = this.props
+
+ return isUnlocked && (
+ <div
+ className="account-menu__icon"
+ onClick={toggleAccountMenu}
+ >
+ <Identicon
+ address={selectedAddress}
+ diameter={32}
+ />
+ </div>
+ )
+ }
+
+ render () {
+ const {
+ network,
+ provider,
+ history,
+ location,
+ isUnlocked,
+ } = this.props
+
+ if (window.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION) {
+ return null
+ }
+
+ return (
+ <div
+ className={classnames('app-header', { 'app-header--back-drop': isUnlocked })}>
+ <div className="app-header__contents">
+ <div
+ className="app-header__logo-container"
+ onClick={() => history.push(DEFAULT_ROUTE)}
+ >
+ <img
+ className="app-header__metafox"
+ src="/images/metamask-fox.svg"
+ height={42}
+ width={42}
+ />
+ <div className="flex-row">
+ <h1>{ this.context.t('appName') }</h1>
+ <div className="app-header__beta-label">
+ { this.context.t('beta') }
+ </div>
+ </div>
+ </div>
+ <div className="app-header__account-menu-container">
+ <div className="network-component-wrapper">
+ <NetworkIndicator
+ network={network}
+ provider={provider}
+ onClick={event => this.handleNetworkIndicatorClick(event)}
+ disabled={location.pathname === CONFIRM_TRANSACTION_ROUTE}
+ />
+ </div>
+ { this.renderAccountMenu() }
+ </div>
+ </div>
+ </div>
+ )
+ }
+}
+
+export default AppHeader
diff --git a/ui/app/components/app-header/app-header.container.js b/ui/app/components/app-header/app-header.container.js
new file mode 100644
index 000000000..30d3f8cc4
--- /dev/null
+++ b/ui/app/components/app-header/app-header.container.js
@@ -0,0 +1,38 @@
+import { connect } from 'react-redux'
+import { withRouter } from 'react-router-dom'
+import { compose } from 'recompose'
+
+import AppHeader from './app-header.component'
+const actions = require('../../actions')
+
+const mapStateToProps = state => {
+ const { appState, metamask } = state
+ const { networkDropdownOpen } = appState
+ const {
+ network,
+ provider,
+ selectedAddress,
+ isUnlocked,
+ } = metamask
+
+ return {
+ networkDropdownOpen,
+ network,
+ provider,
+ selectedAddress,
+ isUnlocked,
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()),
+ hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()),
+ toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
+ }
+}
+
+export default compose(
+ withRouter,
+ connect(mapStateToProps, mapDispatchToProps)
+)(AppHeader)
diff --git a/ui/app/components/app-header/index.js b/ui/app/components/app-header/index.js
new file mode 100644
index 000000000..daa31f621
--- /dev/null
+++ b/ui/app/components/app-header/index.js
@@ -0,0 +1,2 @@
+import AppHeader from './app-header.container'
+module.exports = AppHeader
diff --git a/ui/app/components/export-text-container/export-text-container.scss b/ui/app/components/export-text-container/export-text-container.scss
index a42de8233..975d62f70 100644
--- a/ui/app/components/export-text-container/export-text-container.scss
+++ b/ui/app/components/export-text-container/export-text-container.scss
@@ -37,7 +37,7 @@
display: flex;
justify-content: center;
align-items: center;
- font-size: 14px;
+ font-size: 12px;
cursor: pointer;
color: $curious-blue;
diff --git a/ui/app/components/pages/unlock-page/index.js b/ui/app/components/pages/unlock-page/index.js
new file mode 100644
index 000000000..be80cde4f
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/index.js
@@ -0,0 +1,2 @@
+import UnlockPage from './unlock-page.container'
+module.exports = UnlockPage
diff --git a/ui/app/components/pages/unlock-page/unlock-page.component.js b/ui/app/components/pages/unlock-page/unlock-page.component.js
new file mode 100644
index 000000000..e655b2cc3
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/unlock-page.component.js
@@ -0,0 +1,182 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Button from 'material-ui/Button'
+import TextField from '../../text-field'
+
+const { ENVIRONMENT_TYPE_POPUP } = require('../../../../../app/scripts/lib/enums')
+const { getEnvironmentType } = require('../../../../../app/scripts/lib/util')
+const getCaretCoordinates = require('textarea-caret')
+const EventEmitter = require('events').EventEmitter
+const Mascot = require('../../mascot')
+const { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE } = require('../../../routes')
+
+class UnlockPage extends Component {
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ constructor (props) {
+ super(props)
+
+ this.state = {
+ password: '',
+ error: null,
+ }
+
+ this.animationEventEmitter = new EventEmitter()
+ }
+
+ componentWillMount () {
+ const { isUnlocked, history } = this.props
+
+ if (isUnlocked) {
+ history.push(DEFAULT_ROUTE)
+ }
+ }
+
+ tryUnlockMetamask (password) {
+ const { tryUnlockMetamask, history } = this.props
+ tryUnlockMetamask(password)
+ .then(() => history.push(DEFAULT_ROUTE))
+ .catch(({ message }) => this.setState({ error: message }))
+ }
+
+ handleSubmit (event) {
+ event.preventDefault()
+ event.stopPropagation()
+
+ const { password } = this.state
+ const { tryUnlockMetamask, history } = this.props
+
+ if (password === '') {
+ return
+ }
+
+ this.setState({ error: null })
+
+ tryUnlockMetamask(password)
+ .then(() => history.push(DEFAULT_ROUTE))
+ .catch(({ message }) => this.setState({ error: message }))
+ }
+
+ handleInputChange ({ target }) {
+ this.setState({ password: target.value, error: null })
+
+ // tell mascot to look at page action
+ const element = target
+ const boundingRect = element.getBoundingClientRect()
+ const coordinates = getCaretCoordinates(element, element.selectionEnd)
+ this.animationEventEmitter.emit('point', {
+ x: boundingRect.left + coordinates.left - element.scrollLeft,
+ y: boundingRect.top + coordinates.top - element.scrollTop,
+ })
+ }
+
+ renderSubmitButton () {
+ const style = {
+ backgroundColor: '#f7861c',
+ color: 'white',
+ marginTop: '20px',
+ height: '60px',
+ fontWeight: '400',
+ boxShadow: 'none',
+ borderRadius: '4px',
+ }
+
+ return (
+ <Button
+ type="submit"
+ style={style}
+ disabled={!this.state.password}
+ fullWidth
+ variant="raised"
+ size="large"
+ onClick={event => this.handleSubmit(event)}
+ disableRipple
+ >
+ { this.context.t('login') }
+ </Button>
+ )
+ }
+
+ render () {
+ const { error } = this.state
+
+ return (
+ <div className="unlock-page__container">
+ <div className="unlock-page">
+ <div className="unlock-page__mascot-container">
+ <Mascot
+ animationEventEmitter={this.animationEventEmitter}
+ width="120"
+ height="120"
+ />
+ </div>
+ <h1 className="unlock-page__title">
+ { this.context.t('welcomeBack') }
+ </h1>
+ <div>{ this.context.t('unlockMessage') }</div>
+ <form
+ className="unlock-page__form"
+ onSubmit={event => this.handleSubmit(event)}
+ >
+ <TextField
+ id="password"
+ label="Password"
+ type="password"
+ value={this.state.password}
+ onChange={event => this.handleInputChange(event)}
+ error={error}
+ autoFocus
+ margin="normal"
+ autoComplete="current-password"
+ fullWidth
+ />
+ </form>
+ { this.renderSubmitButton() }
+ <div className="unlock-page__links">
+ <div
+ className="unlock-page__link"
+ onClick={() => {
+ this.props.markPasswordForgotten()
+ this.props.history.push(RESTORE_VAULT_ROUTE)
+
+ if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
+ global.platform.openExtensionInBrowser()
+ }
+ }}
+ >
+ { this.context.t('restoreFromSeed') }
+ </div>
+ <div
+ className="unlock-page__link unlock-page__link--import"
+ onClick={() => {
+ this.props.markPasswordForgotten()
+ this.props.history.push(RESTORE_VAULT_ROUTE)
+
+ if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
+ global.platform.openExtensionInBrowser()
+ }
+ }}
+ >
+ { this.context.t('importUsingSeed') }
+ </div>
+ </div>
+ </div>
+ </div>
+ )
+ }
+}
+
+UnlockPage.propTypes = {
+ forgotPassword: PropTypes.func,
+ tryUnlockMetamask: PropTypes.func,
+ markPasswordForgotten: PropTypes.func,
+ history: PropTypes.object,
+ isUnlocked: PropTypes.bool,
+ t: PropTypes.func,
+ useOldInterface: PropTypes.func,
+ setNetworkEndpoints: PropTypes.func,
+}
+
+export default UnlockPage
diff --git a/ui/app/components/pages/unlock-page/unlock-page.container.js b/ui/app/components/pages/unlock-page/unlock-page.container.js
new file mode 100644
index 000000000..9788a18ea
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/unlock-page.container.js
@@ -0,0 +1,33 @@
+import { connect } from 'react-redux'
+import { withRouter } from 'react-router-dom'
+import { compose } from 'recompose'
+
+const {
+ tryUnlockMetamask,
+ forgotPassword,
+ markPasswordForgotten,
+ setNetworkEndpoints,
+} = require('../../../actions')
+
+import UnlockPage from './unlock-page.component'
+
+const mapStateToProps = state => {
+ const { metamask: { isUnlocked } } = state
+ return {
+ isUnlocked,
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ forgotPassword: () => dispatch(forgotPassword()),
+ tryUnlockMetamask: password => dispatch(tryUnlockMetamask(password)),
+ markPasswordForgotten: () => dispatch(markPasswordForgotten()),
+ setNetworkEndpoints: type => dispatch(setNetworkEndpoints(type)),
+ }
+}
+
+export default compose(
+ withRouter,
+ connect(mapStateToProps, mapDispatchToProps)
+)(UnlockPage)
diff --git a/ui/app/components/pages/unlock-page/unlock-page.scss b/ui/app/components/pages/unlock-page/unlock-page.scss
new file mode 100644
index 000000000..47b6537e7
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/unlock-page.scss
@@ -0,0 +1,51 @@
+.unlock-page {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ width: 357px;
+ padding: 30px;
+ font-weight: 400;
+ color: $silver-chalice;
+
+ &__container {
+ background: $white;
+ display: flex;
+ align-self: stretch;
+ justify-content: center;
+ flex: 1 0 auto;
+ }
+
+ &__mascot-container {
+ margin-top: 24px;
+ }
+
+ &__title {
+ margin-top: 5px;
+ font-size: 2rem;
+ font-weight: 800;
+ color: $tundora;
+ }
+
+ &__form {
+ width: 100%;
+ margin-top: 40px;
+ }
+
+ &__links {
+ margin-top: 25px;
+ width: 100%;
+ }
+
+ &__link {
+ cursor: pointer;
+
+ &--import {
+ color: $ecstasy;
+ }
+
+ &--use-classic {
+ margin-top: 10px;
+ }
+ }
+}
diff --git a/ui/app/components/pages/unlock.js b/ui/app/components/pages/unlock.js
deleted file mode 100644
index 30144b978..000000000
--- a/ui/app/components/pages/unlock.js
+++ /dev/null
@@ -1,194 +0,0 @@
-const { Component } = require('react')
-const PropTypes = require('prop-types')
-const connect = require('../../metamask-connect')
-const h = require('react-hyperscript')
-const { withRouter } = require('react-router-dom')
-const { compose } = require('recompose')
-const {
- tryUnlockMetamask,
- forgotPassword,
- markPasswordForgotten,
- setNetworkEndpoints,
- setFeatureFlag,
-} = require('../../actions')
-const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums')
-const { getEnvironmentType } = require('../../../../app/scripts/lib/util')
-const getCaretCoordinates = require('textarea-caret')
-const EventEmitter = require('events').EventEmitter
-const Mascot = require('../mascot')
-const { OLD_UI_NETWORK_TYPE } = require('../../../../app/scripts/controllers/network/enums')
-const { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE } = require('../../routes')
-
-class UnlockScreen extends Component {
- constructor (props) {
- super(props)
-
- this.state = {
- error: null,
- }
-
- this.animationEventEmitter = new EventEmitter()
- }
-
- componentWillMount () {
- const { isUnlocked, history } = this.props
-
- if (isUnlocked) {
- history.push(DEFAULT_ROUTE)
- }
- }
-
- componentDidMount () {
- const passwordBox = document.getElementById('password-box')
-
- if (passwordBox) {
- passwordBox.focus()
- }
- }
-
- tryUnlockMetamask (password) {
- const { tryUnlockMetamask, history } = this.props
- tryUnlockMetamask(password)
- .then(() => history.push(DEFAULT_ROUTE))
- .catch(({ message }) => this.setState({ error: message }))
- }
-
- onSubmit (event) {
- const input = document.getElementById('password-box')
- const password = input.value
- this.tryUnlockMetamask(password)
- }
-
- onKeyPress (event) {
- if (event.key === 'Enter') {
- this.submitPassword(event)
- }
- }
-
- submitPassword (event) {
- var element = event.target
- var password = element.value
- // reset input
- element.value = ''
- this.tryUnlockMetamask(password)
- }
-
- inputChanged (event) {
- // tell mascot to look at page action
- var element = event.target
- var boundingRect = element.getBoundingClientRect()
- var coordinates = getCaretCoordinates(element, element.selectionEnd)
- this.animationEventEmitter.emit('point', {
- x: boundingRect.left + coordinates.left - element.scrollLeft,
- y: boundingRect.top + coordinates.top - element.scrollTop,
- })
- }
-
- render () {
- const { error } = this.state
- return (
- h('.unlock-screen', [
-
- h(Mascot, {
- animationEventEmitter: this.animationEventEmitter,
- }),
-
- h('h1', {
- style: {
- fontSize: '1.4em',
- textTransform: 'uppercase',
- color: '#7F8082',
- },
- }, this.props.t('appName')),
-
- h('input.large-input', {
- type: 'password',
- id: 'password-box',
- placeholder: 'enter password',
- style: {
- background: 'white',
- },
- onKeyPress: this.onKeyPress.bind(this),
- onInput: this.inputChanged.bind(this),
- }),
-
- h('.error', {
- style: {
- display: error ? 'block' : 'none',
- padding: '0 20px',
- textAlign: 'center',
- },
- }, error),
-
- h('button.primary.cursor-pointer', {
- onClick: this.onSubmit.bind(this),
- style: {
- margin: 10,
- },
- }, this.props.t('login')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.markPasswordForgotten()
- this.props.history.push(RESTORE_VAULT_ROUTE)
-
- if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
- global.platform.openExtensionInBrowser()
- }
- },
- style: {
- fontSize: '0.8em',
- color: 'rgb(247, 134, 28)',
- textDecoration: 'underline',
- },
- }, this.props.t('restoreFromSeed')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.useOldInterface()
- .then(() => this.props.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))
- },
- style: {
- fontSize: '0.8em',
- color: '#aeaeae',
- textDecoration: 'underline',
- marginTop: '32px',
- },
- }, this.props.t('classicInterface')),
- ])
- )
- }
-}
-
-UnlockScreen.propTypes = {
- forgotPassword: PropTypes.func,
- tryUnlockMetamask: PropTypes.func,
- markPasswordForgotten: PropTypes.func,
- history: PropTypes.object,
- isUnlocked: PropTypes.bool,
- t: PropTypes.func,
- useOldInterface: PropTypes.func,
- setNetworkEndpoints: PropTypes.func,
-}
-
-const mapStateToProps = state => {
- const { metamask: { isUnlocked } } = state
- return {
- isUnlocked,
- }
-}
-
-const mapDispatchToProps = dispatch => {
- return {
- forgotPassword: () => dispatch(forgotPassword()),
- tryUnlockMetamask: password => dispatch(tryUnlockMetamask(password)),
- markPasswordForgotten: () => dispatch(markPasswordForgotten()),
- useOldInterface: () => dispatch(setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')),
- setNetworkEndpoints: type => dispatch(setNetworkEndpoints(type)),
- }
-}
-
-module.exports = compose(
- withRouter,
- connect(mapStateToProps, mapDispatchToProps)
-)(UnlockScreen)
diff --git a/ui/app/components/text-field/index.js b/ui/app/components/text-field/index.js
new file mode 100644
index 000000000..171caf7a4
--- /dev/null
+++ b/ui/app/components/text-field/index.js
@@ -0,0 +1,2 @@
+import TextField from './text-field.component'
+module.exports = TextField
diff --git a/ui/app/components/text-field/text-field.component.js b/ui/app/components/text-field/text-field.component.js
new file mode 100644
index 000000000..4a02f76d8
--- /dev/null
+++ b/ui/app/components/text-field/text-field.component.js
@@ -0,0 +1,54 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { withStyles } from 'material-ui/styles'
+import { default as MaterialTextField } from 'material-ui/TextField'
+
+const styles = {
+ cssLabel: {
+ '&$cssFocused': {
+ color: '#aeaeae',
+ },
+ fontWeight: '400',
+ color: '#aeaeae',
+ },
+ cssFocused: {},
+ cssUnderline: {
+ '&:after': {
+ backgroundColor: '#f7861c',
+ },
+ },
+}
+
+const TextField = props => {
+ const { error, classes, ...textFieldProps } = props
+
+ return (
+ <MaterialTextField
+ error={Boolean(error)}
+ helperText={error}
+ InputLabelProps={{
+ FormLabelClasses: {
+ root: classes.cssLabel,
+ focused: classes.cssFocused,
+ },
+ }}
+ InputProps={{
+ classes: {
+ underline: classes.cssUnderline,
+ },
+ }}
+ {...textFieldProps}
+ />
+ )
+}
+
+TextField.defaultProps = {
+ error: null,
+}
+
+TextField.propTypes = {
+ error: PropTypes.string,
+ classes: PropTypes.object,
+}
+
+export default withStyles(styles)(TextField)
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js
index 9e430f87b..3b29dacac 100644
--- a/ui/app/components/wallet-view.js
+++ b/ui/app/components/wallet-view.js
@@ -102,6 +102,7 @@ WalletView.prototype.render = function () {
selectedIdentity,
keyrings,
showAccountDetailModal,
+ sidebarOpen,
hideSidebar,
history,
} = this.props
@@ -182,7 +183,10 @@ WalletView.prototype.render = function () {
h(TokenList),
h('button.btn-primary.wallet-view__add-token-button', {
- onClick: () => history.push(ADD_TOKEN_ROUTE),
+ onClick: () => {
+ history.push(ADD_TOKEN_ROUTE)
+ sidebarOpen && hideSidebar()
+ },
}, this.context.t('addToken')),
])
}
diff --git a/ui/app/css/itcss/components/header.scss b/ui/app/css/itcss/components/header.scss
index eeed9ee06..cef61d0e2 100644
--- a/ui/app/css/itcss/components/header.scss
+++ b/ui/app/css/itcss/components/header.scss
@@ -1,15 +1,15 @@
.app-header {
align-items: center;
- visibility: visible;
background: $gallery;
position: relative;
z-index: $header-z-index;
display: flex;
flex-flow: column nowrap;
+ width: 100%;
+ flex: 0 0 auto;
@media screen and (max-width: 575px) {
padding: 12px;
- width: 100%;
box-shadow: 0 0 0 1px rgba(0, 0, 0, .08);
z-index: $mobile-header-z-index;
}
@@ -17,48 +17,75 @@
@media screen and (min-width: 576px) {
height: 75px;
justify-content: center;
+
+ &--back-drop {
+ &::after {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 32px;
+ background: $gallery;
+ bottom: -32px;
+ }
+ }
}
- .metafox-icon {
+ &__metafox {
cursor: pointer;
}
-}
-
-.app-header--initialized {
- @media screen and (min-width: 576px) {
- &::after {
- content: '';
- position: absolute;
- width: 100%;
- height: 32px;
- background: $gallery;
- bottom: -32px;
+ &__beta-label {
+ font-family: Roboto;
+ text-transform: uppercase;
+ font-weight: 500;
+ font-size: .8rem;
+ color: $buttercup;
+ margin-left: 5px;
+ line-height: initial;
+
+ @media screen and (max-width: 575px) {
+ display: none;
}
}
-}
-.app-header-contents {
- display: flex;
- justify-content: space-between;
- flex-flow: row nowrap;
- width: 100%;
- height: 6.9vh;
+ &__contents {
+ display: flex;
+ justify-content: space-between;
+ flex-flow: row nowrap;
+ width: 100%;
- @media screen and (max-width: 575px) {
- height: 100%;
- }
+ @media screen and (max-width: 575px) {
+ height: 100%;
+ }
- @media screen and (min-width: 576px) {
- width: 85vw;
+ @media screen and (min-width: 576px) {
+ width: 85vw;
+ }
+
+ @media screen and (min-width: 769px) {
+ width: 80vw;
+ }
+
+ @media screen and (min-width: 1281px) {
+ width: 62vw;
+ }
}
- @media screen and (min-width: 769px) {
- width: 80vw;
+ &__logo-container {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ cursor: pointer;
}
- @media screen and (min-width: 1281px) {
- width: 62vw;
+ &__account-menu-container {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+
+ .identicon {
+ cursor: pointer;
+ }
}
}
@@ -76,20 +103,6 @@
}
}
-.beta-label {
- font-family: Roboto;
- text-transform: uppercase;
- font-weight: 500;
- font-size: .8rem;
- color: $buttercup;
- margin-left: 5px;
- line-height: initial;
-
- @media screen and (max-width: 575px) {
- display: none;
- }
-}
-
h2.page-subtitle {
text-transform: uppercase;
color: #aeaeae;
@@ -102,20 +115,3 @@ h2.page-subtitle {
flex-direction: row;
align-items: center;
}
-
-.left-menu-wrapper {
- display: flex;
- flex-direction: row;
- align-items: center;
- cursor: pointer;
-}
-
-.header__right-actions {
- display: flex;
- flex-flow: row nowrap;
- align-items: center;
-
- .identicon {
- cursor: pointer;
- }
-}
diff --git a/ui/app/css/itcss/components/pages/index.scss b/ui/app/css/itcss/components/pages/index.scss
index d0b59da53..195185fff 100644
--- a/ui/app/css/itcss/components/pages/index.scss
+++ b/ui/app/css/itcss/components/pages/index.scss
@@ -1,3 +1,3 @@
-@import './unlock.scss';
-
@import './reveal-seed.scss';
+
+@import '../../../../components/pages/unlock-page/unlock-page.scss';
diff --git a/ui/app/css/itcss/components/pages/unlock.scss b/ui/app/css/itcss/components/pages/unlock.scss
deleted file mode 100644
index 5d438377b..000000000
--- a/ui/app/css/itcss/components/pages/unlock.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.unlock-page {
- box-shadow: none;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- background: rgb(247, 247, 247);
- width: 100%;
-}
diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss
index ace46bd8a..feec71c89 100644
--- a/ui/app/css/itcss/components/sections.scss
+++ b/ui/app/css/itcss/components/sections.scss
@@ -95,19 +95,6 @@ textarea.twelve-word-phrase {
margin: -2px 8px 0px -8px;
}
-.unlock-screen #metamask-mascot-container {
- margin-top: 24px;
-}
-
-.unlock-screen h1 {
- margin-top: -28px;
- margin-bottom: 42px;
-}
-
-.unlock-screen input[type=password] {
- width: 260px;
-}
-
.sizing-input {
font-size: 14px;
height: 30px;
@@ -118,34 +105,6 @@ textarea.twelve-word-phrase {
display: flex;
}
-/* Webkit */
-
-.unlock-screen input::-webkit-input-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
-/* Firefox 18- */
-
-.unlock-screen input:-moz-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
-/* Firefox 19+ */
-
-.unlock-screen input::-moz-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
-/* IE */
-
-.unlock-screen input:-ms-input-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
/* accounts */
.accounts-section {
diff --git a/ui/app/css/itcss/components/settings.scss b/ui/app/css/itcss/components/settings.scss
index dcc9b98d5..0dd61ac5e 100644
--- a/ui/app/css/itcss/components/settings.scss
+++ b/ui/app/css/itcss/components/settings.scss
@@ -3,8 +3,6 @@
background: $white;
display: flex;
flex-flow: column nowrap;
- height: auto;
- overflow: auto;
}
.settings__header {
@@ -29,6 +27,8 @@
.settings__content {
padding: 0 25px;
+ height: auto;
+ overflow: auto;
}
.settings__content-row {
diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss
index b484d5a91..9b2982096 100644
--- a/ui/app/css/itcss/generic/index.scss
+++ b/ui/app/css/itcss/generic/index.scss
@@ -205,10 +205,8 @@ input.large-input {
}
&__content {
- height: 100%;
overflow-y: auto;
- min-height: 250px;
- max-height: 400px;
+ flex: 1;
}
&__warning-container {
@@ -256,6 +254,7 @@ input.large-input {
overflow-y: auto;
background-color: $white;
border-radius: 0;
+ flex: 1;
}
}
diff --git a/ui/app/main-container.js b/ui/app/main-container.js
index c305687ea..c9b05db3b 100644
--- a/ui/app/main-container.js
+++ b/ui/app/main-container.js
@@ -3,7 +3,7 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const AccountAndTransactionDetails = require('./account-and-transaction-details')
const Settings = require('./components/pages/settings')
-const UnlockScreen = require('./components/pages/unlock')
+const UnlockScreen = require('./components/pages/unlock-page')
const log = require('loglevel')
module.exports = MainContainer
diff --git a/ui/app/unlock.js b/ui/app/unlock.js
deleted file mode 100644
index 099e5f9c6..000000000
--- a/ui/app/unlock.js
+++ /dev/null
@@ -1,141 +0,0 @@
-const inherits = require('util').inherits
-const Component = require('react').Component
-const PropTypes = require('prop-types')
-const h = require('react-hyperscript')
-const connect = require('react-redux').connect
-const actions = require('./actions')
-const getCaretCoordinates = require('textarea-caret')
-const EventEmitter = require('events').EventEmitter
-const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/controllers/network/enums')
-const { getEnvironmentType } = require('../../app/scripts/lib/util')
-const { ENVIRONMENT_TYPE_POPUP } = require('../../app/scripts/lib/enums')
-
-const Mascot = require('./components/mascot')
-
-UnlockScreen.contextTypes = {
- t: PropTypes.func,
-}
-
-module.exports = connect(mapStateToProps)(UnlockScreen)
-
-
-inherits(UnlockScreen, Component)
-function UnlockScreen () {
- Component.call(this)
- this.animationEventEmitter = new EventEmitter()
-}
-
-function mapStateToProps (state) {
- return {
- warning: state.appState.warning,
- }
-}
-
-UnlockScreen.prototype.render = function () {
- const state = this.props
- const warning = state.warning
- return (
- h('.unlock-screen', [
-
- h(Mascot, {
- animationEventEmitter: this.animationEventEmitter,
- }),
-
- h('h1', {
- style: {
- fontSize: '1.4em',
- textTransform: 'uppercase',
- color: '#7F8082',
- },
- }, this.context.t('appName')),
-
- h('input.large-input', {
- type: 'password',
- id: 'password-box',
- placeholder: 'enter password',
- style: {
- background: 'white',
- },
- onKeyPress: this.onKeyPress.bind(this),
- onInput: this.inputChanged.bind(this),
- }),
-
- h('.error', {
- style: {
- display: warning ? 'block' : 'none',
- padding: '0 20px',
- textAlign: 'center',
- },
- }, warning),
-
- h('button.primary.cursor-pointer', {
- onClick: this.onSubmit.bind(this),
- style: {
- margin: 10,
- },
- }, this.context.t('login')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.dispatch(actions.markPasswordForgotten())
- if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
- global.platform.openExtensionInBrowser()
- }
- },
- style: {
- fontSize: '0.8em',
- color: 'rgb(247, 134, 28)',
- textDecoration: 'underline',
- },
- }, this.context.t('restoreFromSeed')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL'))
- .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE)))
- },
- style: {
- fontSize: '0.8em',
- color: '#aeaeae',
- textDecoration: 'underline',
- marginTop: '32px',
- },
- }, this.context.t('classicInterface')),
- ])
- )
-}
-
-UnlockScreen.prototype.componentDidMount = function () {
- document.getElementById('password-box').focus()
-}
-
-UnlockScreen.prototype.onSubmit = function (event) {
- const input = document.getElementById('password-box')
- const password = input.value
- this.props.dispatch(actions.tryUnlockMetamask(password))
-}
-
-UnlockScreen.prototype.onKeyPress = function (event) {
- if (event.key === 'Enter') {
- this.submitPassword(event)
- }
-}
-
-UnlockScreen.prototype.submitPassword = function (event) {
- var element = event.target
- var password = element.value
- // reset input
- element.value = ''
- this.props.dispatch(actions.tryUnlockMetamask(password))
-}
-
-UnlockScreen.prototype.inputChanged = function (event) {
- // tell mascot to look at page action
- var element = event.target
- var boundingRect = element.getBoundingClientRect()
- var coordinates = getCaretCoordinates(element, element.selectionEnd)
- this.animationEventEmitter.emit('point', {
- x: boundingRect.left + coordinates.left - element.scrollLeft,
- y: boundingRect.top + coordinates.top - element.scrollTop,
- })
-}