mirror of
https://github.com/element-hq/element-web
synced 2024-11-29 04:48:50 +03:00
Merge pull request #2757 from matrix-org/anoa/accept_all_invites
Ability to bulk accept all invites (and fix rejecting all invites)
This commit is contained in:
commit
e1f9482107
3 changed files with 74 additions and 23 deletions
|
@ -40,6 +40,10 @@ limitations under the License.
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_SecurityUserSettingsTab_bulkOptions .mx_AccessibleButton {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_SecurityUserSettingsTab_importExportButtons {
|
.mx_SecurityUserSettingsTab_importExportButtons {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,13 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
// Get number of rooms we're invited to
|
||||||
|
const invitedRooms = this._getInvitedRooms();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(),
|
ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(),
|
||||||
rejectingInvites: false,
|
managingInvites: false,
|
||||||
|
invitedRoomAmt: invitedRooms.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,24 +97,62 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
this.setState({ignoredUsers});
|
this.setState({ignoredUsers});
|
||||||
};
|
};
|
||||||
|
|
||||||
_onRejectAllInvitesClicked = (rooms, ev) => {
|
_getInvitedRooms = () => {
|
||||||
|
return MatrixClientPeg.get().getRooms().filter((r) => {
|
||||||
|
return r.hasMembershipState(MatrixClientPeg.get().getUserId(), "invite");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_manageInvites = async (accept) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
rejectingInvites: true,
|
managingInvites: true,
|
||||||
});
|
});
|
||||||
// reject the invites
|
|
||||||
const promises = rooms.map((room) => {
|
// Compile array of invitation room ids
|
||||||
return MatrixClientPeg.get().leave(room.roomId).catch((e) => {
|
const invitedRoomIds = this._getInvitedRooms().map((room) => {
|
||||||
// purposefully drop errors to the floor: we'll just have a non-zero number on the UI
|
return room.roomId;
|
||||||
// after trying to reject all the invites.
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Execute all acceptances/rejections sequentially
|
||||||
|
const self = this;
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
const action = accept ? cli.joinRoom.bind(cli) : cli.leave.bind(cli);
|
||||||
|
for (let i = 0; i < invitedRoomIds.length; i++) {
|
||||||
|
const roomId = invitedRoomIds[i];
|
||||||
|
|
||||||
|
// Accept/reject invite
|
||||||
|
await action(roomId).then(() => {
|
||||||
|
// No error, update invited rooms button
|
||||||
|
this.setState({invitedRoomAmt: self.state.invitedRoomAmt - 1});
|
||||||
|
}, async (e) => {
|
||||||
|
// Action failure
|
||||||
|
if (e.errcode === "M_LIMIT_EXCEEDED") {
|
||||||
|
// Add a delay between each invite change in order to avoid rate
|
||||||
|
// limiting by the server.
|
||||||
|
await Promise.delay(e.retry_after_ms || 2500);
|
||||||
|
|
||||||
|
// Redo last action
|
||||||
|
i--;
|
||||||
|
} else {
|
||||||
|
// Print out error with joining/leaving room
|
||||||
|
console.warn(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
Promise.all(promises).then(() => {
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
rejectingInvites: false,
|
managingInvites: false,
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_onAcceptAllInvitesClicked = (ev) => {
|
||||||
|
this._manageInvites(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
_onRejectAllInvitesClicked = (ev) => {
|
||||||
|
this._manageInvites(false);
|
||||||
|
};
|
||||||
|
|
||||||
_renderCurrentDeviceInfo() {
|
_renderCurrentDeviceInfo() {
|
||||||
const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag');
|
const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag');
|
||||||
|
|
||||||
|
@ -173,21 +215,25 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderRejectInvites() {
|
_renderManageInvites() {
|
||||||
const invitedRooms = MatrixClientPeg.get().getRooms().filter((r) => {
|
if (this.state.invitedRoomAmt === 0) {
|
||||||
return r.hasMembershipState(MatrixClientPeg.get().getUserId(), "invite");
|
|
||||||
});
|
|
||||||
if (invitedRooms.length === 0) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClick = this._onRejectAllInvitesClicked.bind(this, invitedRooms);
|
const invitedRooms = this._getInvitedRooms();
|
||||||
|
const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
|
||||||
|
const onClickAccept = this._onAcceptAllInvitesClicked.bind(this, invitedRooms);
|
||||||
|
const onClickReject = this._onRejectAllInvitesClicked.bind(this, invitedRooms);
|
||||||
return (
|
return (
|
||||||
<div className='mx_SettingsTab_section'>
|
<div className='mx_SettingsTab_section mx_SecurityUserSettingsTab_bulkOptions'>
|
||||||
<span className='mx_SettingsTab_subheading'>{_t('Bulk options')}</span>
|
<span className='mx_SettingsTab_subheading'>{_t('Bulk options')}</span>
|
||||||
<AccessibleButton onClick={onClick} kind='danger' disabled={this.state.rejectingInvites}>
|
<AccessibleButton onClick={onClickAccept} kind='primary' disabled={this.state.managingInvites}>
|
||||||
{_t("Reject all %(invitedRooms)s invites", {invitedRooms: invitedRooms.length})}
|
{_t("Accept all %(invitedRooms)s invites", {invitedRooms: this.state.invitedRoomAmt})}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
<AccessibleButton onClick={onClickReject} kind='danger' disabled={this.state.managingInvites}>
|
||||||
|
{_t("Reject all %(invitedRooms)s invites", {invitedRooms: this.state.invitedRoomAmt})}
|
||||||
|
</AccessibleButton>
|
||||||
|
{this.state.managingInvites ? <InlineSpinner /> : <div />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +278,7 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
onChange={this._updateAnalytics} />
|
onChange={this._updateAnalytics} />
|
||||||
</div>
|
</div>
|
||||||
{this._renderIgnoredUsers()}
|
{this._renderIgnoredUsers()}
|
||||||
{this._renderRejectInvites()}
|
{this._renderManageInvites()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -560,6 +560,7 @@
|
||||||
"Device key:": "Device key:",
|
"Device key:": "Device key:",
|
||||||
"Ignored users": "Ignored users",
|
"Ignored users": "Ignored users",
|
||||||
"Bulk options": "Bulk options",
|
"Bulk options": "Bulk options",
|
||||||
|
"Accept all %(invitedRooms)s invites": "Accept all %(invitedRooms)s invites",
|
||||||
"Reject all %(invitedRooms)s invites": "Reject all %(invitedRooms)s invites",
|
"Reject all %(invitedRooms)s invites": "Reject all %(invitedRooms)s invites",
|
||||||
"Key backup": "Key backup",
|
"Key backup": "Key backup",
|
||||||
"Security & Privacy": "Security & Privacy",
|
"Security & Privacy": "Security & Privacy",
|
||||||
|
|
Loading…
Reference in a new issue