Merge pull request #2574 from jryans/auth-login-v2

Adapt login flow for the v2 design
pull/21833/head
J. Ryan Stinnett 2019-02-06 08:48:08 +00:00 committed by GitHub
commit df91e55feb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 119 deletions

View File

@ -1676,11 +1676,6 @@ export default React.createClass({
this.showScreen("forgot_password");
},
onReturnToAppClick: function() {
// treat it the same as if the user had completed the login
this._onLoggedIn();
},
// returns a promise which resolves to the new MatrixClient
onRegistered: function(credentials) {
// XXX: This should be in state or ideally store(s) because we risk not
@ -1936,7 +1931,6 @@ export default React.createClass({
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
onForgotPasswordClick={this.onForgotPasswordClick}
enableGuest={this.props.enableGuest}
onCancelClick={MatrixClientPeg.get() ? this.onReturnToAppClick : null}
onServerConfigChange={this.onServerConfigChange}
/>
);

View File

@ -26,19 +26,18 @@ import Login from '../../../Login';
import SdkConfig from '../../../SdkConfig';
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
import { AutoDiscovery } from "matrix-js-sdk";
import * as ServerType from '../../views/auth/ServerTypeSelector';
// For validating phone numbers without country codes
const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/;
// Phases
// Show controls to configure server details
const PHASE_SERVER_DETAILS = 0;
// Show the appropriate login flow(s) for the server
const PHASE_LOGIN = 1;
const PHASE_LOGIN = 0;
// Show controls to configure server details
const PHASE_SERVER_DETAILS = 1;
// Disable phases for now, pending UX discussion on WK discovery
const PHASES_ENABLED = false;
// Enable phases for login
const PHASES_ENABLED = true;
// These are used in several places, and come from the js-sdk's autodiscovery
// stuff. We define them here so that they'll be picked up by i18n.
@ -77,7 +76,6 @@ module.exports = React.createClass({
// login shouldn't care how password recovery is done.
onForgotPasswordClick: PropTypes.func,
onCancelClick: PropTypes.func,
onServerConfigChange: PropTypes.func.isRequired,
},
@ -87,7 +85,6 @@ module.exports = React.createClass({
errorText: null,
loginIncorrect: false,
serverType: null,
enteredHsUrl: this.props.customHsUrl || this.props.defaultHsUrl,
enteredIsUrl: this.props.customIsUrl || this.props.defaultIsUrl,
@ -97,7 +94,7 @@ module.exports = React.createClass({
phoneNumber: "",
// Phase of the overall login dialog.
phase: PHASE_SERVER_DETAILS,
phase: PHASE_LOGIN,
// The current login flow, such as password, SSO, etc.
currentFlow: "m.login.password",
@ -263,11 +260,6 @@ module.exports = React.createClass({
username: username,
discoveryError: null,
});
// If the free server type is selected, we don't show server details at all,
// so it doesn't make sense to try .well-known discovery.
if (this.state.serverType === ServerType.FREE) {
return;
}
if (username[0] === "@") {
const serverName = username.split(':').slice(1).join(':');
try {
@ -323,39 +315,6 @@ module.exports = React.createClass({
});
},
onServerTypeChange(type) {
this.setState({
serverType: type,
});
// When changing server types, set the HS / IS URLs to reasonable defaults for the
// the new type.
switch (type) {
case ServerType.FREE: {
const { hsUrl, isUrl } = ServerType.TYPES.FREE;
this.onServerConfigChange({
hsUrl,
isUrl,
});
// Move directly to the login phase since the server details are fixed.
this.setState({
phase: PHASE_LOGIN,
});
break;
}
case ServerType.PREMIUM:
case ServerType.ADVANCED:
this.onServerConfigChange({
hsUrl: this.props.defaultHsUrl,
isUrl: this.props.defaultIsUrl,
});
this.setState({
phase: PHASE_SERVER_DETAILS,
});
break;
}
},
onRegisterClick: function(ev) {
ev.preventDefault();
ev.stopPropagation();
@ -391,14 +350,6 @@ module.exports = React.createClass({
try {
const discovery = await AutoDiscovery.findClientConfig(serverName);
// The server type may have changed while discovery began in the background.
// If it has become the free server type which doesn't show server details,
// ignore discovery results.
if (this.state.serverType === ServerType.FREE) {
this.setState({findingHomeserver: false});
return;
}
const state = discovery["m.homeserver"].state;
if (state !== AutoDiscovery.SUCCESS && state !== AutoDiscovery.PROMPT) {
this.setState({
@ -554,51 +505,27 @@ module.exports = React.createClass({
return errorText;
},
renderServerComponentForStep() {
const ServerTypeSelector = sdk.getComponent("auth.ServerTypeSelector");
renderServerComponent() {
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;
}
// 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) {
return <div>
<ServerTypeSelector
defaultHsUrl={this.props.defaultHsUrl}
onChange={this.onServerTypeChange}
/>
</div>;
// TODO: ...
return null;
}
let serverDetails = null;
switch (this.state.serverType) {
case ServerType.FREE:
break;
case ServerType.PREMIUM:
serverDetails = <ModularServerConfig
customHsUrl={this.state.enteredHsUrl}
defaultHsUrl={this.props.defaultHsUrl}
defaultIsUrl={this.props.defaultIsUrl}
onServerConfigChange={this.onServerConfigChange}
delayTimeMs={250}
/>;
break;
case ServerType.ADVANCED:
serverDetails = <ServerConfig
customHsUrl={this.state.enteredHsUrl}
customIsUrl={this.state.enteredIsUrl}
defaultHsUrl={this.props.defaultHsUrl}
defaultIsUrl={this.props.defaultIsUrl}
onServerConfigChange={this.onServerConfigChange}
delayTimeMs={250}
/>;
break;
}
const serverDetails = <ServerConfig
customHsUrl={this.state.enteredHsUrl}
customIsUrl={this.state.enteredIsUrl}
defaultHsUrl={this.props.defaultHsUrl}
defaultIsUrl={this.props.defaultIsUrl}
onServerConfigChange={this.onServerConfigChange}
delayTimeMs={250}
/>;
let nextButton = null;
if (PHASES_ENABLED) {
@ -610,10 +537,6 @@ module.exports = React.createClass({
}
return <div>
<ServerTypeSelector
defaultHsUrl={this.props.defaultHsUrl}
onChange={this.onServerTypeChange}
/>
{serverDetails}
{nextButton}
</div>;
@ -642,13 +565,8 @@ module.exports = React.createClass({
_renderPasswordStep: function() {
const PasswordLogin = sdk.getComponent('auth.PasswordLogin');
let onEditServerDetailsClick = null;
// If custom URLs are allowed and we haven't selected the Free server type, wire
// up the server details edit link.
if (
PHASES_ENABLED &&
!SdkConfig.get()['disable_custom_urls'] &&
this.state.serverType !== ServerType.FREE
) {
// If custom URLs are allowed, wire up the server details edit link.
if (PHASES_ENABLED && !SdkConfig.get()['disable_custom_urls']) {
onEditServerDetailsClick = this.onEditServerDetailsClick;
}
return (
@ -717,11 +635,11 @@ module.exports = React.createClass({
<AuthHeader />
<AuthBody>
<h2>
{_t('Sign in to your account')}
{_t('Sign in')}
{loader}
</h2>
{ errorTextSection }
{ this.renderServerComponentForStep() }
{ this.renderServerComponent() }
{ this.renderLoginComponentForStep() }
<a className="mx_AuthBody_changeFlow" onClick={this.onRegisterClick} href="#">
{ _t('Create account') }

View File

@ -249,10 +249,10 @@ class PasswordLogin extends React.Component {
</span>;
}
let yourMatrixAccountText = _t('Your account');
let signInToText = _t('Sign in');
try {
const parsedHsUrl = new URL(this.props.hsUrl);
yourMatrixAccountText = _t('Your %(serverName)s account', {
signInToText = _t('Sign in to %(serverName)s', {
serverName: parsedHsUrl.hostname,
});
} catch (e) {
@ -264,7 +264,7 @@ class PasswordLogin extends React.Component {
editLink = <a className="mx_AuthBody_editServerDetails"
href="#" onClick={this.props.onEditServerDetailsClick}
>
{_t('Edit')}
{_t('Change')}
</a>;
}
@ -297,7 +297,7 @@ class PasswordLogin extends React.Component {
return (
<div>
<h3>
{yourMatrixAccountText}
{signInToText}
{editLink}
</h3>
<form onSubmit={this.onSubmitForm}>

View File

@ -870,12 +870,12 @@
"Delete widget": "Delete widget",
"Failed to remove widget": "Failed to remove widget",
"An error ocurred whilst trying to remove the widget from the room": "An error ocurred whilst trying to remove the widget from the room",
"Revoke widget access": "Revoke widget access",
"Minimize apps": "Minimize apps",
"Reload widget": "Reload widget",
"Popout widget": "Popout widget",
"Picture": "Picture",
"Edit": "Edit",
"Revoke widget access": "Revoke widget access",
"Create new room": "Create new room",
"Unblacklist": "Unblacklist",
"Blacklist": "Blacklist",
@ -1064,7 +1064,6 @@
"To help avoid duplicate issues, please <existingIssuesLink>view existing issues</existingIssuesLink> first (and add a +1) or <newIssueLink>create a new issue</newIssueLink> if you can't find it.": "To help avoid duplicate issues, please <existingIssuesLink>view existing issues</existingIssuesLink> first (and add a +1) or <newIssueLink>create a new issue</newIssueLink> if you can't find it.",
"Report bugs & give feedback": "Report bugs & give feedback",
"Go back": "Go back",
"Visit old settings": "Visit old settings",
"Room Settings": "Room Settings",
"Failed to upgrade room": "Failed to upgrade room",
"The room upgrade could not be completed": "The room upgrade could not be completed",
@ -1196,10 +1195,10 @@
"Username": "Username",
"Mobile phone number": "Mobile phone number",
"Not sure of your password? <a>Set a new one</a>": "Not sure of your password? <a>Set a new one</a>",
"Your account": "Your account",
"Your %(serverName)s account": "Your %(serverName)s account",
"Sign in with": "Sign in with",
"Sign in": "Sign in",
"Sign in to %(serverName)s": "Sign in to %(serverName)s",
"Change": "Change",
"Sign in with": "Sign in with",
"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",
@ -1403,7 +1402,6 @@
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.",
"Sign in with single sign-on": "Sign in with single sign-on",
"Try the app first": "Try the app first",
"Sign in to your account": "Sign in to your account",
"Create account": "Create account",
"Failed to fetch avatar URL": "Failed to fetch avatar URL",
"Set a display name:": "Set a display name:",

View File

@ -0,0 +1,90 @@
/*
Copyright 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.
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 expect from 'expect';
import sinon from 'sinon';
import React from 'react';
import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-dom/test-utils';
import sdk from 'matrix-react-sdk';
import SdkConfig from '../../../../src/SdkConfig';
import * as TestUtils from '../../../test-utils';
const Login = sdk.getComponent(
'structures.auth.Login',
);
describe('Login', function() {
let parentDiv;
beforeEach(function() {
TestUtils.beforeEach(this);
parentDiv = document.createElement('div');
document.body.appendChild(parentDiv);
});
afterEach(function() {
sinon.restore();
ReactDOM.unmountComponentAtNode(parentDiv);
parentDiv.remove();
});
function render() {
return ReactDOM.render(<Login
defaultHsUrl="https://matrix.org"
defaultIsUrl="https://vector.im"
onLoggedIn={() => {}}
onRegisterClick={() => {}}
onServerConfigChange={() => {}}
/>, parentDiv);
}
it('should show form with change server link', function() {
const root = render();
const form = ReactTestUtils.findRenderedComponentWithType(
root,
sdk.getComponent('auth.PasswordLogin'),
);
expect(form).toBeTruthy();
const changeServerLink = ReactTestUtils.findRenderedDOMComponentWithClass(
root,
'mx_AuthBody_editServerDetails',
);
expect(changeServerLink).toBeTruthy();
});
it('should show form without change server link when custom URLs disabled', function() {
sinon.stub(SdkConfig, "get").returns({
disable_custom_urls: true,
});
const root = render();
const form = ReactTestUtils.findRenderedComponentWithType(
root,
sdk.getComponent('auth.PasswordLogin'),
);
expect(form).toBeTruthy();
const changeServerLinks = ReactTestUtils.scryRenderedDOMComponentsWithClass(
root,
'mx_AuthBody_editServerDetails',
);
expect(changeServerLinks).toHaveLength(0);
});
});