Factor out AddPhoneNumber to a separate component

pull/21833/head
David Baker 2017-03-22 15:18:27 +00:00
parent 6a37fc4325
commit 4cd24d15d4
3 changed files with 177 additions and 109 deletions

View File

@ -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';

View File

@ -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 = [
<div>A text message has been sent to +{msisdn}.
Please enter the verification code it contains</div>
];
if (err) {
let msg = err.error;
if (err.errcode == 'M_THREEPID_AUTH_FAILED') {
msg = "Incorrect verification code";
}
msgElements.push(<div className="error">{msg}</div>);
}
Modal.createDialog(TextInputDialog, {
title: "Enter Code",
description: <div>{msgElements}</div>,
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 = <Loader key="_email_add_spinner" />;
} else if (!MatrixClientPeg.get().isGuest()) {
@ -920,35 +841,10 @@ module.exports = React.createClass({
</div>
);
}
if (this.state.msisdn_add_pending) {
addMsisdnSection = <Loader key="_msisdn_add_spinner" />;
} else if (!MatrixClientPeg.get().isGuest()) {
const CountryDropdown = sdk.getComponent('views.login.CountryDropdown');
addMsisdnSection = (
<div className="mx_UserSettings_profileTableRow" key="_newMsisdn">
<div className="mx_UserSettings_profileLabelCell">
</div>
<div className="mx_UserSettings_profileInputCell">
<form className="mx_Login_phoneSection" onSubmit={this._onAddMsisdnSubmit}>
<CountryDropdown ref="phone_country" onOptionChange={this._onPhoneCountryChange}
className="mx_Login_phoneCountry"
value={this.state.phoneCountry}
/>
<input type="text" ref="phoneNumber"
ref="add_msisdn_input"
className="mx_UserSettings_phoneNumberField"
placeholder="Add phone number"
value={this.state.phoneNumber}
onChange={this._onPhoneNumberChange}
/>
</form>
</div>
<div className="mx_UserSettings_threepidButton mx_filterFlipColor">
<img src="img/plus.svg" width="14" height="14" alt="Add" onClick={this._addMsisdn} />
</div>
</div>
);
}
const AddPhoneNumber = sdk.getComponent('views.settings.AddPhoneNumber');
const addMsisdnSection = (
<AddPhoneNumber key="_addMsisdn" onThreepidAdded={this._refreshFromServer} />
);
threepidsSection.push(addEmailSection);
threepidsSection.push(addMsisdnSection);

View File

@ -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 = [
<div>A text message has been sent to +{msisdn}.
Please enter the verification code it contains</div>
];
if (err) {
let msg = err.error;
if (err.errcode == 'M_THREEPID_AUTH_FAILED') {
msg = "Incorrect verification code";
}
msgElements.push(<div className="error">{msg}</div>);
}
Modal.createDialog(TextInputDialog, {
title: "Enter Code",
description: <div>{msgElements}</div>,
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 <Loader />;
} 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 (
<div className="mx_UserSettings_profileTableRow">
<div className="mx_UserSettings_profileLabelCell">
</div>
<div className="mx_UserSettings_profileInputCell">
<form className="mx_Login_phoneSection" onSubmit={this._onAddMsisdnSubmit}>
<CountryDropdown onOptionChange={this._onPhoneCountryChange}
className="mx_Login_phoneCountry"
value={this.state.phoneCountry}
/>
<input type="text"
ref={this._collectAddMsisdnInput}
className="mx_UserSettings_phoneNumberField"
placeholder="Add phone number"
value={this.state.phoneNumber}
onChange={this._onPhoneNumberChange}
/>
</form>
</div>
<div className="mx_UserSettings_threepidButton mx_filterFlipColor">
<img src="img/plus.svg" width="14" height="14" alt="Add" onClick={this._addMsisdn} />
</div>
</div>
);
}
}
}
AddPhoneNumber.propTypes = {
matrixClient: React.PropTypes.object.isRequired,
onThreepidAdded: React.PropTypes.func,
};
AddPhoneNumber = WithMatrixClient(AddPhoneNumber);
export default AddPhoneNumber;