Merge pull request #5241 from MetaMask/refactor-settings
Refactor settings page to use JSX and follow component file folder st…feature/default_network_editable
commit
04988eca5e
@ -1,64 +1 @@ |
|||||||
const { Component } = require('react') |
export { default } from './settings.component' |
||||||
const { Switch, Route, matchPath } = require('react-router-dom') |
|
||||||
const PropTypes = require('prop-types') |
|
||||||
const h = require('react-hyperscript') |
|
||||||
const TabBar = require('../../tab-bar') |
|
||||||
const Settings = require('./settings') |
|
||||||
const Info = require('./info') |
|
||||||
const { DEFAULT_ROUTE, SETTINGS_ROUTE, INFO_ROUTE } = require('../../../routes') |
|
||||||
|
|
||||||
class Config extends Component { |
|
||||||
renderTabs () { |
|
||||||
const { history, location } = this.props |
|
||||||
|
|
||||||
return h('div.settings__tabs', [ |
|
||||||
h(TabBar, { |
|
||||||
tabs: [ |
|
||||||
{ content: this.context.t('settings'), key: SETTINGS_ROUTE }, |
|
||||||
{ content: this.context.t('info'), key: INFO_ROUTE }, |
|
||||||
], |
|
||||||
isActive: key => matchPath(location.pathname, { path: key, exact: true }), |
|
||||||
onSelect: key => history.push(key), |
|
||||||
}), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
render () { |
|
||||||
const { history } = this.props |
|
||||||
|
|
||||||
return ( |
|
||||||
h('.main-container.settings', {}, [ |
|
||||||
h('.settings__header', [ |
|
||||||
h('div.settings__close-button', { |
|
||||||
onClick: () => history.push(DEFAULT_ROUTE), |
|
||||||
}), |
|
||||||
this.renderTabs(), |
|
||||||
]), |
|
||||||
h(Switch, [ |
|
||||||
h(Route, { |
|
||||||
exact: true, |
|
||||||
path: INFO_ROUTE, |
|
||||||
component: Info, |
|
||||||
}), |
|
||||||
h(Route, { |
|
||||||
exact: true, |
|
||||||
path: SETTINGS_ROUTE, |
|
||||||
component: Settings, |
|
||||||
}), |
|
||||||
]), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Config.propTypes = { |
|
||||||
location: PropTypes.object, |
|
||||||
history: PropTypes.object, |
|
||||||
t: PropTypes.func, |
|
||||||
} |
|
||||||
|
|
||||||
Config.contextTypes = { |
|
||||||
t: PropTypes.func, |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = Config |
|
||||||
|
@ -0,0 +1,80 @@ |
|||||||
|
@import './info-tab/index'; |
||||||
|
|
||||||
|
@import './settings-tab/index'; |
||||||
|
|
||||||
|
.settings-page { |
||||||
|
position: relative; |
||||||
|
background: $white; |
||||||
|
display: flex; |
||||||
|
flex-flow: column nowrap; |
||||||
|
|
||||||
|
&__header { |
||||||
|
padding: 25px 25px 0; |
||||||
|
} |
||||||
|
|
||||||
|
&__close-button::after { |
||||||
|
content: '\00D7'; |
||||||
|
font-size: 40px; |
||||||
|
color: $dusty-gray; |
||||||
|
position: absolute; |
||||||
|
top: 25px; |
||||||
|
right: 30px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
&__content { |
||||||
|
padding: 25px; |
||||||
|
height: auto; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
|
||||||
|
&__content-row { |
||||||
|
display: flex; |
||||||
|
flex-direction: row; |
||||||
|
padding: 10px 0 20px; |
||||||
|
|
||||||
|
@media screen and (max-width: 575px) { |
||||||
|
flex-direction: column; |
||||||
|
padding: 10px 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&__content-item { |
||||||
|
flex: 1; |
||||||
|
min-width: 0; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
padding: 0 5px; |
||||||
|
min-height: 71px; |
||||||
|
|
||||||
|
@media screen and (max-width: 575px) { |
||||||
|
height: initial; |
||||||
|
padding: 5px 0; |
||||||
|
} |
||||||
|
|
||||||
|
&--without-height { |
||||||
|
height: initial; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&__content-label { |
||||||
|
text-transform: capitalize; |
||||||
|
} |
||||||
|
|
||||||
|
&__content-description { |
||||||
|
font-size: 14px; |
||||||
|
color: $dusty-gray; |
||||||
|
padding-top: 5px; |
||||||
|
} |
||||||
|
|
||||||
|
&__content-item-col { |
||||||
|
max-width: 300px; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
|
||||||
|
@media screen and (max-width: 575px) { |
||||||
|
max-width: 100%; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
export { default } from './info-tab.component' |
@ -0,0 +1,56 @@ |
|||||||
|
.info-tab { |
||||||
|
&__logo-wrapper { |
||||||
|
height: 80px; |
||||||
|
margin-bottom: 20px; |
||||||
|
} |
||||||
|
|
||||||
|
&__logo { |
||||||
|
max-height: 100%; |
||||||
|
max-width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
&__item { |
||||||
|
padding: 10px 0; |
||||||
|
} |
||||||
|
|
||||||
|
&__link-header { |
||||||
|
padding-bottom: 15px; |
||||||
|
|
||||||
|
@media screen and (max-width: 575px) { |
||||||
|
padding-bottom: 5px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&__link-item { |
||||||
|
padding: 15px 0; |
||||||
|
|
||||||
|
@media screen and (max-width: 575px) { |
||||||
|
padding: 5px 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&__link-text { |
||||||
|
color: $curious-blue; |
||||||
|
} |
||||||
|
|
||||||
|
&__version-number { |
||||||
|
padding-top: 5px; |
||||||
|
font-size: 13px; |
||||||
|
color: $dusty-gray; |
||||||
|
} |
||||||
|
|
||||||
|
&__separator { |
||||||
|
margin: 15px 0; |
||||||
|
width: 80px; |
||||||
|
border-color: $alto; |
||||||
|
border: none; |
||||||
|
height: 1px; |
||||||
|
background-color: $alto; |
||||||
|
color: $alto; |
||||||
|
} |
||||||
|
|
||||||
|
&__about { |
||||||
|
color: $dusty-gray; |
||||||
|
margin-bottom: 15px; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
import React, { PureComponent } from 'react' |
||||||
|
import PropTypes from 'prop-types' |
||||||
|
|
||||||
|
export default class InfoTab extends PureComponent { |
||||||
|
state = { |
||||||
|
version: global.platform.getVersion(), |
||||||
|
} |
||||||
|
|
||||||
|
static propTypes = { |
||||||
|
tab: PropTypes.string, |
||||||
|
metamask: PropTypes.object, |
||||||
|
setCurrentCurrency: PropTypes.func, |
||||||
|
setRpcTarget: PropTypes.func, |
||||||
|
displayWarning: PropTypes.func, |
||||||
|
revealSeedConfirmation: PropTypes.func, |
||||||
|
warning: PropTypes.string, |
||||||
|
location: PropTypes.object, |
||||||
|
history: PropTypes.object, |
||||||
|
} |
||||||
|
|
||||||
|
static contextTypes = { |
||||||
|
t: PropTypes.func, |
||||||
|
} |
||||||
|
|
||||||
|
renderInfoLinks () { |
||||||
|
const { t } = this.context |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-item settings-page__content-item--without-height"> |
||||||
|
<div className="info-tab__link-header"> |
||||||
|
{ t('links') } |
||||||
|
</div> |
||||||
|
<div className="info-tab__link-item"> |
||||||
|
<a |
||||||
|
href="https://metamask.io/privacy.html" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<span className="info-tab__link-text"> |
||||||
|
{ t('privacyMsg') } |
||||||
|
</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<div className="info-tab__link-item"> |
||||||
|
<a |
||||||
|
href="https://metamask.io/terms.html" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<span className="info-tab__link-text"> |
||||||
|
{ t('terms') } |
||||||
|
</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<div className="info-tab__link-item"> |
||||||
|
<a |
||||||
|
href="https://metamask.io/attributions.html" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<span className="info-tab__link-text"> |
||||||
|
{ t('attributions') } |
||||||
|
</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<hr className="info-tab__separator" /> |
||||||
|
<div className="info-tab__link-item"> |
||||||
|
<a |
||||||
|
href="https://support.metamask.io" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<span className="info-tab__link-text"> |
||||||
|
{ t('supportCenter') } |
||||||
|
</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<div className="info-tab__link-item"> |
||||||
|
<a |
||||||
|
href="https://metamask.io/" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<span className="info-tab__link-text"> |
||||||
|
{ t('visitWebSite') } |
||||||
|
</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<div className="info-tab__link-item"> |
||||||
|
<a |
||||||
|
href="mailto:help@metamask.io?subject=Feedback" |
||||||
|
target="_blank" |
||||||
|
rel="noopener noreferrer" |
||||||
|
> |
||||||
|
<span className="info-tab__link-text"> |
||||||
|
{ t('emailUs') } |
||||||
|
</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
render () { |
||||||
|
const { t } = this.context |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content"> |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item settings-page__content-item--without-height"> |
||||||
|
<div className="info-tab__logo-wrapper"> |
||||||
|
<img |
||||||
|
src="images/info-logo.png" |
||||||
|
className="info-tab__logo" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
<div className="info-tab__item"> |
||||||
|
<div className="info-tab__version-header"> |
||||||
|
{ t('metamaskVersion') } |
||||||
|
</div> |
||||||
|
<div className="info-tab__version-number"> |
||||||
|
{ this.state.version } |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="info-tab__item"> |
||||||
|
<div className="info-tab__about"> |
||||||
|
{ t('builtInCalifornia') } |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{ this.renderInfoLinks() } |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -1,120 +0,0 @@ |
|||||||
const { Component } = require('react') |
|
||||||
const PropTypes = require('prop-types') |
|
||||||
const h = require('react-hyperscript') |
|
||||||
|
|
||||||
class Info extends Component { |
|
||||||
constructor (props) { |
|
||||||
super(props) |
|
||||||
|
|
||||||
this.state = { |
|
||||||
version: global.platform.getVersion(), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
renderLogo () { |
|
||||||
return ( |
|
||||||
h('div.settings__info-logo-wrapper', [ |
|
||||||
h('img.settings__info-logo', { src: 'images/info-logo.png' }), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
renderInfoLinks () { |
|
||||||
return ( |
|
||||||
h('div.settings__content-item.settings__content-item--without-height', [ |
|
||||||
h('div.settings__info-link-header', this.context.t('links')), |
|
||||||
h('div.settings__info-link-item', [ |
|
||||||
h('a', { |
|
||||||
href: 'https://metamask.io/privacy.html', |
|
||||||
target: '_blank', |
|
||||||
}, [ |
|
||||||
h('span.settings__info-link', this.context.t('privacyMsg')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
h('div.settings__info-link-item', [ |
|
||||||
h('a', { |
|
||||||
href: 'https://metamask.io/terms.html', |
|
||||||
target: '_blank', |
|
||||||
}, [ |
|
||||||
h('span.settings__info-link', this.context.t('terms')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
h('div.settings__info-link-item', [ |
|
||||||
h('a', { |
|
||||||
href: 'https://metamask.io/attributions.html', |
|
||||||
target: '_blank', |
|
||||||
}, [ |
|
||||||
h('span.settings__info-link', this.context.t('attributions')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
h('hr.settings__info-separator'), |
|
||||||
h('div.settings__info-link-item', [ |
|
||||||
h('a', { |
|
||||||
href: 'https://support.metamask.io', |
|
||||||
target: '_blank', |
|
||||||
}, [ |
|
||||||
h('span.settings__info-link', this.context.t('supportCenter')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
h('div.settings__info-link-item', [ |
|
||||||
h('a', { |
|
||||||
href: 'https://metamask.io/', |
|
||||||
target: '_blank', |
|
||||||
}, [ |
|
||||||
h('span.settings__info-link', this.context.t('visitWebSite')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
h('div.settings__info-link-item', [ |
|
||||||
h('a', { |
|
||||||
target: '_blank', |
|
||||||
href: 'mailto:help@metamask.io?subject=Feedback', |
|
||||||
}, [ |
|
||||||
h('span.settings__info-link', this.context.t('emailUs')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
render () { |
|
||||||
return ( |
|
||||||
h('div.settings__content', [ |
|
||||||
h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item.settings__content-item--without-height', [ |
|
||||||
this.renderLogo(), |
|
||||||
h('div.settings__info-item', [ |
|
||||||
h('div.settings__info-version-header', 'MetaMask Version'), |
|
||||||
h('div.settings__info-version-number', this.state.version), |
|
||||||
]), |
|
||||||
h('div.settings__info-item', [ |
|
||||||
h( |
|
||||||
'div.settings__info-about', |
|
||||||
this.context.t('builtInCalifornia') |
|
||||||
), |
|
||||||
]), |
|
||||||
]), |
|
||||||
this.renderInfoLinks(), |
|
||||||
]), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Info.propTypes = { |
|
||||||
tab: PropTypes.string, |
|
||||||
metamask: PropTypes.object, |
|
||||||
setCurrentCurrency: PropTypes.func, |
|
||||||
setRpcTarget: PropTypes.func, |
|
||||||
displayWarning: PropTypes.func, |
|
||||||
revealSeedConfirmation: PropTypes.func, |
|
||||||
warning: PropTypes.string, |
|
||||||
location: PropTypes.object, |
|
||||||
history: PropTypes.object, |
|
||||||
t: PropTypes.func, |
|
||||||
} |
|
||||||
|
|
||||||
Info.contextTypes = { |
|
||||||
t: PropTypes.func, |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = Info |
|
@ -0,0 +1 @@ |
|||||||
|
export { default } from './settings-tab.container' |
@ -0,0 +1,51 @@ |
|||||||
|
.settings-tab { |
||||||
|
&__error { |
||||||
|
padding-bottom: 20px; |
||||||
|
text-align: center; |
||||||
|
color: $crimson; |
||||||
|
} |
||||||
|
|
||||||
|
&__rpc-save-button { |
||||||
|
align-self: flex-end; |
||||||
|
padding: 5px; |
||||||
|
text-transform: uppercase; |
||||||
|
color: $dusty-gray; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
&__rpc-save-button { |
||||||
|
align-self: flex-end; |
||||||
|
padding: 5px; |
||||||
|
text-transform: uppercase; |
||||||
|
color: $dusty-gray; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
&__button--red { |
||||||
|
border-color: lighten($monzo, 10%); |
||||||
|
color: $monzo; |
||||||
|
|
||||||
|
&:active { |
||||||
|
background: lighten($monzo, 55%); |
||||||
|
border-color: $monzo; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover { |
||||||
|
border-color: $monzo; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&__button--orange { |
||||||
|
border-color: lighten($ecstasy, 20%); |
||||||
|
color: $ecstasy; |
||||||
|
|
||||||
|
&:active { |
||||||
|
background: lighten($ecstasy, 40%); |
||||||
|
border-color: $ecstasy; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover { |
||||||
|
border-color: $ecstasy; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,359 @@ |
|||||||
|
import React, { PureComponent } from 'react' |
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import infuraCurrencies from '../../../../infura-conversion.json' |
||||||
|
import validUrl from 'valid-url' |
||||||
|
import { exportAsFile } from '../../../../util' |
||||||
|
import SimpleDropdown from '../../../dropdowns/simple-dropdown' |
||||||
|
import ToggleButton from 'react-toggle-button' |
||||||
|
import { REVEAL_SEED_ROUTE } from '../../../../routes' |
||||||
|
import locales from '../../../../../../app/_locales/index.json' |
||||||
|
import TextField from '../../../text-field' |
||||||
|
import Button from '../../../button' |
||||||
|
|
||||||
|
const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { |
||||||
|
return a.quote.name.toLocaleLowerCase().localeCompare(b.quote.name.toLocaleLowerCase()) |
||||||
|
}) |
||||||
|
|
||||||
|
const infuraCurrencyOptions = sortedCurrencies.map(({ quote: { code, name } }) => { |
||||||
|
return { |
||||||
|
displayValue: `${code.toUpperCase()} - ${name}`, |
||||||
|
key: code, |
||||||
|
value: code, |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
const localeOptions = locales.map(locale => { |
||||||
|
return { |
||||||
|
displayValue: `${locale.name}`, |
||||||
|
key: locale.code, |
||||||
|
value: locale.code, |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export default class SettingsTab extends PureComponent { |
||||||
|
static contextTypes = { |
||||||
|
t: PropTypes.func, |
||||||
|
} |
||||||
|
|
||||||
|
static propTypes = { |
||||||
|
metamask: PropTypes.object, |
||||||
|
setUseBlockie: PropTypes.func, |
||||||
|
setHexDataFeatureFlag: PropTypes.func, |
||||||
|
setCurrentCurrency: PropTypes.func, |
||||||
|
setRpcTarget: PropTypes.func, |
||||||
|
displayWarning: PropTypes.func, |
||||||
|
revealSeedConfirmation: PropTypes.func, |
||||||
|
setFeatureFlagToBeta: PropTypes.func, |
||||||
|
showResetAccountConfirmationModal: PropTypes.func, |
||||||
|
warning: PropTypes.string, |
||||||
|
history: PropTypes.object, |
||||||
|
isMascara: PropTypes.bool, |
||||||
|
updateCurrentLocale: PropTypes.func, |
||||||
|
currentLocale: PropTypes.string, |
||||||
|
useBlockie: PropTypes.bool, |
||||||
|
sendHexData: PropTypes.bool, |
||||||
|
currentCurrency: PropTypes.string, |
||||||
|
conversionDate: PropTypes.number, |
||||||
|
} |
||||||
|
|
||||||
|
state = { |
||||||
|
newRpc: '', |
||||||
|
} |
||||||
|
|
||||||
|
renderCurrentConversion () { |
||||||
|
const { t } = this.context |
||||||
|
const { currentCurrency, conversionDate, setCurrentCurrency } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ t('currentConversion') }</span> |
||||||
|
<span className="settings-page__content-description"> |
||||||
|
{ t('updatedWithDate', [Date(conversionDate)]) } |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<SimpleDropdown |
||||||
|
placeholder={t('selectCurrency')} |
||||||
|
options={infuraCurrencyOptions} |
||||||
|
selectedOption={currentCurrency} |
||||||
|
onSelect={newCurrency => setCurrentCurrency(newCurrency)} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
renderCurrentLocale () { |
||||||
|
const { t } = this.context |
||||||
|
const { updateCurrentLocale, currentLocale } = this.props |
||||||
|
const currentLocaleMeta = locales.find(locale => locale.code === currentLocale) |
||||||
|
const currentLocaleName = currentLocaleMeta ? currentLocaleMeta.name : '' |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span className="settings-page__content-label"> |
||||||
|
{ t('currentLanguage') } |
||||||
|
</span> |
||||||
|
<span className="settings-page__content-description"> |
||||||
|
{ currentLocaleName } |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<SimpleDropdown |
||||||
|
placeholder={t('selectLocale')} |
||||||
|
options={localeOptions} |
||||||
|
selectedOption={currentLocale} |
||||||
|
onSelect={async newLocale => updateCurrentLocale(newLocale)} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
renderNewRpcUrl () { |
||||||
|
const { t } = this.context |
||||||
|
const { newRpc } = this.state |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ t('newRPC') }</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<TextField |
||||||
|
type="text" |
||||||
|
id="new-rpc" |
||||||
|
placeholder={t('newRPC')} |
||||||
|
value={newRpc} |
||||||
|
onChange={e => this.setState({ newRpc: e.target.value })} |
||||||
|
onKeyPress={e => { |
||||||
|
if (e.key === 'Enter') { |
||||||
|
this.validateRpc(newRpc) |
||||||
|
} |
||||||
|
}} |
||||||
|
fullWidth |
||||||
|
margin="none" |
||||||
|
/> |
||||||
|
<div |
||||||
|
className="settings-tab__rpc-save-button" |
||||||
|
onClick={e => { |
||||||
|
e.preventDefault() |
||||||
|
this.validateRpc(newRpc) |
||||||
|
}} |
||||||
|
> |
||||||
|
{ t('save') } |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
validateRpc (newRpc) { |
||||||
|
const { setRpcTarget, displayWarning } = this.props |
||||||
|
|
||||||
|
if (validUrl.isWebUri(newRpc)) { |
||||||
|
setRpcTarget(newRpc) |
||||||
|
} else { |
||||||
|
const appendedRpc = `http://${newRpc}` |
||||||
|
|
||||||
|
if (validUrl.isWebUri(appendedRpc)) { |
||||||
|
displayWarning(this.context.t('uriErrorMsg')) |
||||||
|
} else { |
||||||
|
displayWarning(this.context.t('invalidRPC')) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
renderStateLogs () { |
||||||
|
const { t } = this.context |
||||||
|
const { displayWarning } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ t('stateLogs') }</span> |
||||||
|
<span className="settings-page__content-description"> |
||||||
|
{ t('stateLogsDescription') } |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<Button |
||||||
|
type="primary" |
||||||
|
large |
||||||
|
onClick={() => { |
||||||
|
window.logStateString((err, result) => { |
||||||
|
if (err) { |
||||||
|
displayWarning(t('stateLogError')) |
||||||
|
} else { |
||||||
|
exportAsFile('MetaMask State Logs.json', result) |
||||||
|
} |
||||||
|
}) |
||||||
|
}} |
||||||
|
> |
||||||
|
{ t('downloadStateLogs') } |
||||||
|
</Button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
renderSeedWords () { |
||||||
|
const { t } = this.context |
||||||
|
const { history } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ t('revealSeedWords') }</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<Button |
||||||
|
type="secondary" |
||||||
|
large |
||||||
|
onClick={event => { |
||||||
|
event.preventDefault() |
||||||
|
history.push(REVEAL_SEED_ROUTE) |
||||||
|
}} |
||||||
|
> |
||||||
|
{ t('revealSeedWords') } |
||||||
|
</Button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
renderOldUI () { |
||||||
|
const { t } = this.context |
||||||
|
const { setFeatureFlagToBeta } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ t('useOldUI') }</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<Button |
||||||
|
type="secondary" |
||||||
|
large |
||||||
|
className="settings-tab__button--orange" |
||||||
|
onClick={event => { |
||||||
|
event.preventDefault() |
||||||
|
setFeatureFlagToBeta() |
||||||
|
}} |
||||||
|
> |
||||||
|
{ t('useOldUI') } |
||||||
|
</Button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
renderResetAccount () { |
||||||
|
const { t } = this.context |
||||||
|
const { showResetAccountConfirmationModal } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ t('resetAccount') }</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<Button |
||||||
|
type="secondary" |
||||||
|
large |
||||||
|
className="settings-tab__button--orange" |
||||||
|
onClick={event => { |
||||||
|
event.preventDefault() |
||||||
|
showResetAccountConfirmationModal() |
||||||
|
}} |
||||||
|
> |
||||||
|
{ t('resetAccount') } |
||||||
|
</Button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
renderBlockieOptIn () { |
||||||
|
const { useBlockie, setUseBlockie } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ this.context.t('blockiesIdenticon') }</span> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<ToggleButton |
||||||
|
value={useBlockie} |
||||||
|
onToggle={value => setUseBlockie(!value)} |
||||||
|
activeLabel="" |
||||||
|
inactiveLabel="" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
renderHexDataOptIn () { |
||||||
|
const { t } = this.context |
||||||
|
const { sendHexData, setHexDataFeatureFlag } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content-row"> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<span>{ t('showHexData') }</span> |
||||||
|
<div className="settings-page__content-description"> |
||||||
|
{ t('showHexDataDescription') } |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="settings-page__content-item"> |
||||||
|
<div className="settings-page__content-item-col"> |
||||||
|
<ToggleButton |
||||||
|
value={sendHexData} |
||||||
|
onToggle={value => setHexDataFeatureFlag(!value)} |
||||||
|
activeLabel="" |
||||||
|
inactiveLabel="" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
render () { |
||||||
|
const { warning, isMascara } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="settings-page__content"> |
||||||
|
{ warning && <div className="settings-tab__error">{ warning }</div> } |
||||||
|
{ this.renderCurrentConversion() } |
||||||
|
{ this.renderCurrentLocale() } |
||||||
|
{ this.renderNewRpcUrl() } |
||||||
|
{ this.renderStateLogs() } |
||||||
|
{ this.renderSeedWords() } |
||||||
|
{ !isMascara && this.renderOldUI() } |
||||||
|
{ this.renderResetAccount() } |
||||||
|
{ this.renderBlockieOptIn() } |
||||||
|
{ this.renderHexDataOptIn() } |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
import SettingsTab from './settings-tab.component' |
||||||
|
import { compose } from 'recompose' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
import { withRouter } from 'react-router-dom' |
||||||
|
import { |
||||||
|
setCurrentCurrency, |
||||||
|
setRpcTarget, |
||||||
|
displayWarning, |
||||||
|
revealSeedConfirmation, |
||||||
|
setUseBlockie, |
||||||
|
updateCurrentLocale, |
||||||
|
setFeatureFlag, |
||||||
|
showModal, |
||||||
|
} from '../../../../actions' |
||||||
|
|
||||||
|
const mapStateToProps = state => { |
||||||
|
const { appState: { warning }, metamask } = state |
||||||
|
const { |
||||||
|
currentCurrency, |
||||||
|
conversionDate, |
||||||
|
useBlockie, |
||||||
|
featureFlags: { sendHexData } = {}, |
||||||
|
provider = {}, |
||||||
|
isMascara, |
||||||
|
currentLocale, |
||||||
|
} = metamask |
||||||
|
|
||||||
|
return { |
||||||
|
warning, |
||||||
|
isMascara, |
||||||
|
currentLocale, |
||||||
|
currentCurrency, |
||||||
|
conversionDate, |
||||||
|
useBlockie, |
||||||
|
sendHexData, |
||||||
|
provider, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => { |
||||||
|
return { |
||||||
|
setCurrentCurrency: currency => dispatch(setCurrentCurrency(currency)), |
||||||
|
setRpcTarget: newRpc => dispatch(setRpcTarget(newRpc)), |
||||||
|
displayWarning: warning => dispatch(displayWarning(warning)), |
||||||
|
revealSeedConfirmation: () => dispatch(revealSeedConfirmation()), |
||||||
|
setUseBlockie: value => dispatch(setUseBlockie(value)), |
||||||
|
updateCurrentLocale: key => dispatch(updateCurrentLocale(key)), |
||||||
|
setFeatureFlagToBeta: () => { |
||||||
|
return dispatch(setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) |
||||||
|
}, |
||||||
|
setHexDataFeatureFlag: shouldShow => dispatch(setFeatureFlag('sendHexData', shouldShow)), |
||||||
|
showResetAccountConfirmationModal: () => dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default compose( |
||||||
|
withRouter, |
||||||
|
connect(mapStateToProps, mapDispatchToProps) |
||||||
|
)(SettingsTab) |
@ -0,0 +1,54 @@ |
|||||||
|
import React, { PureComponent } from 'react' |
||||||
|
import PropTypes from 'prop-types' |
||||||
|
import { Switch, Route, matchPath } from 'react-router-dom' |
||||||
|
import TabBar from '../../tab-bar' |
||||||
|
import SettingsTab from './settings-tab' |
||||||
|
import InfoTab from './info-tab' |
||||||
|
import { DEFAULT_ROUTE, SETTINGS_ROUTE, INFO_ROUTE } from '../../../routes' |
||||||
|
|
||||||
|
export default class SettingsPage extends PureComponent { |
||||||
|
static propTypes = { |
||||||
|
location: PropTypes.object, |
||||||
|
history: PropTypes.object, |
||||||
|
t: PropTypes.func, |
||||||
|
} |
||||||
|
|
||||||
|
static contextTypes = { |
||||||
|
t: PropTypes.func, |
||||||
|
} |
||||||
|
|
||||||
|
render () { |
||||||
|
const { history, location } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="main-container settings-page"> |
||||||
|
<div className="settings-page__header"> |
||||||
|
<div |
||||||
|
className="settings-page__close-button" |
||||||
|
onClick={() => history.push(DEFAULT_ROUTE)} |
||||||
|
/> |
||||||
|
<TabBar |
||||||
|
tabs={[ |
||||||
|
{ content: this.context.t('settings'), key: SETTINGS_ROUTE }, |
||||||
|
{ content: this.context.t('info'), key: INFO_ROUTE }, |
||||||
|
]} |
||||||
|
isActive={key => matchPath(location.pathname, { path: key, exact: true })} |
||||||
|
onSelect={key => history.push(key)} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
<Switch> |
||||||
|
<Route |
||||||
|
exact |
||||||
|
path={INFO_ROUTE} |
||||||
|
component={InfoTab} |
||||||
|
/> |
||||||
|
<Route |
||||||
|
exact |
||||||
|
path={SETTINGS_ROUTE} |
||||||
|
component={SettingsTab} |
||||||
|
/> |
||||||
|
</Switch> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -1,408 +0,0 @@ |
|||||||
const { Component } = require('react') |
|
||||||
const { withRouter } = require('react-router-dom') |
|
||||||
const { compose } = require('recompose') |
|
||||||
const PropTypes = require('prop-types') |
|
||||||
const h = require('react-hyperscript') |
|
||||||
const connect = require('react-redux').connect |
|
||||||
const actions = require('../../../actions') |
|
||||||
const infuraCurrencies = require('../../../infura-conversion.json') |
|
||||||
const validUrl = require('valid-url') |
|
||||||
const { exportAsFile } = require('../../../util') |
|
||||||
const SimpleDropdown = require('../../dropdowns/simple-dropdown') |
|
||||||
const ToggleButton = require('react-toggle-button') |
|
||||||
const { REVEAL_SEED_ROUTE } = require('../../../routes') |
|
||||||
const locales = require('../../../../../app/_locales/index.json') |
|
||||||
|
|
||||||
import Button from '../../button' |
|
||||||
|
|
||||||
const getInfuraCurrencyOptions = () => { |
|
||||||
const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { |
|
||||||
return a.quote.name.toLocaleLowerCase().localeCompare(b.quote.name.toLocaleLowerCase()) |
|
||||||
}) |
|
||||||
|
|
||||||
return sortedCurrencies.map(({ quote: { code, name } }) => { |
|
||||||
return { |
|
||||||
displayValue: `${code.toUpperCase()} - ${name}`, |
|
||||||
key: code, |
|
||||||
value: code, |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
const getLocaleOptions = () => { |
|
||||||
return locales.map((locale) => { |
|
||||||
return { |
|
||||||
displayValue: `${locale.name}`, |
|
||||||
key: locale.code, |
|
||||||
value: locale.code, |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
class Settings extends Component { |
|
||||||
constructor (props) { |
|
||||||
super(props) |
|
||||||
|
|
||||||
this.state = { |
|
||||||
newRpc: '', |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
renderBlockieOptIn () { |
|
||||||
const { metamask: { useBlockie }, setUseBlockie } = this.props |
|
||||||
|
|
||||||
return h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('span', this.context.t('blockiesIdenticon')), |
|
||||||
]), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(ToggleButton, { |
|
||||||
value: useBlockie, |
|
||||||
onToggle: (value) => setUseBlockie(!value), |
|
||||||
activeLabel: '', |
|
||||||
inactiveLabel: '', |
|
||||||
}), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
renderHexDataOptIn () { |
|
||||||
const { metamask: { featureFlags: { sendHexData } }, setHexDataFeatureFlag } = this.props |
|
||||||
|
|
||||||
return h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('span', this.context.t('showHexData')), |
|
||||||
h( |
|
||||||
'div.settings__content-description', |
|
||||||
this.context.t('showHexDataDescription') |
|
||||||
), |
|
||||||
]), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(ToggleButton, { |
|
||||||
value: sendHexData, |
|
||||||
onToggle: (value) => setHexDataFeatureFlag(!value), |
|
||||||
activeLabel: '', |
|
||||||
inactiveLabel: '', |
|
||||||
}), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
renderCurrentConversion () { |
|
||||||
const { metamask: { currentCurrency, conversionDate }, setCurrentCurrency } = this.props |
|
||||||
|
|
||||||
return h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('span', this.context.t('currentConversion')), |
|
||||||
h('span.settings__content-description', `Updated ${Date(conversionDate)}`), |
|
||||||
]), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(SimpleDropdown, { |
|
||||||
placeholder: this.context.t('selectCurrency'), |
|
||||||
options: getInfuraCurrencyOptions(), |
|
||||||
selectedOption: currentCurrency, |
|
||||||
onSelect: newCurrency => setCurrentCurrency(newCurrency), |
|
||||||
}), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
renderCurrentLocale () { |
|
||||||
const { updateCurrentLocale, currentLocale } = this.props |
|
||||||
const currentLocaleMeta = locales.find(locale => locale.code === currentLocale) |
|
||||||
const currentLocaleName = currentLocaleMeta ? currentLocaleMeta.name : '' |
|
||||||
|
|
||||||
return h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('span', 'Current Language'), |
|
||||||
h('span.settings__content-description', `${currentLocaleName}`), |
|
||||||
]), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(SimpleDropdown, { |
|
||||||
placeholder: 'Select Locale', |
|
||||||
options: getLocaleOptions(), |
|
||||||
selectedOption: currentLocale, |
|
||||||
onSelect: async (newLocale) => { |
|
||||||
updateCurrentLocale(newLocale) |
|
||||||
}, |
|
||||||
}), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
renderCurrentProvider () { |
|
||||||
const { metamask: { provider = {} } } = this.props |
|
||||||
let title, value, color |
|
||||||
|
|
||||||
switch (provider.type) { |
|
||||||
|
|
||||||
case 'mainnet': |
|
||||||
title = this.context.t('currentNetwork') |
|
||||||
value = this.context.t('mainnet') |
|
||||||
color = '#038789' |
|
||||||
break |
|
||||||
|
|
||||||
case 'ropsten': |
|
||||||
title = this.context.t('currentNetwork') |
|
||||||
value = this.context.t('ropsten') |
|
||||||
color = '#e91550' |
|
||||||
break |
|
||||||
|
|
||||||
case 'kovan': |
|
||||||
title = this.context.t('currentNetwork') |
|
||||||
value = this.context.t('kovan') |
|
||||||
color = '#690496' |
|
||||||
break |
|
||||||
|
|
||||||
case 'rinkeby': |
|
||||||
title = this.context.t('currentNetwork') |
|
||||||
value = this.context.t('rinkeby') |
|
||||||
color = '#ebb33f' |
|
||||||
break |
|
||||||
|
|
||||||
default: |
|
||||||
title = this.context.t('currentRpc') |
|
||||||
value = provider.rpcTarget |
|
||||||
} |
|
||||||
|
|
||||||
return h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', title), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h('div.settings__provider-wrapper', [ |
|
||||||
h('div.settings__provider-icon', { style: { background: color } }), |
|
||||||
h('div', value), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
renderNewRpcUrl () { |
|
||||||
return ( |
|
||||||
h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('span', this.context.t('newRPC')), |
|
||||||
]), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h('input.settings__input', { |
|
||||||
placeholder: this.context.t('newRPC'), |
|
||||||
onChange: event => this.setState({ newRpc: event.target.value }), |
|
||||||
onKeyPress: event => { |
|
||||||
if (event.key === 'Enter') { |
|
||||||
this.validateRpc(this.state.newRpc) |
|
||||||
} |
|
||||||
}, |
|
||||||
}), |
|
||||||
h('div.settings__rpc-save-button', { |
|
||||||
onClick: event => { |
|
||||||
event.preventDefault() |
|
||||||
this.validateRpc(this.state.newRpc) |
|
||||||
}, |
|
||||||
}, this.context.t('save')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
validateRpc (newRpc) { |
|
||||||
const { setRpcTarget, displayWarning } = this.props |
|
||||||
|
|
||||||
if (validUrl.isWebUri(newRpc)) { |
|
||||||
setRpcTarget(newRpc) |
|
||||||
} else { |
|
||||||
const appendedRpc = `http://${newRpc}` |
|
||||||
|
|
||||||
if (validUrl.isWebUri(appendedRpc)) { |
|
||||||
displayWarning(this.context.t('uriErrorMsg')) |
|
||||||
} else { |
|
||||||
displayWarning(this.context.t('invalidRPC')) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
renderStateLogs () { |
|
||||||
return ( |
|
||||||
h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div', this.context.t('stateLogs')), |
|
||||||
h( |
|
||||||
'div.settings__content-description', |
|
||||||
this.context.t('stateLogsDescription') |
|
||||||
), |
|
||||||
]), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(Button, { |
|
||||||
type: 'primary', |
|
||||||
large: true, |
|
||||||
className: 'settings__button', |
|
||||||
onClick (event) { |
|
||||||
window.logStateString((err, result) => { |
|
||||||
if (err) { |
|
||||||
this.state.dispatch(actions.displayWarning(this.context.t('stateLogError'))) |
|
||||||
} else { |
|
||||||
exportAsFile('MetaMask State Logs.json', result) |
|
||||||
} |
|
||||||
}) |
|
||||||
}, |
|
||||||
}, this.context.t('downloadStateLogs')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
renderSeedWords () { |
|
||||||
const { history } = this.props |
|
||||||
|
|
||||||
return ( |
|
||||||
h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', this.context.t('revealSeedWords')), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(Button, { |
|
||||||
type: 'primary', |
|
||||||
large: true, |
|
||||||
className: 'settings__button--red', |
|
||||||
onClick: event => { |
|
||||||
event.preventDefault() |
|
||||||
history.push(REVEAL_SEED_ROUTE) |
|
||||||
}, |
|
||||||
}, this.context.t('revealSeedWords')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
renderOldUI () { |
|
||||||
const { setFeatureFlagToBeta } = this.props |
|
||||||
|
|
||||||
return ( |
|
||||||
h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', this.context.t('useOldUI')), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(Button, { |
|
||||||
type: 'primary', |
|
||||||
large: true, |
|
||||||
className: 'settings__button--orange', |
|
||||||
onClick (event) { |
|
||||||
event.preventDefault() |
|
||||||
setFeatureFlagToBeta() |
|
||||||
}, |
|
||||||
}, this.context.t('useOldUI')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
renderResetAccount () { |
|
||||||
const { showResetAccountConfirmationModal } = this.props |
|
||||||
|
|
||||||
return h('div.settings__content-row', [ |
|
||||||
h('div.settings__content-item', this.context.t('resetAccount')), |
|
||||||
h('div.settings__content-item', [ |
|
||||||
h('div.settings__content-item-col', [ |
|
||||||
h(Button, { |
|
||||||
type: 'primary', |
|
||||||
large: true, |
|
||||||
className: 'settings__button--orange', |
|
||||||
onClick (event) { |
|
||||||
event.preventDefault() |
|
||||||
showResetAccountConfirmationModal() |
|
||||||
}, |
|
||||||
}, this.context.t('resetAccount')), |
|
||||||
]), |
|
||||||
]), |
|
||||||
]) |
|
||||||
} |
|
||||||
|
|
||||||
render () { |
|
||||||
const { warning, isMascara } = this.props |
|
||||||
|
|
||||||
return ( |
|
||||||
h('div.settings__content', [ |
|
||||||
warning && h('div.settings__error', warning), |
|
||||||
this.renderCurrentConversion(), |
|
||||||
this.renderCurrentLocale(), |
|
||||||
// this.renderCurrentProvider(),
|
|
||||||
this.renderNewRpcUrl(), |
|
||||||
this.renderStateLogs(), |
|
||||||
this.renderSeedWords(), |
|
||||||
!isMascara && this.renderOldUI(), |
|
||||||
this.renderResetAccount(), |
|
||||||
this.renderBlockieOptIn(), |
|
||||||
this.renderHexDataOptIn(), |
|
||||||
]) |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Settings.propTypes = { |
|
||||||
metamask: PropTypes.object, |
|
||||||
setUseBlockie: PropTypes.func, |
|
||||||
setHexDataFeatureFlag: PropTypes.func, |
|
||||||
setCurrentCurrency: PropTypes.func, |
|
||||||
setRpcTarget: PropTypes.func, |
|
||||||
displayWarning: PropTypes.func, |
|
||||||
revealSeedConfirmation: PropTypes.func, |
|
||||||
setFeatureFlagToBeta: PropTypes.func, |
|
||||||
showResetAccountConfirmationModal: PropTypes.func, |
|
||||||
warning: PropTypes.string, |
|
||||||
history: PropTypes.object, |
|
||||||
isMascara: PropTypes.bool, |
|
||||||
updateCurrentLocale: PropTypes.func, |
|
||||||
currentLocale: PropTypes.string, |
|
||||||
t: PropTypes.func, |
|
||||||
} |
|
||||||
|
|
||||||
const mapStateToProps = state => { |
|
||||||
return { |
|
||||||
metamask: state.metamask, |
|
||||||
warning: state.appState.warning, |
|
||||||
isMascara: state.metamask.isMascara, |
|
||||||
currentLocale: state.metamask.currentLocale, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => { |
|
||||||
return { |
|
||||||
setCurrentCurrency: currency => dispatch(actions.setCurrentCurrency(currency)), |
|
||||||
setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)), |
|
||||||
displayWarning: warning => dispatch(actions.displayWarning(warning)), |
|
||||||
revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), |
|
||||||
setUseBlockie: value => dispatch(actions.setUseBlockie(value)), |
|
||||||
updateCurrentLocale: key => dispatch(actions.updateCurrentLocale(key)), |
|
||||||
setFeatureFlagToBeta: () => { |
|
||||||
return dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) |
|
||||||
}, |
|
||||||
setHexDataFeatureFlag: (featureFlagShowState) => { |
|
||||||
return dispatch(actions.setFeatureFlag('sendHexData', featureFlagShowState)) |
|
||||||
}, |
|
||||||
showResetAccountConfirmationModal: () => { |
|
||||||
return dispatch(actions.showModal({ name: 'CONFIRM_RESET_ACCOUNT' })) |
|
||||||
}, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Settings.contextTypes = { |
|
||||||
t: PropTypes.func, |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = compose( |
|
||||||
withRouter, |
|
||||||
connect(mapStateToProps, mapDispatchToProps) |
|
||||||
)(Settings) |
|
@ -1,214 +0,0 @@ |
|||||||
.settings { |
|
||||||
position: relative; |
|
||||||
background: $white; |
|
||||||
display: flex; |
|
||||||
flex-flow: column nowrap; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__header { |
|
||||||
padding: 25px; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__close-button::after { |
|
||||||
content: '\00D7'; |
|
||||||
font-size: 40px; |
|
||||||
color: $dusty-gray; |
|
||||||
position: absolute; |
|
||||||
top: 25px; |
|
||||||
right: 30px; |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__error { |
|
||||||
padding-bottom: 20px; |
|
||||||
text-align: center; |
|
||||||
color: $crimson; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__content { |
|
||||||
padding: 0 25px; |
|
||||||
height: auto; |
|
||||||
overflow: auto; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__content-row { |
|
||||||
display: flex; |
|
||||||
flex-direction: row; |
|
||||||
padding: 10px 0 20px; |
|
||||||
|
|
||||||
@media screen and (max-width: 575px) { |
|
||||||
flex-direction: column; |
|
||||||
padding: 10px 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.settings__content-item { |
|
||||||
flex: 1; |
|
||||||
min-width: 0; |
|
||||||
display: flex; |
|
||||||
flex-direction: column; |
|
||||||
padding: 0 5px; |
|
||||||
height: 71px; |
|
||||||
|
|
||||||
@media screen and (max-width: 575px) { |
|
||||||
height: initial; |
|
||||||
padding: 5px 0; |
|
||||||
} |
|
||||||
|
|
||||||
&--without-height { |
|
||||||
height: initial; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.settings__content-item-col { |
|
||||||
max-width: 300px; |
|
||||||
display: flex; |
|
||||||
flex-direction: column; |
|
||||||
|
|
||||||
@media screen and (max-width: 575px) { |
|
||||||
max-width: 100%; |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.settings__content-description { |
|
||||||
font-size: 14px; |
|
||||||
color: $dusty-gray; |
|
||||||
padding-top: 5px; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__input { |
|
||||||
padding-left: 10px; |
|
||||||
font-size: 14px; |
|
||||||
height: 40px; |
|
||||||
border: 1px solid $alto; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__input::-webkit-input-placeholder { |
|
||||||
font-weight: 100; |
|
||||||
color: $dusty-gray; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__input::-moz-placeholder { |
|
||||||
font-weight: 100; |
|
||||||
color: $dusty-gray; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__input:-ms-input-placeholder { |
|
||||||
font-weight: 100; |
|
||||||
color: $dusty-gray; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__input:-moz-placeholder { |
|
||||||
font-weight: 100; |
|
||||||
color: $dusty-gray; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__provider-wrapper { |
|
||||||
font-size: 16px; |
|
||||||
border: 1px solid $alto; |
|
||||||
border-radius: 2px; |
|
||||||
padding: 15px; |
|
||||||
background-color: $white; |
|
||||||
display: flex; |
|
||||||
align-items: center; |
|
||||||
justify-content: flex-start; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__provider-icon { |
|
||||||
height: 10px; |
|
||||||
width: 10px; |
|
||||||
margin-right: 10px; |
|
||||||
border-radius: 10px; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__rpc-save-button { |
|
||||||
align-self: flex-end; |
|
||||||
padding: 5px; |
|
||||||
text-transform: uppercase; |
|
||||||
color: $dusty-gray; |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__button--red { |
|
||||||
border-color: lighten($monzo, 10%); |
|
||||||
color: $monzo; |
|
||||||
|
|
||||||
&:active { |
|
||||||
background: lighten($monzo, 55%); |
|
||||||
border-color: $monzo; |
|
||||||
} |
|
||||||
|
|
||||||
&:hover { |
|
||||||
border-color: $monzo; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.settings__button--orange { |
|
||||||
border-color: lighten($ecstasy, 20%); |
|
||||||
color: $ecstasy; |
|
||||||
|
|
||||||
&:active { |
|
||||||
background: lighten($ecstasy, 40%); |
|
||||||
border-color: $ecstasy; |
|
||||||
} |
|
||||||
|
|
||||||
&:hover { |
|
||||||
border-color: $ecstasy; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-logo-wrapper { |
|
||||||
height: 80px; |
|
||||||
margin-bottom: 20px; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-logo { |
|
||||||
max-height: 100%; |
|
||||||
max-width: 100%; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-item { |
|
||||||
padding: 10px 0; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-link-header { |
|
||||||
padding-bottom: 15px; |
|
||||||
|
|
||||||
@media screen and (max-width: 575px) { |
|
||||||
padding-bottom: 5px; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-link-item { |
|
||||||
padding: 15px 0; |
|
||||||
|
|
||||||
@media screen and (max-width: 575px) { |
|
||||||
padding: 5px 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-version-number { |
|
||||||
padding-top: 5px; |
|
||||||
font-size: 13px; |
|
||||||
color: $dusty-gray; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-about { |
|
||||||
color: $dusty-gray; |
|
||||||
margin-bottom: 15px; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-link { |
|
||||||
color: $curious-blue; |
|
||||||
} |
|
||||||
|
|
||||||
.settings__info-separator { |
|
||||||
margin: 15px 0; |
|
||||||
width: 80px; |
|
||||||
border-color: $alto; |
|
||||||
border: none; |
|
||||||
height: 1px; |
|
||||||
background-color: $alto; |
|
||||||
color: $alto; |
|
||||||
} |
|
Loading…
Reference in new issue