Improve no email warning during registration

This commit is contained in:
Michael Telatynski 2020-11-23 10:25:46 +00:00
parent 6f6e850075
commit 2263280035
6 changed files with 159 additions and 31 deletions

View file

@ -78,6 +78,7 @@
@import "./views/dialogs/_MessageEditHistoryDialog.scss";
@import "./views/dialogs/_ModalWidgetDialog.scss";
@import "./views/dialogs/_NewSessionReviewDialog.scss";
@import "./views/dialogs/_RegistrationEmailPromptDialog.scss";
@import "./views/dialogs/_RoomSettingsDialog.scss";
@import "./views/dialogs/_RoomSettingsDialogBridges.scss";
@import "./views/dialogs/_RoomUpgradeDialog.scss";

View file

@ -0,0 +1,28 @@
/*
Copyright 2020 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.
*/
.mx_RegistrationEmailPromptDialog {
width: 417px;
.mx_Dialog_content {
margin-bottom: 24px;
color: $tertiary-fg-color;
}
.mx_Dialog_primary {
width: 100%;
}
}

View file

@ -28,6 +28,9 @@ import withValidation from '../elements/Validation';
import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
import PassphraseField from "./PassphraseField";
import CountlyAnalytics from "../../../CountlyAnalytics";
import Field from '../elements/Field';
import RegistrationEmailPromptDialog from '../dialogs/RegistrationEmailPromptDialog';
import QuestionDialog from '../dialogs/QuestionDialog';
enum RegistrationField {
Email = "field_email",
@ -104,6 +107,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
private onSubmit = async ev => {
ev.preventDefault();
ev.persist();
if (!this.props.canSubmit) return;
@ -116,36 +120,36 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
if (this.state.email === '') {
const haveIs = Boolean(this.props.serverConfig.isUrl);
let desc;
if (this.props.serverRequiresIdServer && !haveIs) {
desc = _t(
"No identity server is configured so you cannot add an email address in order to " +
"reset your password in the future.",
);
Modal.createTrackedDialog("No identity server no email", '', QuestionDialog, {
title: _t("Warning!"),
description: _t(
"No identity server is configured so you cannot add an email address in order to " +
"reset your password in the future.",
),
button: _t("Continue"),
onFinished: async (confirmed) => {
if (confirmed) this.doSubmit(ev);
},
});
} else if (this.showEmail()) {
desc = _t(
"If you don't specify an email address, you won't be able to reset your password. " +
"Are you sure?",
);
CountlyAnalytics.instance.track("onboarding_registration_submit_warn");
Modal.createTrackedDialog("Email prompt dialog", '', RegistrationEmailPromptDialog, {
onFinished: async (confirmed: boolean, email?: string) => {
if (confirmed) {
this.setState({
email,
}, () => {
this.doSubmit(ev);
});
}
},
});
} else {
// user can't set an e-mail so don't prompt them to
this.doSubmit(ev);
return;
}
CountlyAnalytics.instance.track("onboarding_registration_submit_warn");
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
Modal.createTrackedDialog('If you don\'t specify an email address...', '', QuestionDialog, {
title: _t("Warning!"),
description: desc,
button: _t("Continue"),
onFinished: (confirmed) => {
if (confirmed) {
this.doSubmit(ev);
}
},
});
} else {
this.doSubmit(ev);
}
@ -443,7 +447,6 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
if (!this.showEmail()) {
return null;
}
const Field = sdk.getComponent('elements.Field');
const emailPlaceholder = this.authStepIsRequired('m.login.email.identity') ?
_t("Email") :
_t("Email (optional)");
@ -473,7 +476,6 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
}
renderPasswordConfirm() {
const Field = sdk.getComponent('elements.Field');
return <Field
id="mx_RegistrationForm_passwordConfirm"
ref={field => this[RegistrationField.PasswordConfirm] = field}
@ -493,7 +495,6 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
return null;
}
const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown');
const Field = sdk.getComponent('elements.Field');
const phoneLabel = this.authStepIsRequired('m.login.msisdn') ?
_t("Phone") :
_t("Phone (optional)");
@ -515,7 +516,6 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
}
renderUsername() {
const Field = sdk.getComponent('elements.Field');
return <Field
id="mx_RegistrationForm_username"
ref={field => this[RegistrationField.Username] = field}

View file

@ -0,0 +1,96 @@
/*
Copyright 2020 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 * as React from "react";
import { _t } from '../../../languageHandler';
import { IDialogProps } from "./IDialogProps";
import {useRef, useState} from "react";
import Field from "../elements/Field";
import CountlyAnalytics from "../../../CountlyAnalytics";
import withValidation from "../elements/Validation";
import * as Email from "../../../email";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
interface IProps extends IDialogProps {
onFinished(continued: boolean, email?: string): void;
}
const validation = withValidation({
rules: [
{
key: "email",
test: ({ value }) => !value || Email.looksValid(value),
invalid: () => _t("Doesn't look like a valid email address"),
},
],
});
const RegistrationEmailPromptDialog: React.FC<IProps> = ({onFinished}) => {
const [email, setEmail] = useState("");
const fieldRef = useRef<Field>();
const onSubmit = async () => {
if (email) {
const valid = await fieldRef.current.validate({ allowEmpty: false });
if (!valid) {
fieldRef.current.focus();
fieldRef.current.validate({ allowEmpty: false, focused: true });
return;
}
}
onFinished(true, email);
};
return <BaseDialog
title={_t("Continuing without email")}
className="mx_RegistrationEmailPromptDialog"
contentId="mx_RegistrationEmailPromptDialog"
onFinished={() => onFinished(false)}
fixedWidth={false}
>
<div className="mx_Dialog_content" id="mx_RegistrationEmailPromptDialog">
<p>{_t("Just a heads up, if you don't add an email and forget your password, you could " +
"<b>permanently lose access to your account.</b>", {}, {
b: sub => <b>{sub}</b>,
})}</p>
<form onSubmit={onSubmit}>
<Field
ref={fieldRef}
type="text"
label={_t("Email (optional)")}
value={email}
onChange={ev => {
setEmail(ev.target.value);
}}
onValidate={async fieldState => await validation(fieldState)}
onFocus={() => CountlyAnalytics.instance.track("onboarding_registration_email2_focus")}
onBlur={() => CountlyAnalytics.instance.track("onboarding_registration_email2_blur")}
/>
</form>
</div>
<DialogButtons
primaryButton={_t("Continue")}
onPrimaryButtonClick={onSubmit}
hasCancel={false}
/>
</BaseDialog>;
};
export default RegistrationEmailPromptDialog;

View file

@ -167,7 +167,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
}
};
private async validate({ focused, allowEmpty = true }: {focused: boolean, allowEmpty?: boolean}) {
public async validate({ focused, allowEmpty = true }: {focused?: boolean, allowEmpty?: boolean}) {
if (!this.props.onValidate) {
return;
}
@ -196,6 +196,8 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
feedbackVisible: false,
});
}
return valid;
}
public render() {

View file

@ -2045,6 +2045,10 @@
"Use this session to verify your new one, granting it access to encrypted messages:": "Use this session to verify your new one, granting it access to encrypted messages:",
"If you didnt sign in to this session, your account may be compromised.": "If you didnt sign in to this session, your account may be compromised.",
"This wasn't me": "This wasn't me",
"Doesn't look like a valid email address": "Doesn't look like a valid email address",
"Continuing without email": "Continuing without email",
"Just a heads up, if you don't add an email and forget your password, you could <b>permanently lose access to your account.</b>": "Just a heads up, if you don't add an email and forget your password, you could <b>permanently lose access to your account.</b>",
"Email (optional)": "Email (optional)",
"Please fill why you're reporting.": "Please fill why you're reporting.",
"Report Content to Your Homeserver Administrator": "Report Content to Your Homeserver Administrator",
"Reporting this message will send its unique 'event ID' to the administrator of your homeserver. If messages in this room are encrypted, your homeserver administrator will not be able to read the message text or view any files or images.": "Reporting this message will send its unique 'event ID' to the administrator of your homeserver. If messages in this room are encrypted, your homeserver administrator will not be able to read the message text or view any files or images.",
@ -2226,7 +2230,6 @@
"Keep going...": "Keep going...",
"Enter username": "Enter username",
"Enter email address": "Enter email address",
"Doesn't look like a valid email address": "Doesn't look like a valid email address",
"Enter phone number": "Enter phone number",
"Doesn't look like a valid phone number": "Doesn't look like a valid phone number",
"Email": "Email",
@ -2236,14 +2239,12 @@
"Sign in with": "Sign in with",
"Sign in": "Sign in",
"No identity server is configured so you cannot add an email address in order to reset your password in the future.": "No identity server is configured so you cannot add an email address in order to reset your password in the future.",
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "If you don't specify an email address, you won't be able to reset your password. Are you sure?",
"Use an email address to recover your account": "Use an email address to recover your account",
"Enter email address (required on this homeserver)": "Enter email address (required on this homeserver)",
"Passwords don't match": "Passwords don't match",
"Other users can invite you to rooms using your contact details": "Other users can invite you to rooms using your contact details",
"Enter phone number (required on this homeserver)": "Enter phone number (required on this homeserver)",
"Use lowercase letters, numbers, dashes and underscores only": "Use lowercase letters, numbers, dashes and underscores only",
"Email (optional)": "Email (optional)",
"Phone (optional)": "Phone (optional)",
"Register": "Register",
"Set an email for account recovery. Use email or phone to optionally be discoverable by existing contacts.": "Set an email for account recovery. Use email or phone to optionally be discoverable by existing contacts.",