From a05c0f9214833e119f09a0f7742a156482dd88f0 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 11 Jan 2019 15:46:03 -0700 Subject: [PATCH] Rephrase everything to be "invite anyways" rather than "retry" Also handle profile errors better --- ...itesDialog.js => AskInviteAnywayDialog.js} | 33 ++++++------ src/i18n/strings/en_EN.json | 9 ++-- src/settings/Settings.js | 4 +- src/utils/MultiInviter.js | 52 +++++++++++-------- 4 files changed, 54 insertions(+), 44 deletions(-) rename src/components/views/dialogs/{RetryInvitesDialog.js => AskInviteAnywayDialog.js} (63%) diff --git a/src/components/views/dialogs/RetryInvitesDialog.js b/src/components/views/dialogs/AskInviteAnywayDialog.js similarity index 63% rename from src/components/views/dialogs/RetryInvitesDialog.js rename to src/components/views/dialogs/AskInviteAnywayDialog.js index f27b0bc08b..5c61c3a694 100644 --- a/src/components/views/dialogs/RetryInvitesDialog.js +++ b/src/components/views/dialogs/AskInviteAnywayDialog.js @@ -23,20 +23,20 @@ import SettingsStore from "../../../settings/SettingsStore"; export default React.createClass({ propTypes: { - failedInvites: PropTypes.object.isRequired, // { address: { errcode, errorText } } - onTryAgain: PropTypes.func.isRequired, + unknownProfileUsers: PropTypes.array.isRequired, // [ {userId, errorText}... ] + onInviteAnyways: PropTypes.func.isRequired, onGiveUp: PropTypes.func.isRequired, onFinished: PropTypes.func.isRequired, }, - _onTryAgainClicked: function() { - this.props.onTryAgain(); + _onInviteClicked: function() { + this.props.onInviteAnyways(); this.props.onFinished(true); }, - _onTryAgainNeverWarnClicked: function() { - SettingsStore.setValue("alwaysRetryInvites", null, SettingLevel.ACCOUNT, true); - this.props.onTryAgain(); + _onInviteNeverWarnClicked: function() { + SettingsStore.setValue("alwaysInviteUnknownUsers", null, SettingLevel.ACCOUNT, true); + this.props.onInviteAnyways(); this.props.onFinished(true); }, @@ -48,28 +48,31 @@ export default React.createClass({ render: function() { const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); - const errorList = Object.keys(this.props.failedInvites) - .map(address =>

{address}: {this.props.failedInvites[address].errorText}

); + const errorList = this.props.unknownProfileUsers + .map(address =>
  • {address.userId}: {address.errorText}
  • ); return (
    - { errorList } +

    {_t("The following users may not exist - would you like to invite them anyways?")}

    +
      + { errorList } +
    - -
    diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 816506f6c3..4f8674db2f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -293,7 +293,7 @@ "Pin unread rooms to the top of the room list": "Pin unread rooms to the top of the room list", "Enable widget screenshots on supported widgets": "Enable widget screenshots on supported widgets", "Show empty room list headings": "Show empty room list headings", - "Always retry invites for unknown users": "Always retry invites for unknown users", + "Always invite users which may not exist": "Always invite users which may not exist", "Show developer tools": "Show developer tools", "Collecting app version information": "Collecting app version information", "Collecting logs": "Collecting logs", @@ -884,6 +884,10 @@ "That doesn't look like a valid email address": "That doesn't look like a valid email address", "You have entered an invalid address.": "You have entered an invalid address.", "Try using one of the following valid address types: %(validTypesList)s.": "Try using one of the following valid address types: %(validTypesList)s.", + "The following users may not exist": "The following users may not exist", + "The following users may not exist - would you like to invite them anyways?": "The following users may not exist - would you like to invite them anyways?", + "Invite anyways and never warn me again": "Invite anyways and never warn me again", + "Invite anyways": "Invite anyways", "Preparing to send logs": "Preparing to send logs", "Logs sent": "Logs sent", "Thank you!": "Thank you!", @@ -968,9 +972,6 @@ "Clear cache and resync": "Clear cache and resync", "Riot now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!": "Riot now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!", "Updating Riot": "Updating Riot", - "Failed to invite the following users": "Failed to invite the following users", - "Try again and never warn me again": "Try again and never warn me again", - "Try again": "Try again", "Failed to upgrade room": "Failed to upgrade room", "The room upgrade could not be completed": "The room upgrade could not be completed", "Upgrade this room to version %(version)s": "Upgrade this room to version %(version)s", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 507bcf49b8..a007f78c1f 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -317,9 +317,9 @@ export const SETTINGS = { displayName: _td('Show empty room list headings'), default: true, }, - "alwaysRetryInvites": { + "alwaysInviteUnknownUsers": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td('Always retry invites for unknown users'), + displayName: _td('Always invite users which may not exist'), default: false, }, "showDeveloperTools": { diff --git a/src/utils/MultiInviter.js b/src/utils/MultiInviter.js index 0d7a8837b8..b5f4f960a9 100644 --- a/src/utils/MultiInviter.js +++ b/src/utils/MultiInviter.js @@ -101,13 +101,18 @@ export default class MultiInviter { if (addrType === 'email') { return MatrixClientPeg.get().inviteByEmail(roomId, addr); } else if (addrType === 'mx-user-id') { - if (!ignoreProfile && !SettingsStore.getValue("alwaysRetryInvites", this.roomId)) { - const profile = await MatrixClientPeg.get().getProfileInfo(addr); - if (!profile) { - return Promise.reject({ - errcode: "M_NOT_FOUND", - error: "User does not have a profile or does not exist.", - }); + if (!ignoreProfile && !SettingsStore.getValue("alwaysInviteUnknownUsers", this.roomId)) { + try { + const profile = await MatrixClientPeg.get().getProfileInfo(addr); + if (!profile) { + // noinspection ExceptionCaughtLocallyJS + throw new Error("User has no profile"); + } + } catch (e) { + throw { + errcode: "RIOT.USER_NOT_FOUND", + error: "User does not have a profile or does not exist." + }; } } @@ -119,6 +124,8 @@ export default class MultiInviter { _doInvite(address, ignoreProfile) { return new Promise((resolve, reject) => { + console.log(`Inviting ${address}`); + let doInvite; if (this.groupId !== null) { doInvite = GroupStore.inviteUserToGroup(this.groupId, address); @@ -151,13 +158,13 @@ export default class MultiInviter { this._doInvite(address, ignoreProfile).then(resolve, reject); }, 5000); return; - } else if (['M_NOT_FOUND', 'M_USER_NOT_FOUND'].includes(err.errcode)) { + } else if (['M_NOT_FOUND', 'M_USER_NOT_FOUND', 'RIOT.USER_NOT_FOUND'].includes(err.errcode)) { errorText = _t("User %(user_id)s does not exist", {user_id: address}); - } else if (err.errcode === 'M_PROFILE_UNKNOWN') { + } else if (err.errcode === 'M_PROFILE_UNDISCLOSED') { errorText = _t("User %(user_id)s may or may not exist", {user_id: address}); } else if (err.errcode === 'M_PROFILE_NOT_FOUND' && !ignoreProfile) { // Invite without the profile check - console.warn(`User ${address} does not have a profile - trying invite again`); + console.warn(`User ${address} does not have a profile - inviting anyways automatically`); this._doInvite(address, true).then(resolve, reject); } else { errorText = _t('Unknown server error'); @@ -188,28 +195,28 @@ export default class MultiInviter { if (Object.keys(this.errors).length > 0 && !this.groupId) { // There were problems inviting some people - see if we can invite them // without caring if they exist or not. - const reinviteErrors = ['M_NOT_FOUND', 'M_USER_NOT_FOUND', 'M_PROFILE_UNKNOWN', 'M_PROFILE_NOT_FOUND']; - const reinvitableUsers = Object.keys(this.errors).filter(a => reinviteErrors.includes(this.errors[a].errcode)); + const unknownProfileErrors = ['M_NOT_FOUND', 'M_USER_NOT_FOUND', 'M_PROFILE_UNDISCLOSED', 'M_PROFILE_NOT_FOUND', 'RIOT.USER_NOT_FOUND']; + const unknownProfileUsers = Object.keys(this.errors).filter(a => unknownProfileErrors.includes(this.errors[a].errcode)); - if (reinvitableUsers.length > 0) { - const retryInvites = () => { - const promises = reinvitableUsers.map(u => this._doInvite(u, true)); + if (unknownProfileUsers.length > 0) { + const inviteUnknowns = () => { + const promises = unknownProfileUsers.map(u => this._doInvite(u, true)); Promise.all(promises).then(() => this.deferred.resolve(this.completionStates)); }; - if (SettingsStore.getValue("alwaysRetryInvites", this.roomId)) { - retryInvites(); + if (SettingsStore.getValue("alwaysInviteUnknownUsers", this.roomId)) { + inviteUnknowns(); return; } - const RetryInvitesDialog = sdk.getComponent("dialogs.RetryInvitesDialog"); + const AskInviteAnywayDialog = sdk.getComponent("dialogs.AskInviteAnywayDialog"); console.log("Showing failed to invite dialog..."); - Modal.createTrackedDialog('Failed to invite the following users to the room', '', RetryInvitesDialog, { - failedInvites: this.errors, - onTryAgain: () => retryInvites(), + Modal.createTrackedDialog('Failed to invite the following users to the room', '', AskInviteAnywayDialog, { + unknownProfileUsers: unknownProfileUsers.map(u => {return {userId: u, errorText: this.errors[u].errorText};}), + onInviteAnyways: () => inviteUnknowns(), onGiveUp: () => { // Fake all the completion states because we already warned the user - for (const addr of Object.keys(this.completionStates)) { + for (const addr of unknownProfileUsers) { this.completionStates[addr] = 'invited'; } this.deferred.resolve(this.completionStates); @@ -223,7 +230,6 @@ export default class MultiInviter { } const addr = this.addrs[nextIndex]; - console.log(`Inviting ${addr}`); // don't try to invite it if it's an invalid address // (it will already be marked as an error though,