Skip to content

Commit

Permalink
Add togglable advanced gas controls on send and confirm screens (#6112)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
danjm authored and danfinlay committed Feb 6, 2019
1 parent c28fa31 commit 38b91f6
Show file tree
Hide file tree
Showing 20 changed files with 609 additions and 36 deletions.
12 changes: 12 additions & 0 deletions app/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,9 @@
"gasLimitCalculation": {
"message": "We calculate the suggested gas limit based on network success rates."
},
"gasLimitInfoModalContent": {
"message": "Gas limit is the maximum amount of units of gas you are willing to spend."
},
"gasLimitRequired": {
"message": "Gas Limit Required"
},
Expand All @@ -547,6 +550,9 @@
"gasPriceExtremelyLow": {
"message": "Gas Price Extremely Low"
},
"gasPriceInfoModalContent": {
"message": "Gas price specifies the amount of Ether you are willing to pay for each unit of gas."
},
"gasPriceNoDenom": {
"message": "Gas Price"
},
Expand Down Expand Up @@ -1210,6 +1216,12 @@
"shapeshiftBuy": {
"message": "Buy with Shapeshift"
},
"showAdvancedGasInline": {
"message": "Advanced gas controls"
},
"showAdvancedGasInlineDescription": {
"message": "Select this to show gas price and limit controls directly on the send and confirm screens."
},
"showPrivateKeys": {
"message": "Show Private Keys"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@
font-size: .625rem;
}
}

.advanced-gas-inputs__gas-edit-rows {
margin-bottom: 16px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@

&__gas-fee {
border-bottom: 1px solid $geyser;

.advanced-gas-inputs__gas-edit-rows {
margin-bottom: 16px;
}
}

&__function-type {
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
)
}
}
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './advanced-gas-inputs.container'
133 changes: 133 additions & 0 deletions ui/app/components/gas-customization/advanced-gas-inputs/index.scss
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
2 changes: 2 additions & 0 deletions ui/app/components/gas-customization/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
@import './gas-modal-page-container/index';

@import './gas-price-chart/index';

@import './advanced-gas-inputs/index';
34 changes: 34 additions & 0 deletions ui/app/components/modals/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,40 @@ const MODALS = {
},
},

GAS_PRICE_INFO_MODAL: {
contents: [
h(NotifcationModal, {
header: 'gasPriceNoDenom',
message: 'gasPriceInfoModalContent',
}),
],
mobileModalStyle: {
width: '95%',
top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh',
},
laptopModalStyle: {
width: '449px',
top: 'calc(33% + 45px)',
},
},

GAS_LIMIT_INFO_MODAL: {
contents: [
h(NotifcationModal, {
header: 'gasLimit',
message: 'gasLimitInfoModalContent',
}),
],
mobileModalStyle: {
width: '95%',
top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh',
},
laptopModalStyle: {
width: '449px',
top: 'calc(33% + 45px)',
},
},

CONFIRM_RESET_ACCOUNT: {
contents: h(ConfirmResetAccount),
mobileModalStyle: {
Expand Down
Loading

0 comments on commit 38b91f6

Please sign in to comment.