Plugin

MentionAvatars

Shows user avatars and role icons inside mentions

Appearance Customisation
index.tsx
Download

Source

src/plugins/mentionAvatars/index.tsx
1import "./styles.css";
2
3import { definePluginSettings } from "@api/Settings";
4import ErrorBoundary from "@components/ErrorBoundary";
5import { Devs } from "@utils/constants";
6import definePlugin, { OptionType } from "@utils/types";
7import { User } from "@vencord/discord-types";
8import { GuildRoleStore, SelectedGuildStore, useState } from "@webpack/common";
9
10const settings = definePluginSettings({
11 showAtSymbol: {
12 type: OptionType.BOOLEAN,
13 displayName: "Show @ Symbol",
14 description: "Whether the the @ symbol should be displayed on user mentions",
15 default: true
16 }
17});
18
19function DefaultRoleIcon() {
20 return (
21 <svg
22 className="vc-mentionAvatars-icon vc-mentionAvatars-role-icon"
23 xmlns="http:class="ts-cmt">//www.w3.org/2000/svg"
24 viewBox="0 0 24 24"
25 fill="currentColor"
26 >
27 <path
28 d="M14 8.00598C14 10.211 12.206 12.006 10 12.006C7.795 12.006 6 10.211 6 8.00598C6 5.80098 7.794 4.00598 10 4.00598C12.206 4.00598 14 5.80098 14 8.00598ZM2 19.006C2 15.473 5.29 13.006 10 13.006C14.711 13.006 18 15.473 18 19.006V20.006H2V19.006Z"
29 />
30 <path
31 d="M20.0001 20.006H22.0001V19.006C22.0001 16.4433 20.2697 14.4415 17.5213 13.5352C19.0621 14.9127 20.0001 16.8059 20.0001 19.006V20.006Z"
32 />
33 <path
34 d="M14.8834 11.9077C16.6657 11.5044 18.0001 9.9077 18.0001 8.00598C18.0001 5.96916 16.4693 4.28218 14.4971 4.0367C15.4322 5.09511 16.0001 6.48524 16.0001 8.00598C16.0001 9.44888 15.4889 10.7742 14.6378 11.8102C14.7203 11.8418 14.8022 11.8743 14.8834 11.9077Z"
35 />
36 </svg>
37 );
38}
39
40export default definePlugin({
41 name: "MentionAvatars",
42 description: "Shows user avatars and role icons inside mentions",
43 tags: ["Appearance", "Customisation"],
44 authors: [Devs.Ven, Devs.SerStars],
45
46 patches: [{
47 find: ".USER_MENTION)",
48 replacement: {
49 match: /children:`@\$\{(\i\?\?\i)\}`(?<=\.useName\((\i)\).+?)/,
50 replace: "children:$self.renderUsername({username:$1,user:$2})"
51 }
52 },
53 {
54 find: ".ROLE_MENTION)",
55 replacement: {
56 match: /children:\[\i&&.{0,100}className:\i.\i,background:!1,.{0,50}?,\i(?=\])/,
57 replace: "$&,$self.renderRoleIcon(arguments[0])"
58 }
59 }],
60
61 settings,
62
63 renderUsername: ErrorBoundary.wrap((props: { user: User, username: string; }) => {
64 const { user, username } = props;
65 const [isHovering, setIsHovering] = useState(false);
66
67 if (!user) return <>{getUsernameString(username)}</>;
68
69 return (
70 <span
71 onMouseEnter={() => setIsHovering(true)}
72 onMouseLeave={() => setIsHovering(false)}
73 >
74 <img
75 src={user.getAvatarURL(SelectedGuildStore.getGuildId(), 16, isHovering)}
76 className="vc-mentionAvatars-icon"
77 style={{ borderRadius: "50%" }}
78 />
79 {getUsernameString(username)}
80 </span>
81 );
82 }, { noop: true }),
83
84 renderRoleIcon: ErrorBoundary.wrap(({ roleId, guildId }: { roleId: string, guildId: string; }) => {
85 // Discord uses Role Mentions for uncached users because .... idk
86 if (!roleId) return null;
87
88 const role = GuildRoleStore.getRole(guildId, roleId);
89
90 if (!role?.icon) return <DefaultRoleIcon />;
91
92 return (
93 <img
94 className="vc-mentionAvatars-icon vc-mentionAvatars-role-icon"
95 src={`${location.protocol}class="ts-cmt">//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${roleId}/${role.icon}.webp?size=24&quality=lossless`}
96 />
97 );
98 }, { noop: true }),
99});
100
101function getUsernameString(username: string) {
102 return settings.store.showAtSymbol
103 ? `@${username}`
104 : username;
105}
106