Rephrase everything to be "invite anyways" rather than "retry"

Also handle profile errors better
pull/21833/head
Travis Ralston 2019-01-11 15:46:03 -07:00
parent c351ee3d30
commit a05c0f9214
4 changed files with 54 additions and 44 deletions

View File

@ -23,20 +23,20 @@ import SettingsStore from "../../../settings/SettingsStore";
export default React.createClass({ export default React.createClass({
propTypes: { propTypes: {
failedInvites: PropTypes.object.isRequired, // { address: { errcode, errorText } } unknownProfileUsers: PropTypes.array.isRequired, // [ {userId, errorText}... ]
onTryAgain: PropTypes.func.isRequired, onInviteAnyways: PropTypes.func.isRequired,
onGiveUp: PropTypes.func.isRequired, onGiveUp: PropTypes.func.isRequired,
onFinished: PropTypes.func.isRequired, onFinished: PropTypes.func.isRequired,
}, },
_onTryAgainClicked: function() { _onInviteClicked: function() {
this.props.onTryAgain(); this.props.onInviteAnyways();
this.props.onFinished(true); this.props.onFinished(true);
}, },
_onTryAgainNeverWarnClicked: function() { _onInviteNeverWarnClicked: function() {
SettingsStore.setValue("alwaysRetryInvites", null, SettingLevel.ACCOUNT, true); SettingsStore.setValue("alwaysInviteUnknownUsers", null, SettingLevel.ACCOUNT, true);
this.props.onTryAgain(); this.props.onInviteAnyways();
this.props.onFinished(true); this.props.onFinished(true);
}, },
@ -48,28 +48,31 @@ export default React.createClass({
render: function() { render: function() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const errorList = Object.keys(this.props.failedInvites) const errorList = this.props.unknownProfileUsers
.map(address => <p key={address}>{address}: {this.props.failedInvites[address].errorText}</p>); .map(address => <li key={address.userId}>{address.userId}: {address.errorText}</li>);
return ( return (
<BaseDialog className='mx_RetryInvitesDialog' <BaseDialog className='mx_RetryInvitesDialog'
onFinished={this._onGiveUpClicked} onFinished={this._onGiveUpClicked}
title={_t('Failed to invite the following users')} title={_t('The following users may not exist')}
contentId='mx_Dialog_content' contentId='mx_Dialog_content'
> >
<div id='mx_Dialog_content'> <div id='mx_Dialog_content'>
{ errorList } <p>{_t("The following users may not exist - would you like to invite them anyways?")}</p>
<ul>
{ errorList }
</ul>
</div> </div>
<div className="mx_Dialog_buttons"> <div className="mx_Dialog_buttons">
<button onClick={this._onGiveUpClicked}> <button onClick={this._onGiveUpClicked}>
{ _t('Close') } { _t('Close') }
</button> </button>
<button onClick={this._onTryAgainNeverWarnClicked}> <button onClick={this._onInviteNeverWarnClicked}>
{ _t('Try again and never warn me again') } { _t('Invite anyways and never warn me again') }
</button> </button>
<button onClick={this._onTryAgainClicked} autoFocus="true"> <button onClick={this._onInviteClicked} autoFocus="true">
{ _t('Try again') } { _t('Invite anyways') }
</button> </button>
</div> </div>
</BaseDialog> </BaseDialog>

View File

@ -293,7 +293,7 @@
"Pin unread rooms to the top of the room list": "Pin unread rooms to the top of the room list", "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", "Enable widget screenshots on supported widgets": "Enable widget screenshots on supported widgets",
"Show empty room list headings": "Show empty room list headings", "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", "Show developer tools": "Show developer tools",
"Collecting app version information": "Collecting app version information", "Collecting app version information": "Collecting app version information",
"Collecting logs": "Collecting logs", "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", "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.", "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.", "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", "Preparing to send logs": "Preparing to send logs",
"Logs sent": "Logs sent", "Logs sent": "Logs sent",
"Thank you!": "Thank you!", "Thank you!": "Thank you!",
@ -968,9 +972,6 @@
"Clear cache and resync": "Clear cache and resync", "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!", "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", "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", "Failed to upgrade room": "Failed to upgrade room",
"The room upgrade could not be completed": "The room upgrade could not be completed", "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", "Upgrade this room to version %(version)s": "Upgrade this room to version %(version)s",

View File

@ -317,9 +317,9 @@ export const SETTINGS = {
displayName: _td('Show empty room list headings'), displayName: _td('Show empty room list headings'),
default: true, default: true,
}, },
"alwaysRetryInvites": { "alwaysInviteUnknownUsers": {
supportedLevels: LEVELS_ACCOUNT_SETTINGS, supportedLevels: LEVELS_ACCOUNT_SETTINGS,
displayName: _td('Always retry invites for unknown users'), displayName: _td('Always invite users which may not exist'),
default: false, default: false,
}, },
"showDeveloperTools": { "showDeveloperTools": {

View File

@ -101,13 +101,18 @@ export default class MultiInviter {
if (addrType === 'email') { if (addrType === 'email') {
return MatrixClientPeg.get().inviteByEmail(roomId, addr); return MatrixClientPeg.get().inviteByEmail(roomId, addr);
} else if (addrType === 'mx-user-id') { } else if (addrType === 'mx-user-id') {
if (!ignoreProfile && !SettingsStore.getValue("alwaysRetryInvites", this.roomId)) { if (!ignoreProfile && !SettingsStore.getValue("alwaysInviteUnknownUsers", this.roomId)) {
const profile = await MatrixClientPeg.get().getProfileInfo(addr); try {
if (!profile) { const profile = await MatrixClientPeg.get().getProfileInfo(addr);
return Promise.reject({ if (!profile) {
errcode: "M_NOT_FOUND", // noinspection ExceptionCaughtLocallyJS
error: "User does not have a profile or does not exist.", 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) { _doInvite(address, ignoreProfile) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log(`Inviting ${address}`);
let doInvite; let doInvite;
if (this.groupId !== null) { if (this.groupId !== null) {
doInvite = GroupStore.inviteUserToGroup(this.groupId, address); doInvite = GroupStore.inviteUserToGroup(this.groupId, address);
@ -151,13 +158,13 @@ export default class MultiInviter {
this._doInvite(address, ignoreProfile).then(resolve, reject); this._doInvite(address, ignoreProfile).then(resolve, reject);
}, 5000); }, 5000);
return; 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}); 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}); errorText = _t("User %(user_id)s may or may not exist", {user_id: address});
} else if (err.errcode === 'M_PROFILE_NOT_FOUND' && !ignoreProfile) { } else if (err.errcode === 'M_PROFILE_NOT_FOUND' && !ignoreProfile) {
// Invite without the profile check // 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); this._doInvite(address, true).then(resolve, reject);
} else { } else {
errorText = _t('Unknown server error'); errorText = _t('Unknown server error');
@ -188,28 +195,28 @@ export default class MultiInviter {
if (Object.keys(this.errors).length > 0 && !this.groupId) { if (Object.keys(this.errors).length > 0 && !this.groupId) {
// There were problems inviting some people - see if we can invite them // There were problems inviting some people - see if we can invite them
// without caring if they exist or not. // without caring if they exist or not.
const reinviteErrors = ['M_NOT_FOUND', 'M_USER_NOT_FOUND', 'M_PROFILE_UNKNOWN', 'M_PROFILE_NOT_FOUND']; const unknownProfileErrors = ['M_NOT_FOUND', 'M_USER_NOT_FOUND', 'M_PROFILE_UNDISCLOSED', 'M_PROFILE_NOT_FOUND', 'RIOT.USER_NOT_FOUND'];
const reinvitableUsers = Object.keys(this.errors).filter(a => reinviteErrors.includes(this.errors[a].errcode)); const unknownProfileUsers = Object.keys(this.errors).filter(a => unknownProfileErrors.includes(this.errors[a].errcode));
if (reinvitableUsers.length > 0) { if (unknownProfileUsers.length > 0) {
const retryInvites = () => { const inviteUnknowns = () => {
const promises = reinvitableUsers.map(u => this._doInvite(u, true)); const promises = unknownProfileUsers.map(u => this._doInvite(u, true));
Promise.all(promises).then(() => this.deferred.resolve(this.completionStates)); Promise.all(promises).then(() => this.deferred.resolve(this.completionStates));
}; };
if (SettingsStore.getValue("alwaysRetryInvites", this.roomId)) { if (SettingsStore.getValue("alwaysInviteUnknownUsers", this.roomId)) {
retryInvites(); inviteUnknowns();
return; return;
} }
const RetryInvitesDialog = sdk.getComponent("dialogs.RetryInvitesDialog"); const AskInviteAnywayDialog = sdk.getComponent("dialogs.AskInviteAnywayDialog");
console.log("Showing failed to invite dialog..."); console.log("Showing failed to invite dialog...");
Modal.createTrackedDialog('Failed to invite the following users to the room', '', RetryInvitesDialog, { Modal.createTrackedDialog('Failed to invite the following users to the room', '', AskInviteAnywayDialog, {
failedInvites: this.errors, unknownProfileUsers: unknownProfileUsers.map(u => {return {userId: u, errorText: this.errors[u].errorText};}),
onTryAgain: () => retryInvites(), onInviteAnyways: () => inviteUnknowns(),
onGiveUp: () => { onGiveUp: () => {
// Fake all the completion states because we already warned the user // 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.completionStates[addr] = 'invited';
} }
this.deferred.resolve(this.completionStates); this.deferred.resolve(this.completionStates);
@ -223,7 +230,6 @@ export default class MultiInviter {
} }
const addr = this.addrs[nextIndex]; const addr = this.addrs[nextIndex];
console.log(`Inviting ${addr}`);
// don't try to invite it if it's an invalid address // don't try to invite it if it's an invalid address
// (it will already be marked as an error though, // (it will already be marked as an error though,