From 0cba5da03d89fe0952b3efbdfcfb0a60a7d6e53e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 9 Sep 2019 15:10:50 +0200 Subject: [PATCH] add redact recent messages button in member info --- src/components/views/rooms/MemberInfo.js | 86 +++++++++++++++++++++++- src/i18n/strings/en_EN.json | 7 ++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 8d9e5dfe39..8eee2f72b5 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -46,6 +46,8 @@ import SettingsStore from "../../../settings/SettingsStore"; import E2EIcon from "./E2EIcon"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import MatrixClientPeg from "../../../MatrixClientPeg"; +import Matrix from "matrix-js-sdk"; +const EventTimeline = Matrix.EventTimeline; module.exports = withMatrixClient(React.createClass({ displayName: 'MemberInfo', @@ -63,6 +65,7 @@ module.exports = withMatrixClient(React.createClass({ mute: false, modifyLevel: false, synapseDeactivate: false, + redactMessages: false, }, muted: false, isTargetMod: false, @@ -351,6 +354,73 @@ module.exports = withMatrixClient(React.createClass({ }); }, + 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: +
+

{ _t("Try scrolling up in the timeline to see if there are any earlier ones.") }

+
, + }); + } 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: +
+

{ _t("You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?", {count, user}) }

+

{ _t("For large amount of messages, this might take some time. Please don't refresh your client in the meantime.") }

+
, + button: _t("Remove %(count)s messages", {count}), + onFinished: resolve, + }); + }); + + if (!confirmed) { + return; + } + + // Submitting a large number of redactions freezes the UI, + // so first wait 200ms to allow to rerender after closing the dialog. + await new Promise(resolve => setTimeout(resolve, 200)); + + 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.log("Done redacting recent messages!"); + } + }, + _warnSelfDemote: function() { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); return new Promise((resolve) => { @@ -597,6 +667,7 @@ module.exports = withMatrixClient(React.createClass({ mute: false, modifyLevel: false, modifyLevelMax: 0, + redactMessages: false, }; // Calculate permissions for Synapse before doing the PL checks @@ -618,6 +689,7 @@ module.exports = withMatrixClient(React.createClass({ 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; }, @@ -807,6 +879,7 @@ module.exports = withMatrixClient(React.createClass({ let banButton; let muteButton; let giveModButton; + let redactButton; let synapseDeactivateButton; let spinner; @@ -884,6 +957,16 @@ module.exports = withMatrixClient(React.createClass({ ); } + + + if (this.state.can.redactMessages) { + redactButton = ( + + { _t("Remove recent messages") } + + ); + } + if (this.state.can.ban) { let label = _t("Ban"); if (this.props.member.membership === 'ban') { @@ -924,7 +1007,7 @@ module.exports = withMatrixClient(React.createClass({ } let adminTools; - if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton) { + if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton || redactButton) { adminTools =

{ _t("Admin Tools") }

@@ -933,6 +1016,7 @@ module.exports = withMatrixClient(React.createClass({ { muteButton } { kickButton } { banButton } + { redactButton } { giveModButton } { synapseDeactivateButton }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 797a5327cf..6c748018b9 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -724,6 +724,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 large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "For 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", @@ -742,6 +748,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",