From 52e7c7def7cc1548abe920f13a43ee35299246ff Mon Sep 17 00:00:00 2001 From: Creation's Date: Thu, 23 Jan 2025 14:41:45 -0500 Subject: [PATCH] add https://github.com/Vendicated/Vencord/pull/2161/ (#125) --- src/plugins/moreUserTags/index.tsx | 110 +++++++++++++++++++++++++---- src/plugins/moreUserTags/style.css | 7 ++ src/utils/constants.ts | 4 ++ 3 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 src/plugins/moreUserTags/style.css diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 8029b483..69308942 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import "./style.css"; + import { definePluginSettings } from "@api/Settings"; import { Flex } from "@components/Flex"; import { Devs } from "@utils/constants"; @@ -23,7 +25,7 @@ import { getIntlMessage } from "@utils/discord"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; import { findByCodeLazy, findLazy } from "@webpack"; -import { Card, ChannelStore, Forms, GuildStore, PermissionsBits, Switch, TextInput, Tooltip } from "@webpack/common"; +import { Card, ChannelStore, Forms, GuildMemberStore, GuildStore, PermissionsBits, Switch, TextInput, Tooltip } from "@webpack/common"; import type { Permissions, RC } from "@webpack/types"; import type { Channel, Guild, Message, User } from "discord-types/general"; @@ -108,6 +110,16 @@ const defaultSettings = Object.fromEntries( tags.map(({ name, displayName }) => [name, { text: displayName, showInChat: true, showInNotChat: true }]) ) as TagSettings; +// From https://gist.github.com/StevenBlack/960189 +export function getContrastYIQ(hexColor: string | undefined): "#000" | "#fff" | undefined { + if (!hexColor) return; + const r = parseInt(hexColor.substring(1, 3), 16); + const g = parseInt(hexColor.substring(3, 5), 16); + const b = parseInt(hexColor.substring(5, 7), 16); + const yiq = (r * 299 + g * 587 + b * 114) / 1000; + return yiq >= 128 ? "#000" : "#fff"; +} + function SettingsComponent() { const tagSettings = settings.store.tagSettings ??= defaultSettings; @@ -166,6 +178,10 @@ const settings = definePluginSettings({ description: "Only show extra tags for bots / Hide [BOT] text", type: OptionType.BOOLEAN }, + useRoleColors: { + description: "Use the user's role color instead of the default color", + type: OptionType.BOOLEAN + }, tagSettings: { type: OptionType.COMPONENT, component: SettingsComponent, @@ -190,6 +206,11 @@ export default definePlugin({ { find: "#{intl::DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP_OFFICIAL}", replacement: [ + // Grab the colors from the params using the custom params + { + match: /type:\i=\i\.\i\.BOT/, + replace: "$&,moreTags_bgColor:moreTags_bgColor,moreTags_fgColor:moreTags_fgColor" + }, // make the tag show the right text { match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=(.{0,40}#{intl::APP_TAG}\))/, @@ -202,27 +223,34 @@ export default definePlugin({ replace: "$1=$self.isOPTag($2)" }, // add HTML data attributes (for easier theming) + // also set the colors { match: /.botText,children:(\i)}\)]/, - replace: "$&,'data-tag':$1.toLowerCase()" + replace: "$&,'data-tag':$1.toLowerCase(),style:{'background-color':moreTags_bgColor,'color':moreTags_fgColor},'data-moreTags-darkFg':moreTags_fgColor?.includes('0')" } ], }, // in messages { find: ".Types.ORIGINAL_POSTER", - replacement: { - match: /;return\((\(null==\i\?void 0:\i\.isSystemDM\(\).+?.Types.ORIGINAL_POSTER\)),null==(\i)\)/, - replace: ";$1;$2=$self.getTag({...arguments[0],origType:$2,location:'chat'});return $2 == null" - } + replacement: [ + // Pass the tag's colors and type to the next function + { + match: /;return\((\(null==\i\?void 0:\i\.isSystemDM\(\).+?.Types.ORIGINAL_POSTER\)),null==(\i)\)\?null:\(0,(\i)\.jsx\)\((\i).(\i),{/, + replace: ";$1;$2=$self.getTag({...arguments[0],origType:$2,location:'chat'});return $2 == null?null:(0,$3.jsx)($4.$5,{...$self.getTagColors({...arguments[0],tagType:$2,location:'chat'})," + } + ] }, // in the member list { find: "#{intl::GUILD_OWNER}),children:", - replacement: { - match: /(?\i)=\(null==.{0,100}\.BOT;return null!=(?\i)&&\i\.bot/, - replace: "$ = $self.getTag({user: $, channel: arguments[0].channel, origType: $.bot ? 0 : null, location: 'not-chat' }); return typeof $ === 'number'" - } + replacement: [ + // Pass the tag's colors and type to the next function + { + match: /(?\i)=\(null==.{0,100}\.BOT;return null!=(?\i)&&\i\.bot\?\(0,(?\i)\.jsx\)\((?\i)\.(?\i),{/, + replace: "$ = $self.getTag({user: $, channel: arguments[0].channel, origType: $.bot ? 0 : null, location: 'not-chat' }); return typeof $ === 'number'?(0,$.jsx)($.$,{...$self.getTagColors({...arguments[0],tagType:$,location:'not-chat'})," + } + ] }, // pass channel id down props to be used in profiles { @@ -249,12 +277,41 @@ export default definePlugin({ // it's either this or extremely long lookbehind match: /user:\i,nick:\i,/, replace: "$&moreTags_channelId," - }, { + }, + { + // Get the tag type and tag colors so that they can be distributed + match: /(,\i=\i\.isPomelo\(\)\|\|\i;)(.+?botType:(\i),botVerified:(\i),(?!discriminatorClass:)(?<=user:(\i).+?))/, + replace: "$1let moreTags_tagType=$self.getTag({user:$5,channelId:moreTags_channelId,origType:$3,location:'not-chat'});let moreTags_tagColors=$self.getTagColors({user:$5,channelId:moreTags_channelId,tagType:moreTags_tagType,location:'not-chat'});$2" + }, + { match: /,botType:(\i),botVerified:(\i),(?!discriminatorClass:)(?<=user:(\i).+?)/g, - replace: ",botType:$self.getTag({user:$3,channelId:moreTags_channelId,origType:$1,location:'not-chat'}),botVerified:$2," + replace: ",botType:moreTags_tagType,...moreTags_tagColors," + }, { + // Get the parameters from the function that were passed in previously + // because Discord needs to make it hard on us + match: /,botClass:\i,showStreamerModeTooltip:\i/, + replace: "$&,moreTags_bgColor:moreTags_bgColor,moreTags_fgColor:moreTags_fgColor" + }, { + // Finally pass the color information into the renderer + match: /\.jsx\)\(\i\.\i,{type:\i,/, + replace: "$&moreTags_bgColor,moreTags_fgColor," } ] }, + // Colors need to be passed down through this random module. + // If there's a way to bypass this module without modifying discord's random variables (We don't want to break stuff) leave a PR (or comment if an existing one is open) + { + find: ",invertBotTagColor:", + replacement: [ + { + match: /,invertBotTagColor:\i/, + replace: "$&,moreTags_bgColor:moreTags_bgColor,moreTags_fgColor:moreTags_fgColor" + }, { + match: /verified:\i,useRemSizes:\i/, + replace: "$&,moreTags_bgColor,moreTags_fgColor" + } + ] + } ], start() { @@ -316,6 +373,31 @@ export default definePlugin({ } }, + + getTagColors({ + user, channelId, channel, location, tagType + }: { + user: User, + channel?: Channel, + channelId?: string; + location: "chat" | "not-chat"; + tagType: number; + }): { + moreTags_bgColor: string, + moreTags_fgColor: string; + } { + const passedTagName = Object.keys(Tag.Types).find(k => Tag.Types[k] === tagType); + const [tagName, variant] = passedTagName?.split("-") ?? [null, null]; + if (!settings.store.useRoleColors || !tagType || !tagName || (location === "chat" && !settings.store.tagSettings[tagName]?.showInChat) || (location === "not-chat" && !settings.store.tagSettings[tagName]?.showInNotChat) || (user.bot && settings.store.dontShowForBots)) { + return { moreTags_bgColor: "", moreTags_fgColor: "" }; + } + if (!channel && channelId) channel = ChannelStore.getChannel(channelId); + const member = channel?.guild_id != null ? GuildMemberStore.getMember(channel?.guild_id, user.id) : null; + const colorString = member?.colorString; + const fgColorString = colorString != null ? getContrastYIQ(colorString) : null; + return { moreTags_bgColor: colorString ?? "", moreTags_fgColor: fgColorString ?? "" }; + }, + getTag({ message, user, channelId, origType, location, channel }: { @@ -342,8 +424,8 @@ export default definePlugin({ const perms = this.getPermissions(user, channel); for (const tag of tags) { - if (location === "chat" && !settings.tagSettings[tag.name].showInChat) continue; - if (location === "not-chat" && !settings.tagSettings[tag.name].showInNotChat) continue; + if (location === "chat" && !settings.tagSettings[tag.name]?.showInChat) continue; + if (location === "not-chat" && !settings.tagSettings[tag.name]?.showInNotChat) continue; // If the owner tag is disabled, and the user is the owner of the guild, // avoid adding other tags because the owner will always match the condition for them diff --git a/src/plugins/moreUserTags/style.css b/src/plugins/moreUserTags/style.css new file mode 100644 index 00000000..234d6c37 --- /dev/null +++ b/src/plugins/moreUserTags/style.css @@ -0,0 +1,7 @@ +span[class*="botTagCozy"][data-moreTags-darkFg="true"]>svg>path { + fill: #000; +} + +span[class*="botTagCozy"][data-moreTags-darkFg="false"]>svg>path { + fill: #fff; +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 6b2ca504..9c64830e 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -971,6 +971,10 @@ export const EquicordDevs = Object.freeze({ voidbbg: { name: "voidbbg", id: 117126234588184582n + }, + OIRNOIR: { + name: "OIRNOIR", + id: 720842469024989195n } } satisfies Record);