diff --git a/src/components/views/auth/PassphraseConfirmField.tsx b/src/components/views/auth/PassphraseConfirmField.tsx new file mode 100644 index 0000000000..74ce711470 --- /dev/null +++ b/src/components/views/auth/PassphraseConfirmField.tsx @@ -0,0 +1,83 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { PureComponent, RefCallback, RefObject } from "react"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import Field, { IInputProps } from "../elements/Field"; +import withValidation, { IFieldState, IValidationResult } from "../elements/Validation"; +import { _t, _td } from "../../../languageHandler"; + +interface IProps extends Omit { + id?: string; + fieldRef?: RefCallback | RefObject; + autoComplete?: string; + value: string; + password: string; // The password we're confirming + + labelRequired?: string; + labelInvalid?: string; + + onChange(ev: React.FormEvent); + onValidate?(result: IValidationResult); +} + +@replaceableComponent("views.auth.EmailField") +class PassphraseConfirmField extends PureComponent { + static defaultProps = { + label: _td("Confirm password"), + labelRequired: _td("Confirm password"), + labelInvalid: _td("Passwords don't match"), + }; + + private validate = withValidation({ + rules: [ + { + key: "required", + test: ({ value, allowEmpty }) => allowEmpty || !!value, + invalid: () => _t(this.props.labelRequired), + }, + { + key: "match", + test: ({ value }) => !value || value === this.props.password, + invalid: () => _t(this.props.labelInvalid), + }, + ], + }); + + private onValidate = async (fieldState: IFieldState) => { + const result = await this.validate(fieldState); + if (this.props.onValidate) { + this.props.onValidate(result); + } + + return result; + }; + + render() { + return ; + } +} + +export default PassphraseConfirmField; diff --git a/src/components/views/auth/RegistrationForm.tsx b/src/components/views/auth/RegistrationForm.tsx index b593853f34..06ab185218 100644 --- a/src/components/views/auth/RegistrationForm.tsx +++ b/src/components/views/auth/RegistrationForm.tsx @@ -35,6 +35,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import CountryDropdown from "./CountryDropdown"; import { logger } from "matrix-js-sdk/src/logger"; +import PassphraseConfirmField from "./PassphraseConfirmField"; enum RegistrationField { Email = "field_email", @@ -295,29 +296,10 @@ export default class RegistrationForm extends React.PureComponent { - const result = await this.validatePasswordConfirmRules(fieldState); + private onPasswordConfirmValidate = (result: IValidationResult) => { this.markFieldValid(RegistrationField.PasswordConfirm, result.valid); - return result; }; - private validatePasswordConfirmRules = withValidation({ - rules: [ - { - key: "required", - test: ({ value, allowEmpty }) => allowEmpty || !!value, - invalid: () => _t("Confirm password"), - }, - { - key: "match", - test(this: RegistrationForm, { value }) { - return !value || value === this.state.password; - }, - invalid: () => _t("Passwords don't match"), - }, - ], - }); - private onPhoneCountryChange = newVal => { this.setState({ phoneCountry: newVal.iso2, @@ -477,13 +459,12 @@ export default class RegistrationForm extends React.PureComponent this[RegistrationField.PasswordConfirm] = field} - type="password" + fieldRef={field => this[RegistrationField.PasswordConfirm] = field} autoComplete="new-password" - label={_t("Confirm password")} value={this.state.passwordConfirm} + password={this.state.password} onChange={this.onPasswordConfirmChange} onValidate={this.onPasswordConfirmValidate} onFocus={() => CountlyAnalytics.instance.track("onboarding_registration_passwordConfirm_focus")}