diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx
index 6c0be42d..9bc3388f 100644
--- a/src/plugins/messageLogger/index.tsx
+++ b/src/plugins/messageLogger/index.tsx
@@ -14,11 +14,14 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*/
+ */
import "./messageLogger.css";
-import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
+import {
+ findGroupChildrenByChildId,
+ NavContextMenuPatchCallback,
+} from "@api/ContextMenu";
import { updateMessage } from "@api/MessageUpdater";
import { Settings } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles";
@@ -29,7 +32,18 @@ import { Logger } from "@utils/Logger";
import { classes } from "@utils/misc";
import definePlugin, { OptionType } from "@utils/types";
import { findByCodeLazy, findByPropsLazy } from "@webpack";
-import { ChannelStore, FluxDispatcher, i18n, Menu, MessageStore, Parser, SelectedChannelStore, Timestamp, UserStore, useStateFromStores } from "@webpack/common";
+import {
+ ChannelStore,
+ FluxDispatcher,
+ i18n,
+ Menu,
+ MessageStore,
+ Parser,
+ SelectedChannelStore,
+ Timestamp,
+ UserStore,
+ useStateFromStores,
+} from "@webpack/common";
import { Message } from "discord-types/general";
import overlayStyle from "./deleteStyleOverlay.css?managed";
@@ -37,481 +51,538 @@ import textStyle from "./deleteStyleText.css?managed";
import { openHistoryModal } from "./HistoryModal";
interface MLMessage extends Message {
- deleted?: boolean;
- editHistory?: { timestamp: Date; content: string; }[];
- firstEditTimestamp?: Date;
+ deleted?: boolean;
+ editHistory?: { timestamp: Date; content: string }[];
+ firstEditTimestamp?: Date;
}
-const styles = findByPropsLazy("edited", "communicationDisabled", "isSystemMessage");
+const styles = findByPropsLazy(
+ "edited",
+ "communicationDisabled",
+ "isSystemMessage",
+);
const getMessage = findByCodeLazy('replace(/^\\n+|\\n+$/g,"")');
function addDeleteStyle() {
- if (Settings.plugins.MessageLogger.deleteStyle === "text") {
- enableStyle(textStyle);
- disableStyle(overlayStyle);
- } else {
- disableStyle(textStyle);
- enableStyle(overlayStyle);
- }
+ if (Settings.plugins.MessageLogger.deleteStyle === "text") {
+ enableStyle(textStyle);
+ disableStyle(overlayStyle);
+ } else {
+ disableStyle(textStyle);
+ enableStyle(overlayStyle);
+ }
}
const REMOVE_HISTORY_ID = "ml-remove-history";
const TOGGLE_DELETE_STYLE_ID = "ml-toggle-style";
-const patchMessageContextMenu: NavContextMenuPatchCallback = (children, props) => {
- const { message } = props;
- const { deleted, editHistory, id, channel_id } = message;
+const patchMessageContextMenu: NavContextMenuPatchCallback = (
+ children,
+ props,
+) => {
+ const { message } = props;
+ const { deleted, editHistory, id, channel_id } = message;
- if (!deleted && !editHistory?.length) return;
+ if (!deleted && !editHistory?.length) return;
- toggle: {
- if (!deleted) break toggle;
+ toggle: {
+ if (!deleted) break toggle;
- const domElement = document.getElementById(`chat-messages-${channel_id}-${id}`);
- if (!domElement) break toggle;
+ const domElement = document.getElementById(
+ `chat-messages-${channel_id}-${id}`,
+ );
+ if (!domElement) break toggle;
- children.push((
-
domElement.classList.toggle("messagelogger-deleted")}
- />
- ));
- }
+ children.push(
+ domElement.classList.toggle("messagelogger-deleted")}
+ />,
+ );
+ }
- children.push((
- {
- if (deleted) {
- FluxDispatcher.dispatch({
- type: "MESSAGE_DELETE",
- channelId: channel_id,
- id,
- mlDeleted: true
- });
- } else {
- message.editHistory = [];
- }
- }}
- />
- ));
+ children.push(
+ {
+ if (deleted) {
+ FluxDispatcher.dispatch({
+ type: "MESSAGE_DELETE",
+ channelId: channel_id,
+ id,
+ mlDeleted: true,
+ });
+ } else {
+ message.editHistory = [];
+ }
+ }}
+ />,
+ );
};
-const patchChannelContextMenu: NavContextMenuPatchCallback = (children, { channel }) => {
- const messages = MessageStore.getMessages(channel?.id) as MLMessage[];
- if (!messages?.some(msg => msg.deleted || msg.editHistory?.length)) return;
+const patchChannelContextMenu: NavContextMenuPatchCallback = (
+ children,
+ { channel },
+) => {
+ const messages = MessageStore.getMessages(channel?.id) as MLMessage[];
+ if (!messages?.some((msg) => msg.deleted || msg.editHistory?.length)) return;
- const group = findGroupChildrenByChildId("mark-channel-read", children) ?? children;
- group.push(
- {
- messages.forEach(msg => {
- if (msg.deleted)
- FluxDispatcher.dispatch({
- type: "MESSAGE_DELETE",
- channelId: channel.id,
- id: msg.id,
- mlDeleted: true
- });
- else
- updateMessage(channel.id, msg.id, {
- editHistory: []
- });
- });
- }}
- />
- );
+ const group =
+ findGroupChildrenByChildId("mark-channel-read", children) ?? children;
+ group.push(
+ {
+ messages.forEach((msg) => {
+ if (msg.deleted)
+ FluxDispatcher.dispatch({
+ type: "MESSAGE_DELETE",
+ channelId: channel.id,
+ id: msg.id,
+ mlDeleted: true,
+ });
+ else
+ updateMessage(channel.id, msg.id, {
+ editHistory: [],
+ });
+ });
+ }}
+ />,
+ );
};
export function parseEditContent(content: string, message: Message) {
- return Parser.parse(content, true, {
- channelId: message.channel_id,
- messageId: message.id,
- allowLinks: true,
- allowHeading: true,
- allowList: true,
- allowEmojiLinks: true,
- viewingChannelId: SelectedChannelStore.getChannelId(),
- });
+ return Parser.parse(content, true, {
+ channelId: message.channel_id,
+ messageId: message.id,
+ allowLinks: true,
+ allowHeading: true,
+ allowList: true,
+ allowEmojiLinks: true,
+ viewingChannelId: SelectedChannelStore.getChannelId(),
+ });
}
export default definePlugin({
- name: "MessageLogger",
- description: "Temporarily logs deleted and edited messages.",
- authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux, Devs.Kyuuhachi],
- dependencies: ["MessageUpdaterAPI"],
+ name: "MessageLogger",
+ description: "Temporarily logs deleted and edited messages.",
+ authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux, Devs.Kyuuhachi],
+ dependencies: ["MessageUpdaterAPI"],
- contextMenus: {
- "message": patchMessageContextMenu,
- "channel-context": patchChannelContextMenu,
- "thread-context": patchChannelContextMenu,
- "user-context": patchChannelContextMenu,
- "gdm-context": patchChannelContextMenu
+ contextMenus: {
+ message: patchMessageContextMenu,
+ "channel-context": patchChannelContextMenu,
+ "thread-context": patchChannelContextMenu,
+ "user-context": patchChannelContextMenu,
+ "gdm-context": patchChannelContextMenu,
+ },
+
+ start() {
+ addDeleteStyle();
+ },
+
+ renderEdits: ErrorBoundary.wrap(
+ ({
+ message: { id: messageId, channel_id: channelId },
+ }: {
+ message: Message;
+ }) => {
+ const message = useStateFromStores(
+ [MessageStore],
+ () => MessageStore.getMessage(channelId, messageId) as MLMessage,
+ null,
+ (oldMsg, newMsg) => oldMsg?.editHistory === newMsg?.editHistory,
+ );
+
+ return (
+ Settings.plugins.MessageLogger.inlineEdits && (
+ <>
+ {message.editHistory?.map((edit) => (
+
+ {parseEditContent(edit.content, message)}
+
+
+ {" "}
+ ({i18n.Messages.MESSAGE_EDITED})
+
+
+
+ ))}
+ >
+ )
+ );
},
+ { noop: true },
+ ),
- start() {
- addDeleteStyle();
+ makeEdit(newMessage: any, oldMessage: any): any {
+ return {
+ timestamp: new Date(newMessage.edited_timestamp),
+ content: oldMessage.content,
+ };
+ },
+
+ options: {
+ deleteStyle: {
+ type: OptionType.SELECT,
+ description: "The style of deleted messages",
+ default: "text",
+ options: [
+ { label: "Red text", value: "text", default: true },
+ { label: "Red overlay", value: "overlay" },
+ ],
+ onChange: () => addDeleteStyle(),
},
-
- renderEdits: ErrorBoundary.wrap(({ message: { id: messageId, channel_id: channelId } }: { message: Message; }) => {
- const message = useStateFromStores(
- [MessageStore],
- () => MessageStore.getMessage(channelId, messageId) as MLMessage,
- null,
- (oldMsg, newMsg) => oldMsg?.editHistory === newMsg?.editHistory
- );
-
- return Settings.plugins.MessageLogger.inlineEdits && (
- <>
- {message.editHistory?.map(edit => (
-
- {parseEditContent(edit.content, message)}
-
- {" "}({i18n.Messages.MESSAGE_EDITED})
-
-
- ))}
- >
- );
- }, { noop: true }),
-
- makeEdit(newMessage: any, oldMessage: any): any {
- return {
- timestamp: new Date(newMessage.edited_timestamp),
- content: oldMessage.content
- };
+ logDeletes: {
+ type: OptionType.BOOLEAN,
+ description: "Whether to log deleted messages",
+ default: true,
},
-
- options: {
- deleteStyle: {
- type: OptionType.SELECT,
- description: "The style of deleted messages",
- default: "text",
- options: [
- { label: "Red text", value: "text", default: true },
- { label: "Red overlay", value: "overlay" }
- ],
- onChange: () => addDeleteStyle()
- },
- logDeletes: {
- type: OptionType.BOOLEAN,
- description: "Whether to log deleted messages",
- default: true,
- },
- collapseDeleted: {
- type: OptionType.BOOLEAN,
- description: "Whether to collapse deleted messages, similar to blocked messages",
- default: false
- },
- logEdits: {
- type: OptionType.BOOLEAN,
- description: "Whether to log edited messages",
- default: true,
- },
- inlineEdits: {
- type: OptionType.BOOLEAN,
- description: "Whether to display edit history as part of message content",
- default: true
- },
- ignoreBots: {
- type: OptionType.BOOLEAN,
- description: "Whether to ignore messages by bots",
- default: false
- },
- ignoreSelf: {
- type: OptionType.BOOLEAN,
- description: "Whether to ignore messages by yourself",
- default: false
- },
- ignoreUsers: {
- type: OptionType.STRING,
- description: "Comma-separated list of user IDs to ignore",
- default: ""
- },
- ignoreChannels: {
- type: OptionType.STRING,
- description: "Comma-separated list of channel IDs to ignore",
- default: ""
- },
- ignoreGuilds: {
- type: OptionType.STRING,
- description: "Comma-separated list of guild IDs to ignore",
- default: ""
- },
+ collapseDeleted: {
+ type: OptionType.BOOLEAN,
+ description:
+ "Whether to collapse deleted messages, similar to blocked messages",
+ default: false,
},
+ logEdits: {
+ type: OptionType.BOOLEAN,
+ description: "Whether to log edited messages",
+ default: true,
+ },
+ inlineEdits: {
+ type: OptionType.BOOLEAN,
+ description: "Whether to display edit history as part of message content",
+ default: true,
+ },
+ ignoreBots: {
+ type: OptionType.BOOLEAN,
+ description: "Whether to ignore messages by bots",
+ default: false,
+ },
+ ignoreSelf: {
+ type: OptionType.BOOLEAN,
+ description: "Whether to ignore messages by yourself",
+ default: false,
+ },
+ ignoreUsers: {
+ type: OptionType.STRING,
+ description: "Comma-separated list of user IDs to ignore",
+ default: "",
+ },
+ ignoreChannels: {
+ type: OptionType.STRING,
+ description: "Comma-separated list of channel IDs to ignore",
+ default: "",
+ },
+ ignoreGuilds: {
+ type: OptionType.STRING,
+ description: "Comma-separated list of guild IDs to ignore",
+ default: "",
+ },
+ },
- handleDelete(cache: any, data: { ids: string[], id: string; mlDeleted?: boolean; }, isBulk: boolean) {
- try {
- if (cache == null || (!isBulk && !cache.has(data.id))) return cache;
+ handleDelete(
+ cache: any,
+ data: { ids: string[]; id: string; mlDeleted?: boolean },
+ isBulk: boolean,
+ ) {
+ try {
+ if (cache == null || (!isBulk && !cache.has(data.id))) return cache;
- const mutate = (id: string) => {
- const msg = cache.get(id);
- if (!msg) return;
+ const mutate = (id: string) => {
+ const msg = cache.get(id);
+ if (!msg) return;
- const EPHEMERAL = 64;
- const shouldIgnore = data.mlDeleted ||
- (msg.flags & EPHEMERAL) === EPHEMERAL ||
- this.shouldIgnore(msg);
+ const EPHEMERAL = 64;
+ const shouldIgnore =
+ data.mlDeleted ||
+ (msg.flags & EPHEMERAL) === EPHEMERAL ||
+ this.shouldIgnore(msg);
- if (shouldIgnore) {
- cache = cache.remove(id);
- } else {
- cache = cache.update(id, m => m
- .set("deleted", true)
- .set("attachments", m.attachments.map(a => (a.deleted = true, a))));
- }
- };
-
- if (isBulk) {
- data.ids.forEach(mutate);
- } else {
- mutate(data.id);
- }
- } catch (e) {
- new Logger("MessageLogger").error("Error during handleDelete", e);
+ if (shouldIgnore) {
+ cache = cache.remove(id);
+ } else {
+ cache = cache.update(id, (m) =>
+ m.set("deleted", true).set(
+ "attachments",
+ m.attachments.map((a) => ((a.deleted = true), a)),
+ ),
+ );
}
- return cache;
+ };
+
+ if (isBulk) {
+ data.ids.forEach(mutate);
+ } else {
+ mutate(data.id);
+ }
+ } catch (e) {
+ new Logger("MessageLogger").error("Error during handleDelete", e);
+ }
+ return cache;
+ },
+
+ shouldIgnore(message: any, isEdit = false) {
+ const {
+ ignoreBots,
+ ignoreSelf,
+ ignoreUsers,
+ ignoreChannels,
+ ignoreGuilds,
+ logEdits,
+ logDeletes,
+ } = Settings.plugins.MessageLogger;
+ const myId = UserStore.getCurrentUser().id;
+
+ return (
+ (ignoreBots && message.author?.bot) ||
+ (ignoreSelf && message.author?.id === myId) ||
+ ignoreUsers.includes(message.author?.id) ||
+ ignoreChannels.includes(message.channel_id) ||
+ ignoreChannels.includes(
+ ChannelStore.getChannel(message.channel_id)?.parent_id,
+ ) ||
+ (isEdit ? !logEdits : !logDeletes) ||
+ ignoreGuilds.includes(
+ ChannelStore.getChannel(message.channel_id)?.guild_id,
+ ) ||
+ // Ignore Venbot in the support channel
+ (message.channel_id === "1026515880080842772" &&
+ message.author?.id === "1017176847865352332") ||
+ // Ignore VOT on dev-playground
+ (message.channel_id === "1297239805972709521" &&
+ message.author?.id === "1199905841004937257")
+ );
+ },
+
+ EditMarker({ message, className, children, ...props }: any) {
+ return (
+ openHistoryModal(message)}
+ aria-role="button"
+ >
+ {children}
+
+ );
+ },
+
+ Messages: proxyLazy(() => ({
+ DELETED_MESSAGE_COUNT: getMessage(
+ "{count, plural, =0 {No deleted messages} one {{count} deleted message} other {{count} deleted messages}}",
+ ),
+ })),
+
+ patches: [
+ {
+ // MessageStore
+ find: '"MessageStore"',
+ replacement: [
+ {
+ // Add deleted=true to all target messages in the MESSAGE_DELETE event
+ match:
+ /MESSAGE_DELETE:function\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?},/,
+ replace:
+ "MESSAGE_DELETE:function($1){" +
+ " var cache = $2getOrCreate($1.channelId);" +
+ " cache = $self.handleDelete(cache, $1, false);" +
+ " $2commit(cache);" +
+ "},",
+ },
+ {
+ // Add deleted=true to all target messages in the MESSAGE_DELETE_BULK event
+ match:
+ /MESSAGE_DELETE_BULK:function\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?},/,
+ replace:
+ "MESSAGE_DELETE_BULK:function($1){" +
+ " var cache = $2getOrCreate($1.channelId);" +
+ " cache = $self.handleDelete(cache, $1, true);" +
+ " $2commit(cache);" +
+ "},",
+ },
+ {
+ // Add current cached content + new edit time to cached message's editHistory
+ match: /(MESSAGE_UPDATE:function\((\i)\).+?)\.update\((\i)/,
+ replace:
+ "$1" +
+ ".update($3,m =>" +
+ " (($2.message.flags & 64) === 64 || $self.shouldIgnore($2.message, true)) ? m :" +
+ " $2.message.edited_timestamp && $2.message.content !== m.content ?" +
+ " m.set('editHistory',[...(m.editHistory || []), $self.makeEdit($2.message, m)]) :" +
+ " m" +
+ ")" +
+ ".update($3",
+ },
+ {
+ // fix up key (edit last message) attempting to edit a deleted message
+ match: /(?<=getLastEditableMessage\(\i\)\{.{0,200}\.find\((\i)=>)/,
+ replace: "!$1.deleted &&",
+ },
+ ],
},
- shouldIgnore(message: any, isEdit = false) {
- const { ignoreBots, ignoreSelf, ignoreUsers, ignoreChannels, ignoreGuilds, logEdits, logDeletes } = Settings.plugins.MessageLogger;
- const myId = UserStore.getCurrentUser().id;
-
- return ignoreBots && message.author?.bot ||
- ignoreSelf && message.author?.id === myId ||
- ignoreUsers.includes(message.author?.id) ||
- ignoreChannels.includes(message.channel_id) ||
- ignoreChannels.includes(ChannelStore.getChannel(message.channel_id)?.parent_id) ||
- (isEdit ? !logEdits : !logDeletes) ||
- ignoreGuilds.includes(ChannelStore.getChannel(message.channel_id)?.guild_id) ||
- // Ignore Venbot in the support channel
- (message.channel_id === "1026515880080842772" && message.author?.id === "1017176847865352332")
- || // Ignore Gluestick on dev-talk & dev-playground
- (message.channel_id === "1297239805972709521" && message.author?.id === "1247291758857949224") ||
- (message.channel_id === "1297078407653228575" && message.author?.id === "1247291758857949224");
+ {
+ // Message domain model
+ find: "}addReaction(",
+ replacement: [
+ {
+ match: /this\.customRenderedContent=(\i)\.customRenderedContent,/,
+ replace:
+ "this.customRenderedContent = $1.customRenderedContent," +
+ "this.deleted = $1.deleted || false," +
+ "this.editHistory = $1.editHistory || []," +
+ "this.firstEditTimestamp = $1.firstEditTimestamp || this.editedTimestamp || this.timestamp,",
+ },
+ ],
},
- EditMarker({ message, className, children, ...props }: any) {
- return (
- openHistoryModal(message)}
- aria-role="button"
- >
- {children}
-
- );
+ {
+ // Updated message transformer(?)
+ find: "THREAD_STARTER_MESSAGE?null===",
+ replacement: [
+ {
+ // Pass through editHistory & deleted & original attachments to the "edited message" transformer
+ match:
+ /(?<=null!=\i\.edited_timestamp\)return )\i\(\i,\{reactions:(\i)\.reactions.{0,50}\}\)/,
+ replace:
+ "Object.assign($&,{ deleted:$1.deleted, editHistory:$1.editHistory, firstEditTimestamp:$1.firstEditTimestamp })",
+ },
+
+ {
+ // Construct new edited message and add editHistory & deleted (ref above)
+ // Pass in custom data to attachment parser to mark attachments deleted as well
+ match: /attachments:(\i)\((\i)\)/,
+ replace:
+ "attachments: $1((() => {" +
+ " if ($self.shouldIgnore($2)) return $2;" +
+ " let old = arguments[1]?.attachments;" +
+ " if (!old) return $2;" +
+ " let new_ = $2.attachments?.map(a => a.id) ?? [];" +
+ " let diff = old.filter(a => !new_.includes(a.id));" +
+ " old.forEach(a => a.deleted = true);" +
+ " $2.attachments = [...diff, ...$2.attachments];" +
+ " return $2;" +
+ "})())," +
+ "deleted: arguments[1]?.deleted," +
+ "editHistory: arguments[1]?.editHistory," +
+ "firstEditTimestamp: new Date(arguments[1]?.firstEditTimestamp ?? $2.editedTimestamp ?? $2.timestamp)",
+ },
+ {
+ // Preserve deleted attribute on attachments
+ match: /(\((\i)\){return null==\2\.attachments.+?)spoiler:/,
+ replace: "$1deleted: arguments[0]?.deleted," + "spoiler:",
+ },
+ ],
},
- Messages: proxyLazy(() => ({
- DELETED_MESSAGE_COUNT: getMessage("{count, plural, =0 {No deleted messages} one {{count} deleted message} other {{count} deleted messages}}")
- })),
-
- patches: [
+ {
+ // Attachment renderer
+ find: ".removeMosaicItemHoverButton",
+ group: true,
+ replacement: [
{
- // MessageStore
- find: '"MessageStore"',
- replacement: [
- {
- // Add deleted=true to all target messages in the MESSAGE_DELETE event
- match: /MESSAGE_DELETE:function\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?},/,
- replace:
- "MESSAGE_DELETE:function($1){" +
- " var cache = $2getOrCreate($1.channelId);" +
- " cache = $self.handleDelete(cache, $1, false);" +
- " $2commit(cache);" +
- "},"
- },
- {
- // Add deleted=true to all target messages in the MESSAGE_DELETE_BULK event
- match: /MESSAGE_DELETE_BULK:function\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?},/,
- replace:
- "MESSAGE_DELETE_BULK:function($1){" +
- " var cache = $2getOrCreate($1.channelId);" +
- " cache = $self.handleDelete(cache, $1, true);" +
- " $2commit(cache);" +
- "},"
- },
- {
- // Add current cached content + new edit time to cached message's editHistory
- match: /(MESSAGE_UPDATE:function\((\i)\).+?)\.update\((\i)/,
- replace: "$1" +
- ".update($3,m =>" +
- " (($2.message.flags & 64) === 64 || $self.shouldIgnore($2.message, true)) ? m :" +
- " $2.message.edited_timestamp && $2.message.content !== m.content ?" +
- " m.set('editHistory',[...(m.editHistory || []), $self.makeEdit($2.message, m)]) :" +
- " m" +
- ")" +
- ".update($3"
- },
- {
- // fix up key (edit last message) attempting to edit a deleted message
- match: /(?<=getLastEditableMessage\(\i\)\{.{0,200}\.find\((\i)=>)/,
- replace: "!$1.deleted &&"
- }
- ]
- },
-
- {
- // Message domain model
- find: "}addReaction(",
- replacement: [
- {
- match: /this\.customRenderedContent=(\i)\.customRenderedContent,/,
- replace: "this.customRenderedContent = $1.customRenderedContent," +
- "this.deleted = $1.deleted || false," +
- "this.editHistory = $1.editHistory || []," +
- "this.firstEditTimestamp = $1.firstEditTimestamp || this.editedTimestamp || this.timestamp,"
- }
- ]
- },
-
- {
- // Updated message transformer(?)
- find: "THREAD_STARTER_MESSAGE?null===",
- replacement: [
- {
- // Pass through editHistory & deleted & original attachments to the "edited message" transformer
- match: /(?<=null!=\i\.edited_timestamp\)return )\i\(\i,\{reactions:(\i)\.reactions.{0,50}\}\)/,
- replace:
- "Object.assign($&,{ deleted:$1.deleted, editHistory:$1.editHistory, firstEditTimestamp:$1.firstEditTimestamp })"
- },
-
- {
- // Construct new edited message and add editHistory & deleted (ref above)
- // Pass in custom data to attachment parser to mark attachments deleted as well
- match: /attachments:(\i)\((\i)\)/,
- replace:
- "attachments: $1((() => {" +
- " if ($self.shouldIgnore($2)) return $2;" +
- " let old = arguments[1]?.attachments;" +
- " if (!old) return $2;" +
- " let new_ = $2.attachments?.map(a => a.id) ?? [];" +
- " let diff = old.filter(a => !new_.includes(a.id));" +
- " old.forEach(a => a.deleted = true);" +
- " $2.attachments = [...diff, ...$2.attachments];" +
- " return $2;" +
- "})())," +
- "deleted: arguments[1]?.deleted," +
- "editHistory: arguments[1]?.editHistory," +
- "firstEditTimestamp: new Date(arguments[1]?.firstEditTimestamp ?? $2.editedTimestamp ?? $2.timestamp)"
- },
- {
- // Preserve deleted attribute on attachments
- match: /(\((\i)\){return null==\2\.attachments.+?)spoiler:/,
- replace:
- "$1deleted: arguments[0]?.deleted," +
- "spoiler:"
- }
- ]
- },
-
- {
- // Attachment renderer
- find: ".removeMosaicItemHoverButton",
- group: true,
- replacement: [
- {
- match: /(className:\i,item:\i),/,
- replace: "$1,item: deleted,"
- },
- {
- match: /\[\i\.obscured\]:.+?,/,
- replace: "$& 'messagelogger-deleted-attachment': deleted,"
- }
- ]
- },
-
- {
- // Base message component renderer
- find: "Message must not be a thread starter message",
- replacement: [
- {
- // Append messagelogger-deleted to classNames if deleted
- match: /\)\("li",\{(.+?),className:/,
- replace: ")(\"li\",{$1,className:(arguments[0].message.deleted ? \"messagelogger-deleted \" : \"\")+"
- }
- ]
- },
-
- {
- // Message content renderer
- find: "Messages.MESSAGE_EDITED,\")\"",
- replacement: [
- {
- // Render editHistory in the deepest div for message content
- match: /(\)\("div",\{id:.+?children:\[)/,
- replace: "$1 (!!arguments[0].message.editHistory?.length && $self.renderEdits(arguments[0])),"
- },
- {
- // Make edit marker clickable
- match: /"span",\{(?=className:\i\.edited,)/,
- replace: "$self.EditMarker,{message:arguments[0].message,"
- }
- ]
- },
-
- {
- // ReferencedMessageStore
- find: '"ReferencedMessageStore"',
- replacement: [
- {
- match: /MESSAGE_DELETE:function\((\i)\).+?},/,
- replace: "MESSAGE_DELETE:function($1){},"
- },
- {
- match: /MESSAGE_DELETE_BULK:function\((\i)\).+?},/,
- replace: "MESSAGE_DELETE_BULK:function($1){},"
- }
- ]
- },
-
- {
- // Message context base menu
- find: "useMessageMenu:",
- replacement: [
- {
- // Remove the first section if message is deleted
- match: /children:(\[""===.+?\])/,
- replace: "children:arguments[0].message.deleted?[]:$1"
- }
- ]
+ match: /(className:\i,item:\i),/,
+ replace: "$1,item: deleted,",
},
{
- // Message grouping
- find: "NON_COLLAPSIBLE.has(",
- replacement: {
- match: /if\((\i)\.blocked\)return \i\.\i\.MESSAGE_GROUP_BLOCKED;/,
- replace: '$&else if($1.deleted) return"MESSAGE_GROUP_DELETED";',
- },
- predicate: () => Settings.plugins.MessageLogger.collapseDeleted
+ match: /\[\i\.obscured\]:.+?,/,
+ replace: "$& 'messagelogger-deleted-attachment': deleted,",
+ },
+ ],
+ },
+
+ {
+ // Base message component renderer
+ find: "Message must not be a thread starter message",
+ replacement: [
+ {
+ // Append messagelogger-deleted to classNames if deleted
+ match: /\)\("li",\{(.+?),className:/,
+ replace:
+ ')("li",{$1,className:(arguments[0].message.deleted ? "messagelogger-deleted " : "")+',
+ },
+ ],
+ },
+
+ {
+ // Message content renderer
+ find: 'Messages.MESSAGE_EDITED,")"',
+ replacement: [
+ {
+ // Render editHistory in the deepest div for message content
+ match: /(\)\("div",\{id:.+?children:\[)/,
+ replace:
+ "$1 (!!arguments[0].message.editHistory?.length && $self.renderEdits(arguments[0])),",
},
{
- // Message group rendering
- find: "Messages.NEW_MESSAGES_ESTIMATED_WITH_DATE",
- replacement: [
- {
- match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\|\|/,
- replace: '$&$1.type==="MESSAGE_GROUP_DELETED"||',
- },
- {
- match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\?.*?:/,
- replace: '$&$1.type==="MESSAGE_GROUP_DELETED"?$self.Messages.DELETED_MESSAGE_COUNT:',
- },
- ],
- predicate: () => Settings.plugins.MessageLogger.collapseDeleted
- }
- ]
+ // Make edit marker clickable
+ match: /"span",\{(?=className:\i\.edited,)/,
+ replace: "$self.EditMarker,{message:arguments[0].message,",
+ },
+ ],
+ },
+
+ {
+ // ReferencedMessageStore
+ find: '"ReferencedMessageStore"',
+ replacement: [
+ {
+ match: /MESSAGE_DELETE:function\((\i)\).+?},/,
+ replace: "MESSAGE_DELETE:function($1){},",
+ },
+ {
+ match: /MESSAGE_DELETE_BULK:function\((\i)\).+?},/,
+ replace: "MESSAGE_DELETE_BULK:function($1){},",
+ },
+ ],
+ },
+
+ {
+ // Message context base menu
+ find: "useMessageMenu:",
+ replacement: [
+ {
+ // Remove the first section if message is deleted
+ match: /children:(\[""===.+?\])/,
+ replace: "children:arguments[0].message.deleted?[]:$1",
+ },
+ ],
+ },
+ {
+ // Message grouping
+ find: "NON_COLLAPSIBLE.has(",
+ replacement: {
+ match: /if\((\i)\.blocked\)return \i\.\i\.MESSAGE_GROUP_BLOCKED;/,
+ replace: '$&else if($1.deleted) return"MESSAGE_GROUP_DELETED";',
+ },
+ predicate: () => Settings.plugins.MessageLogger.collapseDeleted,
+ },
+ {
+ // Message group rendering
+ find: "Messages.NEW_MESSAGES_ESTIMATED_WITH_DATE",
+ replacement: [
+ {
+ match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\|\|/,
+ replace: '$&$1.type==="MESSAGE_GROUP_DELETED"||',
+ },
+ {
+ match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\?.*?:/,
+ replace:
+ '$&$1.type==="MESSAGE_GROUP_DELETED"?$self.Messages.DELETED_MESSAGE_COUNT:',
+ },
+ ],
+ predicate: () => Settings.plugins.MessageLogger.collapseDeleted,
+ },
+ ],
});