Plugin
MessageClickActions
Hold Backspace and click to delete, double click to edit/reply
1
import { isPluginEnabled } from "@api/PluginManager";2
import { definePluginSettings } from "@api/Settings";3
import NoReplyMentionPlugin from "@plugins/noReplyMention";4
import { Devs } from "@utils/constants";5
import definePlugin, { OptionType } from "@utils/types";6
import { ApplicationIntegrationType, MessageFlags } from "@vencord/discord-types/enums";7
import { findByPropsLazy } from "@webpack";8
import { AuthenticationStore, FluxDispatcher, MessageTypeSets, PermissionsBits, PermissionStore, WindowStore } from "@webpack/common";9
10
const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage");11
const EditStore = findByPropsLazy("isEditing", "isEditingAny");12
13
let isDeletePressed = false;14
const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true);15
const keyup = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = false);16
const focusChanged = () => !WindowStore.isFocused() && (isDeletePressed = false);17
18
const settings = definePluginSettings({19
enableDeleteOnClick: {20
type: OptionType.BOOLEAN,21
description: "Enable delete on click while holding backspace",22
default: true23
},24
enableDoubleClickToEdit: {25
type: OptionType.BOOLEAN,26
description: "Enable double click to edit",27
default: true28
},29
enableDoubleClickToReply: {30
type: OptionType.BOOLEAN,31
description: "Enable double click to reply",32
default: true33
},34
requireModifier: {35
type: OptionType.BOOLEAN,36
description: "Only do double click actions when shift/ctrl is held",37
default: false38
}39
});40
41
export default definePlugin({42
name: "MessageClickActions",43
description: "Hold Backspace and click to delete, double click to edit/reply",44
tags: ["Chat", "Shortcuts"],45
authors: [Devs.Ven],46
47
settings,48
49
start() {50
document.addEventListener("keydown", keydown);51
document.addEventListener("keyup", keyup);52
WindowStore.addChangeListener(focusChanged);53
},54
55
stop() {56
document.removeEventListener("keydown", keydown);57
document.removeEventListener("keyup", keyup);58
WindowStore.removeChangeListener(focusChanged);59
},60
61
onMessageClick(msg, channel, event) {62
const myId = AuthenticationStore.getId();63
const isMe = msg.author.id === myId;64
const isSelfInvokedUserApp = msg.interactionMetadata?.authorizing_integration_owners[ApplicationIntegrationType.USER_INSTALL] === myId;65
if (!isDeletePressed) {66
if (event.detail < 2) return;67
if (settings.store.requireModifier && !event.ctrlKey && !event.shiftKey) return;68
if (channel.guild_id && !PermissionStore.can(PermissionsBits.SEND_MESSAGES, channel)) return;69
if (msg.deleted === true) return;70
71
if (isMe) {72
if (!settings.store.enableDoubleClickToEdit || EditStore.isEditing(channel.id, msg.id) || msg.state !== "SENT") return;73
74
MessageActions.startEditMessage(channel.id, msg.id, msg.content);75
event.preventDefault();76
} else {77
if (!settings.store.enableDoubleClickToReply) return;78
79
if (!MessageTypeSets.REPLYABLE.has(msg.type) || msg.hasFlag(MessageFlags.EPHEMERAL)) return;80
81
const isShiftPress = event.shiftKey && !settings.store.requireModifier;82
const shouldMention = isPluginEnabled(NoReplyMentionPlugin.name)83
? NoReplyMentionPlugin.shouldMention(msg, isShiftPress)84
: !isShiftPress;85
86
FluxDispatcher.dispatch({87
type: "CREATE_PENDING_REPLY",88
channel,89
message: msg,90
shouldMention,91
showMentionToggle: channel.guild_id !== null92
});93
}94
} else if (settings.store.enableDeleteOnClick && (isMe || PermissionStore.can(PermissionsBits.MANAGE_MESSAGES, channel) || isSelfInvokedUserApp)) {95
if (msg.deleted) {96
FluxDispatcher.dispatch({97
type: "MESSAGE_DELETE",98
channelId: channel.id,99
id: msg.id,100
mlDeleted: true101
});102
} else {103
MessageActions.deleteMessage(channel.id, msg.id);104
}105
event.preventDefault();106
}107
},108
});109