diff options
Merge branch 'master' into i18n
Diffstat (limited to 'ui')
59 files changed, 1265 insertions, 297 deletions
diff --git a/ui/app/account-and-transaction-details.js b/ui/app/account-and-transaction-details.js index 60293de77..03101d37a 100644 --- a/ui/app/account-and-transaction-details.js +++ b/ui/app/account-and-transaction-details.js @@ -13,12 +13,7 @@ function AccountAndTransactionDetails () { } AccountAndTransactionDetails.prototype.render = function () { - return h('div', { - style: { - display: 'flex', - flex: '1 0 auto', - }, - }, [ + return h('div.account-and-transaction-details', [ // wallet h(WalletView, { style: { diff --git a/ui/app/accounts/import/index.js b/ui/app/accounts/import/index.js index 6ae74864f..ac6517424 100644 --- a/ui/app/accounts/import/index.js +++ b/ui/app/accounts/import/index.js @@ -38,7 +38,7 @@ AccountImportSubview.prototype.render = function () { h('div.new-account-import-form__select-section', [ - h('div.new-account-import-form__select-label', 'SELECT TYPE'), + h('div.new-account-import-form__select-label', 'Select Type'), h(Select, { className: 'new-account-import-form__select', diff --git a/ui/app/accounts/import/json.js b/ui/app/accounts/import/json.js index eb63a98a9..791759666 100644 --- a/ui/app/accounts/import/json.js +++ b/ui/app/accounts/import/json.js @@ -82,6 +82,12 @@ JsonImportSubview.prototype.createKeyringOnEnter = function (event) { JsonImportSubview.prototype.createNewKeychain = function () { const state = this.state + + if (!state) { + const message = 'You must select a valid file to import.' + return this.props.dispatch(actions.displayWarning(message)) + } + const { fileContents } = state if (!fileContents) { diff --git a/ui/app/accounts/import/private-key.js b/ui/app/accounts/import/private-key.js index e8c192a61..0b49d3281 100644 --- a/ui/app/accounts/import/private-key.js +++ b/ui/app/accounts/import/private-key.js @@ -33,15 +33,22 @@ PrivateKeyImportView.prototype.render = function () { return ( h('div.new-account-import-form__private-key', [ + h('span.new-account-create-form__instruction', t('pastePrivateKey')), - h('input.new-account-import-form__input-password', { - type: 'password', - id: 'private-key-box', - onKeyPress: () => this.createKeyringOnEnter(), - }), + h('div.new-account-import-form__private-key-password-container', [ + + h('span.new-account-import-form__instruction', 'Paste your private key string here:'), + + h('input.new-account-import-form__input-password', { + type: 'password', + id: 'private-key-box', + onKeyPress: () => this.createKeyringOnEnter(), + }), + + ]), - h('div.new-account-create-form__buttons', {}, [ + h('div.new-account-import-form__buttons', {}, [ h('button.new-account-create-form__button-cancel.allcaps', { onClick: () => goHome(), diff --git a/ui/app/accounts/new-account/create-form.js b/ui/app/accounts/new-account/create-form.js index ce8af394a..eb34f7a2f 100644 --- a/ui/app/accounts/new-account/create-form.js +++ b/ui/app/accounts/new-account/create-form.js @@ -8,16 +8,19 @@ const t = require('../../../i18n') class NewAccountCreateForm extends Component { constructor (props) { super(props) + const { numberOfExistingAccounts = 0 } = props const newAccountNumber = numberOfExistingAccounts + 1 this.state = { - newAccountName: `Account ${newAccountNumber}`, + newAccountName: '', + defaultAccountName: t('newAccountNumberName', newAccountNumber), } } render () { - const { newAccountName } = this.state + const { newAccountName, defaultAccountName } = this.state + return h('div.new-account-create-form', [ @@ -27,8 +30,8 @@ class NewAccountCreateForm extends Component { h('div.new-account-create-form__input-wrapper', {}, [ h('input.new-account-create-form__input', { - value: this.state.newAccountName, - placeholder: t('sampleAccountName'), + value: newAccountName, + placeholder: defaultAccountName, onChange: event => this.setState({ newAccountName: event.target.value }), }, []), ]), @@ -42,7 +45,7 @@ class NewAccountCreateForm extends Component { ]), h('button.new-account-create-form__button-create.allcaps', { - onClick: () => this.props.createAccount(newAccountName), + onClick: () => this.props.createAccount(newAccountName || defaultAccountName), }, [ t('create'), ]), diff --git a/ui/app/actions.js b/ui/app/actions.js index 25cb2c23f..8b1480a79 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -47,6 +47,8 @@ var actions = { SHOW_RESTORE_VAULT: 'SHOW_RESTORE_VAULT', FORGOT_PASSWORD: 'FORGOT_PASSWORD', forgotPassword: forgotPassword, + markPasswordForgotten, + unMarkPasswordForgotten, SHOW_INIT_MENU: 'SHOW_INIT_MENU', SHOW_NEW_VAULT_SEED: 'SHOW_NEW_VAULT_SEED', SHOW_INFO_PAGE: 'SHOW_INFO_PAGE', @@ -55,6 +57,7 @@ var actions = { SET_NEW_ACCOUNT_FORM: 'SET_NEW_ACCOUNT_FORM', unlockMetamask: unlockMetamask, unlockFailed: unlockFailed, + unlockSucceeded, showCreateVault: showCreateVault, showRestoreVault: showRestoreVault, showInitializeMenu: showInitializeMenu, @@ -69,15 +72,18 @@ var actions = { addNewAccount, NEW_ACCOUNT_SCREEN: 'NEW_ACCOUNT_SCREEN', navigateToNewAccountScreen, + resetAccount, showNewVaultSeed: showNewVaultSeed, showInfoPage: showInfoPage, // seed recovery actions REVEAL_SEED_CONFIRMATION: 'REVEAL_SEED_CONFIRMATION', revealSeedConfirmation: revealSeedConfirmation, requestRevealSeed: requestRevealSeed, + // unlock screen UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS', UNLOCK_FAILED: 'UNLOCK_FAILED', + UNLOCK_SUCCEEDED: 'UNLOCK_SUCCEEDED', UNLOCK_METAMASK: 'UNLOCK_METAMASK', LOCK_METAMASK: 'LOCK_METAMASK', tryUnlockMetamask: tryUnlockMetamask, @@ -251,6 +257,9 @@ var actions = { updateFeatureFlags, UPDATE_FEATURE_FLAGS: 'UPDATE_FEATURE_FLAGS', + setMouseUserState, + SET_MOUSE_USER_STATE: 'SET_MOUSE_USER_STATE', + // Network setNetworkEndpoints, updateNetworkEndpointType, @@ -284,6 +293,7 @@ function tryUnlockMetamask (password) { if (err) { dispatch(actions.unlockFailed(err.message)) } else { + dispatch(actions.unlockSucceeded()) dispatch(actions.transitionForward()) forceUpdateMetamaskState(dispatch) } @@ -396,6 +406,20 @@ function requestRevealSeed (password) { } } +function resetAccount () { + return (dispatch) => { + background.resetAccount((err, account) => { + dispatch(actions.hideLoadingIndication()) + if (err) { + dispatch(actions.displayWarning(err.message)) + } + + log.info('Transaction history reset for ' + account) + dispatch(actions.showAccountsPage()) + }) + } +} + function addNewKeyring (type, opts) { return (dispatch) => { dispatch(actions.showLoadingIndication()) @@ -816,9 +840,29 @@ function showRestoreVault () { } } -function forgotPassword () { +function markPasswordForgotten () { + return (dispatch) => { + return background.markPasswordForgotten(() => { + dispatch(actions.hideLoadingIndication()) + dispatch(actions.forgotPassword()) + forceUpdateMetamaskState(dispatch) + }) + } +} + +function unMarkPasswordForgotten () { + return (dispatch) => { + return background.unMarkPasswordForgotten(() => { + dispatch(actions.forgotPassword(false)) + forceUpdateMetamaskState(dispatch) + }) + } +} + +function forgotPassword (forgotPasswordState = true) { return { type: actions.FORGOT_PASSWORD, + value: forgotPasswordState, } } @@ -890,6 +934,13 @@ function unlockFailed (message) { } } +function unlockSucceeded (message) { + return { + type: actions.UNLOCK_SUCCEEDED, + value: message, + } +} + function unlockMetamask (account) { return { type: actions.UNLOCK_METAMASK, @@ -1447,6 +1498,7 @@ function pairUpdate (coin) { dispatch(actions.hideWarning()) shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => { dispatch(actions.hideSubLoadingIndication()) + if (mktResponse.error) return dispatch(actions.displayWarning(mktResponse.error)) dispatch({ type: actions.PAIR_UPDATE, value: { @@ -1611,6 +1663,13 @@ function updateFeatureFlags (updatedFeatureFlags) { } } +function setMouseUserState (isMouseUser) { + return { + type: actions.SET_MOUSE_USER_STATE, + value: isMouseUser, + } +} + // Call Background Then Update // // A function generator for a common pattern wherein: diff --git a/ui/app/add-token.js b/ui/app/add-token.js index 3a806d34b..51c577987 100644 --- a/ui/app/add-token.js +++ b/ui/app/add-token.js @@ -52,13 +52,16 @@ function AddTokenScreen () { isShowingConfirmation: false, customAddress: '', customSymbol: '', - customDecimals: 0, + customDecimals: '', searchQuery: '', isCollapsed: true, selectedTokens: {}, errors: {}, + autoFilled: false, } this.tokenAddressDidChange = this.tokenAddressDidChange.bind(this) + this.tokenSymbolDidChange = this.tokenSymbolDidChange.bind(this) + this.tokenDecimalsDidChange = this.tokenDecimalsDidChange.bind(this) this.onNext = this.onNext.bind(this) Component.call(this) } @@ -103,6 +106,16 @@ AddTokenScreen.prototype.tokenAddressDidChange = function (e) { } } +AddTokenScreen.prototype.tokenSymbolDidChange = function (e) { + const customSymbol = e.target.value.trim() + this.setState({ customSymbol }) +} + +AddTokenScreen.prototype.tokenDecimalsDidChange = function (e) { + const customDecimals = e.target.value.trim() + this.setState({ customDecimals }) +} + AddTokenScreen.prototype.checkExistingAddresses = function (address) { if (!address) return false const tokensList = this.props.tokens @@ -125,7 +138,7 @@ AddTokenScreen.prototype.validate = function () { errors.customAddress = 'Address is invalid. ' } - const validDecimals = customDecimals >= 0 && customDecimals < 36 + const validDecimals = customDecimals !== null && customDecimals >= 0 && customDecimals < 36 if (!validDecimals) { errors.customDecimals = 'Decimals must be at least 0, and not over 36.' } @@ -166,12 +179,13 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) this.setState({ customSymbol: symbol, customDecimals: decimals.toString(), + autoFilled: true, }) } } AddTokenScreen.prototype.renderCustomForm = function () { - const { customAddress, customSymbol, customDecimals, errors } = this.state + const { autoFilled, customAddress, customSymbol, customDecimals, errors } = this.state return !this.state.isCollapsed && ( h('div.add-token__add-custom-form', [ @@ -196,8 +210,9 @@ AddTokenScreen.prototype.renderCustomForm = function () { h('div.add-token__add-custom-label', 'Token Symbol'), h('input.add-token__add-custom-input', { type: 'text', + onChange: this.tokenSymbolDidChange, value: customSymbol, - disabled: true, + disabled: autoFilled, }), h('div.add-token__add-custom-error-message', errors.customSymbol), ]), @@ -209,8 +224,9 @@ AddTokenScreen.prototype.renderCustomForm = function () { h('div.add-token__add-custom-label', 'Decimals of Precision'), h('input.add-token__add-custom-input', { type: 'number', + onChange: this.tokenDecimalsDidChange, value: customDecimals, - disabled: true, + disabled: autoFilled, }), h('div.add-token__add-custom-error-message', errors.customDecimals), ]), @@ -240,7 +256,7 @@ AddTokenScreen.prototype.renderTokenList = function () { }, [ h('div.add-token__token-icon', { style: { - backgroundImage: `url(images/contract/${logo})`, + backgroundImage: logo && `url(images/contract/${logo})`, }, }), h('div.add-token__token-data', [ diff --git a/ui/app/app.js b/ui/app/app.js index 3205baebb..8511ee396 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -10,7 +10,8 @@ const t = require('../i18n') const MascaraFirstTime = require('../../mascara/src/app/first-time').default const MascaraBuyEtherScreen = require('../../mascara/src/app/first-time/buy-ether-screen').default // init -const InitializeMenuScreen = require('./first-time/init-menu') +const OldUIInitializeMenuScreen = require('./first-time/init-menu') +const InitializeMenuScreen = MascaraFirstTime const NewKeyChainScreen = require('./new-keychain') // accounts const MainContainer = require('./main-container') @@ -75,17 +76,22 @@ function mapStateToProps (state) { transForward: state.appState.transForward, isMascara: state.metamask.isMascara, isOnboarding: Boolean(!noActiveNotices || seedWords || !isInitialized), + isPopup: state.metamask.isPopup, seedWords: state.metamask.seedWords, unapprovedTxs: state.metamask.unapprovedTxs, unapprovedMsgs: state.metamask.unapprovedMsgs, menuOpen: state.appState.menuOpen, network: state.metamask.network, provider: state.metamask.provider, - forgottenPassword: state.appState.forgottenPassword, + forgottenPassword: state.metamask.forgottenPassword, lastUnreadNotice: state.metamask.lastUnreadNotice, lostAccounts: state.metamask.lostAccounts, frequentRpcList: state.metamask.frequentRpcList || [], currentCurrency: state.metamask.currentCurrency, + isMouseUser: state.appState.isMouseUser, + betaUI: state.metamask.featureFlags.betaUI, + isRevealingSeedWords: state.metamask.isRevealingSeedWords, + Qr: state.appState.Qr, // state needed to get account dropdown temporarily rendering from app bar identities, @@ -102,6 +108,7 @@ function mapDispatchToProps (dispatch, ownProps) { hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')), toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), + setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)), } } @@ -113,7 +120,13 @@ App.prototype.componentWillMount = function () { App.prototype.render = function () { var props = this.props - const { isLoading, loadingMessage, network } = props + const { + isLoading, + loadingMessage, + network, + isMouseUser, + setMouseUserState, + } = props const isLoadingNetwork = network === 'loading' && props.currentView.name !== 'config' const loadMessage = loadingMessage || isLoadingNetwork ? `Connecting to ${this.getNetworkName()}` : null @@ -121,11 +134,19 @@ App.prototype.render = function () { return ( h('.flex-column.full-height', { + className: classnames({ 'mouse-user-styles': isMouseUser }), style: { overflowX: 'hidden', position: 'relative', alignItems: 'center', }, + tabIndex: '0', + onClick: () => setMouseUserState(true), + onKeyDown: (e) => { + if (e.keyCode === 9) { + setMouseUserState(false) + } + }, }, [ // global modal @@ -221,6 +242,9 @@ App.prototype.renderAppBar = function () { showNetworkDropdown, hideNetworkDropdown, currentView, + isInitialized, + betaUI, + isPopup, } = this.props if (window.METAMASK_UI_TYPE === 'notification') { @@ -265,8 +289,10 @@ App.prototype.renderAppBar = function () { }), // metamask name - h('h1', t('appName')), - + h('.flex-row', [ + h('h1', t('appName')), + h('div.beta-label', t('beta')), + ]), ]), h('div.header__right-actions', [ @@ -299,6 +325,9 @@ App.prototype.renderAppBar = function () { ]), ]), + !isInitialized && !isPopup && betaUI && h('h2.alpha-warning', + 'Please be aware that this version is still under development'), + ]) ) } @@ -336,9 +365,17 @@ App.prototype.renderBackButton = function (style, justArrow = false) { App.prototype.renderPrimary = function () { log.debug('rendering primary') var props = this.props - const {isMascara, isOnboarding} = props - - if (isMascara && isOnboarding) { + const { + isMascara, + isOnboarding, + betaUI, + isRevealingSeedWords, + Qr, + } = props + const isMascaraOnboarding = isMascara && isOnboarding + const isBetaUIOnboarding = betaUI && isOnboarding && !props.isPopup && !isRevealingSeedWords + + if (isMascaraOnboarding || isBetaUIOnboarding) { return h(MascaraFirstTime) } @@ -359,20 +396,14 @@ App.prototype.renderPrimary = function () { }) } - // show initialize screen - if (!props.isInitialized || props.forgottenPassword) { - // show current view - log.debug('rendering an initialize screen') - switch (props.currentView.name) { - - case 'restoreVault': - log.debug('rendering restore vault screen') - return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) - - default: - log.debug('rendering menu screen') - return h(InitializeMenuScreen, {key: 'menuScreenInit'}) - } + if (props.isInitialized && props.forgottenPassword) { + log.debug('rendering restore vault screen') + return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) + } else if (!props.isInitialized && !props.isUnlocked && !isRevealingSeedWords) { + log.debug('rendering menu screen') + return props.isPopup + ? h(OldUIInitializeMenuScreen, {key: 'menuScreenInit'}) + : h(InitializeMenuScreen, {key: 'menuScreenInit'}) } // show unlock screen @@ -480,7 +511,7 @@ App.prototype.renderPrimary = function () { width: '285px', }, }, [ - h(QrView, {key: 'qr'}), + h(QrView, {key: 'qr', Qr}), ]), ]) diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index e92da8947..1612d7b6a 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -1,5 +1,5 @@ const Component = require('react').Component -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const actions = require('../actions') const genAccountLink = require('etherscan-link').createAccountLink @@ -174,7 +174,7 @@ class AccountDropdowns extends Component { minWidth: '180px', }, isOpen: optionsMenuActive, - onClickOutside: () => { + onClickOutside: (event) => { const { classList } = event.target const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) if (optionsMenuActive && isNotToggleElement) { diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index d9cf8cdce..043e3d8d1 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -81,12 +81,12 @@ AccountMenu.prototype.render = function () { h(Divider), h(Item, { onClick: () => showNewAccountPage('CREATE'), - icon: h('img', { src: 'images/plus-btn-white.svg' }), + icon: h('img.account-menu__item-icon', { src: 'images/plus-btn-white.svg' }), text: t('createAccount'), }), h(Item, { onClick: () => showNewAccountPage('IMPORT'), - icon: h('img', { src: 'images/import-account.svg' }), + icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }), text: t('importAccount'), }), h(Divider), @@ -99,6 +99,13 @@ AccountMenu.prototype.render = function () { onClick: showConfigPage, icon: h('img', { src: 'images/settings.svg' }), text: t('settings'), + icon: h('img.account-menu__item-icon', { src: 'images/mm-info-icon.svg' }), + text: t('infoHelp'), + }), + h(Item, { + onClick: showConfigPage, + icon: h('img.account-menu__item-icon', { src: 'images/settings.svg' }), + text: t('settings'), }), ]) } diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 620ac8483..af29a4792 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -1,5 +1,5 @@ const Component = require('react').Component -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const actions = require('../../../actions') const genAccountLink = require('../../../../lib/account-link.js') @@ -282,7 +282,7 @@ class AccountDropdowns extends Component { dropdownWrapperStyle, ), isOpen: optionsMenuActive, - onClickOutside: () => { + onClickOutside: (event) => { const { classList } = event.target const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) if (optionsMenuActive && isNotToggleElement) { diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js index 15d064be8..0336dbb8b 100644 --- a/ui/app/components/dropdowns/components/dropdown.js +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -1,5 +1,5 @@ const Component = require('react').Component -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const MenuDroppo = require('../../menu-droppo') const extend = require('xtend') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 0e16048d5..67daaa5fd 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -85,7 +85,7 @@ NetworkDropdown.prototype.render = function () { style: { position: 'absolute', top: '58px', - minWidth: '309px', + width: '309px', zIndex: '55px', }, innerStyle: { @@ -277,11 +277,21 @@ NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) { key: `common${rpc}`, closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setRpcTarget(rpc), + style: { + fontFamily: 'DIN OT', + fontSize: '16px', + lineHeight: '20px', + padding: '12px 0', + }, }, [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - rpc, - rpcTarget === rpc ? h('.check', '✓') : null, + rpcTarget === rpc ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), + h('i.fa.fa-question-circle.fa-med.menu-icon-circle'), + h('span.network-name-item', { + style: { + color: rpcTarget === rpc ? '#ffffff' : '#9b9b9b', + }, + }, rpc), ] ) } @@ -294,12 +304,6 @@ NetworkDropdown.prototype.renderCustomOption = function (provider) { if (type !== 'rpc') return null - // Concatenate long URLs - let label = rpcTarget - if (rpcTarget.length > 31) { - label = label.substr(0, 34) + '...' - } - switch (rpcTarget) { case 'http://localhost:8545': @@ -312,11 +316,21 @@ NetworkDropdown.prototype.renderCustomOption = function (provider) { key: rpcTarget, onClick: () => props.setRpcTarget(rpcTarget), closeMenu: () => this.props.hideNetworkDropdown(), + style: { + fontFamily: 'DIN OT', + fontSize: '16px', + lineHeight: '20px', + padding: '12px 0', + }, }, [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - label, - h('.check', '✓'), + h('i.fa.fa-check'), + h('i.fa.fa-question-circle.fa-med.menu-icon-circle'), + h('span.network-name-item', { + style: { + color: '#ffffff', + }, + }, rpcTarget), ] ) } diff --git a/ui/app/components/dropdowns/simple-dropdown.js b/ui/app/components/dropdowns/simple-dropdown.js index 7bb48e57b..bba088ed1 100644 --- a/ui/app/components/dropdowns/simple-dropdown.js +++ b/ui/app/components/dropdowns/simple-dropdown.js @@ -1,5 +1,5 @@ const { Component } = require('react') -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const classnames = require('classnames') const R = require('ramda') diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js index 1be8c9731..c3d084bdc 100644 --- a/ui/app/components/eth-balance.js +++ b/ui/app/components/eth-balance.js @@ -46,7 +46,7 @@ EthBalanceComponent.prototype.renderBalance = function (value) { incoming, currentCurrency, hideTooltip, - styleOveride, + styleOveride = {}, showFiat = true, } = this.props const { fontSize, color, fontFamily, lineHeight } = styleOveride diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js index 9442121fe..cb6fa51fb 100644 --- a/ui/app/components/loading.js +++ b/ui/app/components/loading.js @@ -1,6 +1,6 @@ const { Component } = require('react') const h = require('react-hyperscript') -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') class LoadingIndicator extends Component { renderMessage () { diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js index 7172d05a5..6c593e4e5 100644 --- a/ui/app/components/modals/deposit-ether-modal.js +++ b/ui/app/components/modals/deposit-ether-modal.js @@ -33,6 +33,9 @@ function mapDispatchToProps (dispatch) { hideModal: () => { dispatch(actions.hideModal()) }, + hideWarning: () => { + dispatch(actions.hideWarning()) + }, showAccountDetailModal: () => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) }, @@ -119,6 +122,7 @@ DepositEtherModal.prototype.render = function () { h('div.deposit-ether-modal__header__close', { onClick: () => { this.setState({ buyingWithShapeshift: false }) + this.props.hideWarning() this.props.hideModal() }, }), @@ -179,6 +183,7 @@ DepositEtherModal.prototype.render = function () { } DepositEtherModal.prototype.goToAccountDetailsModal = function () { + this.props.hideWarning() this.props.hideModal() this.props.showAccountDetailModal() } diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index ea6ac5135..7d4089ab3 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -19,6 +19,7 @@ const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const CustomizeGasModal = require('../customize-gas-modal') const NotifcationModal = require('./notification-modal') +const ConfirmResetAccount = require('./notification-modals/confirm-reset-account') const accountModalStyle = { mobileModalStyle: { @@ -79,6 +80,7 @@ const MODALS = { contents: [ h(DepositEtherModal, {}, []), ], + onHide: (props) => props.hideWarning(), mobileModalStyle: { width: '100%', height: '100%', @@ -201,6 +203,18 @@ const MODALS = { }, }, + CONFIRM_RESET_ACCOUNT: { + contents: h(ConfirmResetAccount), + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '473px', + top: 'calc(33% + 45px)', + }, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), @@ -272,6 +286,10 @@ function mapDispatchToProps (dispatch) { hideModal: () => { dispatch(actions.hideModal()) }, + hideWarning: () => { + dispatch(actions.hideWarning()) + }, + } } @@ -294,7 +312,12 @@ Modal.prototype.render = function () { { className: 'modal', keyboard: false, - onHide: () => { this.onHide() }, + onHide: () => { + if (modal.onHide) { + modal.onHide(this.props) + } + this.onHide() + }, ref: (ref) => { this.modalRef = ref }, diff --git a/ui/app/components/modals/notification-modal.js b/ui/app/components/modals/notification-modal.js index 239144b0c..621a974d0 100644 --- a/ui/app/components/modals/notification-modal.js +++ b/ui/app/components/modals/notification-modal.js @@ -9,26 +9,47 @@ class NotificationModal extends Component { const { header, message, + showCancelButton = false, + showConfirmButton = false, + hideModal, + onConfirm, } = this.props + const showButtons = showCancelButton || showConfirmButton + return h('div', [ - h('div.notification-modal-wrapper', { + h('div.notification-modal__wrapper', { }, [ - h('div.notification-modal-header', {}, [ + h('div.notification-modal__header', {}, [ header, ]), - h('div.notification-modal-message-wrapper', {}, [ - h('div.notification-modal-message', {}, [ + h('div.notification-modal__message-wrapper', {}, [ + h('div.notification-modal__message', {}, [ message, ]), ]), h('div.modal-close-x', { - onClick: this.props.hideModal, + onClick: hideModal, }), + showButtons && h('div.notification-modal__buttons', [ + + showCancelButton && h('div.btn-cancel.notification-modal__buttons__btn', { + onClick: hideModal, + }, 'Cancel'), + + showConfirmButton && h('div.btn-clear.notification-modal__buttons__btn', { + onClick: () => { + onConfirm() + hideModal() + }, + }, 'Confirm'), + + ]), + ]), ]) } @@ -37,7 +58,10 @@ class NotificationModal extends Component { NotificationModal.propTypes = { hideModal: PropTypes.func, header: PropTypes.string, - message: PropTypes.string, + message: PropTypes.node, + showCancelButton: PropTypes.bool, + showConfirmButton: PropTypes.bool, + onConfirm: PropTypes.func, } const mapDispatchToProps = dispatch => { diff --git a/ui/app/components/modals/notification-modals/confirm-reset-account.js b/ui/app/components/modals/notification-modals/confirm-reset-account.js new file mode 100644 index 000000000..e1bc91b24 --- /dev/null +++ b/ui/app/components/modals/notification-modals/confirm-reset-account.js @@ -0,0 +1,46 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const { connect } = require('react-redux') +const actions = require('../../../actions') +const NotifcationModal = require('../notification-modal') + +class ConfirmResetAccount extends Component { + render () { + const { resetAccount } = this.props + + return h(NotifcationModal, { + header: 'Are you sure you want to reset account?', + message: h('div', [ + + h('span', `Resetting is for developer use only. This button wipes the current account's transaction history, + which is used to calculate the current account nonce. `), + + h('a.notification-modal__link', { + href: 'http://metamask.helpscoutdocs.com/article/36-resetting-an-account', + target: '_blank', + onClick (event) { global.platform.openWindow({ url: event.target.href }) }, + }, 'Read more.'), + + ]), + showCancelButton: true, + showConfirmButton: true, + onConfirm: resetAccount, + + }) + } +} + +ConfirmResetAccount.propTypes = { + resetAccount: PropTypes.func, +} + +const mapDispatchToProps = dispatch => { + return { + resetAccount: () => { + dispatch(actions.resetAccount()) + }, + } +} + +module.exports = connect(null, mapDispatchToProps)(ConfirmResetAccount) diff --git a/ui/app/components/notice.js b/ui/app/components/notice.js index 390639297..8b0ce1e8b 100644 --- a/ui/app/components/notice.js +++ b/ui/app/components/notice.js @@ -106,8 +106,7 @@ Notice.prototype.render = function () { h('button.primary', { disabled, onClick: () => { - this.setState({disclaimerDisabled: true}) - onConfirm() + this.setState({disclaimerDisabled: true}, () => onConfirm()) }, style: { marginTop: '18px', diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 21b9b548b..4d4732bdb 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -214,17 +214,15 @@ ConfirmSendEther.prototype.render = function () { this.inputs = [] return ( - h('div.confirm-screen-container.confirm-send-ether', { - style: { minWidth: '355px' }, - }, [ + h('div.confirm-screen-container.confirm-send-ether', [ // Main Send token Card - h('div.confirm-screen-wrapper.flex-column.flex-grow', [ - h('h3.flex-center.confirm-screen-header', [ - h('button.btn-clear.confirm-screen-back-button', { + h('div.page-container', [ + h('div.page-container__header', [ + h('button.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), - }, 'EDIT'), - h('div.confirm-screen-title', 'Confirm Transaction'), - h('div.confirm-screen-header-tip'), + }, 'Edit'), + h('div.page-container__title', 'Confirm'), + h('div.page-container__subtitle', `Please review your transaction.`), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index b1bec946a..606aca3c2 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -309,17 +309,15 @@ ConfirmSendToken.prototype.render = function () { this.inputs = [] return ( - h('div.confirm-screen-container.confirm-send-token', { - style: { minWidth: '355px' }, - }, [ + h('div.confirm-screen-container.confirm-send-token', [ // Main Send token Card - h('div.confirm-screen-wrapper.flex-column.flex-grow', [ - h('h3.flex-center.confirm-screen-header', [ - h('button.btn-clear.confirm-screen-back-button.allcaps', { + h('div.page-container', [ + h('div.page-container__header', [ + h('button.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), }, t('edit')), - h('div.confirm-screen-title', t('confirmTransaction')), - h('div.confirm-screen-header-tip'), + h('div.page-container__title', t('confirm')), + h('div.page-container__subtitle', t('pleaseReviewTransaction')), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index 104f82224..f75d6176e 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -15,11 +15,13 @@ function mapStateToProps (state) { tokenExchangeRates, selectedAddress, } = state.metamask + const { warning } = state.appState return { coinOptions, tokenExchangeRates, selectedAddress, + warning, } } @@ -52,8 +54,7 @@ ShapeshiftForm.prototype.componentWillMount = function () { this.props.shapeShiftSubview() } -ShapeshiftForm.prototype.onCoinChange = function (e) { - const coin = e.target.value +ShapeshiftForm.prototype.onCoinChange = function (coin) { this.setState({ depositCoin: coin, errorMessage: '', @@ -134,7 +135,7 @@ ShapeshiftForm.prototype.renderMarketInfo = function () { } ShapeshiftForm.prototype.renderQrCode = function () { - const { depositAddress, isLoading } = this.state + const { depositAddress, isLoading, depositCoin } = this.state const qrImage = qrcode(4, 'M') qrImage.addData(depositAddress) qrImage.make() @@ -142,7 +143,7 @@ ShapeshiftForm.prototype.renderQrCode = function () { return h('div.shapeshift-form', {}, [ h('div.shapeshift-form__deposit-instruction', [ - t('depositBTC'), + t('depositCoin', depositCoin.toUpperCase()), ]), h('div', depositAddress), @@ -165,7 +166,7 @@ ShapeshiftForm.prototype.renderQrCode = function () { ShapeshiftForm.prototype.render = function () { - const { coinOptions, btnClass } = this.props + const { coinOptions, btnClass, warning } = this.props const { depositCoin, errorMessage, showQrCode, depositAddress } = this.state const coinPair = `${depositCoin}_eth` const { tokenExchangeRates } = this.props @@ -183,7 +184,7 @@ ShapeshiftForm.prototype.render = function () { h(SimpleDropdown, { selectedOption: this.state.depositCoin, - onSelect: this.onCoinChange, + onSelect: (coin) => this.onCoinChange(coin), options: Object.entries(coinOptions).map(([coin]) => ({ value: coin.toLowerCase(), displayValue: coin, @@ -208,7 +209,9 @@ ShapeshiftForm.prototype.render = function () { ]), - h('div', { + warning && h('div.shapeshift-form__address-input-label', warning), + + !warning && h('div', { className: classnames('shapeshift-form__address-input-wrapper', { 'shapeshift-form__address-input-wrapper--error': errorMessage, }), @@ -229,7 +232,7 @@ ShapeshiftForm.prototype.render = function () { h('divshapeshift-form__address-input-error-message', [errorMessage]), ]), - this.renderMarketInfo(), + !warning && this.renderMarketInfo(), ]), diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js index 0d8681fb7..fddbc6821 100644 --- a/ui/app/components/shift-list-item.js +++ b/ui/app/components/shift-list-item.js @@ -30,40 +30,35 @@ function ShiftListItem () { } ShiftListItem.prototype.render = function () { - const { selectedAddress, receivingAddress } = this.props - return ( - selectedAddress === receivingAddress - ? h('div.tx-list-item.tx-list-clickable', { + return h('div.tx-list-item.tx-list-clickable', { + style: { + paddingTop: '20px', + paddingBottom: '20px', + justifyContent: 'space-around', + alignItems: 'center', + }, + }, [ + h('div', { + style: { + width: '0px', + position: 'relative', + bottom: '19px', + }, + }, [ + h('img', { + src: 'https://info.shapeshift.io/sites/default/files/logo.png', style: { - paddingTop: '20px', - paddingBottom: '20px', - justifyContent: 'space-around', - alignItems: 'center', + height: '35px', + width: '132px', + position: 'absolute', + clip: 'rect(0px,23px,34px,0px)', }, - }, [ - h('div', { - style: { - width: '0px', - position: 'relative', - bottom: '19px', - }, - }, [ - h('img', { - src: 'https://info.shapeshift.io/sites/default/files/logo.png', - style: { - height: '35px', - width: '132px', - position: 'absolute', - clip: 'rect(0px,23px,34px,0px)', - }, - }), - ]), + }), + ]), - this.renderInfo(), - this.renderUtilComponents(), - ]) - : null - ) + this.renderInfo(), + this.renderUtilComponents(), + ]) } function formatDate (date) { diff --git a/ui/app/components/tab-bar.js b/ui/app/components/tab-bar.js index 0edced119..a80640116 100644 --- a/ui/app/components/tab-bar.js +++ b/ui/app/components/tab-bar.js @@ -1,6 +1,6 @@ const { Component } = require('react') const h = require('react-hyperscript') -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const classnames = require('classnames') class TabBar extends Component { diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 59552f4a0..0332fde88 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -111,20 +111,24 @@ TokenCell.prototype.render = function () { network, }), - h('h.token-list-item__balance-wrapper', null, [ - h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), + h('div.token-list-item__balance-ellipsis', null, [ + h('div.token-list-item__balance-wrapper', null, [ + h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), + + showFiat && h('div.token-list-item__fiat-amount', { + style: {}, + }, formattedFiat), + ]), + + h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { + onClick: (e) => { + e.stopPropagation() + this.setState({ tokenMenuOpen: true }) + }, + }), - showFiat && h('div.token-list-item__fiat-amount', { - style: {}, - }, formattedFiat), ]), - h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { - onClick: (e) => { - e.stopPropagation() - this.setState({ tokenMenuOpen: true }) - }, - }), tokenMenuOpen && h(TokenMenuDropdown, { onClose: () => this.setState({ tokenMenuOpen: false }), diff --git a/ui/app/components/tooltip-v2.js b/ui/app/components/tooltip-v2.js new file mode 100644 index 000000000..133a0f16a --- /dev/null +++ b/ui/app/components/tooltip-v2.js @@ -0,0 +1,31 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const ReactTippy = require('react-tippy').Tooltip + +module.exports = Tooltip + +inherits(Tooltip, Component) +function Tooltip () { + Component.call(this) +} + +Tooltip.prototype.render = function () { + const props = this.props + const { position, title, children, wrapperClassName } = props + + return h('div', { + className: wrapperClassName, + }, [ + + h(ReactTippy, { + title, + position: position || 'left', + trigger: 'mouseenter', + hideOnClick: false, + size: 'small', + arrow: true, + }, children), + + ]) +} diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 6baf60141..6d6e79bd5 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -181,7 +181,7 @@ function recipientField (txParams, transaction, isTx, isMsg) { } else if (txParams.to) { message = addressSummary(txParams.to) } else { - message = t('contractPublished') + message = t('contractDeployment') } return h('div', { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 7a38096b6..849d70489 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -64,7 +64,7 @@ TxListItem.prototype.getAddressText = function () { default: return address ? `${address.slice(0, 10)}...${address.slice(-4)}` - : t('contractPublished') + : t('contractDeployment') } } diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 8343ec46b..34dc837ae 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -51,6 +51,7 @@ TxList.prototype.render = function () { TxList.prototype.renderTransaction = function () { const { txsToRender, conversionRate } = this.props + return txsToRender.length ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate, i)) : [h( @@ -66,11 +67,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa // refer to transaction-list.js:line 58 if (transaction.key === 'shapeshift') { - return h('div', { - key: `shapeshift${index}`, - }, [ - h(ShiftListItem, transaction), - ]) + return h(ShiftListItem, { ...transaction, key: `shapeshift${index}` }) } const props = { diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 6bd2d0963..18452205c 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -2,8 +2,10 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits +const classnames = require('classnames') const Identicon = require('./identicon') // const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns +const Tooltip = require('./tooltip-v2.js') const copyToClipboard = require('copy-to-clipboard') const actions = require('../actions') const BalanceComponent = require('./balance-component') @@ -46,6 +48,7 @@ function WalletView () { Component.call(this) this.state = { hasCopied: false, + copyToClipboardPressed: false, } } @@ -135,17 +138,30 @@ WalletView.prototype.render = function () { ]), ]), - - h('div.wallet-view__address', { - onClick: () => { - copyToClipboard(selectedAddress) - this.setState({ hasCopied: true }) - setTimeout(() => this.setState({ hasCopied: false }), 3000) - }, + h(Tooltip, { + position: 'bottom', + title: this.state.hasCopied ? t('copiedExclamation') : t('copyToClipboard'), + wrapperClassName: 'wallet-view__tooltip', }, [ - this.state.hasCopied && t('copiedClipboard'), - !this.state.hasCopied && `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, - h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), + h('button.wallet-view__address', { + className: classnames({ + 'wallet-view__address__pressed': this.state.copyToClipboardPressed, + }), + onClick: () => { + copyToClipboard(selectedAddress) + this.setState({ hasCopied: true }) + setTimeout(() => this.setState({ hasCopied: false }), 3000) + }, + onMouseDown: () => { + this.setState({ copyToClipboardPressed: true }) + }, + onMouseUp: () => { + this.setState({ copyToClipboardPressed: false }) + }, + }, [ + `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, + h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), + ]), ]), this.renderWalletBalance(), diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index 9f273aaec..b4ffc48b7 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -108,7 +108,6 @@ ConfirmTxScreen.prototype.render = function () { cancelPersonalMessage: this.cancelPersonalMessage.bind(this, txData), cancelTypedMessage: this.cancelTypedMessage.bind(this, txData), }) - } function currentTxView (opts) { diff --git a/ui/app/css/itcss/base/index.scss b/ui/app/css/itcss/base/index.scss index baa6ea037..1475e8bb5 100644 --- a/ui/app/css/itcss/base/index.scss +++ b/ui/app/css/itcss/base/index.scss @@ -1 +1,7 @@ // Base + +.mouse-user-styles { + button:focus { + outline: 0; + } +} diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss index e16d2e024..8ad7481c7 100644 --- a/ui/app/css/itcss/components/account-menu.scss +++ b/ui/app/css/itcss/components/account-menu.scss @@ -43,7 +43,7 @@ font-weight: 300; } - img { + &__item-icon { width: 16px; height: 16px; } diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss index 255f66e66..878495290 100644 --- a/ui/app/css/itcss/components/confirm.scss +++ b/ui/app/css/itcss/components/confirm.scss @@ -103,15 +103,13 @@ } .confirm-screen-back-button { - background: transparent; - left: 24px; + color: $curious-blue; + font-family: Roboto; + font-size: 1rem; position: absolute; - padding: 6px 12px; - font-size: .7rem; - - @media screen and (max-width: $break-small) { - margin-right: 12px; - } + top: 38px; + right: 38px; + background: none; } .confirm-screen-account-wrapper { diff --git a/ui/app/css/itcss/components/currency-display.scss b/ui/app/css/itcss/components/currency-display.scss index 9459629b6..e043c1966 100644 --- a/ui/app/css/itcss/components/currency-display.scss +++ b/ui/app/css/itcss/components/currency-display.scss @@ -4,7 +4,7 @@ border: 1px solid $alto; border-radius: 4px; background-color: $white; - color: $dusty-gray; + color: $scorpion; font-family: Roboto; font-size: 16px; font-weight: 300; @@ -52,5 +52,6 @@ &__currency-symbol { margin-top: 1px; + color: $scorpion; } }
\ No newline at end of file diff --git a/ui/app/css/itcss/components/header.scss b/ui/app/css/itcss/components/header.scss index ac2cecf7e..eeed9ee06 100644 --- a/ui/app/css/itcss/components/header.scss +++ b/ui/app/css/itcss/components/header.scss @@ -76,6 +76,20 @@ } } +.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; diff --git a/ui/app/css/itcss/components/hero-balance.scss b/ui/app/css/itcss/components/hero-balance.scss index ccc9a0118..4af0c2c55 100644 --- a/ui/app/css/itcss/components/hero-balance.scss +++ b/ui/app/css/itcss/components/hero-balance.scss @@ -71,6 +71,22 @@ font-size: 105%; } } + + @media #{$sub-mid-size-breakpoint-range} { + margin-left: .4em; + margin-right: .4em; + justify-content: flex-start; + align-items: flex-start; + + .token-amount { + font-size: 1rem; + } + + .fiat-amount { + margin-top: .25%; + font-size: 1rem; + } + } } .hero-balance-buttons { @@ -91,4 +107,12 @@ .hero-balance-button { width: 6rem; + + @media #{$sub-mid-size-breakpoint-range} { + padding: 0.4rem; + width: 4rem; + display: flex; + flex: 1; + justify-content: center; + } } diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index d1b9b6277..0219f9fb2 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -53,3 +53,5 @@ @import './editable-label.scss'; @import './new-account.scss'; + +@import './tooltip.scss'; diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 5bca4a07d..53e3bff00 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -547,38 +547,54 @@ //Notification Modal -.notification-modal-wrapper { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - position: relative; - border: 1px solid $alto; - box-shadow: 0 0 2px 2px $alto; - font-family: Roboto; -} +.notification-modal { -.notification-modal-header { - background: $wild-sand; - width: 100%; - display: flex; - justify-content: center; - padding: 30px; - font-size: 22px; - color: $nile-blue; - height: 79px; -} + &__wrapper { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + position: relative; + border: 1px solid $alto; + box-shadow: 0 0 2px 2px $alto; + font-family: Roboto; + } -.notification-modal-message { - padding: 20px; -} + &__header { + background: $wild-sand; + width: 100%; + display: flex; + justify-content: center; + padding: 30px; + font-size: 22px; + color: $nile-blue; + height: 79px; + } -.notification-modal-message { - width: 100%; - display: flex; - justify-content: center; - font-size: 17px; - color: $nile-blue; + &__message { + padding: 20px; + width: 100%; + display: flex; + justify-content: center; + font-size: 17px; + color: $nile-blue; + } + + &__buttons { + display: flex; + justify-content: space-evenly; + width: 100%; + margin-bottom: 24px; + padding: 0px 42px; + + &__btn { + cursor: pointer; + } + } + + &__link { + color: $curious-blue; + } } // Deposit Ether Modal @@ -771,6 +787,10 @@ width: auto; flex: 1; } + + @media screen and (max-width: 575px) { + width: auto; + } } } diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss index d9a39b8d5..c32d1de5e 100644 --- a/ui/app/css/itcss/components/network.scss +++ b/ui/app/css/itcss/components/network.scss @@ -76,8 +76,11 @@ .network-name-item { font-weight: 100; - flex: 1 0 auto; + flex: 1; color: $dusty-gray; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; } .network-check, diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index c5e4ea761..81f919df3 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -55,11 +55,17 @@ } .new-account-import-form { + display: flex; + flex-flow: column; + align-items: center; + padding: 0 30px; + &__select-section { display: flex; - justify-content: space-evenly; + justify-content: space-between; align-items: center; margin-top: 29px; + width: 100%; } &__select-label { @@ -91,19 +97,25 @@ } } + &__private-key-password-container { + display: flex; + flex-flow: column; + align-items: center; + width: 100%; + } + &__instruction { color: $scorpion; font-family: Roboto; font-size: 16px; line-height: 21px; align-self: flex-start; - margin-left: 30px; } &__private-key { display: flex; flex-flow: column; - align-items: center; + align-items: flex-start; margin-top: 34px; } @@ -126,6 +138,13 @@ align-items: center; margin-top: 29px; } + + &__buttons { + margin-top: 39px; + display: flex; + width: 100%; + justify-content: space-between; + } } .new-account-create-form { diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index 1c26882b5..ecf5e1036 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -1,3 +1,6 @@ +$sub-mid-size-breakpoint: 667px; +$sub-mid-size-breakpoint-range: "screen and (min-width: #{$break-large}) and (max-width: #{$sub-mid-size-breakpoint})"; + /* NewUI Container Elements */ @@ -20,6 +23,12 @@ $wallet-view-bg: $alabaster; display: none; } +//Account and transaction details +.account-and-transaction-details { + display: flex; + flex: 1 0 auto; +} + // tx view .tx-view { @@ -60,6 +69,10 @@ $wallet-view-bg: $alabaster; overflow-x: hidden; } + @media #{$sub-mid-size-breakpoint-range} { + min-width: 160px; + } + .wallet-view-account-details { flex: 0 0 auto; } @@ -89,6 +102,13 @@ $wallet-view-bg: $alabaster; flex: 0 0 auto; } + &__tooltip { + display: flex; + justify-content: center; + align-items: center; + padding: 24px; + } + &__address { border-radius: 3px; background-color: $alto; @@ -96,10 +116,13 @@ $wallet-view-bg: $alabaster; font-size: 14px; line-height: 12px; padding: 4px 12px; - margin: 24px auto; font-weight: 300; cursor: pointer; flex: 0 0 auto; + + &__pressed { + background-color: $manatee, + } } &__sidebar-close { @@ -267,3 +290,27 @@ $wallet-view-bg: $alabaster; .token-balance__amount { padding-right: 6px; } + + +// first time +.first-view-main { + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + + @media screen and (max-width: 575px) { + height: 100%; + } + + @media screen and (min-width: 576px) { + width: 85vw; + } + + @media screen and (min-width: 769px) { + width: 80vw; + } + + @media screen and (min-width: 1281px) { + width: 62vw; + } +}
\ No newline at end of file diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index 7a6e2823b..bb17e53cd 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -533,7 +533,6 @@ @media screen and (max-width: $break-small) { padding: 13px 0; margin: 0; - height: 0; overflow-y: auto; flex: 1 1 auto; } @@ -558,6 +557,25 @@ &__form-field { flex: 1 1 auto; + + .currency-display { + color: $tundora; + + &__currency-symbol { + color: $tundora; + } + + &__converted-value, + &__converted-currency { + color: $tundora; + } + } + + .account-list-item { + &__account-secondary-balance { + color: $tundora; + } + } } &__form-label { @@ -566,6 +584,7 @@ font-size: 16px; line-height: 22px; width: 88px; + font-weight: 400; } &__from-dropdown { @@ -621,7 +640,7 @@ border: 1px solid $alto; border-radius: 4px; background-color: $white; - color: $dusty-gray; + color: $tundora; padding: 10px; font-family: Roboto; font-size: 16px; diff --git a/ui/app/css/itcss/components/token-list.scss b/ui/app/css/itcss/components/token-list.scss index e24bf812b..9dc4f1055 100644 --- a/ui/app/css/itcss/components/token-list.scss +++ b/ui/app/css/itcss/components/token-list.scss @@ -15,7 +15,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( font-size: 1.5rem; @media #{$wallet-balance-breakpoint-range} { - font-size: 105%; + font-size: 95%; } } @@ -41,17 +41,22 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( &__identicon { margin-right: 15px; border: '1px solid #dedede'; + min-width: 50px; @media #{$wallet-balance-breakpoint-range} { margin-right: 4%; } } + &__balance-ellipsis { + display: flex; + align-items: center; + width: 100%; + } + &__ellipsis { - // position: absolute; - // top: 20px; - // right: 24px; line-height: 45px; + margin-left: 5px; } &__balance-wrapper { @@ -61,7 +66,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( .token-menu-dropdown { height: 55px; - width: 191px; + width: 80%; border-radius: 4px; background-color: rgba(0, 0, 0, .82); box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .5); @@ -70,6 +75,10 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( right: 25px; z-index: 2000; + @media #{$wallet-balance-breakpoint-range} { + right: 18px; + } + &__close-area { position: fixed; top: 0; @@ -81,7 +90,7 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( } &__container { - padding: 16px 34px 32px; + padding: 16px; z-index: 2200; position: relative; } diff --git a/ui/app/css/itcss/components/tooltip.scss b/ui/app/css/itcss/components/tooltip.scss new file mode 100644 index 000000000..78325865e --- /dev/null +++ b/ui/app/css/itcss/components/tooltip.scss @@ -0,0 +1,7 @@ +.metamask-tooltip { + padding: 5px !important; +} + +// needed for react-tippy +// copied from node_modules/react-tippy/dist/tippy.css +.tippy-touch{cursor:pointer!important}.tippy-notransition{transition:none!important}.tippy-popper{max-width:400px;-webkit-perspective:800px;perspective:800px;z-index:9999;outline:0;transition-timing-function:cubic-bezier(.165,.84,.44,1);pointer-events:none}.tippy-popper.html-template{max-width:96%;max-width:calc(100% - 20px)}.tippy-popper[x-placement^=top] [x-arrow]{border-top:7px solid #333;border-right:7px solid transparent;border-left:7px solid transparent;bottom:-7px;margin:0 9px}.tippy-popper[x-placement^=top] [x-arrow].arrow-small{border-top:5px solid #333;border-right:5px solid transparent;border-left:5px solid transparent;bottom:-5px}.tippy-popper[x-placement^=top] [x-arrow].arrow-big{border-top:10px solid #333;border-right:10px solid transparent;border-left:10px solid transparent;bottom:-10px}.tippy-popper[x-placement^=top] [x-circle]{-webkit-transform-origin:0 33%;transform-origin:0 33%}.tippy-popper[x-placement^=top] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-55%);transform:scale(1) translate(-50%,-55%);opacity:1}.tippy-popper[x-placement^=top] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-50%);transform:scale(.15) translate(-50%,-50%);opacity:0}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow]{border-top:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-top:5px solid #fff;border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-top:10px solid #fff;border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow]{border-top:7px solid rgba(0,0,0,.7);border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-top:5px solid rgba(0,0,0,.7);border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-top:10px solid rgba(0,0,0,.7);border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=top] [data-animation=perspective]{-webkit-transform-origin:bottom;transform-origin:bottom}.tippy-popper[x-placement^=top] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateY(-10px) rotateX(0);transform:translateY(-10px) rotateX(0)}.tippy-popper[x-placement^=top] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateY(0) rotateX(90deg);transform:translateY(0) rotateX(90deg)}.tippy-popper[x-placement^=top] [data-animation=fade].enter{opacity:1;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=fade].leave{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift].enter{opacity:1;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift].leave{opacity:0;-webkit-transform:translateY(0);transform:translateY(0)}.tippy-popper[x-placement^=top] [data-animation=scale].enter{opacity:1;-webkit-transform:translateY(-10px) scale(1);transform:translateY(-10px) scale(1)}.tippy-popper[x-placement^=top] [data-animation=scale].leave{opacity:0;-webkit-transform:translateY(0) scale(0);transform:translateY(0) scale(0)}.tippy-popper[x-placement^=bottom] [x-arrow]{border-bottom:7px solid #333;border-right:7px solid transparent;border-left:7px solid transparent;top:-7px;margin:0 9px}.tippy-popper[x-placement^=bottom] [x-arrow].arrow-small{border-bottom:5px solid #333;border-right:5px solid transparent;border-left:5px solid transparent;top:-5px}.tippy-popper[x-placement^=bottom] [x-arrow].arrow-big{border-bottom:10px solid #333;border-right:10px solid transparent;border-left:10px solid transparent;top:-10px}.tippy-popper[x-placement^=bottom] [x-circle]{-webkit-transform-origin:0 -50%;transform-origin:0 -50%}.tippy-popper[x-placement^=bottom] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-45%);transform:scale(1) translate(-50%,-45%);opacity:1}.tippy-popper[x-placement^=bottom] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-5%);transform:scale(.15) translate(-50%,-5%);opacity:0}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow]{border-bottom:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-bottom:5px solid #fff;border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-bottom:10px solid #fff;border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow]{border-bottom:7px solid rgba(0,0,0,.7);border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-bottom:5px solid rgba(0,0,0,.7);border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-bottom:10px solid rgba(0,0,0,.7);border-right:10px solid transparent;border-left:10px solid transparent}.tippy-popper[x-placement^=bottom] [data-animation=perspective]{-webkit-transform-origin:top;transform-origin:top}.tippy-popper[x-placement^=bottom] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateY(10px) rotateX(0);transform:translateY(10px) rotateX(0)}.tippy-popper[x-placement^=bottom] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateY(0) rotateX(-90deg);transform:translateY(0) rotateX(-90deg)}.tippy-popper[x-placement^=bottom] [data-animation=fade].enter{opacity:1;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=fade].leave{opacity:0;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift].enter{opacity:1;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift].leave{opacity:0;-webkit-transform:translateY(0);transform:translateY(0)}.tippy-popper[x-placement^=bottom] [data-animation=scale].enter{opacity:1;-webkit-transform:translateY(10px) scale(1);transform:translateY(10px) scale(1)}.tippy-popper[x-placement^=bottom] [data-animation=scale].leave{opacity:0;-webkit-transform:translateY(0) scale(0);transform:translateY(0) scale(0)}.tippy-popper[x-placement^=left] [x-arrow]{border-left:7px solid #333;border-top:7px solid transparent;border-bottom:7px solid transparent;right:-7px;margin:6px 0}.tippy-popper[x-placement^=left] [x-arrow].arrow-small{border-left:5px solid #333;border-top:5px solid transparent;border-bottom:5px solid transparent;right:-5px}.tippy-popper[x-placement^=left] [x-arrow].arrow-big{border-left:10px solid #333;border-top:10px solid transparent;border-bottom:10px solid transparent;right:-10px}.tippy-popper[x-placement^=left] [x-circle]{-webkit-transform-origin:50% 0;transform-origin:50% 0}.tippy-popper[x-placement^=left] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%);opacity:1}.tippy-popper[x-placement^=left] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-50%);transform:scale(.15) translate(-50%,-50%);opacity:0}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow]{border-left:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-left:5px solid #fff;border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-left:10px solid #fff;border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow]{border-left:7px solid rgba(0,0,0,.7);border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-left:5px solid rgba(0,0,0,.7);border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-left:10px solid rgba(0,0,0,.7);border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=left] [data-animation=perspective]{-webkit-transform-origin:right;transform-origin:right}.tippy-popper[x-placement^=left] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateX(-10px) rotateY(0);transform:translateX(-10px) rotateY(0)}.tippy-popper[x-placement^=left] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateX(0) rotateY(-90deg);transform:translateX(0) rotateY(-90deg)}.tippy-popper[x-placement^=left] [data-animation=fade].enter{opacity:1;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=fade].leave{opacity:0;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift].enter{opacity:1;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift].leave{opacity:0;-webkit-transform:translateX(0);transform:translateX(0)}.tippy-popper[x-placement^=left] [data-animation=scale].enter{opacity:1;-webkit-transform:translateX(-10px) scale(1);transform:translateX(-10px) scale(1)}.tippy-popper[x-placement^=left] [data-animation=scale].leave{opacity:0;-webkit-transform:translateX(0) scale(0);transform:translateX(0) scale(0)}.tippy-popper[x-placement^=right] [x-arrow]{border-right:7px solid #333;border-top:7px solid transparent;border-bottom:7px solid transparent;left:-7px;margin:6px 0}.tippy-popper[x-placement^=right] [x-arrow].arrow-small{border-right:5px solid #333;border-top:5px solid transparent;border-bottom:5px solid transparent;left:-5px}.tippy-popper[x-placement^=right] [x-arrow].arrow-big{border-right:10px solid #333;border-top:10px solid transparent;border-bottom:10px solid transparent;left:-10px}.tippy-popper[x-placement^=right] [x-circle]{-webkit-transform-origin:-50% 0;transform-origin:-50% 0}.tippy-popper[x-placement^=right] [x-circle].enter{-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%);opacity:1}.tippy-popper[x-placement^=right] [x-circle].leave{-webkit-transform:scale(.15) translate(-50%,-50%);transform:scale(.15) translate(-50%,-50%);opacity:0}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow]{border-right:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-right:5px solid #fff;border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-right:10px solid #fff;border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow]{border-right:7px solid rgba(0,0,0,.7);border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-right:5px solid rgba(0,0,0,.7);border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-right:10px solid rgba(0,0,0,.7);border-top:10px solid transparent;border-bottom:10px solid transparent}.tippy-popper[x-placement^=right] [data-animation=perspective]{-webkit-transform-origin:left;transform-origin:left}.tippy-popper[x-placement^=right] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateX(10px) rotateY(0);transform:translateX(10px) rotateY(0)}.tippy-popper[x-placement^=right] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateX(0) rotateY(90deg);transform:translateX(0) rotateY(90deg)}.tippy-popper[x-placement^=right] [data-animation=fade].enter{opacity:1;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=fade].leave{opacity:0;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift].enter{opacity:1;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift].leave{opacity:0;-webkit-transform:translateX(0);transform:translateX(0)}.tippy-popper[x-placement^=right] [data-animation=scale].enter{opacity:1;-webkit-transform:translateX(10px) scale(1);transform:translateX(10px) scale(1)}.tippy-popper[x-placement^=right] [data-animation=scale].leave{opacity:0;-webkit-transform:translateX(0) scale(0);transform:translateX(0) scale(0)}.tippy-popper .tippy-tooltip.transparent-theme{background-color:rgba(0,0,0,.7)}.tippy-popper .tippy-tooltip.transparent-theme[data-animatefill]{background-color:transparent}.tippy-popper .tippy-tooltip.light-theme{color:#26323d;box-shadow:0 4px 20px 4px rgba(0,20,60,.1),0 4px 80px -8px rgba(0,20,60,.2);background-color:#fff}.tippy-popper .tippy-tooltip.light-theme[data-animatefill]{background-color:transparent}.tippy-tooltip{position:relative;color:#fff;border-radius:4px;font-size:.95rem;padding:.4rem .8rem;text-align:center;will-change:transform;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#333}.tippy-tooltip--small{padding:.25rem .5rem;font-size:.8rem}.tippy-tooltip--big{padding:.6rem 1.2rem;font-size:1.2rem}.tippy-tooltip[data-animatefill]{overflow:hidden;background-color:transparent}.tippy-tooltip[data-interactive]{pointer-events:auto}.tippy-tooltip[data-inertia]{transition-timing-function:cubic-bezier(.53,2,.36,.85)}.tippy-tooltip [x-arrow]{position:absolute;width:0;height:0}.tippy-tooltip [x-circle]{position:absolute;will-change:transform;background-color:#333;border-radius:50%;width:130%;width:calc(110% + 2rem);left:50%;top:50%;z-index:-1;overflow:hidden;transition:all ease}.tippy-tooltip [x-circle]:before{content:"";padding-top:90%;float:left}@media (max-width:450px){.tippy-popper{max-width:96%;max-width:calc(100% - 20px)}} diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss index 91c85f073..38c3b34fb 100644 --- a/ui/app/css/itcss/generic/index.scss +++ b/ui/app/css/itcss/generic/index.scss @@ -73,3 +73,136 @@ input.large-input { .allcaps { text-transform: uppercase; } + +.page-container { + width: 400px; + background-color: $white; + box-shadow: 0 0 7px 0 rgba(0, 0, 0, .08); + z-index: 25; + display: flex; + flex-flow: column; + + &__header { + display: flex; + flex-flow: column; + border-bottom: 1px solid $geyser; + padding: 1.15rem 0.95rem; + flex: 0 0 auto; + background: $alabaster; + position: relative; + } + + &__header-close::after { + content: '\00D7'; + font-size: 40px; + color: $tundora; + position: absolute; + top: 21.5px; + right: 28.5px; + cursor: pointer; + } + + &__footer { + display: flex; + flex-flow: row; + justify-content: center; + border-top: 1px solid $geyser; + padding: 1.6rem; + flex: 0 0 auto; + + .btn-clear, + .btn-cancel { + font-size: 1rem; + } + } + + &__footer-button { + width: 165px; + height: 60px; + font-size: 1rem; + text-transform: uppercase; + margin-right: 1rem; + border-radius: 2px; + + &:last-of-type { + margin-right: 0; + } + } + + &__title { + color: $black; + font-family: Roboto; + font-size: 2rem; + font-weight: 500; + line-height: initial; + } + + &__subtitle { + padding-top: .5rem; + line-height: initial; + font-size: .9rem; + color: $gray; + } + + &__tabs { + padding: 0 1.3rem; + display: flex; + } + + &__tab { + min-width: 5rem; + padding: .2rem .8rem .9rem; + color: $dusty-gray; + font-family: Roboto; + font-size: 1.1rem; + line-height: initial; + text-align: center; + cursor: pointer; + border-bottom: none; + margin-right: 1rem; + + &:hover { + color: $black; + } + + &:last-of-type { + margin-right: 0; + } + + &--selected { + color: $curious-blue; + border-bottom: 3px solid $curious-blue; + + &:hover { + color: $curious-blue; + } + } + } +} + +@media screen and (max-width: 250px) { + .page-container { + &__footer { + flex-flow: column-reverse; + } + + &__footer-button { + width: 100%; + margin-bottom: 1rem; + margin-right: 0; + + &:first-of-type { + margin-bottom: 0; + } + } + } +} + +@media screen and (max-width: 575px) { + .page-container { + height: 100%; + width: 100%; + overflow-y: auto; + background-color: $white; + } +} diff --git a/ui/app/css/itcss/settings/typography.scss b/ui/app/css/itcss/settings/typography.scss index ac8c41336..8a56d9c6c 100644 --- a/ui/app/css/itcss/settings/typography.scss +++ b/ui/app/css/itcss/settings/typography.scss @@ -1,6 +1,340 @@ -@import url('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900'); +@import url('/fonts/Font_Awesome/font-awesome.min.css'); -@import url('https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css'); +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} @font-face { font-family: 'Montserrat Regular'; diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js index 6b50bf504..370fdd5b7 100644 --- a/ui/app/first-time/init-menu.js +++ b/ui/app/first-time/init-menu.js @@ -8,6 +8,8 @@ const actions = require('../actions') const Tooltip = require('../components/tooltip') const t = require('../../i18n') const getCaretCoordinates = require('textarea-caret') +const environmentType = require('../../../app/scripts/lib/environment-type') +const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/config').enums let isSubmitting = false @@ -131,6 +133,18 @@ InitializeMenuScreen.prototype.renderMenu = function (state) { }, t('importDen')), ]), + h('.flex-row.flex-center.flex-grow', [ + h('p.pointer', { + onClick: this.showOldUI.bind(this), + style: { + fontSize: '0.8em', + color: '#aeaeae', + textDecoration: 'underline', + marginTop: '32px', + }, + }, 'Use classic interface'), + ]), + ]) ) } @@ -147,7 +161,15 @@ InitializeMenuScreen.prototype.componentDidMount = function () { } InitializeMenuScreen.prototype.showRestoreVault = function () { - this.props.dispatch(actions.showRestoreVault()) + this.props.dispatch(actions.markPasswordForgotten()) + if (environmentType() === 'popup') { + global.platform.openExtensionInBrowser() + } +} + +InitializeMenuScreen.prototype.showOldUI = function () { + this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) + .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) } InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () { diff --git a/ui/app/keychains/hd/restore-vault.js b/ui/app/keychains/hd/restore-vault.js index 24b37a83d..a4ed137f9 100644 --- a/ui/app/keychains/hd/restore-vault.js +++ b/ui/app/keychains/hd/restore-vault.js @@ -107,6 +107,7 @@ RestoreVaultScreen.prototype.render = function () { } RestoreVaultScreen.prototype.showInitializeMenu = function () { + this.props.dispatch(actions.unMarkPasswordForgotten()) if (this.props.forgottenPassword) { this.props.dispatch(actions.backToUnlockView()) } else { @@ -149,6 +150,9 @@ RestoreVaultScreen.prototype.createNewVaultAndRestore = function () { this.warning = null this.props.dispatch(actions.displayWarning(this.warning)) this.props.dispatch(actions.createNewVaultAndRestore(password, seed)) + .then(() => { + this.props.dispatch(actions.unMarkPasswordForgotten()) + }) .catch((err) => { log.error(err.message) }) diff --git a/ui/app/main-container.js b/ui/app/main-container.js index 031f61e84..292abcc3d 100644 --- a/ui/app/main-container.js +++ b/ui/app/main-container.js @@ -2,7 +2,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const AccountAndTransactionDetails = require('./account-and-transaction-details') -const HDRestoreVaultScreen = require('./keychains/hd/restore-vault') const Settings = require('./settings') const UnlockScreen = require('./unlock') @@ -28,13 +27,6 @@ MainContainer.prototype.render = function () { if (this.props.isUnlocked === false) { switch (this.props.currentViewName) { - case 'restoreVault': - log.debug('rendering restore vault screen') - contents = { - component: HDRestoreVaultScreen, - key: 'HDRestoreVaultScreen', - } - break case 'config': log.debug('rendering config screen from unlock screen.') return h(Settings, {key: 'config'}) diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index c3ade5cdc..4dda839a2 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -59,6 +59,7 @@ function reduceApp (state, action) { // Used to display error text warning: null, buyView: {}, + isMouseUser: false, }, state.appState) switch (action.type) { @@ -139,10 +140,10 @@ function reduceApp (state, action) { case actions.FORGOT_PASSWORD: return extend(appState, { currentView: { - name: 'restoreVault', + name: action.value ? 'restoreVault' : 'accountDetail', }, transForward: false, - forgottenPassword: true, + forgottenPassword: action.value, }) case actions.SHOW_INIT_MENU: @@ -484,6 +485,11 @@ function reduceApp (state, action) { warning: action.value || 'Incorrect password. Try again.', }) + case actions.UNLOCK_SUCCEEDED: + return extend(appState, { + warning: '', + }) + case actions.SHOW_LOADING: return extend(appState, { isLoading: true, @@ -653,6 +659,12 @@ function reduceApp (state, action) { data: action.value.data, }, }) + + case actions.SET_MOUSE_USER_STATE: + return extend(appState, { + isMouseUser: action.value, + }) + default: return appState } diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 294c29948..cddcd0c1f 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -1,6 +1,7 @@ const extend = require('xtend') const actions = require('../actions') const MetamascaraPlatform = require('../../../app/scripts/platforms/window') +const environmentType = require('../../../app/scripts/lib/environment-type') const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/config').enums module.exports = reduceMetamask @@ -14,6 +15,7 @@ function reduceMetamask (state, action) { isUnlocked: false, isAccountMenuOpen: false, isMascara: window.platform instanceof MetamascaraPlatform, + isPopup: environmentType() === 'popup', rpcTarget: 'https://rawtestrpc.metamask.io/', identities: {}, unapprovedTxs: {}, @@ -41,12 +43,15 @@ function reduceMetamask (state, action) { useBlockie: false, featureFlags: {}, networkEndpointType: OLD_UI_NETWORK_TYPE, + isRevealingSeedWords: false, }, state.metamask) switch (action.type) { case actions.SHOW_ACCOUNTS_PAGE: - newState = extend(metamaskState) + newState = extend(metamaskState, { + isRevealingSeedWords: false, + }) delete newState.seedWords return newState @@ -122,10 +127,12 @@ function reduceMetamask (state, action) { }, }) + case actions.SHOW_NEW_VAULT_SEED: return extend(metamaskState, { isUnlocked: true, isInitialized: false, + isRevealingSeedWords: true, seedWords: action.value, }) diff --git a/ui/app/selectors.js b/ui/app/selectors.js index 38a96c48b..5d2635775 100644 --- a/ui/app/selectors.js +++ b/ui/app/selectors.js @@ -116,7 +116,7 @@ function transactionsSelector (state) { // console.log({txsToRender, selectedTokenAddress}) return selectedTokenAddress ? txsToRender - .filter(({ txParams: { to } }) => to === selectedTokenAddress) + .filter(({ txParams }) => txParams && txParams.to === selectedTokenAddress) .sort((a, b) => b.time - a.time) : txsToRender .sort((a, b) => b.time - a.time) @@ -179,11 +179,11 @@ function autoAddToBetaUI (state) { (numberOfAccounts > autoAddAccountsThreshold) && (numberOfTokensAdded > autoAddTokensThreshold) const userIsNotInBeta = !state.metamask.featureFlags.betaUI - + return userIsNotInBeta && userPassesThreshold } function getCurrentViewContext (state) { const { currentView = {} } = state.appState - return currentView.context + return currentView.context }
\ No newline at end of file diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 897caf16e..fc1df1f51 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -5,7 +5,6 @@ const h = require('react-hyperscript') const ethAbi = require('ethereumjs-abi') const ethUtil = require('ethereumjs-util') -const Identicon = require('./components/identicon') const FromDropdown = require('./components/send/from-dropdown') const ToAutoComplete = require('./components/send/to-autocomplete') const CurrencyDisplay = require('./components/send/currency-display') @@ -179,52 +178,22 @@ SendTransactionScreen.prototype.componentDidUpdate = function (prevProps) { } } -SendTransactionScreen.prototype.renderHeaderIcon = function () { - const { selectedToken } = this.props - - return h('div.send-v2__send-header-icon-container', [ - selectedToken - ? h(Identicon, { - diameter: 40, - address: selectedToken.address, - }) - : h('img.send-v2__send-header-icon', { src: '../images/eth_logo.svg' }), - ]) -} - -SendTransactionScreen.prototype.renderTitle = function () { - const { selectedToken } = this.props - - return h('div.send-v2__title', [selectedToken ? 'Send Tokens' : 'Send Funds']) -} - -SendTransactionScreen.prototype.renderCopy = function () { - const { selectedToken } = this.props - - const tokenText = selectedToken ? 'tokens' : 'ETH' - - return h('div.send-v2__form-header-copy', [ - - h('div.send-v2__copy', `Only send ${tokenText} to an Ethereum address.`), - - h('div.send-v2__copy', 'Sending to a different crytpocurrency that is not Ethereum may result in permanent loss.'), - - ]) -} - SendTransactionScreen.prototype.renderHeader = function () { - return h('div', [ - h('div.send-v2__header', {}, [ + const { selectedToken, clearSend, goHome } = this.props + const tokenText = selectedToken ? 'tokens' : 'ETH' - this.renderHeaderIcon(), + return h('div.page-container__header', [ - h('div.send-v2__arrow-background', [ - h('i.fa.fa-lg.fa-arrow-circle-right.send-v2__send-arrow-icon'), - ]), + h('div.page-container__title', selectedToken ? 'Send Tokens' : 'Send ETH'), - h('div.send-v2__header-tip'), + h('div.page-container__subtitle', `Only send ${tokenText} to an Ethereum address.`), - ]), + h('div.page-container__header-close', { + onClick: () => { + clearSend() + goHome() + }, + }), ]) } @@ -392,8 +361,9 @@ SendTransactionScreen.prototype.validateAmount = function (value) { }) } + const verifyTokenBalance = selectedToken && tokenBalance !== null let sufficientTokens - if (selectedToken) { + if (verifyTokenBalance) { sufficientTokens = isTokenBalanceSufficient({ tokenBalance, amount, @@ -408,7 +378,7 @@ SendTransactionScreen.prototype.validateAmount = function (value) { if (conversionRate && !sufficientBalance) { amountError = 'Insufficient funds.' - } else if (selectedToken && !sufficientTokens) { + } else if (verifyTokenBalance && !sufficientTokens) { amountError = 'Insufficient tokens.' } else if (amountLessThanZero) { amountError = 'Can not send negative amounts of ETH.' @@ -427,14 +397,15 @@ SendTransactionScreen.prototype.renderAmountRow = function () { amount, setMaxModeTo, maxModeOn, + gasTotal, } = this.props return h('div.send-v2__form-row', [ - h('div.send-v2__form-label', [ + h('div.send-v2__form-label', [ 'Amount:', this.renderErrorMessage('amount'), - !errors.amount && h('div.send-v2__amount-max', { + !errors.amount && gasTotal && h('div.send-v2__amount-max', { onClick: (event) => { event.preventDefault() setMaxModeTo(true) @@ -504,14 +475,6 @@ SendTransactionScreen.prototype.renderMemoRow = function () { SendTransactionScreen.prototype.renderForm = function () { return h('div.send-v2__form', {}, [ - h('div.sendV2__form-header', [ - - this.renderTitle(), - - this.renderCopy(), - - ]), - this.renderFromRow(), this.renderToRow(), @@ -530,20 +493,23 @@ SendTransactionScreen.prototype.renderFooter = function () { goHome, clearSend, gasTotal, + tokenBalance, + selectedToken, errors: { amount: amountError, to: toError }, } = this.props + const missingTokenBalance = selectedToken && !tokenBalance const noErrors = !amountError && toError === null - return h('div.send-v2__footer', [ - h('button.btn-cancel.send-v2__cancel-btn', { + return h('div.page-container__footer', [ + h('button.btn-cancel.page-container__footer-button', { onClick: () => { clearSend() goHome() }, }, 'Cancel'), - h('button.btn-clear.send-v2__next-btn', { - disabled: !noErrors || !gasTotal, + h('button.btn-clear.page-container__footer-button', { + disabled: !noErrors || !gasTotal || missingTokenBalance, onClick: event => this.onSubmit(event), }, 'Next'), ]) @@ -552,7 +518,7 @@ SendTransactionScreen.prototype.renderFooter = function () { SendTransactionScreen.prototype.render = function () { return ( - h('div.send-v2__container', [ + h('div.page-container', [ this.renderHeader(), diff --git a/ui/app/settings.js b/ui/app/settings.js index 4e25ce084..466f739d5 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -201,7 +201,13 @@ class Settings extends Component { h('div.settings__content-item-col', [ h('button.settings__clear-button', { onClick (event) { - exportAsFile('MetaMask State Logs', window.logState()) + window.logStateString((err, result) => { + if (err) { + this.state.dispatch(actions.displayWarning('Error in retrieving state logs.')) + } else { + exportAsFile('MetaMask State Logs.json', result) + } + }) }, }, 'Download State Logs'), ]), @@ -250,6 +256,24 @@ class Settings extends Component { ) } + renderResetAccount () { + const { showResetAccountConfirmationModal } = this.props + + return h('div.settings__content-row', [ + h('div.settings__content-item', 'Reset Account'), + h('div.settings__content-item', [ + h('div.settings__content-item-col', [ + h('button.settings__clear-button.settings__clear-button--orange', { + onClick (event) { + event.preventDefault() + showResetAccountConfirmationModal() + }, + }, 'Reset Account'), + ]), + ]), + ]) + } + renderSettingsContent () { const { warning, isMascara } = this.props @@ -262,6 +286,7 @@ class Settings extends Component { this.renderStateLogs(), this.renderSeedWords(), !isMascara && this.renderOldUI(), + this.renderResetAccount(), this.renderBlockieOptIn(), ]) ) @@ -342,7 +367,7 @@ class Settings extends Component { this.renderLogo(), h('div.settings__info-item', [ h('div.settings__info-version-header', 'MetaMask Version'), - h('div.settings__info-version-number', version), + h('div.settings__info-version-number', `${version}`), ]), h('div.settings__info-item', [ h( @@ -387,6 +412,7 @@ Settings.propTypes = { displayWarning: PropTypes.func, revealSeedConfirmation: PropTypes.func, setFeatureFlagToBeta: PropTypes.func, + showResetAccountConfirmationModal: PropTypes.func, warning: PropTypes.string, goHome: PropTypes.func, isMascara: PropTypes.bool, @@ -412,6 +438,9 @@ const mapDispatchToProps = dispatch => { return dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) .then(() => dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) }, + showResetAccountConfirmationModal: () => { + return dispatch(actions.showModal({ name: 'CONFIRM_RESET_ACCOUNT' })) + }, } } diff --git a/ui/app/unlock.js b/ui/app/unlock.js index 7a48c5f09..5e44b51ef 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -6,6 +6,8 @@ const actions = require('./actions') const getCaretCoordinates = require('textarea-caret') const EventEmitter = require('events').EventEmitter const t = require('../i18n') +const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/config').enums +const environmentType = require('../../app/scripts/lib/environment-type') const Mascot = require('./components/mascot') @@ -75,7 +77,12 @@ UnlockScreen.prototype.render = function () { h('.flex-row.flex-center.flex-grow', [ h('p.pointer', { - onClick: () => this.props.dispatch(actions.forgotPassword()), + onClick: () => { + this.props.dispatch(actions.markPasswordForgotten()) + if (environmentType() === 'popup') { + global.platform.openExtensionInBrowser() + } + }, style: { fontSize: '0.8em', color: 'rgb(247, 134, 28)', @@ -83,6 +90,22 @@ UnlockScreen.prototype.render = function () { }, }, 'Restore from seed phrase'), ]), + + h('.flex-row.flex-center.flex-grow', [ + 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', + }, + }, 'Use classic interface'), + ]), + ]) ) } diff --git a/ui/index.js b/ui/index.js index bc3676c1f..fdb2f23e0 100644 --- a/ui/index.js +++ b/ui/index.js @@ -25,6 +25,7 @@ function launchMetamaskUi (opts, cb) { function startApp (metamaskState, accountManager, opts) { // parse opts + if (!metamaskState.featureFlags) metamaskState.featureFlags = {} const store = configureStore({ // metamaskState represents the cross-tab state |