From 05eda88ea264e73d6669b0efd20c6d19ae7428b8 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 12 Nov 2015 11:57:33 +0000 Subject: [PATCH 1/6] Split out logic/UI for logging in - Add 'PasswordLogin' UI component - Add 'LoginPage' wire component which, along with Signup from react SDK, replaces the 'Login' page. - Move UI code (state/props) from ServerConfig which was lobotomoised in the React SDK. Unfinished. --- src/skins/vector/skindex.js | 2 + .../vector/views/molecules/ServerConfig.js | 133 +++++++++++-- .../vector/views/organisms/PasswordLogin.js | 64 +++++++ src/skins/vector/views/pages/LoginPage.js | 176 ++++++++++++++++++ src/skins/vector/views/pages/MatrixChat.js | 7 +- 5 files changed, 367 insertions(+), 15 deletions(-) create mode 100644 src/skins/vector/views/organisms/PasswordLogin.js create mode 100644 src/skins/vector/views/pages/LoginPage.js diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js index cf279c87..e05d3e65 100644 --- a/src/skins/vector/skindex.js +++ b/src/skins/vector/skindex.js @@ -71,6 +71,7 @@ skin['molecules.voip.CallView'] = require('./views/molecules/voip/CallView'); skin['molecules.voip.IncomingCallBox'] = require('./views/molecules/voip/IncomingCallBox'); skin['molecules.voip.VideoView'] = require('./views/molecules/voip/VideoView'); skin['organisms.CasLogin'] = require('./views/organisms/CasLogin'); +skin['organisms.PasswordLogin'] = require('./views/organisms/PasswordLogin'); skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom'); skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog'); skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel'); @@ -87,6 +88,7 @@ skin['organisms.UserSettings'] = require('./views/organisms/UserSettings'); skin['organisms.ViewSource'] = require('./views/organisms/ViewSource'); skin['pages.CompatibilityPage'] = require('./views/pages/CompatibilityPage'); skin['pages.MatrixChat'] = require('./views/pages/MatrixChat'); +skin['pages.LoginPage'] = require('./views/pages/LoginPage'); skin['templates.Login'] = require('./views/templates/Login'); skin['templates.Register'] = require('./views/templates/Register'); diff --git a/src/skins/vector/views/molecules/ServerConfig.js b/src/skins/vector/views/molecules/ServerConfig.js index d6947727..fcc8bfc5 100644 --- a/src/skins/vector/views/molecules/ServerConfig.js +++ b/src/skins/vector/views/molecules/ServerConfig.js @@ -20,37 +20,142 @@ var React = require('react'); var Modal = require('matrix-react-sdk/lib/Modal'); var sdk = require('matrix-react-sdk') -var ServerConfigController = require('matrix-react-sdk/lib/controllers/molecules/ServerConfig') - +/** + * A pure UI component which displays the HS and IS to use. + */ module.exports = React.createClass({ displayName: 'ServerConfig', - mixins: [ServerConfigController], + + propTypes: { + onHsUrlChanged: React.PropTypes.func, + onIsUrlChanged: React.PropTypes.func, + defaultHsUrl: React.PropTypes.string, + defaultIsUrl: React.PropTypes.string, + withToggleButton: React.PropTypes.bool, + delayTimeMs: React.PropTypes.number // time to wait before invoking onChanged + }, + + getDefaultProps: function() { + return { + onHsUrlChanged: function() {}, + onIsUrlChanged: function() {}, + withToggleButton: false, + delayTimeMs: 0 + }; + }, + + getInitialState: function() { + return { + hs_url: this.props.defaultHsUrl, + is_url: this.props.defaultIsUrl, + original_hs_url: this.props.defaultHsUrl, + original_is_url: this.props.defaultIsUrl, + // no toggle button = show, toggle button = hide + configVisible: !this.props.withToggleButton + } + }, + + onHomeserverChanged: function(ev) { + this.setState({hs_url: ev.target.value}, function() { + this._hsTimeoutId = this._waitThenInvoke(this._hsTimeoutId, function() { + this.props.onHsUrlChanged(this.state.hs_url); + }); + }); + }, + + onIdentityServerChanged: function(ev) { + this.setState({is_url: ev.target.value}, function() { + this._isTimeoutId = this._waitThenInvoke(this._isTimeoutId, function() { + this.props.onIsUrlChanged(this.state.is_url); + }); + }); + }, + + _waitThenInvoke: function(existingTimeoutId, fn) { + if (existingTimeoutId) { + clearTimeout(existingTimeoutId); + } + return setTimeout(fn.bind(this), this.props.delayTimeMs); + }, + + getHsUrl: function() { + return this.state.hs_url; + }, + + getIsUrl: function() { + return this.state.is_url; + }, + + onServerConfigVisibleChange: function(ev) { + this.setState({ + configVisible: ev.target.checked + }); + }, showHelpPopup: function() { var ErrorDialog = sdk.getComponent('organisms.ErrorDialog'); Modal.createDialog(ErrorDialog, { title: 'Custom Server Options', description: - You can use the custom server options to log into other Matrix servers by specifying a different Home server URL.
- This allows you to use Vector with an existing Matrix account on a different Home server.
+ You can use the custom server options to log into other Matrix + servers by specifying a different Home server URL.
- You can also set a custom Identity server but this will affect people's ability to find you - if you use a server in a group other than the main Matrix.org group. + This allows you to use Vector with an existing Matrix account on + a different Home server. +
+
+ You can also set a custom Identity server but this will affect + people's ability to find you if you use a server in a group other + than the main Matrix.org group.
, button: "Dismiss", - focus: true, + focus: true }); }, render: function() { + var serverConfigStyle = {}; + serverConfigStyle.display = this.state.configVisible ? 'block' : 'none'; + + var toggleButton; + if (this.props.withToggleButton) { + toggleButton = ( +
+ + +
+ ); + } + return ( -
- - - - - What does this mean? +
+ {toggleButton} +
+
+ + + + + + What does this mean? + +
+
); } }); diff --git a/src/skins/vector/views/organisms/PasswordLogin.js b/src/skins/vector/views/organisms/PasswordLogin.js new file mode 100644 index 00000000..ff277ced --- /dev/null +++ b/src/skins/vector/views/organisms/PasswordLogin.js @@ -0,0 +1,64 @@ +/* +Copyright 2015 OpenMarket 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. +*/ + +var React = require('react'); +var ReactDOM = require('react-dom'); + +/** + * A pure UI component which displays a username/password form. + */ +module.exports = React.createClass({displayName: 'PasswordLogin', + propTypes: { + onSubmit: React.PropTypes.func.isRequired // fn(username, password) + }, + + getInitialState: function() { + return { + username: "", + password: "" + }; + }, + + onSubmitForm: function() { + this.props.onSubmit(this.state.username, this.state.password); + }, + + onUsernameChanged: function(ev) { + this.setState({username: ev.target.value}); + }, + + onPasswordChanged: function(ev) { + this.setState({password: ev.target.value}); + }, + + render: function() { + return ( +
+
+ +
+ +
+ +
+
+ ); + } +}); \ No newline at end of file diff --git a/src/skins/vector/views/pages/LoginPage.js b/src/skins/vector/views/pages/LoginPage.js new file mode 100644 index 00000000..7b4f636f --- /dev/null +++ b/src/skins/vector/views/pages/LoginPage.js @@ -0,0 +1,176 @@ +/* +Copyright 2015 OpenMarket 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. +*/ + +'use strict'; + +var React = require('react'); +var ReactDOM = require('react-dom'); +var sdk = require('matrix-react-sdk'); +var Signup = require("matrix-react-sdk/lib/Signup"); + +/** + * A wire component which glues together login UI components and Signup logic + */ +module.exports = React.createClass({displayName: 'LoginPage', + propTypes: { + onLoggedIn: React.PropTypes.func.isRequired, + homeserverUrl: React.PropTypes.string, + identityServerUrl: React.PropTypes.string, + // login shouldn't know or care how registration is done. + onRegisterClick: React.PropTypes.func.isRequired + }, + + getDefaultProps: function() { + return { + homeserverUrl: 'https://matrix.org/', + identityServerUrl: 'https://matrix.org/' + }; + }, + + getInitialState: function() { + return { + busy: false, + errorText: null, + enteredHomeserverUrl: this.props.homeserverUrl, + enteredIdentityServerUrl: this.props.identityServerUrl + }; + }, + + componentWillMount: function() { + this._initLoginLogic(); + }, + + onPasswordLogin: function(username, password) { + // TODO + console.log("onPasswordLogin %s %s", username, password); + }, + + onHsUrlChanged: function(newHsUrl) { + console.log("onHsUrlChanged %s", newHsUrl); + this._initLoginLogic(newHsUrl); + }, + + _initLoginLogic: function(hsUrl, isUrl) { + var self = this; + hsUrl = hsUrl || this.state.enteredHomeserverUrl; + isUrl = isUrl || this.state.enteredIdentityServerUrl; + + var loginLogic = new Signup.Login(hsUrl, isUrl); + this._loginLogic = loginLogic; + + loginLogic.getFlows().then(function(flows) { + // old behaviour was to always use the first flow without presenting + // options. This works in most cases (we don't have a UI for multiple + // logins so let's skip that for now). + loginLogic.chooseFlow(0); + }, function(err) { + self._setErrorTextFromError(err); + }).finally(function() { + self.setState({ + busy: false + }); + }); + + this.setState({ + enteredHomeserverUrl: hsUrl, + enteredIdentityServerUrl: isUrl, + busy: true, + errorText: null // reset err messages + }); + }, + + _getCurrentFlowStep: function() { + return this._loginLogic ? this._loginLogic.getCurrentFlowStep() : null + }, + + _setErrorTextFromError: function(err) { + var errCode = err.errcode; + if (!errCode && err.httpStatus) { + errCode = "HTTP " + err.httpStatus; + } + this.setState({ + errorText: ( + "Error: Problem communicating with the given homeserver " + + (errCode ? "(" + errCode + ")" : "") + ) + }); + }, + + componentForStep: function(step) { + switch (step) { + case 'm.login.password': + var PasswordLogin = sdk.getComponent('organisms.PasswordLogin'); + return ( + + ); + case 'm.login.cas': + var CasLogin = sdk.getComponent('organisms.CasLogin'); + return ( + + ); + default: + if (!step) { + return; + } + return ( +
+ Sorry, this homeserver is using a login which is not + recognised by Vector ({step}) +
+ ); + } + }, + + render: function() { + var Loader = sdk.getComponent("atoms.Spinner"); + var loader = this.state.busy ?
: null; + var ServerConfig = sdk.getComponent("molecules.ServerConfig"); + + return ( +
+
+
+ vector +
+
+

Sign in

+ {this.componentForStep(this._getCurrentFlowStep())} + +
+ { loader } + {this.state.errorText} +
+ + Create a new account + +
+
+ blog  ·   + twitter  ·   + github  ·   + powered by Matrix +
+
+
+
+ ); + } +}); diff --git a/src/skins/vector/views/pages/MatrixChat.js b/src/skins/vector/views/pages/MatrixChat.js index 0553c25a..0fea1f36 100644 --- a/src/skins/vector/views/pages/MatrixChat.js +++ b/src/skins/vector/views/pages/MatrixChat.js @@ -89,6 +89,10 @@ module.exports = React.createClass({ }); }, + onRegisterClick: function() { + this.showScreen("register"); + }, + render: function() { var LeftPanel = sdk.getComponent('organisms.LeftPanel'); var RoomView = sdk.getComponent('organisms.RoomView'); @@ -164,8 +168,9 @@ module.exports = React.createClass({ /> ); } else { + var LoginPage = sdk.getComponent("pages.LoginPage"); return ( - + ); } } From 8826eb60cc0a4401adf59380c58def4c081aca63 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 12 Nov 2015 15:16:29 +0000 Subject: [PATCH 2/6] Call through to password login --- .../vector/views/organisms/PasswordLogin.js | 3 +- src/skins/vector/views/pages/LoginPage.js | 29 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/skins/vector/views/organisms/PasswordLogin.js b/src/skins/vector/views/organisms/PasswordLogin.js index ff277ced..fabd71d6 100644 --- a/src/skins/vector/views/organisms/PasswordLogin.js +++ b/src/skins/vector/views/organisms/PasswordLogin.js @@ -32,7 +32,8 @@ module.exports = React.createClass({displayName: 'PasswordLogin', }; }, - onSubmitForm: function() { + onSubmitForm: function(ev) { + ev.preventDefault(); this.props.onSubmit(this.state.username, this.state.password); }, diff --git a/src/skins/vector/views/pages/LoginPage.js b/src/skins/vector/views/pages/LoginPage.js index 7b4f636f..00f46a37 100644 --- a/src/skins/vector/views/pages/LoginPage.js +++ b/src/skins/vector/views/pages/LoginPage.js @@ -54,15 +54,30 @@ module.exports = React.createClass({displayName: 'LoginPage', }, onPasswordLogin: function(username, password) { - // TODO - console.log("onPasswordLogin %s %s", username, password); + var self = this; + self.setState({ + busy: true + }); + + this._loginLogic.loginViaPassword(username, password).then(function(data) { + self.props.onLoggedIn(data); + }, function(error) { + self._setErrorTextFromError(error); + }).finally(function() { + self.setState({ + busy: false + }); + }); }, onHsUrlChanged: function(newHsUrl) { - console.log("onHsUrlChanged %s", newHsUrl); this._initLoginLogic(newHsUrl); }, + onIsUrlChanged: function(newIsUrl) { + this._initLoginLogic(null, newIsUrl); + }, + _initLoginLogic: function(hsUrl, isUrl) { var self = this; hsUrl = hsUrl || this.state.enteredHomeserverUrl; @@ -97,6 +112,13 @@ module.exports = React.createClass({displayName: 'LoginPage', }, _setErrorTextFromError: function(err) { + if (err.friendlyText) { + this.setState({ + errorText: err.friendlyText + }); + return; + } + var errCode = err.errcode; if (!errCode && err.httpStatus) { errCode = "HTTP " + err.httpStatus; @@ -153,6 +175,7 @@ module.exports = React.createClass({displayName: 'LoginPage', defaultHsUrl={this.props.homeserverUrl} defaultIsUrl={this.props.identityServerUrl} onHsUrlChanged={this.onHsUrlChanged} + onIsUrlChanged={this.onIsUrlChanged} delayTimeMs={1000}/>
{ loader } From 58472b82516f015d3cc5cd7ff3f1027928157df0 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 12 Nov 2015 15:38:04 +0000 Subject: [PATCH 3/6] Move Cas/PasswordLogin to react-sdk. Use them as normal components. --- src/skins/vector/skindex.js | 2 - src/skins/vector/views/organisms/CasLogin.js | 35 ---------- .../vector/views/organisms/PasswordLogin.js | 65 ------------------- src/skins/vector/views/pages/LoginPage.js | 4 +- 4 files changed, 2 insertions(+), 104 deletions(-) delete mode 100644 src/skins/vector/views/organisms/CasLogin.js delete mode 100644 src/skins/vector/views/organisms/PasswordLogin.js diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js index e05d3e65..3ee4caec 100644 --- a/src/skins/vector/skindex.js +++ b/src/skins/vector/skindex.js @@ -70,8 +70,6 @@ skin['molecules.UserSelector'] = require('./views/molecules/UserSelector'); skin['molecules.voip.CallView'] = require('./views/molecules/voip/CallView'); skin['molecules.voip.IncomingCallBox'] = require('./views/molecules/voip/IncomingCallBox'); skin['molecules.voip.VideoView'] = require('./views/molecules/voip/VideoView'); -skin['organisms.CasLogin'] = require('./views/organisms/CasLogin'); -skin['organisms.PasswordLogin'] = require('./views/organisms/PasswordLogin'); skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom'); skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog'); skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel'); diff --git a/src/skins/vector/views/organisms/CasLogin.js b/src/skins/vector/views/organisms/CasLogin.js deleted file mode 100644 index ad9dbed9..00000000 --- a/src/skins/vector/views/organisms/CasLogin.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2015 OpenMarket 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. -*/ - -'use strict'; - -var React = require('react'); - -var CasLoginController = require('matrix-react-sdk/lib/controllers/organisms/CasLogin'); - -module.exports = React.createClass({ - displayName: 'CasLogin', - mixins: [CasLoginController], - - render: function() { - return ( -
- -
- ); - }, - -}); diff --git a/src/skins/vector/views/organisms/PasswordLogin.js b/src/skins/vector/views/organisms/PasswordLogin.js deleted file mode 100644 index fabd71d6..00000000 --- a/src/skins/vector/views/organisms/PasswordLogin.js +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2015 OpenMarket 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. -*/ - -var React = require('react'); -var ReactDOM = require('react-dom'); - -/** - * A pure UI component which displays a username/password form. - */ -module.exports = React.createClass({displayName: 'PasswordLogin', - propTypes: { - onSubmit: React.PropTypes.func.isRequired // fn(username, password) - }, - - getInitialState: function() { - return { - username: "", - password: "" - }; - }, - - onSubmitForm: function(ev) { - ev.preventDefault(); - this.props.onSubmit(this.state.username, this.state.password); - }, - - onUsernameChanged: function(ev) { - this.setState({username: ev.target.value}); - }, - - onPasswordChanged: function(ev) { - this.setState({password: ev.target.value}); - }, - - render: function() { - return ( -
-
- -
- -
- -
-
- ); - } -}); \ No newline at end of file diff --git a/src/skins/vector/views/pages/LoginPage.js b/src/skins/vector/views/pages/LoginPage.js index 00f46a37..bfd2d4b9 100644 --- a/src/skins/vector/views/pages/LoginPage.js +++ b/src/skins/vector/views/pages/LoginPage.js @@ -20,6 +20,8 @@ var React = require('react'); var ReactDOM = require('react-dom'); var sdk = require('matrix-react-sdk'); var Signup = require("matrix-react-sdk/lib/Signup"); +var PasswordLogin = require("matrix-react-sdk/lib/components/PasswordLogin"); +var CasLogin = require("matrix-react-sdk/lib/components/CasLogin"); /** * A wire component which glues together login UI components and Signup logic @@ -134,12 +136,10 @@ module.exports = React.createClass({displayName: 'LoginPage', componentForStep: function(step) { switch (step) { case 'm.login.password': - var PasswordLogin = sdk.getComponent('organisms.PasswordLogin'); return ( ); case 'm.login.cas': - var CasLogin = sdk.getComponent('organisms.CasLogin'); return ( ); From 726afd30bb1c5823f284f6bf2342101880ed5fee Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 12 Nov 2015 15:49:32 +0000 Subject: [PATCH 4/6] Swap old login for new --- src/skins/vector/skindex.js | 3 +- .../views/pages/{LoginPage.js => Login.js} | 2 +- src/skins/vector/views/pages/MatrixChat.js | 5 +- src/skins/vector/views/templates/Login.js | 219 ------------------ 4 files changed, 4 insertions(+), 225 deletions(-) rename src/skins/vector/views/pages/{LoginPage.js => Login.js} (99%) delete mode 100644 src/skins/vector/views/templates/Login.js diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js index 3ee4caec..84f26499 100644 --- a/src/skins/vector/skindex.js +++ b/src/skins/vector/skindex.js @@ -86,8 +86,7 @@ skin['organisms.UserSettings'] = require('./views/organisms/UserSettings'); skin['organisms.ViewSource'] = require('./views/organisms/ViewSource'); skin['pages.CompatibilityPage'] = require('./views/pages/CompatibilityPage'); skin['pages.MatrixChat'] = require('./views/pages/MatrixChat'); -skin['pages.LoginPage'] = require('./views/pages/LoginPage'); -skin['templates.Login'] = require('./views/templates/Login'); +skin['pages.Login'] = require('./views/pages/Login'); skin['templates.Register'] = require('./views/templates/Register'); module.exports = skin; \ No newline at end of file diff --git a/src/skins/vector/views/pages/LoginPage.js b/src/skins/vector/views/pages/Login.js similarity index 99% rename from src/skins/vector/views/pages/LoginPage.js rename to src/skins/vector/views/pages/Login.js index bfd2d4b9..26c243a7 100644 --- a/src/skins/vector/views/pages/LoginPage.js +++ b/src/skins/vector/views/pages/Login.js @@ -26,7 +26,7 @@ var CasLogin = require("matrix-react-sdk/lib/components/CasLogin"); /** * A wire component which glues together login UI components and Signup logic */ -module.exports = React.createClass({displayName: 'LoginPage', +module.exports = React.createClass({displayName: 'Login', propTypes: { onLoggedIn: React.PropTypes.func.isRequired, homeserverUrl: React.PropTypes.string, diff --git a/src/skins/vector/views/pages/MatrixChat.js b/src/skins/vector/views/pages/MatrixChat.js index 0fea1f36..f8708f0e 100644 --- a/src/skins/vector/views/pages/MatrixChat.js +++ b/src/skins/vector/views/pages/MatrixChat.js @@ -97,7 +97,6 @@ module.exports = React.createClass({ var LeftPanel = sdk.getComponent('organisms.LeftPanel'); var RoomView = sdk.getComponent('organisms.RoomView'); var RightPanel = sdk.getComponent('organisms.RightPanel'); - var Login = sdk.getComponent('templates.Login'); var UserSettings = sdk.getComponent('organisms.UserSettings'); var Register = sdk.getComponent('templates.Register'); var CreateRoom = sdk.getComponent('organisms.CreateRoom'); @@ -168,9 +167,9 @@ module.exports = React.createClass({ /> ); } else { - var LoginPage = sdk.getComponent("pages.LoginPage"); + var Login = sdk.getComponent("pages.Login"); return ( - + ); } } diff --git a/src/skins/vector/views/templates/Login.js b/src/skins/vector/views/templates/Login.js deleted file mode 100644 index 8bd9334e..00000000 --- a/src/skins/vector/views/templates/Login.js +++ /dev/null @@ -1,219 +0,0 @@ -/* -Copyright 2015 OpenMarket 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. -*/ - -'use strict'; - -var React = require('react'); -var ReactDOM = require('react-dom'); - -var sdk = require('matrix-react-sdk') -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); - -var LoginController = require('matrix-react-sdk/lib/controllers/templates/Login') - -var config = require('../../../../../config.json'); - -module.exports = React.createClass({ - displayName: 'Login', - mixins: [LoginController], - - getInitialState: function() { - // TODO: factor out all localstorage stuff into its own home. - // This is common to Login, Register and MatrixClientPeg - var localStorage = window.localStorage; - var hs_url, is_url; - if (localStorage) { - hs_url = localStorage.getItem("mx_hs_url"); - is_url = localStorage.getItem("mx_is_url"); - } - - return { - customHsUrl: hs_url || config.default_hs_url, - customIsUrl: is_url || config.default_is_url, - serverConfigVisible: (hs_url && hs_url !== config.default_hs_url || - is_url && is_url !== config.default_is_url) - }; - }, - - componentDidMount: function() { - this.onHSChosen(); - }, - - componentDidUpdate: function() { - if (!this.state.focusFired && this.refs.user) { - this.refs.user.focus(); - this.setState({ focusFired: true }); - } - }, - - getHsUrl: function() { - if (this.state.serverConfigVisible) { - return this.state.customHsUrl; - } else { - return config.default_hs_url; - } - }, - - getIsUrl: function() { - if (this.state.serverConfigVisible) { - return this.state.customIsUrl; - } else { - return config.default_is_url; - } - }, - - onServerConfigVisibleChange: function(ev) { - this.setState({ - serverConfigVisible: ev.target.checked - }, this.onHSChosen); - }, - - /** - * Gets the form field values for the current login stage - */ - getFormVals: function() { - return { - 'username': this.refs.user.value.trim(), - 'password': this.refs.pass.value.trim() - }; - }, - - onHsUrlChanged: function() { - var newHsUrl = this.refs.serverConfig.getHsUrl().trim(); - var newIsUrl = this.refs.serverConfig.getIsUrl().trim(); - - if (newHsUrl == this.state.customHsUrl && - newIsUrl == this.state.customIsUrl) - { - return; - } - else { - this.setState({ - customHsUrl: newHsUrl, - customIsUrl: newIsUrl, - }); - } - - // XXX: why are we replacing the MatrixClientPeg here when we're about - // to do it again 1s later in the setTimeout to onHSChosen? -- matthew - // Commenting it out for now to see what breaks. - /* - MatrixClientPeg.replaceUsingUrls( - this.getHsUrl(), - this.getIsUrl() - ); - this.setState({ - hs_url: this.getHsUrl(), - is_url: this.getIsUrl() - }); - */ - - // XXX: HSes do not have to offer password auth, so we - // need to update and maybe show a different component - // when a new HS is entered. - if (this.updateHsTimeout) { - clearTimeout(this.updateHsTimeout); - } - var self = this; - this.updateHsTimeout = setTimeout(function() { - self.onHSChosen(); - }, 1000); - }, - - componentForStep: function(step) { - switch (step) { - case 'choose_hs': - case 'fetch_stages': - var serverConfigStyle = {}; - serverConfigStyle.display = this.state.serverConfigVisible ? 'block' : 'none'; - var ServerConfig = sdk.getComponent("molecules.ServerConfig"); - - return ( -
- - -
- -
-
- ); - // XXX: clearly these should be separate organisms - case 'stage_m.login.password': - return ( -
-
-
-
- { this.componentForStep('choose_hs') } - -
-
- ); - case 'stage_m.login.cas': - var CasLogin = sdk.getComponent('organisms.CasLogin'); - return ( - - ); - } - }, - - onUsernameChanged: function(ev) { - this.setState({username: ev.target.value}); - }, - - onPasswordChanged: function(ev) { - this.setState({password: ev.target.value}); - }, - - loginContent: function() { - var Loader = sdk.getComponent("atoms.Spinner"); - var loader = this.state.busy ?
: null; - return ( -
-

Sign in

- {this.componentForStep(this.state.step)} -
- { loader } - {this.state.errorText} -
- Create a new account -
-
- blog  ·   - twitter  ·   - github  ·   - powered by Matrix -
-
- ); - }, - - render: function() { - return ( -
-
-
- vector -
- {this.loginContent()} -
-
- ); - } -}); From 021eaf5c29c21a75fa4aed66f5c905f0bf5a5c60 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 12 Nov 2015 15:54:07 +0000 Subject: [PATCH 5/6] Vector is the default IS in Vector --- src/skins/vector/views/pages/Login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skins/vector/views/pages/Login.js b/src/skins/vector/views/pages/Login.js index 26c243a7..b8f0e43e 100644 --- a/src/skins/vector/views/pages/Login.js +++ b/src/skins/vector/views/pages/Login.js @@ -38,7 +38,7 @@ module.exports = React.createClass({displayName: 'Login', getDefaultProps: function() { return { homeserverUrl: 'https://matrix.org/', - identityServerUrl: 'https://matrix.org/' + identityServerUrl: 'https://vector.im' }; }, From b1438355e28ff543d528b19f86a491cdad4dc771 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 12 Nov 2015 15:58:12 +0000 Subject: [PATCH 6/6] Github and Sublime don't like this not being escaped. Displays fine though in React like this. --- src/skins/vector/views/molecules/ServerConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skins/vector/views/molecules/ServerConfig.js b/src/skins/vector/views/molecules/ServerConfig.js index fcc8bfc5..8f1eab38 100644 --- a/src/skins/vector/views/molecules/ServerConfig.js +++ b/src/skins/vector/views/molecules/ServerConfig.js @@ -105,7 +105,7 @@ module.exports = React.createClass({

You can also set a custom Identity server but this will affect - people's ability to find you if you use a server in a group other + people's ability to find you if you use a server in a group other than the main Matrix.org group. , button: "Dismiss",