Plugin

CharacterCounter

Adds a character counter to the chat input

Utility
index.tsx
Download

Source

src/plugins/characterCounter/index.tsx
1/*
2 * FiveCord — a Discord client mod
3 * Copyright (c) 2025 FiveCord
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7import "./style.css";
8
9import { definePluginSettings } from "@api/Settings";
10import ErrorBoundary from "@components/ErrorBoundary";
11import { Devs } from "@utils/constants";
12import { classNameFactory } from "@utils/css";
13import definePlugin, { OptionType } from "@utils/types";
14import { UserStore } from "@webpack/common";
15
16const cl = classNameFactory("vc-charCounter-");
17
18const settings = definePluginSettings({
19 colorEffects: {
20 type: OptionType.BOOLEAN,
21 description: "Enable yellow/red colouring as you get closer to the character limit",
22 default: true,
23 }
24});
25
26function getCounterColor(percentage: number) {
27 if (!settings.store.colorEffects) return "var(--primary-330)";
28 if (percentage < 50) return "var(--text-muted)";
29 if (percentage < 75) return "var(--yellow-330)";
30 if (percentage < 90) return "var(--orange-330)";
31 return "var(--red-360)";
32}
33
34export default definePlugin({
35 name: "CharacterCounter",
36 description: "Adds a character counter to the chat input",
37 authors: [Devs.thororen],
38 tags: ["Utility"],
39 settings,
40 patches: [
41 {
42 find: ".CREATE_FORUM_POST||",
43 replacement: [
44 {
45 match: /(?<=textValue:(\i),editorHeight:\i,channelId:\i\.id\}\)),\i/,
46 replace: ",$self.renderCharCounter({text:$1})"
47 }
48 ]
49 },
50 {
51 find: "#{intl::PREMIUM_MESSAGE_LENGTH_UPSELL_TOOLTIP}",
52 replacement: {
53 match: /(?<=\.PREMIUM_UPSELL\);)(?=.{0,50}\.PREMIUM_UPSELL_VIEWED)/,
54 replace: "return null;"
55 }
56 }
57 ],
58
59 renderCharCounter: ErrorBoundary.wrap(({ text }: { text: string; }) => {
60 if (!text.length) return null;
61
62 const premiumType = UserStore.getCurrentUser().premiumType ?? 0;
63 const charMax = premiumType === 2 ? 4000 : 2000;
64
65 const color = getCounterColor((text.length / charMax) * 100);
66
67 return (
68 <div className={cl("counter")} style={{ color }}>
69 <span className={cl("count")}>{text.length}</span>
70 /
71 <span className={cl("max")}>{charMax}</span>
72 </div>
73 );
74 }, { noop: true })
75});
76