diff --git a/src/boundThreepids.js b/src/boundThreepids.js index 799728f801..90a5bd2a6f 100644 --- a/src/boundThreepids.js +++ b/src/boundThreepids.js @@ -16,7 +16,7 @@ limitations under the License. import IdentityAuthClient from './IdentityAuthClient'; -export async function getThreepidBindStatus(client, filterMedium) { +export async function getThreepidsWithBindStatus(client, filterMedium) { const userId = client.getUserId(); let { threepids } = await client.getThreePids(); @@ -24,7 +24,8 @@ export async function getThreepidBindStatus(client, filterMedium) { threepids = threepids.filter((a) => a.medium === filterMedium); } - if (threepids.length > 0) { + // Check bind status assuming we have an IS and terms are agreed + if (threepids.length > 0 && client.getIdentityServerUrl()) { // TODO: Handle terms agreement // See https://github.com/vector-im/riot-web/issues/10522 const authClient = new IdentityAuthClient(); diff --git a/src/components/views/settings/SetIdServer.js b/src/components/views/settings/SetIdServer.js index ae550725f1..9ef5fb295e 100644 --- a/src/components/views/settings/SetIdServer.js +++ b/src/components/views/settings/SetIdServer.js @@ -22,7 +22,7 @@ import sdk from '../../../index'; import MatrixClientPeg from "../../../MatrixClientPeg"; import Modal from '../../../Modal'; import dis from "../../../dispatcher"; -import { getThreepidBindStatus } from '../../../boundThreepids'; +import { getThreepidsWithBindStatus } from '../../../boundThreepids'; import IdentityAuthClient from "../../../IdentityAuthClient"; import {SERVICE_TYPES} from "matrix-js-sdk"; import {abbreviateUrl, unabbreviateUrl} from "../../../utils/UrlUtils"; @@ -249,7 +249,7 @@ export default class SetIdServer extends React.Component { }; async _showServerChangeWarning({ title, unboundMessage, button }) { - const threepids = await getThreepidBindStatus(MatrixClientPeg.get()); + const threepids = await getThreepidsWithBindStatus(MatrixClientPeg.get()); const boundThreepids = threepids.filter(tp => tp.bound); let message; diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js index eb60d4a322..b7324eb272 100644 --- a/src/components/views/settings/account/EmailAddresses.js +++ b/src/components/views/settings/account/EmailAddresses.js @@ -23,8 +23,8 @@ import Field from "../../elements/Field"; import AccessibleButton from "../../elements/AccessibleButton"; import * as Email from "../../../../email"; import AddThreepid from "../../../../AddThreepid"; -const sdk = require('../../../../index'); -const Modal = require("../../../../Modal"); +import sdk from '../../../../index'; +import Modal from '../../../../Modal'; /* TODO: Improve the UX for everything in here. @@ -113,11 +113,15 @@ export class ExistingEmailAddress extends React.Component { } export default class EmailAddresses extends React.Component { - constructor() { - super(); + static propTypes = { + emails: PropTypes.array.isRequired, + onEmailsChange: PropTypes.func.isRequired, + } + + constructor(props) { + super(props); this.state = { - emails: [], verifying: false, addTask: null, continueDisabled: false, @@ -125,16 +129,9 @@ export default class EmailAddresses extends React.Component { }; } - componentWillMount(): void { - const client = MatrixClientPeg.get(); - - client.getThreePids().then((addresses) => { - this.setState({emails: addresses.threepids.filter((a) => a.medium === 'email')}); - }); - } - _onRemoved = (address) => { - this.setState({emails: this.state.emails.filter((e) => e !== address)}); + const emails = this.props.emails.filter((e) => e !== address); + this.props.onEmailsChange(emails); }; _onChangeNewEmailAddress = (e) => { @@ -184,12 +181,16 @@ export default class EmailAddresses extends React.Component { this.state.addTask.checkEmailLinkClicked().then(() => { const email = this.state.newEmailAddress; this.setState({ - emails: [...this.state.emails, {address: email, medium: "email"}], addTask: null, continueDisabled: false, verifying: false, newEmailAddress: "", }); + const emails = [ + ...this.props.emails, + { address: email, medium: "email" }, + ]; + this.props.onEmailsChange(emails); }).catch((err) => { this.setState({continueDisabled: false}); if (err.errcode !== 'M_THREEPID_AUTH_FAILED') { @@ -204,7 +205,7 @@ export default class EmailAddresses extends React.Component { }; render() { - const existingEmailElements = this.state.emails.map((e) => { + const existingEmailElements = this.props.emails.map((e) => { return ; }); diff --git a/src/components/views/settings/account/PhoneNumbers.js b/src/components/views/settings/account/PhoneNumbers.js index fbb5b7e561..8f91eb22cc 100644 --- a/src/components/views/settings/account/PhoneNumbers.js +++ b/src/components/views/settings/account/PhoneNumbers.js @@ -23,8 +23,8 @@ import Field from "../../elements/Field"; import AccessibleButton from "../../elements/AccessibleButton"; import AddThreepid from "../../../../AddThreepid"; import CountryDropdown from "../../auth/CountryDropdown"; -const sdk = require('../../../../index'); -const Modal = require("../../../../Modal"); +import sdk from '../../../../index'; +import Modal from '../../../../Modal'; /* TODO: Improve the UX for everything in here. @@ -108,11 +108,15 @@ export class ExistingPhoneNumber extends React.Component { } export default class PhoneNumbers extends React.Component { - constructor() { - super(); + static propTypes = { + msisdns: PropTypes.array.isRequired, + onMsisdnsChange: PropTypes.func.isRequired, + } + + constructor(props) { + super(props); this.state = { - msisdns: [], verifying: false, verifyError: false, verifyMsisdn: "", @@ -124,16 +128,9 @@ export default class PhoneNumbers extends React.Component { }; } - componentWillMount(): void { - const client = MatrixClientPeg.get(); - - client.getThreePids().then((addresses) => { - this.setState({msisdns: addresses.threepids.filter((a) => a.medium === 'msisdn')}); - }); - } - _onRemoved = (address) => { - this.setState({msisdns: this.state.msisdns.filter((e) => e !== address)}); + const msisdns = this.props.msisdns.filter((e) => e !== address); + this.props.onMsisdnsChange(msisdns); }; _onChangeNewPhoneNumber = (e) => { @@ -181,7 +178,6 @@ export default class PhoneNumbers extends React.Component { const token = this.state.newPhoneNumberCode; this.state.addTask.haveMsisdnToken(token).then(() => { this.setState({ - msisdns: [...this.state.msisdns, {address: this.state.verifyMsisdn, medium: "msisdn"}], addTask: null, continueDisabled: false, verifying: false, @@ -190,6 +186,11 @@ export default class PhoneNumbers extends React.Component { newPhoneNumber: "", newPhoneNumberCode: "", }); + const msisdns = [ + ...this.props.msisdns, + { address: this.state.verifyMsisdn, medium: "msisdn" }, + ]; + this.props.onMsisdnsChange(msisdns); }).catch((err) => { this.setState({continueDisabled: false}); if (err.errcode !== 'M_THREEPID_AUTH_FAILED') { @@ -210,7 +211,7 @@ export default class PhoneNumbers extends React.Component { }; render() { - const existingPhoneElements = this.state.msisdns.map((p) => { + const existingPhoneElements = this.props.msisdns.map((p) => { return ; }); diff --git a/src/components/views/settings/discovery/EmailAddresses.js b/src/components/views/settings/discovery/EmailAddresses.js index 4d18c1d355..c6ec826de6 100644 --- a/src/components/views/settings/discovery/EmailAddresses.js +++ b/src/components/views/settings/discovery/EmailAddresses.js @@ -23,7 +23,6 @@ import MatrixClientPeg from "../../../../MatrixClientPeg"; import sdk from '../../../../index'; import Modal from '../../../../Modal'; import AddThreepid from '../../../../AddThreepid'; -import { getThreepidBindStatus } from '../../../../boundThreepids'; /* TODO: Improve the UX for everything in here. @@ -187,27 +186,14 @@ export class EmailAddress extends React.Component { } export default class EmailAddresses extends React.Component { - constructor() { - super(); - - this.state = { - loaded: false, - emails: [], - }; - } - - async componentWillMount() { - const client = MatrixClientPeg.get(); - - const emails = await getThreepidBindStatus(client, 'email'); - - this.setState({ emails }); + static propTypes = { + emails: PropTypes.array.isRequired, } render() { let content; - if (this.state.emails.length > 0) { - content = this.state.emails.map((e) => { + if (this.props.emails.length > 0) { + content = this.props.emails.map((e) => { return ; }); } else { diff --git a/src/components/views/settings/discovery/PhoneNumbers.js b/src/components/views/settings/discovery/PhoneNumbers.js index fdebac5d22..6d5c8ad3b4 100644 --- a/src/components/views/settings/discovery/PhoneNumbers.js +++ b/src/components/views/settings/discovery/PhoneNumbers.js @@ -23,7 +23,6 @@ import MatrixClientPeg from "../../../../MatrixClientPeg"; import sdk from '../../../../index'; import Modal from '../../../../Modal'; import AddThreepid from '../../../../AddThreepid'; -import { getThreepidBindStatus } from '../../../../boundThreepids'; /* TODO: Improve the UX for everything in here. @@ -206,27 +205,14 @@ export class PhoneNumber extends React.Component { } export default class PhoneNumbers extends React.Component { - constructor() { - super(); - - this.state = { - loaded: false, - msisdns: [], - }; - } - - async componentWillMount() { - const client = MatrixClientPeg.get(); - - const msisdns = await getThreepidBindStatus(client, 'msisdn'); - - this.setState({ msisdns }); + static propTypes = { + msisdns: PropTypes.array.isRequired, } render() { let content; - if (this.state.msisdns.length > 0) { - content = this.state.msisdns.map((e) => { + if (this.props.msisdns.length > 0) { + content = this.props.msisdns.map((e) => { return ; }); } else { diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 9c37730fc5..02f9cf3cd3 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -37,6 +37,7 @@ import {Service, startTermsFlow} from "../../../../../Terms"; import {SERVICE_TYPES} from "matrix-js-sdk"; import IdentityAuthClient from "../../../../../IdentityAuthClient"; import {abbreviateUrl} from "../../../../../utils/UrlUtils"; +import { getThreepidsWithBindStatus } from '../../../../../boundThreepids'; export default class GeneralUserSettingsTab extends React.Component { static propTypes = { @@ -58,17 +59,27 @@ export default class GeneralUserSettingsTab extends React.Component { // agreedUrls, // From the startTermsFlow callback // resolve, // Promise resolve function for startTermsFlow callback }, + emails: [], + msisdns: [], }; this.dispatcherRef = dis.register(this._onAction); } async componentWillMount() { - const serverRequiresIdServer = await MatrixClientPeg.get().doesServerRequireIdServerParam(); + const cli = MatrixClientPeg.get(); + + const serverRequiresIdServer = await cli.doesServerRequireIdServerParam(); this.setState({serverRequiresIdServer}); // Check to see if terms need accepting this._checkTerms(); + + // Need to get 3PIDs generally for Account section and possibly also for + // Discovery (assuming we have an IS and terms are agreed). + const threepids = await getThreepidsWithBindStatus(cli); + this.setState({ emails: threepids.filter((a) => a.medium === 'email') }); + this.setState({ msisdns: threepids.filter((a) => a.medium === 'msisdn') }); } componentWillUnmount() { @@ -82,6 +93,14 @@ export default class GeneralUserSettingsTab extends React.Component { } }; + _onEmailsChange = (emails) => { + this.setState({ emails }); + } + + _onMsisdnsChange = (msisdns) => { + this.setState({ msisdns }); + } + async _checkTerms() { if (!this.state.haveIdServer) { this.setState({idServerHasUnsignedTerms: false}); @@ -200,10 +219,16 @@ export default class GeneralUserSettingsTab extends React.Component { if (this.state.haveIdServer || this.state.serverRequiresIdServer === false) { threepidSection =
{_t("Email addresses")} - + {_t("Phone numbers")} - +
; } else if (this.state.serverRequiresIdServer === null) { threepidSection = ; @@ -279,10 +304,10 @@ export default class GeneralUserSettingsTab extends React.Component { const threepidSection = this.state.haveIdServer ?
{_t("Email addresses")} - + {_t("Phone numbers")} - +
: null; return (