/* * Vencord, a modification for Discord's desktop app * Copyright (c) 2023 Vendicated and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; import { addButton, removeButton } from "@api/MessagePopover"; import { classNameFactory } from "@api/Styles"; import { EquicordDevs } from "@utils/constants"; import { sendMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import definePlugin from "@utils/types"; import { ChannelStore, Menu } from "@webpack/common"; import { Message } from "discord-types/general"; function RepeatMessageIcon({ className }: { className?: string; }) { return ( ); } let shift = false; function repeatMessage(channelId: string, id: string, content: string, stickers: any[]) { sendMessage(channelId, { content }, true, { allowedMentions: { parse: [], replied_user: false }, messageReference: shift ? { channel_id: channelId, message_id: id } : undefined, stickerIds: stickers.map(s => s.id) }); } const messageCtxPatch: NavContextMenuPatchCallback = (children, { message }: { message: Message; }) => { if (!message.content && message.stickerItems.length === 0) return; const group = findGroupChildrenByChildId("copy-text", children); if (!group) return; group.splice(group.findIndex(c => c?.props?.id === "reply") + 1, 0, ( repeatMessage(message.channel_id, message.id, message.content, message.stickerItems)} /> )); }; function setTitle(title: string) { const contextMenuOption = document.querySelector("#message-vc-repeat .label__563c3"); if (contextMenuOption) contextMenuOption.innerHTML = title; } const keyupListener = (event: KeyboardEvent) => { if (event.key === "Shift") { shift = false; setTitle("Repeat"); } }; const keydownListener = (event: KeyboardEvent) => { if (event.key === "Shift") { shift = true; setTitle("Repeat and Reply"); } }; export default definePlugin({ name: "RepeatMessage", description: "Allows you to repeat messages quickly. If you hold shift while clicking the Repeat option, it will reply to the message.", authors: [EquicordDevs.Tolgchu], contextMenus: { "message": messageCtxPatch }, start() { addButton("vc-repeat", message => { if (!message.content && message.stickerItems.length === 0) return null; return { label: "Repeat (Click) / Repeat and Reply (Shift + Click)", icon: RepeatMessageIcon, message, channel: ChannelStore.getChannel(message.channel_id), onClick: async () => repeatMessage(message.channel_id, message.id, message.content, message.stickerItems) }; }); document.addEventListener("keyup", keyupListener); document.addEventListener("keydown", keydownListener); }, stop() { removeButton("vc-repeat"); document.removeEventListener("keyup", keyupListener); document.removeEventListener("keydown", keydownListener); }, });