mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Refactor settings page to use JSX and follow component file folder structure
This commit is contained in:
parent
3c3fed46cb
commit
b579ee9619
@ -216,6 +216,9 @@
|
|||||||
"currentConversion": {
|
"currentConversion": {
|
||||||
"message": "Current Conversion"
|
"message": "Current Conversion"
|
||||||
},
|
},
|
||||||
|
"currentLanguage": {
|
||||||
|
"message": "current language"
|
||||||
|
},
|
||||||
"currentNetwork": {
|
"currentNetwork": {
|
||||||
"message": "Current Network"
|
"message": "Current Network"
|
||||||
},
|
},
|
||||||
@ -596,6 +599,9 @@
|
|||||||
"metamaskSeedWords": {
|
"metamaskSeedWords": {
|
||||||
"message": "MetaMask Seed Words"
|
"message": "MetaMask Seed Words"
|
||||||
},
|
},
|
||||||
|
"metamaskVersion": {
|
||||||
|
"message": "metamask version"
|
||||||
|
},
|
||||||
"min": {
|
"min": {
|
||||||
"message": "Minimum"
|
"message": "Minimum"
|
||||||
},
|
},
|
||||||
@ -906,6 +912,9 @@
|
|||||||
"selectCurrency": {
|
"selectCurrency": {
|
||||||
"message": "Select Currency"
|
"message": "Select Currency"
|
||||||
},
|
},
|
||||||
|
"selectLocale": {
|
||||||
|
"message": "Select Locale"
|
||||||
|
},
|
||||||
"selectService": {
|
"selectService": {
|
||||||
"message": "Select Service"
|
"message": "Select Service"
|
||||||
},
|
},
|
||||||
|
@ -1043,7 +1043,7 @@ describe('MetaMask', function () {
|
|||||||
await customRpcInput.clear()
|
await customRpcInput.clear()
|
||||||
await customRpcInput.sendKeys(customRpcUrl)
|
await customRpcInput.sendKeys(customRpcUrl)
|
||||||
|
|
||||||
const customRpcSave = await findElement(driver, By.css('.settings__rpc-save-button'))
|
const customRpcSave = await findElement(driver, By.css('.settings-tab__rpc-save-button'))
|
||||||
await customRpcSave.click()
|
await customRpcSave.click()
|
||||||
await delay(largeDelayMs * 2)
|
await delay(largeDelayMs * 2)
|
||||||
})
|
})
|
||||||
|
@ -19,9 +19,9 @@ const Sidebar = require('./components/sidebars').default
|
|||||||
|
|
||||||
// other views
|
// other views
|
||||||
import Home from './components/pages/home'
|
import Home from './components/pages/home'
|
||||||
|
import Settings from './components/pages/settings'
|
||||||
const Authenticated = require('./components/pages/authenticated')
|
const Authenticated = require('./components/pages/authenticated')
|
||||||
const Initialized = require('./components/pages/initialized')
|
const Initialized = require('./components/pages/initialized')
|
||||||
const Settings = require('./components/pages/settings')
|
|
||||||
const RestoreVaultPage = require('./components/pages/keychains/restore-vault').default
|
const RestoreVaultPage = require('./components/pages/keychains/restore-vault').default
|
||||||
const RevealSeedConfirmation = require('./components/pages/keychains/reveal-seed')
|
const RevealSeedConfirmation = require('./components/pages/keychains/reveal-seed')
|
||||||
const AddTokenPage = require('./components/pages/add-token')
|
const AddTokenPage = require('./components/pages/add-token')
|
||||||
|
@ -3,3 +3,5 @@
|
|||||||
@import './add-token/index';
|
@import './add-token/index';
|
||||||
|
|
||||||
@import './confirm-add-token/index';
|
@import './confirm-add-token/index';
|
||||||
|
|
||||||
|
@import './settings/index';
|
||||||
|
@ -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
|
|
||||||
|
80
ui/app/components/pages/settings/index.scss
Normal file
80
ui/app/components/pages/settings/index.scss
Normal file
@ -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%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
ui/app/components/pages/settings/info-tab/index.js
Normal file
1
ui/app/components/pages/settings/info-tab/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './info-tab.component'
|
60
ui/app/components/pages/settings/info-tab/index.scss
Normal file
60
ui/app/components/pages/settings/info-tab/index.scss
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
.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-header {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__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;
|
||||||
|
}
|
||||||
|
}
|
136
ui/app/components/pages/settings/info-tab/info-tab.component.js
Normal file
136
ui/app/components/pages/settings/info-tab/info-tab.component.js
Normal file
@ -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
|
|
1
ui/app/components/pages/settings/settings-tab/index.js
Normal file
1
ui/app/components/pages/settings/settings-tab/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './settings-tab.container'
|
51
ui/app/components/pages/settings/settings-tab/index.scss
Normal file
51
ui/app/components/pages/settings/settings-tab/index.scss
Normal file
@ -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">
|
||||||
|
{ `Updated ${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)
|
54
ui/app/components/pages/settings/settings.component.js
Normal file
54
ui/app/components/pages/settings/settings.component.js
Normal file
@ -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)
|
|
@ -36,8 +36,6 @@
|
|||||||
|
|
||||||
@import './gas-slider.scss';
|
@import './gas-slider.scss';
|
||||||
|
|
||||||
@import './settings.scss';
|
|
||||||
|
|
||||||
@import './tab-bar.scss';
|
@import './tab-bar.scss';
|
||||||
|
|
||||||
@import './simple-dropdown.scss';
|
@import './simple-dropdown.scss';
|
||||||
|
@ -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
Block a user