diff --git a/skins/base/views/pages/MatrixChat.js b/skins/base/views/pages/MatrixChat.js
index f9e199e6..f2480ddc 100644
--- a/skins/base/views/pages/MatrixChat.js
+++ b/skins/base/views/pages/MatrixChat.js
@@ -23,6 +23,7 @@ var RoomList = ComponentBroker.get('organisms/RoomList');
var RoomView = ComponentBroker.get('organisms/RoomView');
var MatrixToolbar = ComponentBroker.get('molecules/MatrixToolbar');
var Login = ComponentBroker.get('templates/Login');
+var Register = ComponentBroker.get('templates/Register');
var MatrixChatController = require("../../../../src/controllers/pages/MatrixChat");
@@ -51,6 +52,10 @@ module.exports = React.createClass({
return (
);
+ } else if (this.state.screen == 'register') {
+ return (
+
+ );
} else {
return (
diff --git a/skins/base/views/templates/Login.js b/skins/base/views/templates/Login.js
index 6cd721e2..ceae07ec 100644
--- a/skins/base/views/templates/Login.js
+++ b/skins/base/views/templates/Login.js
@@ -40,6 +40,7 @@ module.exports = React.createClass({
Please log in:
{this.componentForStep(this.state.step)}
{this.state.errorText}
+ Create a new account
);
}
diff --git a/skins/base/views/templates/Register.js b/skins/base/views/templates/Register.js
new file mode 100644
index 00000000..676fa2e2
--- /dev/null
+++ b/skins/base/views/templates/Register.js
@@ -0,0 +1,55 @@
+/*
+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 ComponentBroker = require("../../../../src/ComponentBroker");
+
+var Loader = require("react-loader");
+
+var RegisterController = require("../../../../src/controllers/templates/Register");
+
+module.exports = React.createClass({
+ displayName: 'Register',
+ mixins: [RegisterController],
+
+ registerContent: function() {
+ if (this.state.busy) {
+ return (
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ },
+
+ render: function() {
+ return (
+
+ {this.registerContent()}
+
+ );
+ }
+});
diff --git a/src/ComponentBroker.js b/src/ComponentBroker.js
index 32b07a03..c9f9eefb 100644
--- a/src/ComponentBroker.js
+++ b/src/ComponentBroker.js
@@ -81,5 +81,6 @@ require('../skins/base/views/molecules/MemberTile');
require('../skins/base/views/organisms/RoomList');
require('../skins/base/views/organisms/RoomView');
require('../skins/base/views/templates/Login');
+require('../skins/base/views/templates/Register');
require('../skins/base/views/organisms/Notifier');
}
diff --git a/src/controllers/pages/MatrixChat.js b/src/controllers/pages/MatrixChat.js
index 717f91e7..1ac1c679 100644
--- a/src/controllers/pages/MatrixChat.js
+++ b/src/controllers/pages/MatrixChat.js
@@ -67,10 +67,25 @@ module.exports = {
logged_in: false,
ready: false
});
+ localStorage.removeItem("mx_hs_url");
+ localStorage.removeItem("mx_user_id");
+ localStorage.removeItem("mx_access_token");
Notifier.stop();
MatrixClientPeg.get().removeAllListeners();
MatrixClientPeg.replace(null);
break;
+ case 'start_registration':
+ if (this.state.logged_in) return;
+ this.setState({
+ screen: 'register'
+ });
+ break;
+ case 'start_login':
+ if (this.state.logged_in) return;
+ this.setState({
+ screen: 'login'
+ });
+ break;
case 'view_room':
this.focusComposer = true;
this.setState({
@@ -99,7 +114,10 @@ module.exports = {
},
onLoggedIn: function() {
- this.setState({logged_in: true});
+ this.setState({
+ screen: 'register',
+ logged_in: true
+ });
this.startMatrixClient();
},
diff --git a/src/controllers/templates/Login.js b/src/controllers/templates/Login.js
index f3c58cf2..a5bd43cc 100644
--- a/src/controllers/templates/Login.js
+++ b/src/controllers/templates/Login.js
@@ -20,6 +20,7 @@ var React = require('react');
var MatrixClientPeg = require("../../MatrixClientPeg");
var Matrix = require("matrix-js-sdk");
+var dis = require("../../dispatcher");
var ComponentBroker = require("../../ComponentBroker");
@@ -85,9 +86,6 @@ module.exports = {
if (that.props.onLoggedIn) {
that.props.onLoggedIn();
}
- /*dis.dispatch({
- 'action': 'logged_in'
- });*/
}, function(error) {
that.setStep("stage_m.login.password");
that.setState({errorText: 'Login failed.'});
@@ -118,4 +116,10 @@ module.exports = {
);
}
},
+
+ showRegister: function() {
+ dis.dispatch({
+ action: 'start_registration'
+ });
+ }
};
diff --git a/src/controllers/templates/Register.js b/src/controllers/templates/Register.js
new file mode 100644
index 00000000..12e10c0d
--- /dev/null
+++ b/src/controllers/templates/Register.js
@@ -0,0 +1,179 @@
+/*
+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 MatrixClientPeg = require("../../MatrixClientPeg");
+var Matrix = require("matrix-js-sdk");
+var dis = require("../../dispatcher");
+
+var ComponentBroker = require("../../ComponentBroker");
+
+var ServerConfig = ComponentBroker.get("molecules/ServerConfig");
+
+module.exports = {
+ getInitialState: function() {
+ return {
+ step: 'initial',
+ busy: false,
+ currentStep: 0,
+ totalSteps: 1
+ };
+ },
+
+ setStep: function(step) {
+ this.setState({ step: step, errorText: '', busy: false });
+ },
+
+ getSupportedStageTypes: function() {
+ return ['m.login.email.identity', 'm.login.recaptcha'];
+ },
+
+ chooseFlow: function(flows) {
+ // this is fairly simple right now
+ var supportedTypes = this.getSupportedStageTypes();
+
+ var emailFlow = null;
+ var otherFlow = null;
+ for (var flowI = 0; flowI < flows.length; ++flowI) {
+ var flow = flows[flowI];
+ var flowHasEmail = false;
+ var flowSupported = true;
+ for (var stageI = 0; stageI < flow.stages.length; ++stageI) {
+ var stage = flow.stages[stageI];
+
+ if (supportedTypes.indexOf(stage) == -1) {
+ flowSupported = false;
+ }
+
+ if (stage == 'm.login.email.identity') {
+ flowHasEmail = true;
+ }
+ }
+ if (flowSupported) {
+ if (flowHasEmail) {
+ emailFlow = flow;
+ } else {
+ otherFlow = flow;
+ }
+ }
+ }
+
+ if (this.savedParams.email != '') {
+ return emailFlow;
+ } else {
+ return otherFlow;
+ }
+ },
+
+ onInitialStageSubmit: function(ev) {
+ ev.preventDefault();
+ MatrixClientPeg.replaceUsingUrl(this.refs.serverConfig.getHsUrl());
+ this.setState({hs_url: this.refs.serverConfig.getHsUrl()});
+ var cli = MatrixClientPeg.get();
+ this.setState({busy: true});
+ var self = this;
+
+ var email = this.refs.email.getDOMNode().value;
+ var username = this.refs.username.getDOMNode().value;
+ var password = this.refs.password.getDOMNode().value;
+
+ this.savedParams = {
+ email: email,
+ username: username,
+ password: password
+ };
+
+ cli.register(username, password).done(function(result) {
+ self.onRegistered();
+ }, function(error) {
+ if (error.httpStatus == 401) {
+ var flow = self.chooseFlow(error.data.flows);
+ self.setState({
+ busy: false,
+ flows: flow,
+ currentStep: 1,
+ totalSteps: flow.stages.length+1,
+ flowStage: 0
+ });
+ self.setStep('stage_'+flow.stages[0]);
+ } else {
+ self.setStep("initial");
+ self.setState({
+ busy: false,
+ errorText: 'Unable to contact the given Home Server'
+ });
+ }
+ });
+ },
+
+ onRegistered: function(user_id, access_token) {
+ MatrixClientPeg.replace(Matrix.createClient({
+ baseUrl: this.state.hs_url,
+ userId: data.user_id,
+ accessToken: data.access_token
+ }));
+ var localStorage = window.localStorage;
+ if (localStorage) {
+ localStorage.setItem("mx_hs_url", this.state.hs_url);
+ localStorage.setItem("mx_user_id", user_id);
+ localStorage.setItem("mx_access_token", access_token);
+ } else {
+ console.warn("No local storage available: can't persist session!");
+ }
+ if (that.props.onLoggedIn) {
+ that.props.onLoggedIn();
+ }
+ },
+
+ componentForStep: function(step) {
+ switch (step) {
+ case 'initial':
+ return (
+
+
+
+ );
+ // XXX: clearly these should be separate organisms
+ case 'stage_m.login.email.identity':
+ return (
+
+ Please check your email to continue registration.
+
+ );
+ case 'stage_m.login.recaptcha':
+ return (
+
+ This is the recaptcha stage. Sucks, doesn't it.
+
+ );
+ }
+ },
+
+ showLogin: function() {
+ dis.dispatch({
+ action: 'start_login'
+ });
+ }
+};