Convert PhoneNumbers to TS

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
pull/21833/head
Šimon Brandner 2021-09-21 12:21:51 +02:00
parent a2ecf18096
commit 39f92c4ddc
No known key found for this signature in database
GPG Key ID: 55C211A1226CB17D
1 changed files with 57 additions and 44 deletions

View File

@ -16,16 +16,17 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import Field from "../../elements/Field"; import Field from "../../elements/Field";
import AccessibleButton from "../../elements/AccessibleButton"; import AccessibleButton from "../../elements/AccessibleButton";
import AddThreepid from "../../../../AddThreepid"; import AddThreepid from "../../../../AddThreepid";
import CountryDropdown from "../../auth/CountryDropdown"; import CountryDropdown from "../../auth/CountryDropdown";
import * as sdk from '../../../../index';
import Modal from '../../../../Modal'; import Modal from '../../../../Modal';
import { replaceableComponent } from "../../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../../utils/replaceableComponent";
import { IThreepid, ThreepidMedium } from "matrix-js-sdk/src/@types/threepids";
import ErrorDialog from "../../dialogs/ErrorDialog";
import { PhoneNumberCountryDefinition } from "../../../../phonenumber";
/* /*
TODO: Improve the UX for everything in here. TODO: Improve the UX for everything in here.
@ -34,42 +35,45 @@ This is a copy/paste of EmailAddresses, mostly.
// TODO: Combine EmailAddresses and PhoneNumbers to be 3pid agnostic // TODO: Combine EmailAddresses and PhoneNumbers to be 3pid agnostic
export class ExistingPhoneNumber extends React.Component { interface IExistingPhoneNumberProps {
static propTypes = { msisdn: IThreepid;
msisdn: PropTypes.object.isRequired, onRemoved: (phoneNumber: IThreepid) => void;
onRemoved: PropTypes.func.isRequired, }
};
constructor() { interface IExistingPhoneNumberState {
super(); verifyRemove: boolean;
}
export class ExistingPhoneNumber extends React.Component<IExistingPhoneNumberProps, IExistingPhoneNumberState> {
constructor(props: IExistingPhoneNumberProps) {
super(props);
this.state = { this.state = {
verifyRemove: false, verifyRemove: false,
}; };
} }
_onRemove = (e) => { private onRemove = (e: React.MouseEvent): void => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
this.setState({ verifyRemove: true }); this.setState({ verifyRemove: true });
}; };
_onDontRemove = (e) => { private onDontRemove = (e: React.MouseEvent): void => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
this.setState({ verifyRemove: false }); this.setState({ verifyRemove: false });
}; };
_onActuallyRemove = (e) => { private onActuallyRemove = (e: React.MouseEvent): void => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
MatrixClientPeg.get().deleteThreePid(this.props.msisdn.medium, this.props.msisdn.address).then(() => { MatrixClientPeg.get().deleteThreePid(this.props.msisdn.medium, this.props.msisdn.address).then(() => {
return this.props.onRemoved(this.props.msisdn); return this.props.onRemoved(this.props.msisdn);
}).catch((err) => { }).catch((err) => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Unable to remove contact information: " + err); console.error("Unable to remove contact information: " + err);
Modal.createTrackedDialog('Remove 3pid failed', '', ErrorDialog, { Modal.createTrackedDialog('Remove 3pid failed', '', ErrorDialog, {
title: _t("Unable to remove contact information"), title: _t("Unable to remove contact information"),
@ -78,7 +82,7 @@ export class ExistingPhoneNumber extends React.Component {
}); });
}; };
render() { public render(): JSX.Element {
if (this.state.verifyRemove) { if (this.state.verifyRemove) {
return ( return (
<div className="mx_ExistingPhoneNumber"> <div className="mx_ExistingPhoneNumber">
@ -86,14 +90,14 @@ export class ExistingPhoneNumber extends React.Component {
{ _t("Remove %(phone)s?", { phone: this.props.msisdn.address }) } { _t("Remove %(phone)s?", { phone: this.props.msisdn.address }) }
</span> </span>
<AccessibleButton <AccessibleButton
onClick={this._onActuallyRemove} onClick={this.onActuallyRemove}
kind="danger_sm" kind="danger_sm"
className="mx_ExistingPhoneNumber_confirmBtn" className="mx_ExistingPhoneNumber_confirmBtn"
> >
{ _t("Remove") } { _t("Remove") }
</AccessibleButton> </AccessibleButton>
<AccessibleButton <AccessibleButton
onClick={this._onDontRemove} onClick={this.onDontRemove}
kind="link_sm" kind="link_sm"
className="mx_ExistingPhoneNumber_confirmBtn" className="mx_ExistingPhoneNumber_confirmBtn"
> >
@ -106,7 +110,7 @@ export class ExistingPhoneNumber extends React.Component {
return ( return (
<div className="mx_ExistingPhoneNumber"> <div className="mx_ExistingPhoneNumber">
<span className="mx_ExistingPhoneNumber_address">+{ this.props.msisdn.address }</span> <span className="mx_ExistingPhoneNumber_address">+{ this.props.msisdn.address }</span>
<AccessibleButton onClick={this._onRemove} kind="danger_sm"> <AccessibleButton onClick={this.onRemove} kind="danger_sm">
{ _t("Remove") } { _t("Remove") }
</AccessibleButton> </AccessibleButton>
</div> </div>
@ -114,19 +118,30 @@ export class ExistingPhoneNumber extends React.Component {
} }
} }
@replaceableComponent("views.settings.account.PhoneNumbers") interface IProps {
export default class PhoneNumbers extends React.Component { msisdns: IThreepid[];
static propTypes = { onMsisdnsChange: (phoneNumbers: Partial<IThreepid>[]) => void;
msisdns: PropTypes.array.isRequired, }
onMsisdnsChange: PropTypes.func.isRequired,
}
constructor(props) { interface IState {
verifying: boolean;
verifyError: string;
verifyMsisdn: string;
addTask: any; // FIXME: When AddThreepid is TSfied
continueDisabled: boolean;
phoneCountry: string;
newPhoneNumber: string;
newPhoneNumberCode: string;
}
@replaceableComponent("views.settings.account.PhoneNumbers")
export default class PhoneNumbers extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props); super(props);
this.state = { this.state = {
verifying: false, verifying: false,
verifyError: false, verifyError: null,
verifyMsisdn: "", verifyMsisdn: "",
addTask: null, addTask: null,
continueDisabled: false, continueDisabled: false,
@ -136,30 +151,29 @@ export default class PhoneNumbers extends React.Component {
}; };
} }
_onRemoved = (address) => { private onRemoved = (address: IThreepid): void => {
const msisdns = this.props.msisdns.filter((e) => e !== address); const msisdns = this.props.msisdns.filter((e) => e !== address);
this.props.onMsisdnsChange(msisdns); this.props.onMsisdnsChange(msisdns);
}; };
_onChangeNewPhoneNumber = (e) => { private onChangeNewPhoneNumber = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({ this.setState({
newPhoneNumber: e.target.value, newPhoneNumber: e.target.value,
}); });
}; };
_onChangeNewPhoneNumberCode = (e) => { private onChangeNewPhoneNumberCode = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({ this.setState({
newPhoneNumberCode: e.target.value, newPhoneNumberCode: e.target.value,
}); });
}; };
_onAddClick = (e) => { private onAddClick = (e: React.MouseEvent | React.FormEvent): void => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
if (!this.state.newPhoneNumber) return; if (!this.state.newPhoneNumber) return;
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const phoneNumber = this.state.newPhoneNumber; const phoneNumber = this.state.newPhoneNumber;
const phoneCountry = this.state.phoneCountry; const phoneCountry = this.state.phoneCountry;
@ -178,7 +192,7 @@ export default class PhoneNumbers extends React.Component {
}); });
}; };
_onContinueClick = (e) => { private onContinueClick = (e: React.MouseEvent | React.FormEvent): void => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@ -190,7 +204,7 @@ export default class PhoneNumbers extends React.Component {
if (finished) { if (finished) {
const msisdns = [ const msisdns = [
...this.props.msisdns, ...this.props.msisdns,
{ address, medium: "msisdn" }, { address, medium: ThreepidMedium.Phone },
]; ];
this.props.onMsisdnsChange(msisdns); this.props.onMsisdnsChange(msisdns);
newPhoneNumber = ""; newPhoneNumber = "";
@ -207,7 +221,6 @@ export default class PhoneNumbers extends React.Component {
}).catch((err) => { }).catch((err) => {
this.setState({ continueDisabled: false }); this.setState({ continueDisabled: false });
if (err.errcode !== 'M_THREEPID_AUTH_FAILED') { if (err.errcode !== 'M_THREEPID_AUTH_FAILED') {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Unable to verify phone number: " + err); console.error("Unable to verify phone number: " + err);
Modal.createTrackedDialog('Unable to verify phone number', '', ErrorDialog, { Modal.createTrackedDialog('Unable to verify phone number', '', ErrorDialog, {
title: _t("Unable to verify phone number."), title: _t("Unable to verify phone number."),
@ -219,17 +232,17 @@ export default class PhoneNumbers extends React.Component {
}); });
}; };
_onCountryChanged = (e) => { private onCountryChanged = (country: PhoneNumberCountryDefinition): void => {
this.setState({ phoneCountry: e.iso2 }); this.setState({ phoneCountry: country.iso2 });
}; };
render() { public render(): JSX.Element {
const existingPhoneElements = this.props.msisdns.map((p) => { const existingPhoneElements = this.props.msisdns.map((p) => {
return <ExistingPhoneNumber msisdn={p} onRemoved={this._onRemoved} key={p.address} />; return <ExistingPhoneNumber msisdn={p} onRemoved={this.onRemoved} key={p.address} />;
}); });
let addVerifySection = ( let addVerifySection = (
<AccessibleButton onClick={this._onAddClick} kind="primary"> <AccessibleButton onClick={this.onAddClick} kind="primary">
{ _t("Add") } { _t("Add") }
</AccessibleButton> </AccessibleButton>
); );
@ -243,17 +256,17 @@ export default class PhoneNumbers extends React.Component {
<br /> <br />
{ this.state.verifyError } { this.state.verifyError }
</div> </div>
<form onSubmit={this._onContinueClick} autoComplete="off" noValidate={true}> <form onSubmit={this.onContinueClick} autoComplete="off" noValidate={true}>
<Field <Field
type="text" type="text"
label={_t("Verification code")} label={_t("Verification code")}
autoComplete="off" autoComplete="off"
disabled={this.state.continueDisabled} disabled={this.state.continueDisabled}
value={this.state.newPhoneNumberCode} value={this.state.newPhoneNumberCode}
onChange={this._onChangeNewPhoneNumberCode} onChange={this.onChangeNewPhoneNumberCode}
/> />
<AccessibleButton <AccessibleButton
onClick={this._onContinueClick} onClick={this.onContinueClick}
kind="primary" kind="primary"
disabled={this.state.continueDisabled} disabled={this.state.continueDisabled}
> >
@ -264,7 +277,7 @@ export default class PhoneNumbers extends React.Component {
); );
} }
const phoneCountry = <CountryDropdown onOptionChange={this._onCountryChanged} const phoneCountry = <CountryDropdown onOptionChange={this.onCountryChanged}
className="mx_PhoneNumbers_country" className="mx_PhoneNumbers_country"
value={this.state.phoneCountry} value={this.state.phoneCountry}
disabled={this.state.verifying} disabled={this.state.verifying}
@ -275,7 +288,7 @@ export default class PhoneNumbers extends React.Component {
return ( return (
<div className="mx_PhoneNumbers"> <div className="mx_PhoneNumbers">
{ existingPhoneElements } { existingPhoneElements }
<form onSubmit={this._onAddClick} autoComplete="off" noValidate={true} className="mx_PhoneNumbers_new"> <form onSubmit={this.onAddClick} autoComplete="off" noValidate={true} className="mx_PhoneNumbers_new">
<div className="mx_PhoneNumbers_input"> <div className="mx_PhoneNumbers_input">
<Field <Field
type="text" type="text"
@ -284,7 +297,7 @@ export default class PhoneNumbers extends React.Component {
disabled={this.state.verifying} disabled={this.state.verifying}
prefixComponent={phoneCountry} prefixComponent={phoneCountry}
value={this.state.newPhoneNumber} value={this.state.newPhoneNumber}
onChange={this._onChangeNewPhoneNumber} onChange={this.onChangeNewPhoneNumber}
/> />
</div> </div>
</form> </form>