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 b50c3318ce..5633bd0bc7 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. @@ -135,8 +136,6 @@ module.exports = React.createClass({ msisdn_add_pending: false, vectorVersion: null, rejectingInvites: false, - phoneCountry: null, - phoneNumber: "", }; }, @@ -218,14 +217,6 @@ module.exports = React.createClass({ }); }, - _onPhoneCountryChange: function(phoneCountry) { - this.setState({ phoneCountry: phoneCountry }); - }, - - _onPhoneNumberChange: function(ev) { - this.setState({ phoneNumber: ev.target.value }); - }, - onAction: function(payload) { if (payload.action === "notifier_enabled") { this.forceUpdate(); @@ -338,16 +329,6 @@ module.exports = React.createClass({ this._addEmail(); }, - _onAddMsisdnEditFinished: function(value, shouldSubmit) { - if (!shouldSubmit) return; - this._addMsisdn(); - }, - - _onAddMsisdnSubmit: function(ev) { - ev.preventDefault(); - this._addMsisdn(); - }, - _addEmail: function() { var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); @@ -382,65 +363,6 @@ module.exports = React.createClass({ this.setState({email_add_pending: true}); }, - _addMsisdn: function() { - const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - - this._addThreepid = new AddThreepid(); - // we always bind phone numbers when registering, so let's do the - // same here. - this._addThreepid.addMsisdn(this.state.phoneCountry, this.state.phoneNumber, true).then((resp) => { - this._promptForMsisdnVerificationCode(resp.msisdn); - }).catch((err) => { - console.error("Unable to add phone number: " + err); - let msg = err.message; - Modal.createDialog(ErrorDialog, { - title: "Error", - description: msg, - }); - }).finally(() => { - this.setState({msisdn_add_pending: false}); - }).done();; - ReactDOM.findDOMNode(this.refs.add_msisdn_input).blur(); - this.setState({msisdn_add_pending: true}); - }, - - _promptForMsisdnVerificationCode(msisdn, err) { - const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog"); - let msgElements = [ -
A text message has been sent to +{msisdn}. - Please enter the verification code it contains
- ]; - if (err) { - let msg = err.error; - if (err.errcode == 'M_THREEPID_AUTH_FAILED') { - msg = "Incorrect verification code"; - } - msgElements.push(
{msg}
); - } - Modal.createDialog(TextInputDialog, { - title: "Enter Code", - description:
{msgElements}
, - button: "Submit", - onFinished: (should_verify, token) => { - if (!should_verify) { - this._addThreepid = null; - return; - } - this.setState({msisdn_add_pending: true}); - this._addThreepid.haveMsisdnToken(token).then(() => { - this._addThreepid = null; - this.setState({phoneNumber: ''}); - return this._refreshFromServer(); - }).catch((err) => { - this._promptForMsisdnVerificationCode(msisdn, err); - }).finally(() => { - this.setState({msisdn_add_pending: false}); - }).done(); - } - }); - }, - onRemoveThreepidClicked: function(threepid) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); Modal.createDialog(QuestionDialog, { @@ -897,7 +819,6 @@ module.exports = React.createClass({ ); }); let addEmailSection; - let addMsisdnSection; if (this.state.email_add_pending) { addEmailSection = ; } else if (!MatrixClientPeg.get().isGuest()) { @@ -920,35 +841,10 @@ module.exports = React.createClass({ ); } - if (this.state.msisdn_add_pending) { - addMsisdnSection = ; - } else if (!MatrixClientPeg.get().isGuest()) { - const CountryDropdown = sdk.getComponent('views.login.CountryDropdown'); - addMsisdnSection = ( -
-
-
-
-
- - - -
-
- Add -
-
- ); - } + const AddPhoneNumber = sdk.getComponent('views.settings.AddPhoneNumber'); + const addMsisdnSection = ( + + ); threepidsSection.push(addEmailSection); threepidsSection.push(addMsisdnSection); diff --git a/src/components/views/settings/AddPhoneNumber.js b/src/components/views/settings/AddPhoneNumber.js new file mode 100644 index 0000000000..905a21f61d --- /dev/null +++ b/src/components/views/settings/AddPhoneNumber.js @@ -0,0 +1,170 @@ +/* +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. +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 React from 'react'; + +import sdk from '../../../index'; +import AddThreepid from '../../../AddThreepid'; +import WithMatrixClient from '../../../wrappers/WithMatrixClient'; +import Modal from '../../../Modal'; + + +class AddPhoneNumber extends React.Component { + constructor(props, context) { + super(props, context); + + this._addThreepid = null; + this._addMsisdnInput = null; + + this.state = { + busy: false, + phoneCountry: null, + phoneNumber: "", + }; + + this._onPhoneCountryChange = this._onPhoneCountryChange.bind(this); + this._onPhoneNumberChange = this._onPhoneNumberChange.bind(this); + this._onAddMsisdnEditFinished = this._onAddMsisdnEditFinished.bind(this); + this._onAddMsisdnSubmit = this._onAddMsisdnSubmit.bind(this); + this._collectAddMsisdnInput = this._collectAddMsisdnInput.bind(this); + this._addMsisdn = this._addMsisdn.bind(this); + this._promptForMsisdnVerificationCode = this._promptForMsisdnVerificationCode.bind(this); + } + + _onPhoneCountryChange(phoneCountry) { + this.setState({ phoneCountry: phoneCountry }); + } + + _onPhoneNumberChange(ev) { + this.setState({ phoneNumber: ev.target.value }); + } + + _onAddMsisdnEditFinished(value, shouldSubmit) { + if (!shouldSubmit) return; + this._addMsisdn(); + } + + _onAddMsisdnSubmit(ev) { + ev.preventDefault(); + this._addMsisdn(); + } + + _collectAddMsisdnInput(e) { + this._addMsisdnInput = e; + } + + _addMsisdn() { + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + + this._addThreepid = new AddThreepid(); + // we always bind phone numbers when registering, so let's do the + // same here. + this._addThreepid.addMsisdn(this.state.phoneCountry, this.state.phoneNumber, true).then((resp) => { + this._promptForMsisdnVerificationCode(resp.msisdn); + }).catch((err) => { + console.error("Unable to add phone number: " + err); + let msg = err.message; + Modal.createDialog(ErrorDialog, { + title: "Error", + description: msg, + }); + }).finally(() => { + this.setState({msisdn_add_pending: false}); + }).done();; + this._addMsisdnInput.blur(); + this.setState({msisdn_add_pending: true}); + } + + _promptForMsisdnVerificationCode(msisdn, err) { + const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog"); + let msgElements = [ +
A text message has been sent to +{msisdn}. + Please enter the verification code it contains
+ ]; + if (err) { + let msg = err.error; + if (err.errcode == 'M_THREEPID_AUTH_FAILED') { + msg = "Incorrect verification code"; + } + msgElements.push(
{msg}
); + } + Modal.createDialog(TextInputDialog, { + title: "Enter Code", + description:
{msgElements}
, + button: "Submit", + onFinished: (should_verify, token) => { + if (!should_verify) { + this._addThreepid = null; + return; + } + this.setState({msisdn_add_pending: true}); + this._addThreepid.haveMsisdnToken(token).then(() => { + this._addThreepid = null; + this.setState({phoneNumber: ''}); + if (this.props.onThreepidAdded) this.props.onThreepidAdded(); + }).catch((err) => { + this._promptForMsisdnVerificationCode(msisdn, err); + }).finally(() => { + this.setState({msisdn_add_pending: false}); + }).done(); + } + }); + } + + render() { + const Loader = sdk.getComponent("elements.Spinner"); + if (this.state.msisdn_add_pending) { + return ; + } else if (!this.props.matrixClient.isGuest()) { + const CountryDropdown = sdk.getComponent('views.login.CountryDropdown'); + // XXX: This CSS relies on the CSS surrounding it in UserSettings as its in + // a tabular format to align the submit buttons + return ( +
+
+
+
+
+ + + +
+
+ Add +
+
+ ); + } + } +} + +AddPhoneNumber.propTypes = { + matrixClient: React.PropTypes.object.isRequired, + onThreepidAdded: React.PropTypes.func, +}; + +AddPhoneNumber = WithMatrixClient(AddPhoneNumber); +export default AddPhoneNumber;