SMYN: Integrate PR#1337 + Cleanup. (#1338)

* Integrate PR#1337 + Cleanup.

* Typo.

* Typo.
This commit is contained in:
Etorix 2026-09-02 08:00:40 -07:00 • committed by GitHub
parent 5288054afc
commit 57a83b52b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 142 additions and 34 deletions

View file

@ -21,12 +21,35 @@ import { classNameFactory } from "@utils/index";
import definePlugin, { OptionType } from "@utils/types";
import { GuildMember, Message, RenderModalProps, User } from "@vencord/discord-types";
import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack";
import { AccessibilityStore, ChannelStore, GuildMemberStore, GuildStore, Menu, MessageStore, Modal, openModal, RelationshipStore, StreamerModeStore, TextInput, useEffect, UserStore, useState } from "@webpack/common";
import { AccessibilityStore, ChannelStore, GuildMemberStore, GuildStore, Menu, MessageStore, Modal, openModal, RelationshipStore, StreamerModeStore, TextInput, useEffect, UsernameUtils, UserStore, useState } from "@webpack/common";
import { JSX } from "react";
const SMYNC = classNameFactory();
const wrapEmojis = findByCodeLazy("lastIndex;return");
interface SearchUserResult {
text: string;
user: User;
}
interface UserAutocompleteResult {
record: User;
}
interface UserAutocompleteUtils {
queryUsers(options: {
query: string;
users: User[];
limit: number;
}): UserAutocompleteResult[];
}
const AutocompleteUtils: UserAutocompleteUtils = findByPropsLazy(
"queryUsers",
"queryGuildUsers",
"queryChannelUsers"
);
interface DisplayNameStyles {
colors: number[];
effectId: number;
@ -332,6 +355,16 @@ function getProcessedNames(
return { username, display, nick, friend, custom };
}
interface SearchAutocompleteProps {
currentToken?: {
getFullMatch(): string | undefined;
} | null;
maxResults?: number;
searchContext: {
guildId: string;
};
}
interface mentionProps {
userId: string;
channelId?: string;
@ -352,7 +385,7 @@ interface messageProps {
interface memberListProfileReactionProps {
user: User | null | undefined;
type: "typingIndicator" | "membersList" | "profilesPopout" | "profilesTooltip" | "reactionsTooltip" | "reactionsPopout" | "voiceChannel";
type: "typingIndicator" | "membersList" | "profilesPopout" | "profilesTooltip" | "reactionsTooltip" | "reactionsPopout" | "voiceChannel" | "searchAutocomplete";
guildId?: string;
tags?: any;
isHovered?: boolean;
@ -366,6 +399,55 @@ interface activeNowNameProps {
type colorStringsType = { primaryColor: string | null, secondaryColor: string | null, tertiaryColor: string | null; } | null | undefined;
function addCustomNameResults(
results: SearchUserResult[],
{ currentToken, maxResults = 10, searchContext }: SearchAutocompleteProps
) {
const query = currentToken?.getFullMatch()?.trim();
if (!query) return results;
const candidates = new Map(
results.map(({ user }) => [user.id, user])
);
let hasCustomCandidates = false;
for (const userId in customNicknames) {
if (!matchableCustomName(userId)) continue;
if (!GuildMemberStore.getMember(searchContext.guildId, userId)) continue;
const user = UserStore.getUser(userId);
if (!user || user.isNonUserBot()) continue;
candidates.set(userId, user);
hasCustomCandidates = true;
}
if (!hasCustomCandidates) return results;
const ranked = AutocompleteUtils.queryUsers({
query,
users: [...candidates.values()],
limit: maxResults
});
const rerankedResults: SearchUserResult[] = [];
for (const { record: user } of ranked) {
const text = UsernameUtils.getUserTag(user);
if (text != null) rerankedResults.push({ text, user });
}
const rerankedIds = new Set(
rerankedResults.map(({ user }) => user.id)
);
return [
...rerankedResults,
...results.filter(({ user }) => !rerankedIds.has(user.id))
].slice(0, maxResults);
}
function getTypingMemberListProfilesReactionsVoiceName(
props: memberListProfileReactionProps,
): [string | null, JSX.Element | null, string | null] {
@ -582,7 +664,7 @@ function renderUsername(
author: User | GuildMember | null,
channelId: string | null,
messageId: string | null,
type: "messages" | "replies" | "typingIndicator" | "mentions" | "membersList" | "profilesPopout" | "profilesTooltip" | "reactionsTooltip" | "reactionsPopout" | "voiceChannel",
type: "messages" | "replies" | "typingIndicator" | "mentions" | "membersList" | "profilesPopout" | "profilesTooltip" | "reactionsTooltip" | "reactionsPopout" | "voiceChannel" | "searchAutocomplete",
mentionSymbol: string,
hookless: boolean,
inGuild: boolean,
@ -595,14 +677,15 @@ function renderUsername(
const isMention = type === "mentions";
const isTyping = type === "typingIndicator";
const isMember = type === "membersList";
const isAutocomplete = type === "searchAutocomplete";
const isProfile = type === "profilesPopout";
const isReactionsPopout = type === "reactionsPopout";
const isReactionsTooltip = type === "reactionsTooltip";
const isReaction = isReactionsTooltip || isReactionsPopout;
const isVoice = type === "voiceChannel";
const config = hookless ? settings.store : settings.use(["messages", "replies", "mentions", "typingIndicator", "memberList", "styleDirectMessagesList", "styleDirectMessagesMessages", "styleFriendsList", "styleActiveNow", "profilePopout", "reactions", "friendNameOnlyInDirectMessages", "customNameOnlyInDirectMessages", "discriminators", "hideDefaultAtSign", "truncateAllNamesWithStreamerMode", "removeDuplicates", "ignoreEffects", "ignoreFonts", "animateEffects", "alwaysAnimateEffects", "gradientGlow", "includedNames", "customNameColor", "friendNameColor", "nicknameColor", "displayNameColor", "usernameColor", "nameSeparator", "triggerNameRerender"]);
const { messages, replies, mentions, typingIndicator, memberList, styleDirectMessagesMessages, profilePopout, reactions, friendNameOnlyInDirectMessages, customNameOnlyInDirectMessages, discriminators, truncateAllNamesWithStreamerMode, removeDuplicates, ignoreEffects, ignoreFonts, animateEffects, includedNames, customNameColor, friendNameColor, nicknameColor, displayNameColor, usernameColor, nameSeparator, triggerNameRerender } = config;
const config = hookless ? settings.store : settings.use(["messages", "replies", "mentions", "typingIndicator", "memberList", "searchAutocomplete", "styleDirectMessagesList", "styleDirectMessagesMessages", "styleFriendsList", "styleActiveNow", "profilePopout", "reactions", "friendNameOnlyInDirectMessages", "customNameOnlyInDirectMessages", "discriminators", "hideDefaultAtSign", "truncateAllNamesWithStreamerMode", "removeDuplicates", "ignoreEffects", "ignoreFonts", "animateEffects", "alwaysAnimateEffects", "gradientGlow", "includedNames", "customNameColor", "friendNameColor", "nicknameColor", "displayNameColor", "usernameColor", "nameSeparator", "triggerNameRerender"]);
const { messages, replies, mentions, typingIndicator, memberList, searchAutocomplete, styleDirectMessagesMessages, profilePopout, reactions, friendNameOnlyInDirectMessages, customNameOnlyInDirectMessages, discriminators, truncateAllNamesWithStreamerMode, removeDuplicates, ignoreEffects, ignoreFonts, animateEffects, includedNames, customNameColor, friendNameColor, nicknameColor, displayNameColor, usernameColor, nameSeparator, triggerNameRerender } = config;
const channel = channelId ? ChannelStore.getChannel(channelId) || null : null;
const message = channelId && messageId ? MessageStore.getMessage(channelId, messageId) : null;
@ -750,6 +833,8 @@ function renderUsername(
return [null, null, null];
} else if (isMember && !memberList) {
return [null, null, null];
} else if (isAutocomplete && !searchAutocomplete) {
return [null, null, null];
} else if (isProfile && !profilePopout) {
return [null, null, null];
} else if (isReaction && !reactions) {
@ -1116,29 +1201,10 @@ const settings = definePluginSettings({
default: true,
description: "Display the first available name listed in your custom name format in the members list, DMs list, friends list, and Active Now.",
},
styleDirectMessagesList: {
searchAutocomplete: {
type: OptionType.BOOLEAN,
default: true,
displayName: "Style Direct Messages List",
description: "Show display name effects on unselected entries without requiring hover. Selected and hovered entries are still styled when disabled.",
},
styleDirectMessagesMessages: {
type: OptionType.BOOLEAN,
default: true,
displayName: "Style Direct Messages Messages",
description: "Show display name effects on message authors without requiring hover. Hovered names are still styled when disabled.",
},
styleFriendsList: {
type: OptionType.BOOLEAN,
default: true,
displayName: "Style Friends List",
description: "Show display name effects without requiring hover. Hovered entries are still styled when disabled.",
},
styleActiveNow: {
type: OptionType.BOOLEAN,
default: true,
displayName: "Style Active Now",
description: "Show display name effects without requiring hover. Hovered entries are still styled when disabled.",
description: "Display the first available name listed in your custom name format in mention and search autocomplete",
},
profilePopout: {
type: OptionType.BOOLEAN,
@ -1155,6 +1221,26 @@ const settings = definePluginSettings({
default: true,
description: "Display the first available name listed in your custom name format in reaction tooltips, and the full name in reaction popouts.",
},
styleDirectMessagesList: {
type: OptionType.BOOLEAN,
default: true,
description: "Show display name effects on unselected entries without requiring hover. Selected and hovered entries are still styled when disabled.",
},
styleDirectMessagesMessages: {
type: OptionType.BOOLEAN,
default: true,
description: "Show display name effects on message authors without requiring hover. Hovered names are still styled when disabled.",
},
styleFriendsList: {
type: OptionType.BOOLEAN,
default: true,
description: "Show display name effects without requiring hover. Hovered entries are still styled when disabled.",
},
styleActiveNow: {
type: OptionType.BOOLEAN,
default: true,
description: "Show display name effects without requiring hover. Hovered entries are still styled when disabled.",
},
discriminators: {
type: OptionType.BOOLEAN,
default: true,
@ -1263,7 +1349,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "ShowMeYourName",
description: "Display any permutation of custom nicknames, friend nicknames, server nicknames, display names, and usernames in chat.",
authors: [EquicordDevs.Etorix, Devs.Rini, Devs.TheKodeToad, Devs.sadan, Devs.prism],
authors: [EquicordDevs.Etorix, Devs.Rini, Devs.TheKodeToad, Devs.sadan, Devs.prism, EquicordDevs.penguinwokrs],
tags: ["Appearance", "Customisation"],
searchTerms: ["SMYN", "Nicknames", "Custom Nicknames"],
isModified: true,
@ -1509,28 +1595,45 @@ export default definePlugin({
}
},
{
// Let the mention autocomplete match custom names too.
// Allow custom names to be considered in the mention auto complete.
find: "queryGuildMentionResults(",
group: true,
replacement: [
{
// Rank a leading match the same as one on a username, nickname or display name.
// Rank a leading match the same as friend names, global names, nicknames, and usernames.
match: /\i&&\i===(\i)\.id\|\|\i\.substring\(0,(\i)\.length\)===\2\|\|/,
replace: "$&$self.matchableCustomName($1.id).startsWith($2)||"
},
{
// Rank a looser match with the same matcher and tier as those names.
// Rank a looser match using the same matcher and tie breaker as friend names, global names, nicknames, and usernames.
match: /\i<50&&\((\i)\(\)\((\i),\i\).{0,120}?(?=\)&&\(\i\.push\(\{type:\i\.\i\.\i,record:(\i),)/,
replace: "$&||$1()($2,$self.matchableCustomName($3.id))"
}
]
},
{
// Let the mention autocomplete ui have our custom names, support our formatting, etc.
// Allow custom names to be considered in the search autocomplete by
// inserting custom names into the results and re-sorting them by rank.
find: '="SearchAutocompleteStore"',
replacement: {
match: /(?<=&&!\i\)\i=)\i\(\i\)\.results/,
replace: "$self.addCustomNameResults($&,arguments[0])"
}
},
{
// Replace names in the from: and mentions: search filter suggestions.
find: "hasOtherSearchFiltersVisible",
replacement: {
match: /(\i)=(\i\.\i\.useName\((\i),\i,(\i)\))/,
replace: '$1=$self.getTypingMemberListProfilesReactionsVoiceNameText({user:$4,guildId:$3,type:"searchAutocomplete"})??$2'
}
},
{
// Replace names in the mention autocomplete.
find: "#{intl::COMMANDS_OPTIONAL_COUNT}",
replacement: {
match: /\i\?\?\i\?\?\i\.\i\.getName\(\i\)/,
replace: '$self.getTypingMemberListProfilesReactionsVoiceNameText({user:this.props.user,guildId:this.props.guildId,type:"membersList"})'
match: /(\i\?\?\i\?\?\i\.\i\.getName\(\i\))/,
replace: '$self.getTypingMemberListProfilesReactionsVoiceNameText({user:this.props.user,guildId:this.props.guildId,type:"searchAutocomplete"})??$1'
}
}
],
@ -1584,5 +1687,6 @@ export default definePlugin({
shouldAnimateNameEffects,
getTypingMemberListProfilesReactionsVoiceNameText,
getTypingMemberListProfilesReactionsVoiceNameElement,
matchableCustomName
matchableCustomName,
addCustomNameResults,
});

View file

@ -1430,6 +1430,10 @@ export const EquicordDevs = Object.freeze({
name: "ELJoOker",
id: 605894319408283678n
},
penguinwokrs: {
name: "penguinwokrs",
id: 385266832136863746n
},
} satisfies Record<string, Dev>);
// iife so #__PURE__ works correctly