aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/pages/settings
diff options
context:
space:
mode:
authorDan <danjm.com@gmail.com>2018-04-10 03:22:26 +0800
committerDan <danjm.com@gmail.com>2018-04-10 03:22:26 +0800
commit2c4426e4de745be880a994674dc1dc74c7ec74eb (patch)
tree1de9b836026d3222b490793099b66372404b83ab /ui/app/components/pages/settings
parent9dbb9d12ad31d53b8911db171cb7d6b3fcb477e2 (diff)
parent4cae3d3b0d2a9cc0279e44de256e7fc7e219dca1 (diff)
downloadtangerine-wallet-browser-2c4426e4de745be880a994674dc1dc74c7ec74eb.tar.gz
tangerine-wallet-browser-2c4426e4de745be880a994674dc1dc74c7ec74eb.tar.zst
tangerine-wallet-browser-2c4426e4de745be880a994674dc1dc74c7ec74eb.zip
Merge branch 'master' into i3580-InternationalizeCurrency
Diffstat (limited to 'ui/app/components/pages/settings')
-rw-r--r--ui/app/components/pages/settings/index.js59
-rw-r--r--ui/app/components/pages/settings/info.js112
-rw-r--r--ui/app/components/pages/settings/settings.js367
3 files changed, 538 insertions, 0 deletions
diff --git a/ui/app/components/pages/settings/index.js b/ui/app/components/pages/settings/index.js
new file mode 100644
index 000000000..384ae4b41
--- /dev/null
+++ b/ui/app/components/pages/settings/index.js
@@ -0,0 +1,59 @@
+const { Component } = require('react')
+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: 'Settings', key: SETTINGS_ROUTE },
+ { content: '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,
+}
+
+module.exports = Config
diff --git a/ui/app/components/pages/settings/info.js b/ui/app/components/pages/settings/info.js
new file mode 100644
index 000000000..eb9be66e6
--- /dev/null
+++ b/ui/app/components/pages/settings/info.js
@@ -0,0 +1,112 @@
+const { Component } = require('react')
+const PropTypes = require('prop-types')
+const h = require('react-hyperscript')
+
+class Info extends Component {
+ 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', '4.0.0'),
+ ]),
+ 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
diff --git a/ui/app/components/pages/settings/settings.js b/ui/app/components/pages/settings/settings.js
new file mode 100644
index 000000000..05a7379fb
--- /dev/null
+++ b/ui/app/components/pages/settings/settings.js
@@ -0,0 +1,367 @@
+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')
+const { OLD_UI_NETWORK_TYPE } = require('../../../../../app/scripts/config').enums
+
+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: '',
+ }),
+ ]),
+ ]),
+ ])
+ }
+
+ 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.btn-primary--lg.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.btn-primary--lg.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.btn-primary--lg.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.btn-primary--lg.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(),
+ ])
+ )
+ }
+}
+
+Settings.propTypes = {
+ metamask: PropTypes.object,
+ setUseBlockie: 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'))
+ .then(() => dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE)))
+ },
+ showResetAccountConfirmationModal: () => {
+ return dispatch(actions.showModal({ name: 'CONFIRM_RESET_ACCOUNT' }))
+ },
+ }
+}
+
+Settings.contextTypes = {
+ t: PropTypes.func,
+}
+
+module.exports = compose(
+ withRouter,
+ connect(mapStateToProps, mapDispatchToProps)
+)(Settings)