mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Restore timing function (#8774)
* restore and enhance the time est feature background: we had a feature for showing a time estimate on pending txs that was accidently removed during the redesign implementation. This PR restores that feature and also enhances it: 1. Displays the time estimate on all views instead of just fullscreen 2. Uses Intl.RelativeTimeFormat to format the time 3. Adds a way to toggle the feature flag. 4. Uses a hook to calculate the time remaining instead of a component * Update app/_locales/en/messages.json Co-authored-by: Mark Stacey <markjstacey@gmail.com> * do not display on test nets Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
parent
5aabe2ac75
commit
2f50e9fd72
@ -1603,6 +1603,9 @@
|
|||||||
"transactionTime": {
|
"transactionTime": {
|
||||||
"message": "Transaction Time"
|
"message": "Transaction Time"
|
||||||
},
|
},
|
||||||
|
"showTransactionTimeDescription": {
|
||||||
|
"message": "Select this to display pending transaction time estimates in the activity tab while on the Main Ethereum Network. Note: estimates are approximations based on network conditions."
|
||||||
|
},
|
||||||
"transfer": {
|
"transfer": {
|
||||||
"message": "Transfer"
|
"message": "Transfer"
|
||||||
},
|
},
|
||||||
|
@ -4,6 +4,7 @@ import './lib/freezeGlobals'
|
|||||||
|
|
||||||
// polyfills
|
// polyfills
|
||||||
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'
|
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'
|
||||||
|
import '@formatjs/intl-relativetimeformat/polyfill'
|
||||||
|
|
||||||
import PortStream from 'extension-port-stream'
|
import PortStream from 'extension-port-stream'
|
||||||
import { getEnvironmentType } from './lib/util'
|
import { getEnvironmentType } from './lib/util'
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
"3box": "^1.10.2",
|
"3box": "^1.10.2",
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"@download/blockies": "^1.0.3",
|
"@download/blockies": "^1.0.3",
|
||||||
|
"@formatjs/intl-relativetimeformat": "^5.2.6",
|
||||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||||
"@material-ui/core": "1.0.0",
|
"@material-ui/core": "1.0.0",
|
||||||
"@metamask/controllers": "^2.0.0",
|
"@metamask/controllers": "^2.0.0",
|
||||||
|
@ -92,6 +92,8 @@
|
|||||||
|
|
||||||
@import '../ui/icon/index';
|
@import '../ui/icon/index';
|
||||||
|
|
||||||
|
@import '../ui/icon-with-label/index';
|
||||||
|
|
||||||
@import '../ui/circle-icon/index';
|
@import '../ui/circle-icon/index';
|
||||||
|
|
||||||
@import '../ui/alert-circle-icon/index';
|
@import '../ui/alert-circle-icon/index';
|
||||||
|
@ -22,6 +22,8 @@ import {
|
|||||||
import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp'
|
import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp'
|
||||||
import TransactionStatus from '../transaction-status/transaction-status.component'
|
import TransactionStatus from '../transaction-status/transaction-status.component'
|
||||||
import TransactionIcon from '../transaction-icon'
|
import TransactionIcon from '../transaction-icon'
|
||||||
|
import { useTransactionTimeRemaining } from '../../../hooks/useTransactionTimeRemaining'
|
||||||
|
import IconWithLabel from '../../ui/icon-with-label'
|
||||||
|
|
||||||
|
|
||||||
export default function TransactionListItem ({ transactionGroup, isEarliestNonce = false }) {
|
export default function TransactionListItem ({ transactionGroup, isEarliestNonce = false }) {
|
||||||
@ -30,8 +32,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
const { hasCancelled } = transactionGroup
|
const { hasCancelled } = transactionGroup
|
||||||
const [showDetails, setShowDetails] = useState(false)
|
const [showDetails, setShowDetails] = useState(false)
|
||||||
|
|
||||||
const { initialTransaction: { id }, primaryTransaction } = transactionGroup
|
const { initialTransaction: { id }, primaryTransaction: { err, submittedTime, gasPrice } } = transactionGroup
|
||||||
|
|
||||||
const [cancelEnabled, cancelTransaction] = useCancelTransaction(transactionGroup)
|
const [cancelEnabled, cancelTransaction] = useCancelTransaction(transactionGroup)
|
||||||
const retryTransaction = useRetryTransaction(transactionGroup)
|
const retryTransaction = useRetryTransaction(transactionGroup)
|
||||||
const shouldShowSpeedUp = useShouldShowSpeedUp(transactionGroup, isEarliestNonce)
|
const shouldShowSpeedUp = useShouldShowSpeedUp(transactionGroup, isEarliestNonce)
|
||||||
@ -49,6 +50,9 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
senderAddress,
|
senderAddress,
|
||||||
} = useTransactionDisplayData(transactionGroup)
|
} = useTransactionDisplayData(transactionGroup)
|
||||||
|
|
||||||
|
const timeRemaining = useTransactionTimeRemaining(isPending, isEarliestNonce, submittedTime, gasPrice)
|
||||||
|
|
||||||
|
|
||||||
const isSignatureReq = category === TRANSACTION_CATEGORY_SIGNATURE_REQUEST
|
const isSignatureReq = category === TRANSACTION_CATEGORY_SIGNATURE_REQUEST
|
||||||
const isUnapproved = status === UNAPPROVED_STATUS
|
const isUnapproved = status === UNAPPROVED_STATUS
|
||||||
|
|
||||||
@ -112,9 +116,9 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
className={className}
|
className={className}
|
||||||
title={title}
|
title={title}
|
||||||
titleIcon={!isUnapproved && isPending && isEarliestNonce && (
|
titleIcon={!isUnapproved && isPending && isEarliestNonce && (
|
||||||
<Preloader
|
<IconWithLabel
|
||||||
size={16}
|
icon={<Preloader size={16} color="#D73A49" />}
|
||||||
color="#D73A49"
|
label={timeRemaining}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
icon={<TransactionIcon category={category} status={status} />}
|
icon={<TransactionIcon category={category} status={status} />}
|
||||||
@ -123,7 +127,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
<TransactionStatus
|
<TransactionStatus
|
||||||
isPending={isPending}
|
isPending={isPending}
|
||||||
isEarliestNonce={isEarliestNonce}
|
isEarliestNonce={isEarliestNonce}
|
||||||
error={primaryTransaction.err}
|
error={err}
|
||||||
date={date}
|
date={date}
|
||||||
status={status}
|
status={status}
|
||||||
/>
|
/>
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { default } from './transaction-time-remaining.container'
|
|
@ -1,52 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { calcTransactionTimeRemaining } from './transaction-time-remaining.util'
|
|
||||||
|
|
||||||
export default class TransactionTimeRemaining extends PureComponent {
|
|
||||||
static propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
initialTimeEstimate: PropTypes.number,
|
|
||||||
submittedTime: PropTypes.number,
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor (props) {
|
|
||||||
super(props)
|
|
||||||
const { initialTimeEstimate, submittedTime } = props
|
|
||||||
this.state = {
|
|
||||||
timeRemaining: calcTransactionTimeRemaining(initialTimeEstimate, submittedTime),
|
|
||||||
}
|
|
||||||
this.interval = setInterval(
|
|
||||||
() => this.setState({ timeRemaining: calcTransactionTimeRemaining(initialTimeEstimate, submittedTime) }),
|
|
||||||
1000
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
|
||||||
const { initialTimeEstimate, submittedTime } = this.props
|
|
||||||
if (initialTimeEstimate !== prevProps.initialTimeEstimate) {
|
|
||||||
clearInterval(this.interval)
|
|
||||||
const calcedTimeRemaining = calcTransactionTimeRemaining(initialTimeEstimate, submittedTime)
|
|
||||||
this.setState({ timeRemaining: calcedTimeRemaining })
|
|
||||||
this.interval = setInterval(
|
|
||||||
() => this.setState({ timeRemaining: calcTransactionTimeRemaining(initialTimeEstimate, submittedTime) }),
|
|
||||||
1000
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount () {
|
|
||||||
clearInterval(this.interval)
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { className } = this.props
|
|
||||||
const { timeRemaining } = this.state
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
{ timeRemaining }
|
|
||||||
</div>
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
import { connect } from 'react-redux'
|
|
||||||
import TransactionTimeRemaining from './transaction-time-remaining.component'
|
|
||||||
import {
|
|
||||||
getEstimatedGasPrices,
|
|
||||||
getEstimatedGasTimes,
|
|
||||||
} from '../../../selectors'
|
|
||||||
import { getRawTimeEstimateData } from '../../../helpers/utils/gas-time-estimates.util'
|
|
||||||
import { hexWEIToDecGWEI } from '../../../helpers/utils/conversions.util'
|
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => {
|
|
||||||
const { transaction } = ownProps
|
|
||||||
const { gasPrice: currentGasPrice } = transaction.txParams
|
|
||||||
const customGasPrice = calcCustomGasPrice(currentGasPrice)
|
|
||||||
const gasPrices = getEstimatedGasPrices(state)
|
|
||||||
const estimatedTimes = getEstimatedGasTimes(state)
|
|
||||||
|
|
||||||
const {
|
|
||||||
newTimeEstimate: initialTimeEstimate,
|
|
||||||
} = getRawTimeEstimateData(customGasPrice, gasPrices, estimatedTimes)
|
|
||||||
|
|
||||||
const submittedTime = transaction.submittedTime
|
|
||||||
|
|
||||||
return {
|
|
||||||
initialTimeEstimate,
|
|
||||||
submittedTime,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(TransactionTimeRemaining)
|
|
||||||
|
|
||||||
function calcCustomGasPrice (customGasPriceInHex) {
|
|
||||||
return Number(hexWEIToDecGWEI(customGasPriceInHex))
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { formatTimeEstimate } from '../../../helpers/utils/gas-time-estimates.util'
|
|
||||||
|
|
||||||
export function calcTransactionTimeRemaining (initialTimeEstimate, submittedTime) {
|
|
||||||
const currentTime = (new Date()).getTime()
|
|
||||||
const timeElapsedSinceSubmission = (currentTime - submittedTime) / 1000
|
|
||||||
const timeRemainingOnEstimate = initialTimeEstimate - timeElapsedSinceSubmission
|
|
||||||
|
|
||||||
const renderingTimeRemainingEstimate = timeRemainingOnEstimate < 30
|
|
||||||
? '< 30 s'
|
|
||||||
: formatTimeEstimate(timeRemainingOnEstimate)
|
|
||||||
|
|
||||||
return renderingTimeRemainingEstimate
|
|
||||||
}
|
|
18
ui/app/components/ui/icon-with-label/icon-with-label.js
Normal file
18
ui/app/components/ui/icon-with-label/icon-with-label.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
export default function IconWithLabel ({ icon, label, className }) {
|
||||||
|
return (
|
||||||
|
<div className={classnames('icon-with-label', className)}>
|
||||||
|
{icon}
|
||||||
|
{label && <span className="icon-with-label__label">{label}</span>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
IconWithLabel.propTypes = {
|
||||||
|
icon: PropTypes.node.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
label: PropTypes.string,
|
||||||
|
}
|
1
ui/app/components/ui/icon-with-label/index.js
Normal file
1
ui/app/components/ui/icon-with-label/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './icon-with-label'
|
10
ui/app/components/ui/icon-with-label/index.scss
Normal file
10
ui/app/components/ui/icon-with-label/index.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.icon-with-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 10px;
|
||||||
|
margin-left: 4px;
|
||||||
|
color: $Grey-500;
|
||||||
|
}
|
||||||
|
}
|
@ -33,12 +33,11 @@
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 160%;
|
line-height: 160%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
&-wrap {
|
&-wrap {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,9 @@ export default function ListItem ({
|
|||||||
)}
|
)}
|
||||||
<h2 className="list-item__heading">
|
<h2 className="list-item__heading">
|
||||||
{ title } {titleIcon && (
|
{ title } {titleIcon && (
|
||||||
<span className="list-item__heading-wrap">
|
<div className="list-item__heading-wrap">
|
||||||
{titleIcon}
|
{titleIcon}
|
||||||
</span>
|
</div>
|
||||||
)}
|
)}
|
||||||
</h2>
|
</h2>
|
||||||
<h3 className="list-item__subheading">
|
<h3 className="list-item__subheading">
|
||||||
|
98
ui/app/hooks/useTransactionTimeRemaining.js
Normal file
98
ui/app/hooks/useTransactionTimeRemaining.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { getEstimatedGasPrices, getEstimatedGasTimes, getFeatureFlags, getIsMainnet } from '../selectors'
|
||||||
|
import { hexWEIToDecGWEI } from '../helpers/utils/conversions.util'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { useRef, useEffect, useState, useMemo } from 'react'
|
||||||
|
import { isEqual } from 'lodash'
|
||||||
|
import { getRawTimeEstimateData } from '../helpers/utils/gas-time-estimates.util'
|
||||||
|
import { getCurrentLocale } from '../ducks/metamask/metamask'
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the number of minutes remaining until the transaction completes.
|
||||||
|
* @param {number} initialTimeEstimate - timestamp for the projected completion time
|
||||||
|
* @param {number} submittedTime - timestamp of when the tx was submitted
|
||||||
|
* @return {number} minutes remaining
|
||||||
|
*/
|
||||||
|
function calcTransactionTimeRemaining (initialTimeEstimate, submittedTime) {
|
||||||
|
const currentTime = (new Date()).getTime()
|
||||||
|
const timeElapsedSinceSubmission = (currentTime - submittedTime) / 1000
|
||||||
|
const timeRemainingOnEstimate = initialTimeEstimate - timeElapsedSinceSubmission
|
||||||
|
|
||||||
|
const renderingTimeRemainingEstimate = Math.round(timeRemainingOnEstimate / 60)
|
||||||
|
return renderingTimeRemainingEstimate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a string representing the number of minutes predicted for the transaction to be
|
||||||
|
* completed. Only returns this prediction if the transaction is the earliest pending
|
||||||
|
* transaction, and the feature flag for showing timing is enabled.
|
||||||
|
* @param {bool} isPending - is the transaction currently pending
|
||||||
|
* @param {bool} isEarliestNonce - is this transaction the earliest nonce in list
|
||||||
|
* @param {number} submittedTime - the timestamp for when the transaction was submitted
|
||||||
|
* @param {number} currentGasPrice - gas price to use for calculation of time
|
||||||
|
* @returns {string | undefined} i18n formatted string if applicable
|
||||||
|
*/
|
||||||
|
export function useTransactionTimeRemaining (
|
||||||
|
isPending,
|
||||||
|
isEarliestNonce,
|
||||||
|
submittedTime,
|
||||||
|
currentGasPrice
|
||||||
|
) {
|
||||||
|
// the following two selectors return the result of mapping over an array, as such they
|
||||||
|
// will always be new objects and trigger effects. To avoid this, we use isEqual as the
|
||||||
|
// equalityFn to only update when the data is new.
|
||||||
|
const gasPrices = useSelector(getEstimatedGasPrices, isEqual)
|
||||||
|
const estimatedTimes = useSelector(getEstimatedGasTimes, isEqual)
|
||||||
|
const locale = useSelector(getCurrentLocale)
|
||||||
|
const isMainNet = useSelector(getIsMainnet)
|
||||||
|
const interval = useRef()
|
||||||
|
const [timeRemaining, setTimeRemaining] = useState(null)
|
||||||
|
const featureFlags = useSelector(getFeatureFlags)
|
||||||
|
const transactionTimeFeatureActive = featureFlags?.transactionTime
|
||||||
|
|
||||||
|
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto', style: 'narrow' })
|
||||||
|
|
||||||
|
// Memoize this value so it can be used as a dependency in the effect below
|
||||||
|
const initialTimeEstimate = useMemo(() => {
|
||||||
|
const customGasPrice = Number(hexWEIToDecGWEI(currentGasPrice))
|
||||||
|
const {
|
||||||
|
newTimeEstimate,
|
||||||
|
} = getRawTimeEstimateData(customGasPrice, gasPrices, estimatedTimes)
|
||||||
|
return newTimeEstimate
|
||||||
|
}, [ currentGasPrice, gasPrices, estimatedTimes ])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
isMainNet &&
|
||||||
|
transactionTimeFeatureActive &&
|
||||||
|
isPending &&
|
||||||
|
isEarliestNonce &&
|
||||||
|
!isNaN(initialTimeEstimate)
|
||||||
|
) {
|
||||||
|
clearInterval(interval.current)
|
||||||
|
setTimeRemaining(
|
||||||
|
calcTransactionTimeRemaining(initialTimeEstimate, submittedTime)
|
||||||
|
)
|
||||||
|
interval.current = setInterval(() => {
|
||||||
|
setTimeRemaining(
|
||||||
|
calcTransactionTimeRemaining(initialTimeEstimate, submittedTime)
|
||||||
|
)
|
||||||
|
}, 10000)
|
||||||
|
return () => clearInterval(interval.current)
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
isMainNet,
|
||||||
|
transactionTimeFeatureActive,
|
||||||
|
isEarliestNonce,
|
||||||
|
isPending,
|
||||||
|
submittedTime,
|
||||||
|
initialTimeEstimate,
|
||||||
|
])
|
||||||
|
|
||||||
|
// there are numerous checks to determine if time should be displayed.
|
||||||
|
// if any of the following are true, the timeRemaining will be null
|
||||||
|
// User is currently not on the mainnet
|
||||||
|
// User does not have the transactionTime feature flag enabled
|
||||||
|
// The transaction is not pending, or isn't the earliest nonce
|
||||||
|
return timeRemaining ? rtf.format(timeRemaining, 'minute') : undefined
|
||||||
|
}
|
@ -24,6 +24,8 @@ export default class AdvancedTab extends PureComponent {
|
|||||||
sendHexData: PropTypes.bool,
|
sendHexData: PropTypes.bool,
|
||||||
setAdvancedInlineGasFeatureFlag: PropTypes.func,
|
setAdvancedInlineGasFeatureFlag: PropTypes.func,
|
||||||
advancedInlineGas: PropTypes.bool,
|
advancedInlineGas: PropTypes.bool,
|
||||||
|
setTransactionTimeFeatureFlag: PropTypes.func,
|
||||||
|
transactionTime: PropTypes.bool,
|
||||||
showFiatInTestnets: PropTypes.bool,
|
showFiatInTestnets: PropTypes.bool,
|
||||||
autoLockTimeLimit: PropTypes.number,
|
autoLockTimeLimit: PropTypes.number,
|
||||||
setAutoLockTimeLimit: PropTypes.func.isRequired,
|
setAutoLockTimeLimit: PropTypes.func.isRequired,
|
||||||
@ -194,6 +196,32 @@ export default class AdvancedTab extends PureComponent {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderTransactionTimeEstimates () {
|
||||||
|
const { t } = this.context
|
||||||
|
const { transactionTime, setTransactionTimeFeatureFlag } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="settings-page__content-row" data-testid="advanced-setting-transaction-time-inline">
|
||||||
|
<div className="settings-page__content-item">
|
||||||
|
<span>{ t('transactionTime') }</span>
|
||||||
|
<div className="settings-page__content-description">
|
||||||
|
{ t('showTransactionTimeDescription') }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="settings-page__content-item">
|
||||||
|
<div className="settings-page__content-item-col">
|
||||||
|
<ToggleButton
|
||||||
|
value={transactionTime}
|
||||||
|
onToggle={(value) => setTransactionTimeFeatureFlag(!value)}
|
||||||
|
offLabel={t('off')}
|
||||||
|
onLabel={t('on')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
renderShowConversionInTestnets () {
|
renderShowConversionInTestnets () {
|
||||||
const { t } = this.context
|
const { t } = this.context
|
||||||
const {
|
const {
|
||||||
@ -447,6 +475,7 @@ export default class AdvancedTab extends PureComponent {
|
|||||||
{ this.renderMobileSync() }
|
{ this.renderMobileSync() }
|
||||||
{ this.renderResetAccount() }
|
{ this.renderResetAccount() }
|
||||||
{ this.renderAdvancedGasInputInline() }
|
{ this.renderAdvancedGasInputInline() }
|
||||||
|
{ this.renderTransactionTimeEstimates() }
|
||||||
{ this.renderHexDataOptIn() }
|
{ this.renderHexDataOptIn() }
|
||||||
{ this.renderShowConversionInTestnets() }
|
{ this.renderShowConversionInTestnets() }
|
||||||
{ this.renderUseNonceOptIn() }
|
{ this.renderUseNonceOptIn() }
|
||||||
|
@ -20,6 +20,7 @@ export const mapStateToProps = (state) => {
|
|||||||
const {
|
const {
|
||||||
featureFlags: {
|
featureFlags: {
|
||||||
sendHexData,
|
sendHexData,
|
||||||
|
transactionTime,
|
||||||
advancedInlineGas,
|
advancedInlineGas,
|
||||||
} = {},
|
} = {},
|
||||||
threeBoxSyncingAllowed,
|
threeBoxSyncingAllowed,
|
||||||
@ -33,6 +34,7 @@ export const mapStateToProps = (state) => {
|
|||||||
warning,
|
warning,
|
||||||
sendHexData,
|
sendHexData,
|
||||||
advancedInlineGas,
|
advancedInlineGas,
|
||||||
|
transactionTime,
|
||||||
showFiatInTestnets,
|
showFiatInTestnets,
|
||||||
autoLockTimeLimit,
|
autoLockTimeLimit,
|
||||||
threeBoxSyncingAllowed,
|
threeBoxSyncingAllowed,
|
||||||
@ -48,6 +50,7 @@ export const mapDispatchToProps = (dispatch) => {
|
|||||||
displayWarning: (warning) => dispatch(displayWarning(warning)),
|
displayWarning: (warning) => dispatch(displayWarning(warning)),
|
||||||
showResetAccountConfirmationModal: () => dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })),
|
showResetAccountConfirmationModal: () => dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })),
|
||||||
setAdvancedInlineGasFeatureFlag: (shouldShow) => dispatch(setFeatureFlag('advancedInlineGas', shouldShow)),
|
setAdvancedInlineGasFeatureFlag: (shouldShow) => dispatch(setFeatureFlag('advancedInlineGas', shouldShow)),
|
||||||
|
setTransactionTimeFeatureFlag: (shouldShow) => dispatch(setFeatureFlag('transactionTime', shouldShow)),
|
||||||
setUseNonceField: (value) => dispatch(setUseNonceField(value)),
|
setUseNonceField: (value) => dispatch(setUseNonceField(value)),
|
||||||
setShowFiatConversionOnTestnetsPreference: (value) => {
|
setShowFiatConversionOnTestnetsPreference: (value) => {
|
||||||
return dispatch(setShowFiatConversionOnTestnetsPreference(value))
|
return dispatch(setShowFiatConversionOnTestnetsPreference(value))
|
||||||
|
@ -24,7 +24,7 @@ describe('AdvancedTab Component', function () {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.equal(root.find('.settings-page__content-row').length, 10)
|
assert.equal(root.find('.settings-page__content-row').length, 11)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should update autoLockTimeLimit', function () {
|
it('should update autoLockTimeLimit', function () {
|
||||||
@ -46,7 +46,7 @@ describe('AdvancedTab Component', function () {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const autoTimeout = root.find('.settings-page__content-row').at(7)
|
const autoTimeout = root.find('.settings-page__content-row').at(8)
|
||||||
const textField = autoTimeout.find(TextField)
|
const textField = autoTimeout.find(TextField)
|
||||||
|
|
||||||
textField.props().onChange({ target: { value: 1440 } })
|
textField.props().onChange({ target: { value: 1440 } })
|
||||||
|
19
yarn.lock
19
yarn.lock
@ -1261,6 +1261,20 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
|
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
|
||||||
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
|
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
|
||||||
|
|
||||||
|
"@formatjs/intl-relativetimeformat@^5.2.6":
|
||||||
|
version "5.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-5.2.6.tgz#3d67b75a900e7b5416615beeb2d0eeff33a1e01a"
|
||||||
|
integrity sha512-UPCY7IoyeqieUxdbfhINVjbCGXCzRr4xZpoiNsr1da4Fwm4uV6l53OXsx1zDRXoiNmMtDuKCKkRzlSfBL89L1g==
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/intl-utils" "^3.3.1"
|
||||||
|
|
||||||
|
"@formatjs/intl-utils@^3.3.1":
|
||||||
|
version "3.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@formatjs/intl-utils/-/intl-utils-3.3.1.tgz#7ceadbb7e251318729d9bf693731e1a5dcdfa15a"
|
||||||
|
integrity sha512-7AAicg2wqCJQ+gFEw5Nxp+ttavajBrPAD1HDmzA4jzvUCrF5a2NCJm/c5qON3VBubWWF2cu8HglEouj2h/l7KQ==
|
||||||
|
dependencies:
|
||||||
|
emojis-list "^3.0.0"
|
||||||
|
|
||||||
"@fortawesome/fontawesome-free@^5.13.0":
|
"@fortawesome/fontawesome-free@^5.13.0":
|
||||||
version "5.13.0"
|
version "5.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz#fcb113d1aca4b471b709e8c9c168674fbd6e06d9"
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz#fcb113d1aca4b471b709e8c9c168674fbd6e06d9"
|
||||||
@ -9162,6 +9176,11 @@ emojis-list@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
||||||
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
|
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
|
||||||
|
|
||||||
|
emojis-list@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
|
||||||
|
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
|
||||||
|
|
||||||
emotion-theming@^10.0.19:
|
emotion-theming@^10.0.19:
|
||||||
version "10.0.27"
|
version "10.0.27"
|
||||||
resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.27.tgz#1887baaec15199862c89b1b984b79806f2b9ab10"
|
resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.27.tgz#1887baaec15199862c89b1b984b79806f2b9ab10"
|
||||||
|
Loading…
Reference in New Issue
Block a user