diff --git a/src/plugins/ircColors/README.md b/src/plugins/ircColors/README.md new file mode 100644 index 00000000..9d9c7634 --- /dev/null +++ b/src/plugins/ircColors/README.md @@ -0,0 +1,17 @@ +# IrcColors + +Makes username colors in chat unique, like in IRC clients + +![Chat with IrcColors and Compact++ enabled](https://github.com/Vendicated/Vencord/assets/33988779/88e05c0b-a60a-4d10-949e-8b46e1d7226c) + +Improves chat readability by assigning every user an unique nickname color, +making distinguishing between different users easier. Inspired by the feature +in many IRC clients, such as HexChat or WeeChat. + +Keep in mind this overrides role colors in chat, so if you wish to know +someone's role color without checking their profile, enable the role dot: go to +**User Settings**, **Accessibility** and switch **Role Colors** to **Show role +colors next to names**. + +Created for use with the [Compact++](https://gitlab.com/Grzesiek11/compactplusplus-discord-theme) +theme. diff --git a/src/plugins/ircColors/index.ts b/src/plugins/ircColors/index.ts new file mode 100644 index 00000000..d5cc5f3e --- /dev/null +++ b/src/plugins/ircColors/index.ts @@ -0,0 +1,94 @@ +/* + * 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 { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +// Compute a 64-bit FNV-1a hash of the passed data +function hash(id: bigint) { + const fnvPrime = 1099511628211n; + const offsetBasis = 14695981039346656037n; + + let result = offsetBasis; + for (let i = 7n; i >= 0n; i--) { + result ^= (id >> (8n * i)) & 0xffn; + result = (result * fnvPrime) % 2n ** 32n; + } + + return result; +} + +// Calculate a CSS color string based on the user ID +function calculateNameColorForUser(id: bigint) { + const idHash = hash(id); + + return `hsl(${idHash % 360n}, 100%, ${settings.store.lightness}%)`; +} + +const settings = definePluginSettings({ + lightness: { + description: "Lightness, in %. Change if the colors are too light or too dark. Reopen the chat to apply.", + type: OptionType.NUMBER, + default: 70, + }, + memberListColors: { + description: "Replace role colors in the member list", + restartNeeded: true, + type: OptionType.BOOLEAN, + default: true, + }, +}); + +export default definePlugin({ + name: "IrcColors", + description: "Makes username colors in chat unique, like in IRC clients", + authors: [Devs.Grzesiek11], + patches: [ + { + find: '="SYSTEM_TAG"', + replacement: { + match: /(?<=className:\i\.username,style:.{0,50}:void 0,)/, + replace: "style:{color:$self.calculateNameColorForMessageContext(arguments[0])},", + }, + }, + { + find: ".NameWithRole,{roleName:", + replacement: { + match: /(?<=color:)null!=.{0,50}?(?=,)/, + replace: "$self.calculateNameColorForListContext(arguments[0])", + }, + predicate: () => settings.store.memberListColors, + }, + ], + settings, + calculateNameColorForMessageContext(context: any) { + const id = context?.message?.author?.id; + if (id == null) { + return null; + } + return calculateNameColorForUser(BigInt(id)); + }, + calculateNameColorForListContext(context: any) { + const id = context?.user?.id; + if (id == null) { + return null; + } + return calculateNameColorForUser(BigInt(id)); + }, +});