Plugin
MentionAvatars
Shows user avatars and role icons inside mentions
1
import "./styles.css";2
3
import { definePluginSettings } from "@api/Settings";4
import ErrorBoundary from "@components/ErrorBoundary";5
import { Devs } from "@utils/constants";6
import definePlugin, { OptionType } from "@utils/types";7
import { User } from "@vencord/discord-types";8
import { GuildRoleStore, SelectedGuildStore, useState } from "@webpack/common";9
10
const 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: true16
}17
});18
19
function DefaultRoleIcon() {20
return (21
<svg22
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
<path28
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
<path31
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
<path34
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
40
export 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
<span71
onMouseEnter={() => setIsHovering(true)}72
onMouseLeave={() => setIsHovering(false)}73
>74
<img75
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 .... idk86
if (!roleId) return null;87
88
const role = GuildRoleStore.getRole(guildId, roleId);89
90
if (!role?.icon) return <DefaultRoleIcon />;91
92
return (93
<img94
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
101
function getUsernameString(username: string) {102
return settings.store.showAtSymbol103
? `@${username}`104
: username;105
}106