diff --git a/examples/trivial/index.js b/examples/trivial/index.js
index 5752e6bd..6e48ac1b 100644
--- a/examples/trivial/index.js
+++ b/examples/trivial/index.js
@@ -24,7 +24,30 @@ var React = require("react");
// maps cannot pass through two stages).
var MatrixReactSdk = require("../../src/index");
-React.render(
- ,
+function routeUrl(location) {
+ if (location.hash.indexOf('#/register') == 0) {
+ var hashparts = location.hash.split('?');
+ if (hashparts.length != 2) return;
+ var pairs = hashparts[1].split('&');
+ var params = {};
+ for (var i = 0; i < pairs.length; ++i) {
+ var parts = pairs[i].split('=');
+ if (parts.length != 2) continue;
+ params[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
+ }
+ window.matrixChat.resumeRegistration(params);
+ }
+}
+
+window.onload = function() {
+ routeUrl(window.location);
+}
+
+var onNewScreen = function(screen) {
+ window.location.hash = '#/'+screen;
+}
+
+window.matrixChat = React.render(
+ ,
document.getElementById('matrixchat')
);
diff --git a/skins/base/views/pages/MatrixChat.js b/skins/base/views/pages/MatrixChat.js
index f2480ddc..e2123b15 100644
--- a/skins/base/views/pages/MatrixChat.js
+++ b/skins/base/views/pages/MatrixChat.js
@@ -54,7 +54,10 @@ module.exports = React.createClass({
);
} else if (this.state.screen == 'register') {
return (
-
+
);
} else {
return (
diff --git a/src/controllers/pages/MatrixChat.js b/src/controllers/pages/MatrixChat.js
index 1ac1c679..a687aee2 100644
--- a/src/controllers/pages/MatrixChat.js
+++ b/src/controllers/pages/MatrixChat.js
@@ -44,6 +44,11 @@ module.exports = {
this.focusComposer = false;
document.addEventListener("keydown", this.onKeyDown);
window.addEventListener("focus", this.onFocus);
+ if (this.state.logged_in) {
+ this.notifyNewScreen('');
+ } else {
+ this.notifyNewScreen('login');
+ }
},
componentWillUnmount: function() {
@@ -63,7 +68,7 @@ module.exports = {
switch (payload.action) {
case 'logout':
- this.setState({
+ this.replaceState({
logged_in: false,
ready: false
});
@@ -76,15 +81,17 @@ module.exports = {
break;
case 'start_registration':
if (this.state.logged_in) return;
- this.setState({
+ this.replaceState({
screen: 'register'
});
+ this.notifyNewScreen('register');
break;
case 'start_login':
if (this.state.logged_in) return;
- this.setState({
+ this.replaceState({
screen: 'login'
});
+ this.notifyNewScreen('login');
break;
case 'view_room':
this.focusComposer = true;
@@ -115,10 +122,11 @@ module.exports = {
onLoggedIn: function() {
this.setState({
- screen: 'register',
+ screen: undefined,
logged_in: true
});
this.startMatrixClient();
+ this.notifyNewScreen('');
},
startMatrixClient: function() {
@@ -155,6 +163,30 @@ module.exports = {
onFocus: function(ev) {
dis.dispatch({action: 'focus_composer'});
+ },
+
+ resumeRegistration(params) {
+ if (!params.hs_url) return false;
+ if (!params.is_url) return false;
+ if (!params.client_secret) return false;
+ if (!params.session_id) return false;
+ if (!params.sid) return false;
+ if (this.state.logged_in) return false;
+
+ this.setState({
+ screen: 'register',
+ register_client_secret: params.client_secret,
+ register_session_id: params.session_id,
+ register_hs_url: params.hs_url,
+ register_is_url: params.is_url,
+ register_id_sid: params.sid
+ });
+ },
+
+ notifyNewScreen: function(screen) {
+ if (this.props.onNewScreen) {
+ this.props.onNewScreen(screen);
+ }
}
};
diff --git a/src/controllers/templates/Login.js b/src/controllers/templates/Login.js
index 48ff6dc9..714fb272 100644
--- a/src/controllers/templates/Login.js
+++ b/src/controllers/templates/Login.js
@@ -125,7 +125,8 @@ module.exports = {
}
},
- showRegister: function() {
+ showRegister: function(ev) {
+ ev.preventDefault();
dis.dispatch({
action: 'start_registration'
});
diff --git a/src/controllers/templates/Register.js b/src/controllers/templates/Register.js
index c562a79e..3e7f07c7 100644
--- a/src/controllers/templates/Register.js
+++ b/src/controllers/templates/Register.js
@@ -36,6 +36,45 @@ module.exports = {
};
},
+ componentWillMount: function() {
+ this.readNewProps();
+ },
+
+ componentWillReceiveProps: function() {
+ this.readNewProps();
+ },
+
+ readNewProps: function() {
+ if (this.props.clientSecret && this.props.hsUrl &&
+ this.props.isUrl && this.props.sessionId &&
+ this.props.idSid) {
+ this.authSessionId = this.props.sessionId;
+ MatrixClientPeg.replaceUsingUrls(
+ this.props.hsUrl,
+ this.props.isUrl
+ );
+ this.setState({
+ hs_url: this.props.hsUrl,
+ is_url: this.props.isUrl
+ });
+ this.savedParams = {client_secret: this.props.clientSecret};
+ this.setState({busy: true});
+
+ var isLocation = document.createElement('a');
+ isLocation.href = this.props.isUrl;
+
+ var auth = {
+ type: 'm.login.email.identity',
+ threepid_creds: {
+ sid: this.props.idSid,
+ client_secret: this.savedParams.client_secret,
+ id_server: isLocation.host
+ }
+ };
+ this.tryRegister(auth);
+ }
+ },
+
componentDidUpdate: function() {
// Just putting a script tag into the returned jsx doesn't work, annoyingly,
// so we do this instead.
@@ -85,13 +124,36 @@ module.exports = {
}
}
- if (this.savedParams.email != '') {
+ if (
+ this.savedParams.email != '' ||
+ this.completedStages.indexOf('m.login.email.identity' > -1)
+ ) {
return emailFlow;
} else {
return otherFlow;
}
},
+ firstUncompletedStageIndex: function(flow) {
+ if (this.completedStages === undefined) return 0;
+ for (var i = 0; i < flow.stages.length; ++i) {
+ if (this.completedStages.indexOf(flow.stages[i]) == -1) {
+ return i;
+ }
+ }
+ },
+
+ numCompletedStages: function(flow) {
+ if (this.completedStages === undefined) return 0;
+ var nCompleted = 0;
+ for (var i = 0; i < flow.stages.length; ++i) {
+ if (this.completedStages.indexOf(flow.stages[i]) > -1) {
+ ++nCompleted;
+ }
+ }
+ return nCompleted;
+ },
+
onInitialStageSubmit: function(ev) {
ev.preventDefault();
MatrixClientPeg.replaceUsingUrls(
@@ -126,10 +188,24 @@ module.exports = {
var cli = MatrixClientPeg.get();
this.savedParams.client_secret = cli.generateClientSecret();
this.savedParams.send_attempt = 1;
+
+ var nextLink = window.location.protocol + '//' +
+ window.location.host +
+ window.location.pathname +
+ '#/register?client_secret=' +
+ encodeURIComponent(this.savedParams.client_secret) +
+ "&hs_url=" +
+ encodeURIComponent(this.state.hs_url) +
+ "&is_url=" +
+ encodeURIComponent(this.state.is_url) +
+ "&session_id=" +
+ encodeURIComponent(this.authSessionId);
+
cli.requestEmailToken(
this.savedParams.email,
this.savedParams.client_secret,
- this.savedParams.send_attempt
+ this.savedParams.send_attempt,
+ nextLink
).done(function(response) {
self.setState({
busy: false,
@@ -230,28 +306,41 @@ module.exports = {
).done(function(result) {
self.onRegistered(result.user_id, result.access_token);
}, function(error) {
- if (error.httpStatus == 401) {
+ if (error.httpStatus == 401 && error.data.flows) {
self.authParams = error.data.params;
+ self.authSessionId = error.data.session;
+
+ self.completedStages = error.data.completed;
+
var flow = self.chooseFlow(error.data.flows);
+
+ var flowStage = self.firstUncompletedStageIndex(flow);
+ var numDone = self.numCompletedStages(flow);
+
self.setState({
busy: false,
flows: flow,
- currentStep: 1,
+ currentStep: 1+numDone,
totalSteps: flow.stages.length+1,
- flowStage: 0
+ flowStage: flowStage
});
- self.startStage(flow.stages[0]);
+ self.startStage(flow.stages[flowStage]);
} else {
+ var errorText = "Unable to contact the given Home Server";
+ if (error.httpStatus == 401) {
+ errorText = "Authorisation failed!";
+ }
self.setStep("initial");
self.setState({
busy: false,
- errorText: 'Unable to contact the given Home Server'
+ errorText: errorText
});
}
});
},
- showLogin: function() {
+ showLogin: function(ev) {
+ ev.preventDefault();
dis.dispatch({
action: 'start_login'
});