mirror of
https://github.com/element-hq/element-web
synced 2024-11-24 02:05:45 +03:00
Merge pull request #3409 from matrix-org/bwindels/redact-recent
Add "Remove recent messages" button in member info for administrator
This commit is contained in:
commit
e0ea0db013
2 changed files with 91 additions and 1 deletions
|
@ -48,6 +48,7 @@ import SettingsStore from "../../../settings/SettingsStore";
|
|||
import E2EIcon from "./E2EIcon";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import MatrixClientPeg from "../../../MatrixClientPeg";
|
||||
import {EventTimeline} from "matrix-js-sdk";
|
||||
|
||||
module.exports = createReactClass({
|
||||
displayName: 'MemberInfo',
|
||||
|
@ -64,6 +65,7 @@ module.exports = createReactClass({
|
|||
mute: false,
|
||||
modifyLevel: false,
|
||||
synapseDeactivate: false,
|
||||
redactMessages: false,
|
||||
},
|
||||
muted: false,
|
||||
isTargetMod: false,
|
||||
|
@ -356,6 +358,74 @@ module.exports = createReactClass({
|
|||
});
|
||||
},
|
||||
|
||||
onRedactAllMessages: async function() {
|
||||
const {roomId, userId} = this.props.member;
|
||||
const room = this.context.matrixClient.getRoom(roomId);
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
let timeline = room.getLiveTimeline();
|
||||
let eventsToRedact = [];
|
||||
while (timeline) {
|
||||
eventsToRedact = timeline.getEvents().reduce((events, event) => {
|
||||
if (event.getSender() === userId && !event.isRedacted()) {
|
||||
return events.concat(event);
|
||||
} else {
|
||||
return events;
|
||||
}
|
||||
}, eventsToRedact);
|
||||
timeline = timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS);
|
||||
}
|
||||
|
||||
const count = eventsToRedact.length;
|
||||
const user = this.props.member.name;
|
||||
|
||||
if (count === 0) {
|
||||
const InfoDialog = sdk.getComponent("dialogs.InfoDialog");
|
||||
Modal.createTrackedDialog('No user messages found to remove', '', InfoDialog, {
|
||||
title: _t("No recent messages by %(user)s found", {user}),
|
||||
description:
|
||||
<div>
|
||||
<p>{ _t("Try scrolling up in the timeline to see if there are any earlier ones.") }</p>
|
||||
</div>,
|
||||
});
|
||||
} else {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const confirmed = await new Promise((resolve) => {
|
||||
Modal.createTrackedDialog('Remove recent messages by user', '', QuestionDialog, {
|
||||
title: _t("Remove recent messages by %(user)s", {user}),
|
||||
description:
|
||||
<div>
|
||||
<p>{ _t("You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?", {count, user}) }</p>
|
||||
<p>{ _t("For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.") }</p>
|
||||
</div>,
|
||||
button: _t("Remove %(count)s messages", {count}),
|
||||
onFinished: resolve,
|
||||
});
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Submitting a large number of redactions freezes the UI,
|
||||
// so first yield to allow to rerender after closing the dialog.
|
||||
await Promise.resolve();
|
||||
|
||||
console.info(`Started redacting recent ${count} messages for ${user} in ${roomId}`);
|
||||
await Promise.all(eventsToRedact.map(async event => {
|
||||
try {
|
||||
await this.context.matrixClient.redactEvent(roomId, event.getId());
|
||||
} catch (err) {
|
||||
// log and swallow errors
|
||||
console.error("Could not redact", event.getId());
|
||||
console.error(err);
|
||||
}
|
||||
}));
|
||||
console.info(`Finished redacting recent ${count} messages for ${user} in ${roomId}`);
|
||||
}
|
||||
},
|
||||
|
||||
_warnSelfDemote: function() {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
return new Promise((resolve) => {
|
||||
|
@ -602,6 +672,7 @@ module.exports = createReactClass({
|
|||
mute: false,
|
||||
modifyLevel: false,
|
||||
modifyLevelMax: 0,
|
||||
redactMessages: false,
|
||||
};
|
||||
|
||||
// Calculate permissions for Synapse before doing the PL checks
|
||||
|
@ -623,6 +694,7 @@ module.exports = createReactClass({
|
|||
can.mute = me.powerLevel >= editPowerLevel;
|
||||
can.modifyLevel = me.powerLevel >= editPowerLevel && (isMe || me.powerLevel > them.powerLevel);
|
||||
can.modifyLevelMax = me.powerLevel;
|
||||
can.redactMessages = me.powerLevel >= powerLevels.redact;
|
||||
|
||||
return can;
|
||||
},
|
||||
|
@ -812,6 +884,7 @@ module.exports = createReactClass({
|
|||
let banButton;
|
||||
let muteButton;
|
||||
let giveModButton;
|
||||
let redactButton;
|
||||
let synapseDeactivateButton;
|
||||
let spinner;
|
||||
|
||||
|
@ -892,6 +965,15 @@ module.exports = createReactClass({
|
|||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.state.can.redactMessages) {
|
||||
redactButton = (
|
||||
<AccessibleButton className="mx_MemberInfo_field" onClick={this.onRedactAllMessages}>
|
||||
{ _t("Remove recent messages") }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.state.can.ban) {
|
||||
let label = _t("Ban");
|
||||
if (this.props.member.membership === 'ban') {
|
||||
|
@ -932,7 +1014,7 @@ module.exports = createReactClass({
|
|||
}
|
||||
|
||||
let adminTools;
|
||||
if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton) {
|
||||
if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton || redactButton) {
|
||||
adminTools =
|
||||
<div>
|
||||
<h3>{ _t("Admin Tools") }</h3>
|
||||
|
@ -941,6 +1023,7 @@ module.exports = createReactClass({
|
|||
{ muteButton }
|
||||
{ kickButton }
|
||||
{ banButton }
|
||||
{ redactButton }
|
||||
{ giveModButton }
|
||||
{ synapseDeactivateButton }
|
||||
</div>
|
||||
|
|
|
@ -794,6 +794,12 @@
|
|||
"Unban this user?": "Unban this user?",
|
||||
"Ban this user?": "Ban this user?",
|
||||
"Failed to ban user": "Failed to ban user",
|
||||
"No recent messages by %(user)s found": "No recent messages by %(user)s found",
|
||||
"Try scrolling up in the timeline to see if there are any earlier ones.": "Try scrolling up in the timeline to see if there are any earlier ones.",
|
||||
"Remove recent messages by %(user)s": "Remove recent messages by %(user)s",
|
||||
"You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?",
|
||||
"For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.",
|
||||
"Remove %(count)s messages|other": "Remove %(count)s messages",
|
||||
"Demote yourself?": "Demote yourself?",
|
||||
"You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.",
|
||||
"Demote": "Demote",
|
||||
|
@ -813,6 +819,7 @@
|
|||
"Share Link to User": "Share Link to User",
|
||||
"User Options": "User Options",
|
||||
"Direct chats": "Direct chats",
|
||||
"Remove recent messages": "Remove recent messages",
|
||||
"Unmute": "Unmute",
|
||||
"Mute": "Mute",
|
||||
"Revoke Moderator": "Revoke Moderator",
|
||||
|
|
Loading…
Reference in a new issue