diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js index 5316235fe0..a772e72c5a 100644 --- a/src/components/structures/auth/ForgotPassword.js +++ b/src/components/structures/auth/ForgotPassword.js @@ -124,13 +124,7 @@ module.exports = React.createClass({ }); }, - async onServerDetailsNextPhaseClick(ev) { - 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(); - } + async onServerDetailsNextPhaseClick() { this.setState({ phase: PHASE_FORGOT, }); @@ -160,25 +154,19 @@ 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; } - // TODO: TravisR - Pull out server discovery from ServerConfig to disable the next button? - return <div> - <ServerConfig - ref={r => this._serverConfigRef = r} - serverConfig={this.props.serverConfig} - onServerConfigChange={this.props.onServerConfigChange} - delayTimeMs={0} /> - <AccessibleButton className="mx_Login_submit" - onClick={this.onServerDetailsNextPhaseClick} - > - {_t("Next")} - </AccessibleButton> - </div>; + return <ServerConfig + serverConfig={this.props.serverConfig} + onServerConfigChange={this.props.onServerConfigChange} + delayTimeMs={0} + onAfterSubmit={this.onServerDetailsNextPhaseClick} + submitText={_t("Next")} + submitClass="mx_Login_submit" + />; }, renderForgot() { diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index af9370f2db..68b440d064 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -20,11 +20,11 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import { _t, _td } from '../../../languageHandler'; +import {_t, _td} from '../../../languageHandler'; import sdk from '../../../index'; import Login from '../../../Login'; import SdkConfig from '../../../SdkConfig'; -import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; +import {messageForResourceLimitError} from '../../../utils/ErrorUtils'; import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; // For validating phone numbers without country codes @@ -283,13 +283,7 @@ module.exports = React.createClass({ this.props.onRegisterClick(); }, - async onServerDetailsNextPhaseClick(ev) { - 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(); - } + async onServerDetailsNextPhaseClick() { this.setState({ phase: PHASE_LOGIN, }); @@ -421,7 +415,6 @@ module.exports = React.createClass({ renderServerComponent() { const ServerConfig = sdk.getComponent("auth.ServerConfig"); - const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); if (SdkConfig.get()['disable_custom_urls']) { return null; @@ -431,26 +424,19 @@ module.exports = React.createClass({ return null; } - const serverDetails = <ServerConfig - ref={r => this._serverConfigRef = r} + const serverDetailsProps = {}; + if (PHASES_ENABLED) { + serverDetailsProps.onAfterSubmit = this.onServerDetailsNextPhaseClick; + serverDetailsProps.submitText = _t("Next"); + serverDetailsProps.submitClass = "mx_Login_submit"; + } + + return <ServerConfig serverConfig={this.props.serverConfig} onServerConfigChange={this.props.onServerConfigChange} delayTimeMs={250} + {...serverDetailsProps} />; - - let nextButton = null; - if (PHASES_ENABLED) { - // TODO: TravisR - Pull out server discovery from ServerConfig to disable the next button? - nextButton = <AccessibleButton className="mx_Login_submit" - onClick={this.onServerDetailsNextPhaseClick}> - {_t("Next")} - </AccessibleButton>; - } - - return <div> - {serverDetails} - {nextButton} - </div>; }, renderLoginComponentForStep() { diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index faab8190bd..f516816033 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -286,13 +286,7 @@ module.exports = React.createClass({ }); }, - async onServerDetailsNextPhaseClick(ev) { - 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(); - } + async onServerDetailsNextPhaseClick() { this.setState({ phase: PHASE_REGISTRATION, }); @@ -337,7 +331,6 @@ module.exports = React.createClass({ const ServerTypeSelector = sdk.getComponent("auth.ServerTypeSelector"); const ServerConfig = sdk.getComponent("auth.ServerConfig"); const ModularServerConfig = sdk.getComponent("auth.ModularServerConfig"); - const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); if (SdkConfig.get()['disable_custom_urls']) { return null; @@ -354,45 +347,41 @@ module.exports = React.createClass({ </div>; } + const serverDetailsProps = {}; + if (PHASES_ENABLED) { + serverDetailsProps.onAfterSubmit = this.onServerDetailsNextPhaseClick; + serverDetailsProps.submitText = _t("Next"); + serverDetailsProps.submitClass = "mx_Login_submit"; + } + let serverDetails = null; switch (this.state.serverType) { case ServerType.FREE: break; case ServerType.PREMIUM: serverDetails = <ModularServerConfig - ref={r => this._serverConfigRef = r} serverConfig={this.props.serverConfig} onServerConfigChange={this.props.onServerConfigChange} delayTimeMs={250} + {...serverDetailsProps} />; break; case ServerType.ADVANCED: serverDetails = <ServerConfig - ref={r => this._serverConfigRef = r} serverConfig={this.props.serverConfig} onServerConfigChange={this.props.onServerConfigChange} delayTimeMs={250} + {...serverDetailsProps} />; break; } - let nextButton = null; - if (PHASES_ENABLED) { - // TODO: TravisR - Pull out server discovery from ServerConfig to disable the next button? - nextButton = <AccessibleButton className="mx_Login_submit" - onClick={this.onServerDetailsNextPhaseClick} - > - {_t("Next")} - </AccessibleButton>; - } - return <div> <ServerTypeSelector selected={this.state.serverType} onChange={this.onServerTypeChange} /> {serverDetails} - {nextButton} </div>; }, diff --git a/src/components/views/auth/ModularServerConfig.js b/src/components/views/auth/ModularServerConfig.js index ea22577dbd..5a3bc23596 100644 --- a/src/components/views/auth/ModularServerConfig.js +++ b/src/components/views/auth/ModularServerConfig.js @@ -41,6 +41,16 @@ export default class ModularServerConfig extends React.PureComponent { serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired, delayTimeMs: PropTypes.number, // time to wait before invoking onChanged + + // Called after the component calls onServerConfigChange + onAfterSubmit: PropTypes.func, + + // Optional text for the submit button. If falsey, no button will be shown. + submitText: PropTypes.string, + + // Optional class for the submit button. Only applies if the submit button + // is to be rendered. + submitClass: PropTypes.string, }; static defaultProps = { @@ -119,6 +129,16 @@ export default class ModularServerConfig extends React.PureComponent { this.setState({ hsUrl }); }; + onSubmit = async (ev) => { + ev.preventDefault(); + ev.stopPropagation(); + await this.validateServer(); + + if (this.props.onAfterSubmit) { + this.props.onAfterSubmit(); + } + }; + _waitThenInvoke(existingTimeoutId, fn) { if (existingTimeoutId) { clearTimeout(existingTimeoutId); @@ -128,6 +148,16 @@ export default class ModularServerConfig extends React.PureComponent { render() { const Field = sdk.getComponent('elements.Field'); + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + + const submitButton = this.props.submitText + ? <AccessibleButton + element="button" + type="submit" + className={this.props.submitClass} + onClick={this.onSubmit} + disabled={this.state.busy}>{this.props.submitText}</AccessibleButton> + : null; return ( <div className="mx_ServerConfig"> @@ -141,15 +171,18 @@ export default class ModularServerConfig extends React.PureComponent { </a>, }, )} - <div className="mx_ServerConfig_fields"> - <Field id="mx_ServerConfig_hsUrl" - label={_t("Server Name")} - placeholder={this.props.serverConfig.hsUrl} - value={this.state.hsUrl} - onBlur={this.onHomeserverBlur} - onChange={this.onHomeserverChange} - /> - </div> + <form onSubmit={this.onSubmit} autoComplete={false} action={null}> + <div className="mx_ServerConfig_fields"> + <Field id="mx_ServerConfig_hsUrl" + label={_t("Server Name")} + placeholder={this.props.serverConfig.hsUrl} + value={this.state.hsUrl} + onBlur={this.onHomeserverBlur} + onChange={this.onHomeserverChange} + /> + </div> + {submitButton} + </form> </div> ); } diff --git a/src/components/views/auth/ServerConfig.js b/src/components/views/auth/ServerConfig.js index 096e461efe..3967f49f18 100644 --- a/src/components/views/auth/ServerConfig.js +++ b/src/components/views/auth/ServerConfig.js @@ -30,12 +30,22 @@ import SdkConfig from "../../../SdkConfig"; export default class ServerConfig extends React.PureComponent { static propTypes = { - onServerConfigChange: PropTypes.func, + onServerConfigChange: PropTypes.func.isRequired, // The current configuration that the user is expecting to change. serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired, delayTimeMs: PropTypes.number, // time to wait before invoking onChanged + + // Called after the component calls onServerConfigChange + onAfterSubmit: PropTypes.func, + + // Optional text for the submit button. If falsey, no button will be shown. + submitText: PropTypes.string, + + // Optional class for the submit button. Only applies if the submit button + // is to be rendered. + submitClass: PropTypes.string, }; static defaultProps = { @@ -124,6 +134,16 @@ export default class ServerConfig extends React.PureComponent { this.setState({ isUrl }); }; + onSubmit = async (ev) => { + ev.preventDefault(); + ev.stopPropagation(); + await this.validateServer(); + + if (this.props.onAfterSubmit) { + this.props.onAfterSubmit(); + } + }; + _waitThenInvoke(existingTimeoutId, fn) { if (existingTimeoutId) { clearTimeout(existingTimeoutId); @@ -138,11 +158,21 @@ export default class ServerConfig extends React.PureComponent { render() { const Field = sdk.getComponent('elements.Field'); + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const errorText = this.state.errorText ? <span className='mx_ServerConfig_error'>{this.state.errorText}</span> : null; + const submitButton = this.props.submitText + ? <AccessibleButton + element="button" + type="submit" + className={this.props.submitClass} + onClick={this.onSubmit} + disabled={this.state.busy}>{this.props.submitText}</AccessibleButton> + : null; + return ( <div className="mx_ServerConfig"> <h3>{_t("Other servers")}</h3> @@ -152,24 +182,27 @@ export default class ServerConfig extends React.PureComponent { </a>, })} {errorText} - <div className="mx_ServerConfig_fields"> - <Field id="mx_ServerConfig_hsUrl" - label={_t("Homeserver URL")} - placeholder={this.props.serverConfig.hsUrl} - value={this.state.hsUrl} - onBlur={this.onHomeserverBlur} - onChange={this.onHomeserverChange} - disabled={this.state.busy} - /> - <Field id="mx_ServerConfig_isUrl" - label={_t("Identity Server URL")} - placeholder={this.props.serverConfig.isUrl} - value={this.state.isUrl} - onBlur={this.onIdentityServerBlur} - onChange={this.onIdentityServerChange} - disabled={this.state.busy} - /> - </div> + <form onSubmit={this.onSubmit} autoComplete={false} action={null}> + <div className="mx_ServerConfig_fields"> + <Field id="mx_ServerConfig_hsUrl" + label={_t("Homeserver URL")} + placeholder={this.props.serverConfig.hsUrl} + value={this.state.hsUrl} + onBlur={this.onHomeserverBlur} + onChange={this.onHomeserverChange} + disabled={this.state.busy} + /> + <Field id="mx_ServerConfig_isUrl" + label={_t("Identity Server URL")} + placeholder={this.props.serverConfig.isUrl} + value={this.state.isUrl} + onBlur={this.onIdentityServerBlur} + onChange={this.onIdentityServerChange} + disabled={this.state.busy} + /> + </div> + {submitButton} + </form> </div> ); }