Make login pass around server config objects
Very similar to password resets and registration, the components pass around a server config for usage by other components. Login is a bit more complicated and needs a few more changes to pull the logic out to a more generic layer.
This commit is contained in:
parent
b6e027f5cb
commit
0b1a0c77b7
2 changed files with 86 additions and 180 deletions
|
@ -25,7 +25,7 @@ import sdk from '../../../index';
|
||||||
import Login from '../../../Login';
|
import Login from '../../../Login';
|
||||||
import SdkConfig from '../../../SdkConfig';
|
import SdkConfig from '../../../SdkConfig';
|
||||||
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
|
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
|
||||||
import { AutoDiscovery } from "matrix-js-sdk";
|
import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
|
||||||
|
|
||||||
// For validating phone numbers without country codes
|
// For validating phone numbers without country codes
|
||||||
const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/;
|
const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/;
|
||||||
|
@ -59,19 +59,14 @@ module.exports = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
onLoggedIn: PropTypes.func.isRequired,
|
onLoggedIn: PropTypes.func.isRequired,
|
||||||
|
|
||||||
// The default server name to use when the user hasn't specified
|
|
||||||
// one. If set, `defaultHsUrl` and `defaultHsUrl` were derived for this
|
|
||||||
// via `.well-known` discovery. The server name is used instead of the
|
|
||||||
// HS URL when talking about where to "sign in to".
|
|
||||||
defaultServerName: PropTypes.string,
|
|
||||||
// An error passed along from higher up explaining that something
|
// An error passed along from higher up explaining that something
|
||||||
// went wrong when finding the defaultHsUrl.
|
// went wrong. May be replaced with a different error within the
|
||||||
defaultServerDiscoveryError: PropTypes.string,
|
// Login component.
|
||||||
|
errorText: PropTypes.string,
|
||||||
|
|
||||||
|
// If true, the component will consider itself busy.
|
||||||
|
busy: PropTypes.bool,
|
||||||
|
|
||||||
customHsUrl: PropTypes.string,
|
|
||||||
customIsUrl: PropTypes.string,
|
|
||||||
defaultHsUrl: PropTypes.string,
|
|
||||||
defaultIsUrl: PropTypes.string,
|
|
||||||
// Secondary HS which we try to log into if the user is using
|
// Secondary HS which we try to log into if the user is using
|
||||||
// the default HS but login fails. Useful for migrating to a
|
// the default HS but login fails. Useful for migrating to a
|
||||||
// different homeserver without confusing users.
|
// different homeserver without confusing users.
|
||||||
|
@ -79,12 +74,13 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
defaultDeviceDisplayName: PropTypes.string,
|
defaultDeviceDisplayName: PropTypes.string,
|
||||||
|
|
||||||
// login shouldn't know or care how registration is done.
|
// login shouldn't know or care how registration, password recovery,
|
||||||
|
// etc is done.
|
||||||
onRegisterClick: PropTypes.func.isRequired,
|
onRegisterClick: PropTypes.func.isRequired,
|
||||||
|
|
||||||
// login shouldn't care how password recovery is done.
|
|
||||||
onForgotPasswordClick: PropTypes.func,
|
onForgotPasswordClick: PropTypes.func,
|
||||||
onServerConfigChange: PropTypes.func.isRequired,
|
onServerConfigChange: PropTypes.func.isRequired,
|
||||||
|
|
||||||
|
serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -93,9 +89,6 @@ module.exports = React.createClass({
|
||||||
errorText: null,
|
errorText: null,
|
||||||
loginIncorrect: false,
|
loginIncorrect: false,
|
||||||
|
|
||||||
enteredHsUrl: this.props.customHsUrl || this.props.defaultHsUrl,
|
|
||||||
enteredIsUrl: this.props.customIsUrl || this.props.defaultIsUrl,
|
|
||||||
|
|
||||||
// used for preserving form values when changing homeserver
|
// used for preserving form values when changing homeserver
|
||||||
username: "",
|
username: "",
|
||||||
phoneCountry: null,
|
phoneCountry: null,
|
||||||
|
@ -105,10 +98,6 @@ module.exports = React.createClass({
|
||||||
phase: PHASE_LOGIN,
|
phase: PHASE_LOGIN,
|
||||||
// The current login flow, such as password, SSO, etc.
|
// The current login flow, such as password, SSO, etc.
|
||||||
currentFlow: "m.login.password",
|
currentFlow: "m.login.password",
|
||||||
|
|
||||||
// .well-known discovery
|
|
||||||
discoveryError: "",
|
|
||||||
findingHomeserver: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -139,10 +128,17 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isBusy: function() {
|
||||||
|
return this.state.busy || this.props.busy;
|
||||||
|
},
|
||||||
|
|
||||||
|
hasError: function() {
|
||||||
|
return this.state.errorText || this.props.errorText;
|
||||||
|
},
|
||||||
|
|
||||||
onPasswordLogin: function(username, phoneCountry, phoneNumber, password) {
|
onPasswordLogin: function(username, phoneCountry, phoneNumber, password) {
|
||||||
// Prevent people from submitting their password when homeserver
|
// Prevent people from submitting their password when something isn't right.
|
||||||
// discovery went wrong
|
if (this.isBusy() || this.hasError()) return;
|
||||||
if (this.state.discoveryError || this.props.defaultServerDiscoveryError) return;
|
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
busy: true,
|
busy: true,
|
||||||
|
@ -164,7 +160,7 @@ module.exports = React.createClass({
|
||||||
const usingEmail = username.indexOf("@") > 0;
|
const usingEmail = username.indexOf("@") > 0;
|
||||||
if (error.httpStatus === 400 && usingEmail) {
|
if (error.httpStatus === 400 && usingEmail) {
|
||||||
errorText = _t('This homeserver does not support login using email address.');
|
errorText = _t('This homeserver does not support login using email address.');
|
||||||
} else if (error.errcode == 'M_RESOURCE_LIMIT_EXCEEDED') {
|
} else if (error.errcode === 'M_RESOURCE_LIMIT_EXCEEDED') {
|
||||||
const errorTop = messageForResourceLimitError(
|
const errorTop = messageForResourceLimitError(
|
||||||
error.data.limit_type,
|
error.data.limit_type,
|
||||||
error.data.admin_contact, {
|
error.data.admin_contact, {
|
||||||
|
@ -194,11 +190,10 @@ module.exports = React.createClass({
|
||||||
<div>
|
<div>
|
||||||
<div>{ _t('Incorrect username and/or password.') }</div>
|
<div>{ _t('Incorrect username and/or password.') }</div>
|
||||||
<div className="mx_Login_smallError">
|
<div className="mx_Login_smallError">
|
||||||
{ _t('Please note you are logging into the %(hs)s server, not matrix.org.',
|
{_t(
|
||||||
{
|
'Please note you are logging into the %(hs)s server, not matrix.org.',
|
||||||
hs: this.props.defaultHsUrl.replace(/^https?:\/\//, ''),
|
{hs: this.props.serverConfig.hsName},
|
||||||
})
|
)}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -235,9 +230,9 @@ module.exports = React.createClass({
|
||||||
onUsernameBlur: function(username) {
|
onUsernameBlur: function(username) {
|
||||||
this.setState({
|
this.setState({
|
||||||
username: username,
|
username: username,
|
||||||
discoveryError: null,
|
errorText: null,
|
||||||
});
|
});
|
||||||
if (username[0] === "@") {
|
if (username[0] === "@" && false) { // TODO: TravisR - Restore this
|
||||||
const serverName = username.split(':').slice(1).join(':');
|
const serverName = username.split(':').slice(1).join(':');
|
||||||
try {
|
try {
|
||||||
// we have to append 'https://' to make the URL constructor happy
|
// we have to append 'https://' to make the URL constructor happy
|
||||||
|
@ -246,7 +241,7 @@ module.exports = React.createClass({
|
||||||
this._tryWellKnownDiscovery(url.hostname);
|
this._tryWellKnownDiscovery(url.hostname);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Problem parsing URL or unhandled error doing .well-known discovery:", e);
|
console.error("Problem parsing URL or unhandled error doing .well-known discovery:", e);
|
||||||
this.setState({discoveryError: _t("Failed to perform homeserver discovery")});
|
this.setState({errorText: _t("Failed to perform homeserver discovery")});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -274,32 +269,19 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onServerConfigChange: function(config) {
|
|
||||||
const self = this;
|
|
||||||
const newState = {
|
|
||||||
errorText: null, // reset err messages
|
|
||||||
};
|
|
||||||
if (config.hsUrl !== undefined) {
|
|
||||||
newState.enteredHsUrl = config.hsUrl;
|
|
||||||
}
|
|
||||||
if (config.isUrl !== undefined) {
|
|
||||||
newState.enteredIsUrl = config.isUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.onServerConfigChange(config);
|
|
||||||
this.setState(newState, function() {
|
|
||||||
self._initLoginLogic(config.hsUrl || null, config.isUrl);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onRegisterClick: function(ev) {
|
onRegisterClick: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.props.onRegisterClick();
|
this.props.onRegisterClick();
|
||||||
},
|
},
|
||||||
|
|
||||||
onServerDetailsNextPhaseClick(ev) {
|
async onServerDetailsNextPhaseClick(ev) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
// TODO: TravisR - Capture the user's input somehow else
|
||||||
|
if (this._serverConfigRef) {
|
||||||
|
// Just to make sure the user's input gets captured
|
||||||
|
await this._serverConfigRef.validateServer();
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
phase: PHASE_LOGIN,
|
phase: PHASE_LOGIN,
|
||||||
});
|
});
|
||||||
|
@ -313,64 +295,13 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_tryWellKnownDiscovery: async function(serverName) {
|
|
||||||
if (!serverName.trim()) {
|
|
||||||
// Nothing to discover
|
|
||||||
this.setState({
|
|
||||||
discoveryError: "",
|
|
||||||
findingHomeserver: false,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({findingHomeserver: true});
|
|
||||||
try {
|
|
||||||
const discovery = await AutoDiscovery.findClientConfig(serverName);
|
|
||||||
|
|
||||||
const state = discovery["m.homeserver"].state;
|
|
||||||
if (state !== AutoDiscovery.SUCCESS && state !== AutoDiscovery.PROMPT) {
|
|
||||||
this.setState({
|
|
||||||
discoveryError: discovery["m.homeserver"].error,
|
|
||||||
findingHomeserver: false,
|
|
||||||
});
|
|
||||||
} else if (state === AutoDiscovery.PROMPT) {
|
|
||||||
this.setState({
|
|
||||||
discoveryError: "",
|
|
||||||
findingHomeserver: false,
|
|
||||||
});
|
|
||||||
} else if (state === AutoDiscovery.SUCCESS) {
|
|
||||||
this.setState({
|
|
||||||
discoveryError: "",
|
|
||||||
findingHomeserver: false,
|
|
||||||
});
|
|
||||||
this.onServerConfigChange({
|
|
||||||
hsUrl: discovery["m.homeserver"].base_url,
|
|
||||||
isUrl: discovery["m.identity_server"].state === AutoDiscovery.SUCCESS
|
|
||||||
? discovery["m.identity_server"].base_url
|
|
||||||
: "",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.warn("Unknown state for m.homeserver in discovery response: ", discovery);
|
|
||||||
this.setState({
|
|
||||||
discoveryError: _t("Unknown failure discovering homeserver"),
|
|
||||||
findingHomeserver: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
this.setState({
|
|
||||||
findingHomeserver: false,
|
|
||||||
discoveryError: _t("Unknown error discovering homeserver"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_initLoginLogic: function(hsUrl, isUrl) {
|
_initLoginLogic: function(hsUrl, isUrl) {
|
||||||
const self = this;
|
const self = this;
|
||||||
hsUrl = hsUrl || this.state.enteredHsUrl;
|
hsUrl = hsUrl || this.props.serverConfig.hsUrl;
|
||||||
isUrl = isUrl || this.state.enteredIsUrl;
|
isUrl = isUrl || this.props.serverConfig.isUrl;
|
||||||
|
|
||||||
const fallbackHsUrl = hsUrl === this.props.defaultHsUrl ? this.props.fallbackHsUrl : null;
|
// TODO: TravisR - Only use this if the homeserver is the default homeserver
|
||||||
|
const fallbackHsUrl = this.props.fallbackHsUrl;
|
||||||
|
|
||||||
const loginLogic = new Login(hsUrl, isUrl, fallbackHsUrl, {
|
const loginLogic = new Login(hsUrl, isUrl, fallbackHsUrl, {
|
||||||
defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
|
defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
|
||||||
|
@ -378,8 +309,6 @@ module.exports = React.createClass({
|
||||||
this._loginLogic = loginLogic;
|
this._loginLogic = loginLogic;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
enteredHsUrl: hsUrl,
|
|
||||||
enteredIsUrl: isUrl,
|
|
||||||
busy: true,
|
busy: true,
|
||||||
loginIncorrect: false,
|
loginIncorrect: false,
|
||||||
});
|
});
|
||||||
|
@ -445,8 +374,8 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
if (err.cors === 'rejected') {
|
if (err.cors === 'rejected') {
|
||||||
if (window.location.protocol === 'https:' &&
|
if (window.location.protocol === 'https:' &&
|
||||||
(this.state.enteredHsUrl.startsWith("http:") ||
|
(this.props.serverConfig.hsUrl.startsWith("http:") ||
|
||||||
!this.state.enteredHsUrl.startsWith("http"))
|
!this.props.serverConfig.hsUrl.startsWith("http"))
|
||||||
) {
|
) {
|
||||||
errorText = <span>
|
errorText = <span>
|
||||||
{ _t("Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. " +
|
{ _t("Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. " +
|
||||||
|
@ -469,9 +398,9 @@ module.exports = React.createClass({
|
||||||
"is not blocking requests.", {},
|
"is not blocking requests.", {},
|
||||||
{
|
{
|
||||||
'a': (sub) => {
|
'a': (sub) => {
|
||||||
return <a target="_blank" rel="noopener"
|
return <a target="_blank" rel="noopener" href={this.props.serverConfig.hsUrl}>
|
||||||
href={this.state.enteredHsUrl}
|
{ sub }
|
||||||
>{ sub }</a>;
|
</a>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
) }
|
) }
|
||||||
|
@ -495,19 +424,17 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverDetails = <ServerConfig
|
const serverDetails = <ServerConfig
|
||||||
customHsUrl={this.state.enteredHsUrl}
|
ref={r => this._serverConfigRef = r}
|
||||||
customIsUrl={this.state.enteredIsUrl}
|
serverConfig={this.props.serverConfig}
|
||||||
defaultHsUrl={this.props.defaultHsUrl}
|
onServerConfigChange={this.props.onServerConfigChange}
|
||||||
defaultIsUrl={this.props.defaultIsUrl}
|
|
||||||
onServerConfigChange={this.onServerConfigChange}
|
|
||||||
delayTimeMs={250}
|
delayTimeMs={250}
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
let nextButton = null;
|
let nextButton = null;
|
||||||
if (PHASES_ENABLED) {
|
if (PHASES_ENABLED) {
|
||||||
|
// TODO: TravisR - Pull out server discovery from ServerConfig to disable the next button?
|
||||||
nextButton = <AccessibleButton className="mx_Login_submit"
|
nextButton = <AccessibleButton className="mx_Login_submit"
|
||||||
onClick={this.onServerDetailsNextPhaseClick}
|
onClick={this.onServerDetailsNextPhaseClick}>
|
||||||
>
|
|
||||||
{_t("Next")}
|
{_t("Next")}
|
||||||
</AccessibleButton>;
|
</AccessibleButton>;
|
||||||
}
|
}
|
||||||
|
@ -547,13 +474,6 @@ module.exports = React.createClass({
|
||||||
onEditServerDetailsClick = this.onEditServerDetailsClick;
|
onEditServerDetailsClick = this.onEditServerDetailsClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current HS URL is the default HS URL, then we can label it
|
|
||||||
// with the default HS name (if it exists).
|
|
||||||
let hsName;
|
|
||||||
if (this.state.enteredHsUrl === this.props.defaultHsUrl) {
|
|
||||||
hsName = this.props.defaultServerName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PasswordLogin
|
<PasswordLogin
|
||||||
onSubmit={this.onPasswordLogin}
|
onSubmit={this.onPasswordLogin}
|
||||||
|
@ -569,10 +489,9 @@ module.exports = React.createClass({
|
||||||
onPhoneNumberBlur={this.onPhoneNumberBlur}
|
onPhoneNumberBlur={this.onPhoneNumberBlur}
|
||||||
onForgotPasswordClick={this.props.onForgotPasswordClick}
|
onForgotPasswordClick={this.props.onForgotPasswordClick}
|
||||||
loginIncorrect={this.state.loginIncorrect}
|
loginIncorrect={this.state.loginIncorrect}
|
||||||
hsName={hsName}
|
serverConfig={this.props.serverConfig}
|
||||||
hsUrl={this.state.enteredHsUrl}
|
disableSubmit={this.isBusy()}
|
||||||
disableSubmit={this.state.findingHomeserver}
|
/>
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -595,9 +514,9 @@ module.exports = React.createClass({
|
||||||
const AuthPage = sdk.getComponent("auth.AuthPage");
|
const AuthPage = sdk.getComponent("auth.AuthPage");
|
||||||
const AuthHeader = sdk.getComponent("auth.AuthHeader");
|
const AuthHeader = sdk.getComponent("auth.AuthHeader");
|
||||||
const AuthBody = sdk.getComponent("auth.AuthBody");
|
const AuthBody = sdk.getComponent("auth.AuthBody");
|
||||||
const loader = this.state.busy ? <div className="mx_Login_loader"><Loader /></div> : null;
|
const loader = this.isBusy() ? <div className="mx_Login_loader"><Loader /></div> : null;
|
||||||
|
|
||||||
const errorText = this.props.defaultServerDiscoveryError || this.state.discoveryError || this.state.errorText;
|
const errorText = this.state.errorText || this.props.errorText;
|
||||||
|
|
||||||
let errorTextSection;
|
let errorTextSection;
|
||||||
if (errorText) {
|
if (errorText) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
Copyright 2017 Vector Creations Ltd
|
Copyright 2017,2019 Vector Creations Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -21,11 +21,29 @@ import classNames from 'classnames';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import SdkConfig from '../../../SdkConfig';
|
import SdkConfig from '../../../SdkConfig';
|
||||||
|
import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pure UI component which displays a username/password form.
|
* A pure UI component which displays a username/password form.
|
||||||
*/
|
*/
|
||||||
class PasswordLogin extends React.Component {
|
export default class PasswordLogin extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
onSubmit: PropTypes.func.isRequired, // fn(username, password)
|
||||||
|
onError: PropTypes.func,
|
||||||
|
onForgotPasswordClick: PropTypes.func, // fn()
|
||||||
|
initialUsername: PropTypes.string,
|
||||||
|
initialPhoneCountry: PropTypes.string,
|
||||||
|
initialPhoneNumber: PropTypes.string,
|
||||||
|
initialPassword: PropTypes.string,
|
||||||
|
onUsernameChanged: PropTypes.func,
|
||||||
|
onPhoneCountryChanged: PropTypes.func,
|
||||||
|
onPhoneNumberChanged: PropTypes.func,
|
||||||
|
onPasswordChanged: PropTypes.func,
|
||||||
|
loginIncorrect: PropTypes.bool,
|
||||||
|
disableSubmit: PropTypes.bool,
|
||||||
|
serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
onError: function() {},
|
onError: function() {},
|
||||||
onEditServerDetailsClick: null,
|
onEditServerDetailsClick: null,
|
||||||
|
@ -40,13 +58,12 @@ class PasswordLogin extends React.Component {
|
||||||
initialPhoneNumber: "",
|
initialPhoneNumber: "",
|
||||||
initialPassword: "",
|
initialPassword: "",
|
||||||
loginIncorrect: false,
|
loginIncorrect: false,
|
||||||
// This is optional and only set if we used a server name to determine
|
|
||||||
// the HS URL via `.well-known` discovery. The server name is used
|
|
||||||
// instead of the HS URL when talking about where to "sign in to".
|
|
||||||
hsName: null,
|
|
||||||
hsUrl: "",
|
|
||||||
disableSubmit: false,
|
disableSubmit: false,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
static LOGIN_FIELD_EMAIL = "login_field_email";
|
||||||
|
static LOGIN_FIELD_MXID = "login_field_mxid";
|
||||||
|
static LOGIN_FIELD_PHONE = "login_field_phone";
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -258,20 +275,14 @@ class PasswordLogin extends React.Component {
|
||||||
</span>;
|
</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let signInToText = _t('Sign in to your Matrix account');
|
let signInToText = _t('Sign in to your Matrix account on %(serverName)s', {
|
||||||
if (this.props.hsName) {
|
serverName: this.props.serverConfig.hsName,
|
||||||
signInToText = _t('Sign in to your Matrix account on %(serverName)s', {
|
});
|
||||||
serverName: this.props.hsName,
|
if (this.props.serverConfig.hsNameIsDifferent) {
|
||||||
|
// TODO: TravisR - Use tooltip to underline
|
||||||
|
signInToText = _t('Sign in to your Matrix account on <underlinedServerName />', {}, {
|
||||||
|
'underlinedServerName': () => <u>{this.props.serverConfig.hsName}</u>,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const parsedHsUrl = new URL(this.props.hsUrl);
|
|
||||||
signInToText = _t('Sign in to your Matrix account on %(serverName)s', {
|
|
||||||
serverName: parsedHsUrl.hostname,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let editLink = null;
|
let editLink = null;
|
||||||
|
@ -353,27 +364,3 @@ class PasswordLogin extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PasswordLogin.LOGIN_FIELD_EMAIL = "login_field_email";
|
|
||||||
PasswordLogin.LOGIN_FIELD_MXID = "login_field_mxid";
|
|
||||||
PasswordLogin.LOGIN_FIELD_PHONE = "login_field_phone";
|
|
||||||
|
|
||||||
PasswordLogin.propTypes = {
|
|
||||||
onSubmit: PropTypes.func.isRequired, // fn(username, password)
|
|
||||||
onError: PropTypes.func,
|
|
||||||
onForgotPasswordClick: PropTypes.func, // fn()
|
|
||||||
initialUsername: PropTypes.string,
|
|
||||||
initialPhoneCountry: PropTypes.string,
|
|
||||||
initialPhoneNumber: PropTypes.string,
|
|
||||||
initialPassword: PropTypes.string,
|
|
||||||
onUsernameChanged: PropTypes.func,
|
|
||||||
onPhoneCountryChanged: PropTypes.func,
|
|
||||||
onPhoneNumberChanged: PropTypes.func,
|
|
||||||
onPasswordChanged: PropTypes.func,
|
|
||||||
loginIncorrect: PropTypes.bool,
|
|
||||||
hsName: PropTypes.string,
|
|
||||||
hsUrl: PropTypes.string,
|
|
||||||
disableSubmit: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = PasswordLogin;
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue