mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-30 08:09:15 +01:00
2931957870
* 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
169 lines
4.6 KiB
JavaScript
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,
|
|
};
|