diff --git a/src/AddThreepid.js b/src/AddThreepid.js
index d6a1d58aa0..c89de4f5fa 100644
--- a/src/AddThreepid.js
+++ b/src/AddThreepid.js
@@ -1,5 +1,6 @@
/*
Copyright 2016 OpenMarket Ltd
+Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -51,11 +52,36 @@ class AddThreepid {
});
}
+ /**
+ * Attempt to add a msisdn threepid. This will trigger a side-effect of
+ * sending a test message to the provided phone number.
+ * @param {string} phoneCountry The ISO 2 letter code of the country to resolve phoneNumber in
+ * @param {string} phoneNumber The national or international formatted phone number to add
+ * @param {boolean} bind If True, bind this phone number to this mxid on the Identity Server
+ * @return {Promise} Resolves when the text message has been sent. Then call haveMsisdnToken().
+ */
+ addMsisdn(phoneCountry, phoneNumber, bind) {
+ this.bind = bind;
+ return MatrixClientPeg.get().requestAdd3pidMsisdnToken(
+ phoneCountry, phoneNumber, this.clientSecret, 1,
+ ).then((res) => {
+ this.sessionId = res.sid;
+ return res;
+ }, function(err) {
+ if (err.errcode == 'M_THREEPID_IN_USE') {
+ err.message = "This phone number is already in use";
+ } else if (err.httpStatus) {
+ err.message = err.message + ` (Status ${err.httpStatus})`;
+ }
+ throw err;
+ });
+ }
+
/**
* Checks if the email link has been clicked by attempting to add the threepid
- * @return {Promise} Resolves if the password was reset. Rejects with an object
+ * @return {Promise} Resolves if the email address was added. Rejects with an object
* with a "message" property which contains a human-readable message detailing why
- * the reset failed, e.g. "There is no mapped matrix user ID for the given email address".
+ * the request failed.
*/
checkEmailLinkClicked() {
var identityServerDomain = MatrixClientPeg.get().idBaseUrl.split("://")[1];
@@ -73,6 +99,29 @@ class AddThreepid {
throw err;
});
}
+
+ /**
+ * Takes a phone number verification code as entered by the user and validates
+ * it with the ID server, then if successful, adds the phone number.
+ * @return {Promise} Resolves if the phone number was added. Rejects with an object
+ * with a "message" property which contains a human-readable message detailing why
+ * the request failed.
+ */
+ haveMsisdnToken(token) {
+ return MatrixClientPeg.get().submitMsisdnToken(
+ this.sessionId, this.clientSecret, token,
+ ).then((result) => {
+ if (result.errcode) {
+ throw result;
+ }
+ const identityServerDomain = MatrixClientPeg.get().idBaseUrl.split("://")[1];
+ return MatrixClientPeg.get().addThreePid({
+ sid: this.sessionId,
+ client_secret: this.clientSecret,
+ id_server: identityServerDomain
+ }, this.bind);
+ });
+ }
}
module.exports = AddThreepid;
diff --git a/src/component-index.js b/src/component-index.js
index c83c0dbb11..d6873c6dfd 100644
--- a/src/component-index.js
+++ b/src/component-index.js
@@ -229,6 +229,8 @@ import views$rooms$TopUnreadMessagesBar from './components/views/rooms/TopUnread
views$rooms$TopUnreadMessagesBar && (module.exports.components['views.rooms.TopUnreadMessagesBar'] = views$rooms$TopUnreadMessagesBar);
import views$rooms$UserTile from './components/views/rooms/UserTile';
views$rooms$UserTile && (module.exports.components['views.rooms.UserTile'] = views$rooms$UserTile);
+import views$settings$AddPhoneNumber from './components/views/settings/AddPhoneNumber';
+views$settings$AddPhoneNumber && (module.exports.components['views.settings.AddPhoneNumber'] = views$settings$AddPhoneNumber);
import views$settings$ChangeAvatar from './components/views/settings/ChangeAvatar';
views$settings$ChangeAvatar && (module.exports.components['views.settings.ChangeAvatar'] = views$settings$ChangeAvatar);
import views$settings$ChangeDisplayName from './components/views/settings/ChangeDisplayName';
diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js
index 91ecc4fb0f..0cb120019e 100644
--- a/src/components/structures/UserSettings.js
+++ b/src/components/structures/UserSettings.js
@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -139,6 +140,7 @@ module.exports = React.createClass({
componentWillMount: function() {
this._unmounted = false;
+ this._addThreepid = null;
if (PlatformPeg.get()) {
q().then(() => {
@@ -321,12 +323,16 @@ module.exports = React.createClass({
UserSettingsStore.setEnableNotifications(event.target.checked);
},
- onAddThreepidClicked: function(value, shouldSubmit) {
+ _onAddEmailEditFinished: function(value, shouldSubmit) {
if (!shouldSubmit) return;
+ this._addEmail();
+ },
+
+ _addEmail: function() {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
- var email_address = this.refs.add_threepid_input.value;
+ var email_address = this.refs.add_email_input.value;
if (!Email.looksValid(email_address)) {
Modal.createDialog(ErrorDialog, {
title: "Invalid Email Address",
@@ -334,10 +340,10 @@ module.exports = React.createClass({
});
return;
}
- this.add_threepid = new AddThreepid();
+ this._addThreepid = new AddThreepid();
// we always bind emails when registering, so let's do the
// same here.
- this.add_threepid.addEmailAddress(email_address, true).done(() => {
+ this._addThreepid.addEmailAddress(email_address, true).done(() => {
Modal.createDialog(QuestionDialog, {
title: "Verification Pending",
description: "Please check your email and click on the link it contains. Once this is done, click continue.",
@@ -352,7 +358,7 @@ module.exports = React.createClass({
description: "Unable to add email address"
});
});
- ReactDOM.findDOMNode(this.refs.add_threepid_input).blur();
+ ReactDOM.findDOMNode(this.refs.add_email_input).blur();
this.setState({email_add_pending: true});
},
@@ -391,8 +397,8 @@ module.exports = React.createClass({
},
verifyEmailAddress: function() {
- this.add_threepid.checkEmailLinkClicked().done(() => {
- this.add_threepid = undefined;
+ this._addThreepid.checkEmailLinkClicked().done(() => {
+ this._addThreepid = null;
this.setState({
phase: "UserSettings.LOADING",
});
@@ -811,30 +817,35 @@ module.exports = React.createClass({
);
});
- var addThreepidSection;
+ let addEmailSection;
if (this.state.email_add_pending) {
- addThreepidSection =