mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 09:23:21 +01:00
Fix autolock field to accept decimals in Firefox (#19653)
The autolock field on the Settings screen — the field that allows users to set the duration that MetaMask will wait for until automatically locking — does not always accept decimal numbers. This breaks the e2e test for this feature as it attempts to set this field to "0.1". More specifically, the React component responsible for this field passes whatever the user inputs through the `Number` function immediately and then uses this to repopulate the input. Therefore, if the user enters "3" followed by a ".", `Number("3.")` will be called. This evaluates to the number 3, and "3" becomes the new value of the field. As a result, the "." can never be typed. Curiously, this behavior only happens in Firefox; Chrome seems to keep the "." in the input field when it's typed. This happens because `onChange` event doesn't seem to get fired until a number is typed *after* the ".". This may be due to underlying differences in the DOM between Chrome and Firefox. Regardless, always passing the input through `Number` creates other odd behavior, such as the fact that the input can never be cleared (because `Number("")` evaluates to 0). This commit solves these problems by saving the "raw" version of the user's input as well as the normalized version. The raw version is always used to populate the input, whereas the normalized version is saved in state.
This commit is contained in:
parent
16dad66da9
commit
bd12ea733a
3
app/_locales/de/messages.json
generated
3
app/_locales/de/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Ausloggen"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Sperrzeit ist zu groß"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1-Logo",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/el/messages.json
generated
3
app/_locales/el/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Αποσύνδεση"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Ο χρόνος κλειδώματος είναι πολύ μεγάλος"
|
||||
},
|
||||
"logo": {
|
||||
"message": "Λογότυπο $1",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
4
app/_locales/en/messages.json
generated
4
app/_locales/en/messages.json
generated
@ -2171,8 +2171,8 @@
|
||||
"lockMetaMask": {
|
||||
"message": "Lock MetaMask"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Lock time is too great"
|
||||
"lockTimeInvalid": {
|
||||
"message": "Lock time must be a number between 0 and 10080"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1 logo",
|
||||
|
3
app/_locales/es/messages.json
generated
3
app/_locales/es/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Bloquear"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "El tiempo de bloqueo es demasiado largo"
|
||||
},
|
||||
"logo": {
|
||||
"message": "Logo de $1",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/es_419/messages.json
generated
3
app/_locales/es_419/messages.json
generated
@ -1269,9 +1269,6 @@
|
||||
"lock": {
|
||||
"message": "Bloquear"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "El tiempo de bloqueo es demasiado largo"
|
||||
},
|
||||
"low": {
|
||||
"message": "Baja"
|
||||
},
|
||||
|
3
app/_locales/fr/messages.json
generated
3
app/_locales/fr/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Déconnexion"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Le temps de verrouillage est trop important"
|
||||
},
|
||||
"logo": {
|
||||
"message": "Logo $1",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/hi/messages.json
generated
3
app/_locales/hi/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "लॉक"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "लॉक समय बहुत अधिक है"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1 लोगो",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/id/messages.json
generated
3
app/_locales/id/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Kunci"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Lock time terlalu besar"
|
||||
},
|
||||
"logo": {
|
||||
"message": "Logo $1",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/it/messages.json
generated
3
app/_locales/it/messages.json
generated
@ -1117,9 +1117,6 @@
|
||||
"lock": {
|
||||
"message": "Disconnetti"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Tempo di inattività troppo lungo"
|
||||
},
|
||||
"mainnet": {
|
||||
"message": "Rete Ethereum Principale"
|
||||
},
|
||||
|
3
app/_locales/ja/messages.json
generated
3
app/_locales/ja/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "ロック"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "ロック時間が長すぎます"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1 ロゴ",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/ko/messages.json
generated
3
app/_locales/ko/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "잠금"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "잠금 시간이 너무 깁니다"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1 로고",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/ph/messages.json
generated
3
app/_locales/ph/messages.json
generated
@ -816,9 +816,6 @@
|
||||
"lock": {
|
||||
"message": "I-lock"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Masyadong matagal ang oras ng pag-lock"
|
||||
},
|
||||
"mainnet": {
|
||||
"message": "Ethereum Mainnet"
|
||||
},
|
||||
|
3
app/_locales/pt/messages.json
generated
3
app/_locales/pt/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Sair"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "O tempo de bloqueio é longo demais"
|
||||
},
|
||||
"logo": {
|
||||
"message": "Logotipo do $1",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/pt_BR/messages.json
generated
3
app/_locales/pt_BR/messages.json
generated
@ -1269,9 +1269,6 @@
|
||||
"lock": {
|
||||
"message": "Bloquear"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "O tempo de bloqueio é longo demais"
|
||||
},
|
||||
"low": {
|
||||
"message": "Baixa"
|
||||
},
|
||||
|
3
app/_locales/ru/messages.json
generated
3
app/_locales/ru/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Заблокировать"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Время блокировки слишком велико"
|
||||
},
|
||||
"logo": {
|
||||
"message": "логотип $1",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/tl/messages.json
generated
3
app/_locales/tl/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "I-lock"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Masyadong matagal ang oras ng pag-lock"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1 logo",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/tr/messages.json
generated
3
app/_locales/tr/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Kilitle"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Kilitleme süresi çok fazla"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1 logosu",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/vi/messages.json
generated
3
app/_locales/vi/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "Khóa"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "Thời gian khóa quá lớn"
|
||||
},
|
||||
"logo": {
|
||||
"message": "Logo $1",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/zh_CN/messages.json
generated
3
app/_locales/zh_CN/messages.json
generated
@ -1863,9 +1863,6 @@
|
||||
"lock": {
|
||||
"message": "注销"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "锁定时间过长"
|
||||
},
|
||||
"logo": {
|
||||
"message": "$1标志",
|
||||
"description": "$1 is the name of the ticker"
|
||||
|
3
app/_locales/zh_TW/messages.json
generated
3
app/_locales/zh_TW/messages.json
generated
@ -821,9 +821,6 @@
|
||||
"lock": {
|
||||
"message": "鎖定"
|
||||
},
|
||||
"lockTimeTooGreat": {
|
||||
"message": "鎖定時間過長"
|
||||
},
|
||||
"mainnet": {
|
||||
"message": "以太坊 主網路"
|
||||
},
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
POLLING_TOKEN_ENVIRONMENT_TYPES,
|
||||
ORIGIN_METAMASK,
|
||||
} from '../../../shared/constants/app';
|
||||
import { DEFAULT_AUTO_LOCK_TIME_LIMIT } from '../../../shared/constants/preferences';
|
||||
|
||||
export default class AppStateController extends EventEmitter {
|
||||
/**
|
||||
@ -32,7 +33,7 @@ export default class AppStateController extends EventEmitter {
|
||||
|
||||
this.onInactiveTimeout = onInactiveTimeout || (() => undefined);
|
||||
this.store = new ObservableStore({
|
||||
timeoutMinutes: 0,
|
||||
timeoutMinutes: DEFAULT_AUTO_LOCK_TIME_LIMIT,
|
||||
connectedStatusPopoverHasBeenShown: true,
|
||||
defaultHomeActiveTabName: null,
|
||||
browserEnvironment: {},
|
||||
|
@ -3,3 +3,5 @@ export enum ThemeType {
|
||||
dark = 'dark',
|
||||
os = 'os',
|
||||
}
|
||||
|
||||
export const DEFAULT_AUTO_LOCK_TIME_LIMIT = 0;
|
||||
|
@ -38,7 +38,7 @@ describe('Auto-Lock Timer', function () {
|
||||
await autoLockTimerInput.fill(10081);
|
||||
await driver.waitForSelector({
|
||||
css: '#autoTimeout-helper-text',
|
||||
text: 'Lock time is too great',
|
||||
text: 'Lock time must be a number between 0 and 10080',
|
||||
});
|
||||
await autoLockTimerInput.fill(sixSecsInMins);
|
||||
await driver.assertElementNotPresent('#autoTimeout-helper-text');
|
||||
|
@ -15,6 +15,7 @@ import { updateTransactionGasFees } from '../../store/actions';
|
||||
import { setCustomGasLimit, setCustomGasPrice } from '../gas/gas.duck';
|
||||
|
||||
import { KeyringType } from '../../../shared/constants/keyring';
|
||||
import { DEFAULT_AUTO_LOCK_TIME_LIMIT } from '../../../shared/constants/preferences';
|
||||
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
||||
import { stripHexPrefix } from '../../../shared/modules/hexstring-utils';
|
||||
import { decGWEIToHexWEI } from '../../../shared/modules/conversion.utils';
|
||||
@ -37,7 +38,7 @@ const initialState = {
|
||||
currentLocale: '',
|
||||
currentBlockGasLimit: '',
|
||||
preferences: {
|
||||
autoLockTimeLimit: undefined,
|
||||
autoLockTimeLimit: DEFAULT_AUTO_LOCK_TIME_LIMIT,
|
||||
showFiatInTestnets: false,
|
||||
showTestNetworks: false,
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
|
@ -25,12 +25,14 @@ import { pageChanged } from '../../ducks/history/history';
|
||||
import { prepareToLeaveSwaps } from '../../ducks/swaps/swaps';
|
||||
import { getSendStage } from '../../ducks/send';
|
||||
import { getProviderConfig } from '../../ducks/metamask/metamask';
|
||||
import { DEFAULT_AUTO_LOCK_TIME_LIMIT } from '../../../shared/constants/preferences';
|
||||
import Routes from './routes.component';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const { appState } = state;
|
||||
const { alertOpen, alertMessage, isLoading, loadingMessage } = appState;
|
||||
const { autoLockTimeLimit = 0 } = getPreferences(state);
|
||||
const { autoLockTimeLimit = DEFAULT_AUTO_LOCK_TIME_LIMIT } =
|
||||
getPreferences(state);
|
||||
const { completedOnboarding } = state.metamask;
|
||||
|
||||
return {
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
MetaMetricsEventCategory,
|
||||
MetaMetricsEventName,
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
import { DEFAULT_AUTO_LOCK_TIME_LIMIT } from '../../../../shared/constants/preferences';
|
||||
import { exportAsFile } from '../../../helpers/utils/export-utils';
|
||||
import ActionableMessage from '../../../components/ui/actionable-message';
|
||||
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
|
||||
@ -72,6 +73,7 @@ export default class AdvancedTab extends PureComponent {
|
||||
|
||||
state = {
|
||||
autoLockTimeLimit: this.props.autoLockTimeLimit,
|
||||
autoLockTimeLimitBeforeNormalization: this.props.autoLockTimeLimit,
|
||||
lockTimeError: '',
|
||||
showLedgerTransportWarning: false,
|
||||
showResultMessage: false,
|
||||
@ -379,11 +381,10 @@ export default class AdvancedTab extends PureComponent {
|
||||
<div className="settings-page__content-item">
|
||||
<div className="settings-page__content-item-col">
|
||||
<TextField
|
||||
type="number"
|
||||
id="autoTimeout"
|
||||
data-testid="auto-lockout-time"
|
||||
placeholder="5"
|
||||
value={this.state.autoLockTimeLimit}
|
||||
placeholder="0"
|
||||
value={this.state.autoLockTimeLimitBeforeNormalization}
|
||||
onChange={(e) => this.handleLockChange(e.target.value)}
|
||||
error={lockTimeError}
|
||||
fullWidth
|
||||
@ -601,21 +602,41 @@ export default class AdvancedTab extends PureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
handleLockChange(time) {
|
||||
handleLockChange(autoLockTimeLimitBeforeNormalization) {
|
||||
const { t } = this.context;
|
||||
const autoLockTimeLimit = Math.max(Number(time), 0);
|
||||
|
||||
this.setState(() => {
|
||||
let lockTimeError = '';
|
||||
if (autoLockTimeLimitBeforeNormalization === '') {
|
||||
this.setState({
|
||||
autoLockTimeLimitBeforeNormalization,
|
||||
autoLockTimeLimit: DEFAULT_AUTO_LOCK_TIME_LIMIT.toString(),
|
||||
lockTimeError: '',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (autoLockTimeLimit > 10080) {
|
||||
lockTimeError = t('lockTimeTooGreat');
|
||||
}
|
||||
const autoLockTimeLimitAfterNormalization = Number(
|
||||
autoLockTimeLimitBeforeNormalization,
|
||||
);
|
||||
|
||||
return {
|
||||
autoLockTimeLimit,
|
||||
lockTimeError,
|
||||
};
|
||||
if (
|
||||
Number.isNaN(autoLockTimeLimitAfterNormalization) ||
|
||||
autoLockTimeLimitAfterNormalization < 0 ||
|
||||
autoLockTimeLimitAfterNormalization > 10080
|
||||
) {
|
||||
this.setState({
|
||||
autoLockTimeLimitBeforeNormalization,
|
||||
autoLockTimeLimit: null,
|
||||
lockTimeError: t('lockTimeInvalid'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const autoLockTimeLimit = autoLockTimeLimitAfterNormalization;
|
||||
|
||||
this.setState({
|
||||
autoLockTimeLimitBeforeNormalization,
|
||||
autoLockTimeLimit,
|
||||
lockTimeError: '',
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,14 +31,21 @@ describe('AdvancedTab Component', () => {
|
||||
expect(restoreFile).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should update autoLockTimeLimit', () => {
|
||||
it('should default the auto-lockout time to 0', () => {
|
||||
const { queryByTestId } = renderWithProvider(<AdvancedTab />, mockStore);
|
||||
const autoLockoutTime = queryByTestId('auto-lockout-time');
|
||||
|
||||
expect(autoLockoutTime).toHaveValue('0');
|
||||
});
|
||||
|
||||
it('should update the auto-lockout time', () => {
|
||||
const { queryByTestId } = renderWithProvider(<AdvancedTab />, mockStore);
|
||||
const autoLockoutTime = queryByTestId('auto-lockout-time');
|
||||
const autoLockoutButton = queryByTestId('auto-lockout-button');
|
||||
|
||||
fireEvent.change(autoLockoutTime, { target: { value: 1440 } });
|
||||
fireEvent.change(autoLockoutTime, { target: { value: '1440' } });
|
||||
|
||||
expect(autoLockoutTime).toHaveValue(1440);
|
||||
expect(autoLockoutTime).toHaveValue('1440');
|
||||
|
||||
fireEvent.click(autoLockoutButton);
|
||||
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
} from '../../../store/actions';
|
||||
import { getPreferences } from '../../../selectors';
|
||||
import { doesUserHaveALedgerAccount } from '../../../ducks/metamask/metamask';
|
||||
import { DEFAULT_AUTO_LOCK_TIME_LIMIT } from '../../../../shared/constants/preferences';
|
||||
import AdvancedTab from './advanced-tab.component';
|
||||
|
||||
export const mapStateToProps = (state) => {
|
||||
@ -37,7 +38,7 @@ export const mapStateToProps = (state) => {
|
||||
const {
|
||||
showFiatInTestnets,
|
||||
showTestNetworks,
|
||||
autoLockTimeLimit = 0,
|
||||
autoLockTimeLimit = DEFAULT_AUTO_LOCK_TIME_LIMIT,
|
||||
} = getPreferences(state);
|
||||
|
||||
const userHasALedgerAccount = doesUserHaveALedgerAccount(state);
|
||||
|
Loading…
Reference in New Issue
Block a user