diff --git a/src/plugins/characterCounter/README.md b/src/plugins/characterCounter/README.md new file mode 100644 index 000000000..7064707ee --- /dev/null +++ b/src/plugins/characterCounter/README.md @@ -0,0 +1,7 @@ +# Character Counter + +Adds a character counter to the message input box + + + + diff --git a/src/plugins/characterCounter/index.tsx b/src/plugins/characterCounter/index.tsx new file mode 100644 index 000000000..209924bc2 --- /dev/null +++ b/src/plugins/characterCounter/index.tsx @@ -0,0 +1,74 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./style.css"; + +import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import { classNameFactory } from "@utils/css"; +import definePlugin, { OptionType } from "@utils/types"; +import { UserStore } from "@webpack/common"; + +const cl = classNameFactory("vc-charCounter-"); + +const settings = definePluginSettings({ + colorEffects: { + type: OptionType.BOOLEAN, + description: "Enable yellow/red colouring as you get closer to the character limit", + default: true, + } +}); + +function getCounterColor(percentage: number) { + if (!settings.store.colorEffects) return "var(--primary-330)"; + if (percentage < 50) return "var(--text-muted)"; + if (percentage < 75) return "var(--yellow-330)"; + if (percentage < 90) return "var(--orange-330)"; + return "var(--red-360)"; +} + +export default definePlugin({ + name: "CharacterCounter", + description: "Adds a character counter to the chat input", + authors: [Devs.thororen], + settings, + patches: [ + { + find: ".CREATE_FORUM_POST||", + replacement: [ + { + match: /(?<=textValue:(\i),editorHeight:\i,channelId:\i\.id\}\)),\i/, + replace: ",$self.renderCharCounter({text:$1})" + } + ] + }, + { + find: "#{intl::PREMIUM_MESSAGE_LENGTH_UPSELL_TOOLTIP}", + replacement: { + match: /return \i\?\i\(\):\i\(\)(?<=#{intl::PREMIUM_MESSAGE_LENGTH_UPSELL_TOOLTIP_WITHOUT_LINK}.{0,200}?)/, + replace: "return null" + } + } + ], + + renderCharCounter: ErrorBoundary.wrap(({ text }: { text: string; }) => { + if (!text.length) return null; + + const premiumType = UserStore.getCurrentUser().premiumType ?? 0; + const charMax = premiumType === 2 ? 4000 : 2000; + + const color = getCounterColor((text.length / charMax) * 100); + + return ( +