Plugin

ShowMeYourName

Display usernames next to nicks, or no nicks at all

Appearance Customisation
index.tsx
Download

Source

src/plugins/showMeYourName/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 { Channel, Message, User } from "@vencord/discord-types";
8import { RelationshipStore, StreamerModeStore } from "@webpack/common";
9
10interface UsernameProps {
11 author: { nick: string; authorId: string; };
12 channel: Channel;
13 message: Message;
14 withMentionPrefix?: boolean;
15 isRepliedMessage: boolean;
16 userOverride?: User;
17}
18
19const settings = definePluginSettings({
20 mode: {
21 type: OptionType.SELECT,
22 description: "How to display usernames and nicks",
23 options: [
24 { label: "Username then nickname", value: "user-nick", default: true },
25 { label: "Nickname then username", value: "nick-user" },
26 { label: "Username only", value: "user" },
27 ],
28 },
29 friendNicknames: {
30 type: OptionType.SELECT,
31 description: "How to prioritise friend nicknames over server nicknames",
32 options: [
33 { label: "Show friend nicknames only in direct messages", value: "dms", default: true },
34 { label: "Prefer friend nicknames over server nicknames", value: "always" },
35 { label: "Prefer server nicknames over friend nicknames", value: "fallback" }
36 ]
37 },
38 displayNames: {
39 type: OptionType.BOOLEAN,
40 description: "Use display names in place of usernames",
41 default: false
42 },
43 inReplies: {
44 type: OptionType.BOOLEAN,
45 default: false,
46 description: "Also apply functionality to reply previews",
47 },
48});
49
50export default definePlugin({
51 name: "ShowMeYourName",
52 description: "Display usernames next to nicks, or no nicks at all",
53 tags: ["Appearance", "Customisation"],
54 authors: [Devs.Rini, Devs.TheKodeToad, Devs.rae],
55 patches: [
56 {
57 find: '="SYSTEM_TAG"',
58 replacement: {
59 // The field is named "userName", but as this is unusual casing, the regex also matches username, in case they change it
60 match: /(?<=onContextMenu:\i,children:)\i\?(?=.{0,100}?user[Nn]ame:)/,
61 replace: "$self.renderUsername(arguments[0]),_oldChildren:$&"
62 }
63 },
64 ],
65 settings,
66
67 renderUsername: ErrorBoundary.wrap(({ author, channel, message, isRepliedMessage, withMentionPrefix, userOverride }: UsernameProps) => {
68 try {
69 const { mode, friendNicknames, displayNames, inReplies } = settings.store;
70
71 const user = userOverride ?? message.author;
72 let username = StreamerModeStore.enabled
73 ? user.username[0] + "…"
74 : user.username;
75
76 if (displayNames)
77 username = user.globalName || username;
78
79 let { nick } = author;
80
81 const friendNickname = RelationshipStore.getNickname(author.authorId);
82
83 if (friendNickname) {
84 const shouldUseFriendNickname =
85 friendNicknames === "always" ||
86 (friendNicknames === "dms" && channel.isPrivate()) ||
87 (friendNicknames === "fallback" && !nick);
88
89 if (shouldUseFriendNickname)
90 nick = friendNickname;
91 }
92
93 const prefix = withMentionPrefix ? "@" : "";
94
95 if (isRepliedMessage && !inReplies || username.toLowerCase() === nick.toLowerCase())
96 return <>{prefix}{nick}</>;
97
98 if (mode === "user-nick")
99 return <>{prefix}{username} <span className="vc-smyn-suffix">{nick}</span></>;
100
101 if (mode === "nick-user")
102 return <>{prefix}{nick} <span className="vc-smyn-suffix">{username}</span></>;
103
104 return <>{prefix}{username}</>;
105 } catch {
106 return <>{author?.nick}</>;
107 }
108 }, { noop: true }),
109});
110