diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 8bc1fbdd07..7de4141192 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1887,6 +1887,7 @@ export default React.createClass({ sessionId={this.state.register_session_id} idSid={this.state.register_id_sid} email={this.props.startingFragmentQueryParams.email} + defaultServerName={this.getDefaultServerName()} defaultServerDiscoveryError={this.state.defaultServerDiscoveryError} defaultHsUrl={this.getDefaultHsUrl()} defaultIsUrl={this.getDefaultIsUrl()} @@ -1923,6 +1924,7 @@ export default React.createClass({ { err }; } - let yourMatrixAccountText = _t('Your account'); - try { - const parsedHsUrl = new URL(this.state.enteredHsUrl); - yourMatrixAccountText = _t('Your account on %(serverName)s', { - serverName: parsedHsUrl.hostname, + let yourMatrixAccountText = _t('Your Matrix account'); + if (this.state.enteredHsUrl === this.props.defaultHsUrl) { + yourMatrixAccountText = _t('Your Matrix account on %(serverName)s', { + serverName: this.props.defaultServerName, }); - } 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, - })}
; + } else { + try { + const parsedHsUrl = new URL(this.state.enteredHsUrl); + yourMatrixAccountText = _t('Your Matrix 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. diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 025f68bb8f..4e3048483b 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -56,6 +56,15 @@ module.exports = React.createClass({ enableGuest: PropTypes.bool, + // 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 + // went wrong when finding the defaultHsUrl. + defaultServerDiscoveryError: PropTypes.string, + customHsUrl: PropTypes.string, customIsUrl: PropTypes.string, defaultHsUrl: PropTypes.string, @@ -65,10 +74,6 @@ module.exports = React.createClass({ // different homeserver without confusing users. fallbackHsUrl: PropTypes.string, - // An error passed along from higher up explaining that something - // went wrong when finding the defaultHsUrl. - defaultServerDiscoveryError: PropTypes.string, - defaultDeviceDisplayName: PropTypes.string, // login shouldn't know or care how registration is done. @@ -563,11 +568,20 @@ module.exports = React.createClass({ _renderPasswordStep: function() { const PasswordLogin = sdk.getComponent('auth.PasswordLogin'); + let onEditServerDetailsClick = null; // If custom URLs are allowed, wire up the server details edit link. if (PHASES_ENABLED && !SdkConfig.get()['disable_custom_urls']) { 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 ( diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index 03c7645721..30b553a5b1 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -48,15 +48,20 @@ module.exports = React.createClass({ sessionId: PropTypes.string, makeRegistrationUrl: PropTypes.func.isRequired, idSid: PropTypes.string, + // 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 "your account". + defaultServerName: PropTypes.string, + // An error passed along from higher up explaining that something + // went wrong when finding the defaultHsUrl. + defaultServerDiscoveryError: PropTypes.string, customHsUrl: PropTypes.string, customIsUrl: PropTypes.string, defaultHsUrl: PropTypes.string, defaultIsUrl: PropTypes.string, brand: PropTypes.string, email: PropTypes.string, - // An error passed along from higher up explaining that something - // went wrong when finding the defaultHsUrl. - defaultServerDiscoveryError: PropTypes.string, // registration shouldn't know or care how login is done. onLoginClick: PropTypes.func.isRequired, onServerConfigChange: PropTypes.func.isRequired, @@ -94,7 +99,7 @@ module.exports = React.createClass({ // If we've been given a session ID, we're resuming // straight back into UI auth doingUIAuth: Boolean(this.props.sessionId), - serverType: null, + serverType: ServerType.getTypeFromHsUrl(this.props.customHsUrl), hsUrl: this.props.customHsUrl, isUrl: this.props.customIsUrl, // Phase of the overall registration dialog. @@ -122,7 +127,7 @@ module.exports = React.createClass({ }); }, - onServerTypeChange(type, initial) { + onServerTypeChange(type) { this.setState({ serverType: type, }); @@ -148,15 +153,10 @@ module.exports = React.createClass({ hsUrl: this.props.defaultHsUrl, isUrl: this.props.defaultIsUrl, }); - // if this is the initial value from the control and we're - // already in the registration phase, don't go back to the - // server details phase (but do if it's actually a change resulting - // from user interaction). - if (!initial || !this.state.phase === PHASE_REGISTRATION) { - this.setState({ - phase: PHASE_SERVER_DETAILS, - }); - } + // Reset back to server details on type change. + this.setState({ + phase: PHASE_SERVER_DETAILS, + }); break; } }, @@ -389,12 +389,9 @@ module.exports = React.createClass({ // If we're on a different phase, we only show the server type selector, // which is always shown if we allow custom URLs at all. if (PHASES_ENABLED && this.state.phase !== PHASE_SERVER_DETAILS) { - // if we've been given a custom HS URL we should actually pass that, so - // that the appropriate section is selected at the start to match the - // homeserver URL we're using return
; @@ -436,7 +433,7 @@ module.exports = React.createClass({ return
{serverDetails} @@ -478,6 +475,14 @@ module.exports = React.createClass({ ) { 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.hsUrl === this.props.defaultHsUrl) { + hsName = this.props.defaultServerName; + } + return ; } diff --git a/src/components/views/auth/PasswordLogin.js b/src/components/views/auth/PasswordLogin.js index 8db30c6d43..1ad93f6075 100644 --- a/src/components/views/auth/PasswordLogin.js +++ b/src/components/views/auth/PasswordLogin.js @@ -40,6 +40,10 @@ class PasswordLogin extends React.Component { initialPhoneNumber: "", initialPassword: "", 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, } @@ -54,6 +58,7 @@ class PasswordLogin extends React.Component { loginType: PasswordLogin.LOGIN_FIELD_MXID, }; + this.onForgotPasswordClick = this.onForgotPasswordClick.bind(this); this.onSubmitForm = this.onSubmitForm.bind(this); this.onUsernameChanged = this.onUsernameChanged.bind(this); this.onUsernameBlur = this.onUsernameBlur.bind(this); @@ -70,6 +75,12 @@ class PasswordLogin extends React.Component { this._loginField = null; } + onForgotPasswordClick(ev) { + ev.preventDefault(); + ev.stopPropagation(); + this.props.onForgotPasswordClick(); + } + onSubmitForm(ev) { ev.preventDefault(); @@ -240,7 +251,7 @@ class PasswordLogin extends React.Component { forgotPasswordJsx = {_t('Not sure of your password? Set a new one', {}, { a: sub => {sub} @@ -249,14 +260,20 @@ class PasswordLogin extends React.Component { ; } - let signInToText = _t('Sign in'); - try { - const parsedHsUrl = new URL(this.props.hsUrl); - signInToText = _t('Sign in to %(serverName)s', { - serverName: parsedHsUrl.hostname, + let signInToText = _t('Sign in to your Matrix account'); + if (this.props.hsName) { + signInToText = _t('Sign in to your Matrix account on %(serverName)s', { + serverName: this.props.hsName, }); - } catch (e) { - // ignore + } 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; @@ -338,6 +355,8 @@ PasswordLogin.propTypes = { onPhoneNumberChanged: PropTypes.func, onPasswordChanged: PropTypes.func, loginIncorrect: PropTypes.bool, + hsName: PropTypes.string, + hsUrl: PropTypes.string, disableSubmit: PropTypes.bool, }; diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js index acde4d03fe..056411033b 100644 --- a/src/components/views/auth/RegistrationForm.js +++ b/src/components/views/auth/RegistrationForm.js @@ -50,6 +50,10 @@ module.exports = React.createClass({ onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise onEditServerDetailsClick: PropTypes.func, flows: PropTypes.arrayOf(PropTypes.object).isRequired, + // 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 "your account". + hsName: PropTypes.string, hsUrl: PropTypes.string, }, @@ -295,14 +299,20 @@ module.exports = React.createClass({ }, render: function() { - let yourMatrixAccountText = _t('Create your account'); - try { - const parsedHsUrl = new URL(this.props.hsUrl); - yourMatrixAccountText = _t('Create your %(serverName)s account', { - serverName: parsedHsUrl.hostname, + let yourMatrixAccountText = _t('Create your Matrix account'); + if (this.props.hsName) { + yourMatrixAccountText = _t('Create your Matrix account on %(serverName)s', { + serverName: this.props.hsName, }); - } catch (e) { - // ignore + } else { + try { + const parsedHsUrl = new URL(this.props.hsUrl); + yourMatrixAccountText = _t('Create your Matrix account on %(serverName)s', { + serverName: parsedHsUrl.hostname, + }); + } catch (e) { + // ignore + } } let editLink = null; diff --git a/src/components/views/auth/ServerTypeSelector.js b/src/components/views/auth/ServerTypeSelector.js index 7a28eec0ed..a9311acd7b 100644 --- a/src/components/views/auth/ServerTypeSelector.js +++ b/src/components/views/auth/ServerTypeSelector.js @@ -56,14 +56,14 @@ export const TYPES = { }, }; -function getDefaultType(defaultHsUrl) { - if (!defaultHsUrl) { +export function getTypeFromHsUrl(hsUrl) { + if (!hsUrl) { return null; - } else if (defaultHsUrl === TYPES.FREE.hsUrl) { + } else if (hsUrl === TYPES.FREE.hsUrl) { return FREE; - } else if (new URL(defaultHsUrl).hostname.endsWith('.modular.im')) { - // TODO: Use a Riot config parameter to detect Modular-ness. - // https://github.com/vector-im/riot-web/issues/8253 + } else if (new URL(hsUrl).hostname.endsWith('.modular.im')) { + // This is an unlikely case to reach, as Modular defaults to hiding the + // server type selector. return PREMIUM; } else { return ADVANCED; @@ -72,8 +72,8 @@ function getDefaultType(defaultHsUrl) { export default class ServerTypeSelector extends React.PureComponent { static propTypes = { - // The default HS URL as another way to set the initially selected type. - defaultHsUrl: PropTypes.string, + // The default selected type. + selected: PropTypes.string, // Handler called when the selected type changes. onChange: PropTypes.func.isRequired, } @@ -82,20 +82,12 @@ export default class ServerTypeSelector extends React.PureComponent { super(props); const { - defaultHsUrl, - onChange, + selected, } = props; - const type = getDefaultType(defaultHsUrl); + this.state = { - selected: type, + selected, }; - if (onChange) { - // FIXME: Supply a second 'initial' param here to flag that this is - // initialising the value rather than from user interaction - // (which sometimes we'll want to ignore). Must be a better way - // to do this. - onChange(type, true); - } } updateSelectedType(type) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5c813b1ae6..92391ee19c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1251,13 +1251,14 @@ "Username": "Username", "Mobile phone number": "Mobile phone number", "Not sure of your password? Set a new one": "Not sure of your password? Set a new one", - "Sign in to %(serverName)s": "Sign in to %(serverName)s", + "Sign in to your Matrix account": "Sign in to your Matrix account", + "Sign in to your Matrix account on %(serverName)s": "Sign in to your Matrix account on %(serverName)s", "Change": "Change", "Sign in with": "Sign in with", "Phone": "Phone", "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?", - "Create your account": "Create your account", - "Create your %(serverName)s account": "Create your %(serverName)s account", + "Create your Matrix account": "Create your Matrix account", + "Create your Matrix account on %(serverName)s": "Create your Matrix account on %(serverName)s", "Email": "Email", "Email (optional)": "Email (optional)", "Phone (optional)": "Phone (optional)", @@ -1407,8 +1408,8 @@ "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", + "Your Matrix account": "Your Matrix account", + "Your Matrix account on %(serverName)s": "Your Matrix 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", @@ -1452,6 +1453,7 @@ "A phone number is required to register on this homeserver.": "A phone number is required to register on this homeserver.", "You need to enter a username.": "You need to enter a username.", "An unknown error occurred.": "An unknown error occurred.", + "Create your account": "Create your account", "Commands": "Commands", "Results from DuckDuckGo": "Results from DuckDuckGo", "Emoji": "Emoji",