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