diff options
author | Dan J Miller <danjm.com@gmail.com> | 2019-02-06 08:24:28 +0800 |
---|---|---|
committer | Dan Finlay <542863+danfinlay@users.noreply.github.com> | 2019-02-06 08:24:28 +0800 |
commit | 38b91f63a21d1563cf88307e280f52836df005db (patch) | |
tree | 4632fe335ab9ff05df98f6739891a00a5229d90c /ui/app/components/gas-customization | |
parent | c28fa312503b7c868bfcfceb42b3a79c0f25d492 (diff) | |
download | tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.gz tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.bz2 tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.lz tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.xz tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.zst tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.zip |
Add togglable advanced gas controls on send and confirm screens (#6112)
* Extract advanced gas input controls to their own component
* Add advanced inline gas toggle to settings
* Add optional advanced inline gas to send send screen
* Adds optional advanced gas inputs to the confirm screen
* Add info modals for advanced gas inputs.
* Fix translation of advance gas toggle description.
* Lint and unit test fixes for inline-advanced-gas-inputs
* Increase margin above advanced options button on send screen
* Move methods from constructor to property syntax in advanced-gas-inputs.component
Diffstat (limited to 'ui/app/components/gas-customization')
5 files changed, 294 insertions, 0 deletions
diff --git a/ui/app/components/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js b/ui/app/components/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js new file mode 100644 index 000000000..f0abff478 --- /dev/null +++ b/ui/app/components/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js @@ -0,0 +1,146 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' +import debounce from 'lodash.debounce' + +export default class AdvancedTabContent extends Component { + static contextTypes = { + t: PropTypes.func, + } + + static propTypes = { + updateCustomGasPrice: PropTypes.func, + updateCustomGasLimit: PropTypes.func, + customGasPrice: PropTypes.number, + customGasLimit: PropTypes.number, + insufficientBalance: PropTypes.bool, + customPriceIsSafe: PropTypes.bool, + isSpeedUp: PropTypes.bool, + showGasPriceInfoModal: PropTypes.func, + showGasLimitInfoModal: PropTypes.func, + } + + debouncedGasLimitReset = debounce((dVal) => { + if (dVal < 21000) { + this.props.updateCustomGasLimit(21000) + } + }, 1000, { trailing: true }) + + onChangeGasLimit = (val) => { + this.props.updateCustomGasLimit(val) + this.debouncedGasLimitReset(val) + } + + gasInputError ({ labelKey, insufficientBalance, customPriceIsSafe, isSpeedUp, value }) { + const { t } = this.context + let errorText + let errorType + let isInError = true + + + if (insufficientBalance) { + errorText = t('insufficientBalance') + errorType = 'error' + } else if (labelKey === 'gasPrice' && isSpeedUp && value === 0) { + errorText = t('zeroGasPriceOnSpeedUpError') + errorType = 'error' + } else if (labelKey === 'gasPrice' && !customPriceIsSafe) { + errorText = t('gasPriceExtremelyLow') + errorType = 'warning' + } else { + isInError = false + } + + return { + isInError, + errorText, + errorType, + } + } + + gasInput ({ labelKey, value, onChange, insufficientBalance, showGWEI, customPriceIsSafe, isSpeedUp }) { + const { + isInError, + errorText, + errorType, + } = this.gasInputError({ labelKey, insufficientBalance, customPriceIsSafe, isSpeedUp, value }) + + return ( + <div className="advanced-gas-inputs__gas-edit-row__input-wrapper"> + <input + className={classnames('advanced-gas-inputs__gas-edit-row__input', { + 'advanced-gas-inputs__gas-edit-row__input--error': isInError && errorType === 'error', + 'advanced-gas-inputs__gas-edit-row__input--warning': isInError && errorType === 'warning', + })} + type="number" + value={value} + onChange={event => onChange(Number(event.target.value))} + /> + <div className={classnames('advanced-gas-inputs__gas-edit-row__input-arrows', { + 'advanced-gas-inputs__gas-edit-row__input--error': isInError && errorType === 'error', + 'advanced-gas-inputs__gas-edit-row__input--warning': isInError && errorType === 'warning', + })}> + <div className="advanced-gas-inputs__gas-edit-row__input-arrows__i-wrap" onClick={() => onChange(value + 1)}><i className="fa fa-sm fa-angle-up" /></div> + <div className="advanced-gas-inputs__gas-edit-row__input-arrows__i-wrap" onClick={() => onChange(value - 1)}><i className="fa fa-sm fa-angle-down" /></div> + </div> + { isInError + ? <div className={`advanced-gas-inputs__gas-edit-row__${errorType}-text`}> + { errorText } + </div> + : null } + </div> + ) + } + + infoButton (onClick) { + return <i className="fa fa-info-circle" onClick={onClick} /> + } + + renderGasEditRow (gasInputArgs) { + return ( + <div className="advanced-gas-inputs__gas-edit-row"> + <div className="advanced-gas-inputs__gas-edit-row__label"> + { this.context.t(gasInputArgs.labelKey) } + { this.infoButton(() => gasInputArgs.infoOnClick()) } + </div> + { this.gasInput(gasInputArgs) } + </div> + ) + } + + render () { + const { + customGasPrice, + updateCustomGasPrice, + customGasLimit, + insufficientBalance, + customPriceIsSafe, + isSpeedUp, + showGasPriceInfoModal, + showGasLimitInfoModal, + } = this.props + + return ( + <div className="advanced-gas-inputs__gas-edit-rows"> + { this.renderGasEditRow({ + labelKey: 'gasPrice', + value: customGasPrice, + onChange: updateCustomGasPrice, + insufficientBalance, + customPriceIsSafe, + showGWEI: true, + isSpeedUp, + infoOnClick: showGasPriceInfoModal, + }) } + { this.renderGasEditRow({ + labelKey: 'gasLimit', + value: customGasLimit, + onChange: this.onChangeGasLimit, + insufficientBalance, + customPriceIsSafe, + infoOnClick: showGasLimitInfoModal, + }) } + </div> + ) + } +} diff --git a/ui/app/components/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js b/ui/app/components/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js new file mode 100644 index 000000000..883d11c6d --- /dev/null +++ b/ui/app/components/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js @@ -0,0 +1,12 @@ +import { connect } from 'react-redux' +import { showModal } from '../../../actions' +import AdvancedGasInputs from './advanced-gas-inputs.component' + +const mapDispatchToProps = dispatch => { + return { + showGasPriceInfoModal: modalName => dispatch(showModal({ name: 'GAS_PRICE_INFO_MODAL' })), + showGasLimitInfoModal: modalName => dispatch(showModal({ name: 'GAS_LIMIT_INFO_MODAL' })), + } +} + +export default connect(null, mapDispatchToProps)(AdvancedGasInputs) diff --git a/ui/app/components/gas-customization/advanced-gas-inputs/index.js b/ui/app/components/gas-customization/advanced-gas-inputs/index.js new file mode 100644 index 000000000..bd8abaa3e --- /dev/null +++ b/ui/app/components/gas-customization/advanced-gas-inputs/index.js @@ -0,0 +1 @@ +export { default } from './advanced-gas-inputs.container' diff --git a/ui/app/components/gas-customization/advanced-gas-inputs/index.scss b/ui/app/components/gas-customization/advanced-gas-inputs/index.scss new file mode 100644 index 000000000..50953cbe5 --- /dev/null +++ b/ui/app/components/gas-customization/advanced-gas-inputs/index.scss @@ -0,0 +1,133 @@ +.advanced-gas-inputs { + &__gas-edit-rows { + display: flex; + flex-flow: row; + justify-content: space-between; + } + + &__gas-edit-row { + display: flex; + flex-flow: column; + width: 47.5%; + + &__label { + color: #313B5E; + font-size: 12px; + display: flex; + justify-content: space-between; + align-items: center; + + @media screen and (max-width: 576px) { + font-size: 10px; + } + + .fa-info-circle { + color: $silver; + margin-left: 10px; + cursor: pointer; + } + + .fa-info-circle:hover { + color: $mid-gray; + } + } + + &__error-text { + font-size: 12px; + color: red; + } + + &__warning-text { + font-size: 12px; + color: orange; + } + + &__input-wrapper { + position: relative; + } + + &__input { + border: 1px solid $dusty-gray; + border-radius: 4px; + color: $mid-gray; + font-size: 16px; + height: 24px; + width: 100%; + padding-left: 8px; + padding-top: 2px; + margin-top: 7px; + } + + &__input--error { + border: 1px solid $red; + } + + &__input--warning { + border: 1px solid $orange; + } + + &__input-arrows { + position: absolute; + top: 7px; + right: 0px; + width: 17px; + height: 24px; + border: 1px solid #dadada; + border-top-right-radius: 4px; + display: flex; + flex-direction: column; + color: #9b9b9b; + font-size: .8em; + border-bottom-right-radius: 4px; + cursor: pointer; + + &__i-wrap { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + cursor: pointer; + } + + &__i-wrap:hover { + background: #4EADE7; + color: $white; + } + + i:hover { + background: #4EADE7; + } + + i { + font-size: 10px; + } + } + + &__input-arrows--error { + border: 1px solid $red; + } + + &__input-arrows--warning { + border: 1px solid $orange; + } + + input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + + input[type="number"]:hover::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + + &__gwei-symbol { + position: absolute; + top: 8px; + right: 10px; + color: $dusty-gray; + } + } +}
\ No newline at end of file diff --git a/ui/app/components/gas-customization/index.scss b/ui/app/components/gas-customization/index.scss index e99d4e57f..b06c1d044 100644 --- a/ui/app/components/gas-customization/index.scss +++ b/ui/app/components/gas-customization/index.scss @@ -3,3 +3,5 @@ @import './gas-modal-page-container/index'; @import './gas-price-chart/index'; + +@import './advanced-gas-inputs/index'; |