1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-30 08:09:15 +01:00
metamask-extension/ui/components/app/create-new-vault/create-new-vault.js
Mark Stacey 2931957870
Split SRP input by word (#14016)
* Initial implementation of new SrpInput component

This new version of the SrpInput component uses a separate field for
each word of the SRP. Only one field can be revealed at a time, making
it less likely that it gets accidentally revealed to somebody.

* Fix copy mistakes

* Move container div from 'create vault' to 'srp-input', and setup grid layout

* Increase size of title

* Remove hard-coded width in Storybook to allow testing different viewport sizes

* Improve layout

* Improve margins

* Update dropdown text

* Expand SRP input section

* Remove unused localized messages

* Update dropdown option names in unit tests

* Replace checkbox with show/hide toggle

* Remove unused localized message

* Fix 'data-testid' prop name

* Fix e2e test imports using paste

* Use 'ActionableMessage' component for error message

* Convert error popover to actionable message

* Add tip about pasting the SRP

* Remove invalid prop

The "info" style of `ActionableMessage` is the default, so no type is
required.

* Use more readable test convenience methods

The method `toBeInTheDocument()` is now used over `not.toBeNull()` to
improve the readability of tests. Likewise, the convenience method
`.clear` is now used to clear fields rather than manually entering the
key combination to clear a field.

* Fix misspelled word
2022-03-21 16:39:26 -02:30

169 lines
4.6 KiB
JavaScript

import React, { useCallback, useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import TextField from '../../ui/text-field';
import Button from '../../ui/button';
import CheckBox from '../../ui/check-box';
import Typography from '../../ui/typography';
import SrpInput from '../srp-input';
export default function CreateNewVault({
disabled = false,
includeTerms = false,
onSubmit,
submitText,
}) {
const [confirmPassword, setConfirmPassword] = useState('');
const [confirmPasswordError, setConfirmPasswordError] = useState('');
const [password, setPassword] = useState('');
const [passwordError, setPasswordError] = useState('');
const [seedPhrase, setSeedPhrase] = useState('');
const [termsChecked, setTermsChecked] = useState(false);
const t = useI18nContext();
const metricsEvent = useContext(MetaMetricsContext);
const onPasswordChange = useCallback(
(newPassword) => {
let newConfirmPasswordError = '';
let newPasswordError = '';
if (newPassword && newPassword.length < 8) {
newPasswordError = t('passwordNotLongEnough');
}
if (confirmPassword && newPassword !== confirmPassword) {
newConfirmPasswordError = t('passwordsDontMatch');
}
setPassword(newPassword);
setPasswordError(newPasswordError);
setConfirmPasswordError(newConfirmPasswordError);
},
[confirmPassword, t],
);
const onConfirmPasswordChange = useCallback(
(newConfirmPassword) => {
let newConfirmPasswordError = '';
if (password !== newConfirmPassword) {
newConfirmPasswordError = t('passwordsDontMatch');
}
setConfirmPassword(newConfirmPassword);
setConfirmPasswordError(newConfirmPasswordError);
},
[password, t],
);
const isValid =
!disabled &&
password &&
confirmPassword &&
password === confirmPassword &&
seedPhrase &&
(!includeTerms || termsChecked) &&
!passwordError &&
!confirmPasswordError;
const onImport = useCallback(
async (event) => {
event.preventDefault();
if (!isValid) {
return;
}
await onSubmit(password, seedPhrase);
},
[isValid, onSubmit, password, seedPhrase],
);
const toggleTermsCheck = useCallback(() => {
metricsEvent({
eventOpts: {
category: 'Onboarding',
action: 'Import Seed Phrase',
name: 'Check ToS',
},
});
setTermsChecked((currentTermsChecked) => !currentTermsChecked);
}, [metricsEvent]);
const termsOfUse = t('acceptTermsOfUse', [
<a
className="create-new-vault__terms-link"
key="create-new-vault__link-text"
href="https://metamask.io/terms.html"
target="_blank"
rel="noopener noreferrer"
>
{t('terms')}
</a>,
]);
return (
<form className="create-new-vault__form" onSubmit={onImport}>
<SrpInput onChange={setSeedPhrase} />
<div className="create-new-vault__create-password">
<TextField
id="password"
label={t('newPassword')}
type="password"
value={password}
onChange={(event) => onPasswordChange(event.target.value)}
error={passwordError}
autoComplete="new-password"
margin="normal"
largeLabel
/>
<TextField
id="confirm-password"
label={t('confirmPassword')}
type="password"
value={confirmPassword}
onChange={(event) => onConfirmPasswordChange(event.target.value)}
error={confirmPasswordError}
autoComplete="new-password"
margin="normal"
largeLabel
/>
</div>
{includeTerms ? (
<div className="create-new-vault__terms">
<CheckBox
id="create-new-vault__terms-checkbox"
dataTestId="create-new-vault__terms-checkbox"
checked={termsChecked}
onClick={toggleTermsCheck}
/>
<label
className="create-new-vault__terms-label"
htmlFor="create-new-vault__terms-checkbox"
>
<Typography tag="span">{termsOfUse}</Typography>
</label>
</div>
) : null}
<Button
className="create-new-vault__submit-button"
type="primary"
submit
disabled={!isValid}
>
{submitText}
</Button>
</form>
);
}
CreateNewVault.propTypes = {
disabled: PropTypes.bool,
includeTerms: PropTypes.bool,
onSubmit: PropTypes.func.isRequired,
submitText: PropTypes.string.isRequired,
};