/* * Vencord, a modification for Discord's desktop app * Copyright (c) 2022 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 { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatButtons"; import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands"; import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { FluxDispatcher, Menu, React } from "@webpack/common"; const settings = definePluginSettings({ showIcon: { type: OptionType.BOOLEAN, default: false, description: "Show an icon for toggling the plugin", restartNeeded: true, }, contextMenu: { type: OptionType.BOOLEAN, description: "Add option to toggle the functionality in the chat input context menu", default: true }, isEnabled: { type: OptionType.BOOLEAN, description: "Toggle functionality", default: true, } }); const SilentTypingToggle: ChatBarButton = ({ isMainChat }) => { const { isEnabled, showIcon } = settings.use(["isEnabled", "showIcon"]); const toggle = () => settings.store.isEnabled = !settings.store.isEnabled; if (!isMainChat || !showIcon) return null; return ( {isEnabled && } ); }; const ChatBarContextCheckbox: NavContextMenuPatchCallback = children => { const { isEnabled, contextMenu } = settings.use(["isEnabled", "contextMenu"]); if (!contextMenu) return; const group = findGroupChildrenByChildId("submit-button", children); if (!group) return; const idx = group.findIndex(c => c?.props?.id === "submit-button"); group.splice(idx + 1, 0, settings.store.isEnabled = !settings.store.isEnabled} /> ); }; export default definePlugin({ name: "SilentTyping", authors: [Devs.Ven, Devs.Rini, Devs.ImBanana], description: "Hide that you are typing", dependencies: ["CommandsAPI", "ChatInputButtonAPI"], settings, contextMenus: { "textarea-context": ChatBarContextCheckbox }, patches: [ { find: '.dispatch({type:"TYPING_START_LOCAL"', replacement: { match: /startTyping\(\i\){.+?},stop/, replace: "startTyping:$self.startTyping,stop" } }, ], commands: [{ name: "silenttype", description: "Toggle whether you're hiding that you're typing or not.", inputType: ApplicationCommandInputType.BUILT_IN, options: [ { name: "value", description: "whether to hide or not that you're typing (default is toggle)", required: false, type: ApplicationCommandOptionType.BOOLEAN, }, ], execute: async (args, ctx) => { settings.store.isEnabled = !!findOption(args, "value", !settings.store.isEnabled); sendBotMessage(ctx.channel.id, { content: settings.store.isEnabled ? "Silent typing enabled!" : "Silent typing disabled!", }); }, }], async startTyping(channelId: string) { if (settings.store.isEnabled) return; FluxDispatcher.dispatch({ type: "TYPING_START_LOCAL", channelId }); }, start: () => addChatBarButton("SilentTyping", SilentTypingToggle), stop: () => removeChatBarButton("SilentTyping"), });