Plugin

ShowMeYourName

Display usernames next to nicks, or no nicks at all

Appearance Customisation
index.tsx
Download

Source

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