diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js index 7b7a700d60e..8eb1e9ce705 100644 --- a/src/components/structures/auth/ForgotPassword.js +++ b/src/components/structures/auth/ForgotPassword.js @@ -1,6 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd -Copyright 2017, 2018 New Vector Ltd +Copyright 2017, 2018, 2019 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,6 +25,18 @@ import SdkConfig from "../../../SdkConfig"; import PasswordReset from "../../../PasswordReset"; +// Phases +// Show controls to configure server details +const PHASE_SERVER_DETAILS = 0; +// Show the forgot password inputs +const PHASE_FORGOT = 1; +// Email is in the process of being sent +const PHASE_SENDING_EMAIL = 2; +// Email has been sent +const PHASE_EMAIL_SENT = 3; +// User has clicked the link in email and completed reset +const PHASE_DONE = 4; + module.exports = React.createClass({ displayName: 'ForgotPassword', @@ -47,28 +59,29 @@ module.exports = React.createClass({ getInitialState: function() { return { - enteredHomeserverUrl: this.props.customHsUrl || this.props.defaultHsUrl, - enteredIdentityServerUrl: this.props.customIsUrl || this.props.defaultIsUrl, - progress: null, - password: null, - password2: null, + enteredHsUrl: this.props.customHsUrl || this.props.defaultHsUrl, + enteredIsUrl: this.props.customIsUrl || this.props.defaultIsUrl, + phase: PHASE_FORGOT, + email: "", + password: "", + password2: "", errorText: null, }; }, submitPasswordReset: function(hsUrl, identityUrl, email, password) { this.setState({ - progress: "sending_email", + phase: PHASE_SENDING_EMAIL, }); this.reset = new PasswordReset(hsUrl, identityUrl); this.reset.resetPassword(email, password).done(() => { this.setState({ - progress: "sent_email", + phase: PHASE_EMAIL_SENT, }); }, (err) => { this.showErrorDialog(_t('Failed to send email') + ": " + err.message); this.setState({ - progress: null, + phase: PHASE_FORGOT, }); }); }, @@ -80,7 +93,7 @@ module.exports = React.createClass({ return; } this.reset.checkEmailLinkClicked().done((res) => { - this.setState({ progress: "complete" }); + this.setState({ phase: PHASE_DONE }); }, (err) => { this.showErrorDialog(err.message); }); @@ -126,7 +139,7 @@ module.exports = React.createClass({ onFinished: (confirmed) => { if (confirmed) { this.submitPasswordReset( - this.state.enteredHomeserverUrl, this.state.enteredIdentityServerUrl, + this.state.enteredHsUrl, this.state.enteredIsUrl, this.state.email, this.state.password, ); } @@ -153,14 +166,29 @@ module.exports = React.createClass({ onServerConfigChange: function(config) { const newState = {}; if (config.hsUrl !== undefined) { - newState.enteredHomeserverUrl = config.hsUrl; + newState.enteredHsUrl = config.hsUrl; } if (config.isUrl !== undefined) { - newState.enteredIdentityServerUrl = config.isUrl; + newState.enteredIsUrl = config.isUrl; } this.setState(newState); }, + onServerDetailsNextPhaseClick(ev) { + ev.stopPropagation(); + this.setState({ + phase: PHASE_FORGOT, + }); + }, + + onEditServerDetailsClick(ev) { + ev.preventDefault(); + ev.stopPropagation(); + this.setState({ + phase: PHASE_SERVER_DETAILS, + }); + }, + onLoginClick: function(ev) { ev.preventDefault(); ev.stopPropagation(); @@ -175,95 +203,152 @@ module.exports = React.createClass({ }); }, + renderServerDetails() { + const ServerConfig = sdk.getComponent("auth.ServerConfig"); + const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); + + if (SdkConfig.get()['disable_custom_urls']) { + return null; + } + + return
+ + + {_t("Next")} + +
; + }, + + renderForgot() { + let errorText = null; + const err = this.state.errorText || this.props.defaultServerDiscoveryError; + if (err) { + errorText =
{ err }
; + } + + let yourMatrixAccountText = _t('Your account'); + try { + const parsedHsUrl = new URL(this.state.enteredHsUrl); + yourMatrixAccountText = _t('Your account on %(serverName)s', { + serverName: parsedHsUrl.hostname, + }); + } catch (e) { + errorText =
{_t( + "The homeserver URL %(hsUrl)s doesn't seem to be valid URL. Please " + + "enter a valid URL including the protocol prefix.", + { + hsUrl: this.state.enteredHsUrl, + })}
; + } + + // If custom URLs are allowed, wire up the server details edit link. + let editLink = null; + if (!SdkConfig.get()['disable_custom_urls']) { + editLink = + {_t('Change')} + ; + } + + return
+

+ {yourMatrixAccountText} + {editLink} +

+ {errorText} +
+
+ +
+
+ + +
+ {_t( + 'A verification email will be sent to your inbox to confirm ' + + 'setting your new password.', + )} + +
+ + {_t('Sign in instead')} + +
; + }, + + renderSendingEmail() { + const Spinner = sdk.getComponent("elements.Spinner"); + return ; + }, + + renderEmailSent() { + return
+ {_t("An email has been sent to %(emailAddress)s. Once you've followed the " + + "link it contains, click below.", { emailAddress: this.state.email })} +
+ +
; + }, + + renderDone() { + return
+

{_t("Your password has been reset.")}

+

{_t( + "You have been logged out of all devices and will no longer receive " + + "push notifications. To re-enable notifications, sign in again on each " + + "device.", + )}

+ +
; + }, + render: function() { const AuthPage = sdk.getComponent("auth.AuthPage"); const AuthHeader = sdk.getComponent("auth.AuthHeader"); const AuthBody = sdk.getComponent("auth.AuthBody"); - const ServerConfig = sdk.getComponent("auth.ServerConfig"); - const Spinner = sdk.getComponent("elements.Spinner"); let resetPasswordJsx; - - if (this.state.progress === "sending_email") { - resetPasswordJsx = ; - } else if (this.state.progress === "sent_email") { - resetPasswordJsx = ( -
- { _t("An email has been sent to %(emailAddress)s. Once you've followed the link it contains, " + - "click below.", { emailAddress: this.state.email }) } -
- -
- ); - } else if (this.state.progress === "complete") { - resetPasswordJsx = ( -
-

{ _t('Your password has been reset') }.

-

{ _t('You have been logged out of all devices and will no longer receive push notifications. ' + - 'To re-enable notifications, sign in again on each device') }.

- -
- ); - } else { - let serverConfigSection; - if (!SdkConfig.get()['disable_custom_urls']) { - serverConfigSection = ( - - ); - } - - let errorText = null; - const err = this.state.errorText || this.props.defaultServerDiscoveryError; - if (err) { - errorText =
{ err }
; - } - - resetPasswordJsx = ( -
-

- { _t('To reset your password, enter the email address linked to your account') }: -

-
-
- -
- -
- -
- -
- { serverConfigSection } - { errorText } - - { _t('Sign in instead') } - -
-
- ); + switch (this.state.phase) { + case PHASE_SERVER_DETAILS: + resetPasswordJsx = this.renderServerDetails(); + break; + case PHASE_FORGOT: + resetPasswordJsx = this.renderForgot(); + break; + case PHASE_SENDING_EMAIL: + resetPasswordJsx = this.renderSendingEmail(); + break; + case PHASE_EMAIL_SENT: + resetPasswordJsx = this.renderEmailSent(); + break; + case PHASE_DONE: + resetPasswordJsx = this.renderDone(); + break; } - return ( diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 8524447ed4e..025f68bb8f5 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -31,10 +31,10 @@ import { AutoDiscovery } from "matrix-js-sdk"; const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/; // Phases -// Show the appropriate login flow(s) for the server -const PHASE_LOGIN = 0; // Show controls to configure server details -const PHASE_SERVER_DETAILS = 1; +const PHASE_SERVER_DETAILS = 0; +// Show the appropriate login flow(s) for the server +const PHASE_LOGIN = 1; // Enable phases for login const PHASES_ENABLED = true; @@ -514,7 +514,6 @@ module.exports = React.createClass({ } if (PHASES_ENABLED && this.state.phase !== PHASE_SERVER_DETAILS) { - // TODO: ... return null; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9e5b32f24c8..b411a7c003f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1374,16 +1374,17 @@ "A new password must be entered.": "A new password must be entered.", "New passwords must match each other.": "New passwords must match each other.", "Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.", + "Your account": "Your account", + "Your account on %(serverName)s": "Your account on %(serverName)s", + "The homeserver URL %(hsUrl)s doesn't seem to be valid URL. Please enter a valid URL including the protocol prefix.": "The homeserver URL %(hsUrl)s doesn't seem to be valid URL. Please enter a valid URL including the protocol prefix.", + "A verification email will be sent to your inbox to confirm setting your new password.": "A verification email will be sent to your inbox to confirm setting your new password.", + "Send Reset Email": "Send Reset Email", + "Sign in instead": "Sign in instead", "An email has been sent to %(emailAddress)s. Once you've followed the link it contains, click below.": "An email has been sent to %(emailAddress)s. Once you've followed the link it contains, click below.", "I have verified my email address": "I have verified my email address", - "Your password has been reset": "Your password has been reset", - "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device", + "Your password has been reset.": "Your password has been reset.", + "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device.": "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device.", "Return to login screen": "Return to login screen", - "To reset your password, enter the email address linked to your account": "To reset your password, enter the email address linked to your account", - "New password": "New password", - "Confirm your new password": "Confirm your new password", - "Send Reset Email": "Send Reset Email", - "Sign in instead": "Sign in instead", "Set a new password": "Set a new password", "Invalid homeserver discovery response": "Invalid homeserver discovery response", "Invalid identity server discovery response": "Invalid identity server discovery response",