diff --git a/lib/shared/markdown.js b/lib/shared/markdown.js --- a/lib/shared/markdown.js +++ b/lib/shared/markdown.js @@ -6,6 +6,7 @@ markdownUserMentionRegex, decodeChatMentionText, } from './mention-utils.js'; +import { useENSNames } from '../hooks/ens-cache.js'; import type { ChatMentionCandidates, RelativeMemberInfo, @@ -197,15 +198,28 @@ }; } -function createMemberMapForUserMentions( +const useENSNamesOptions = { allAtOnce: true }; +function useMemberMapForUserMentions( members: $ReadOnlyArray, ): $ReadOnlyMap { const membersMap = new Map(); - members.forEach(member => { - if (member.role && member.username) { - membersMap.set(member.username.toLowerCase(), member.id); + const resolvedMembers = useENSNames(members, useENSNamesOptions); + + for (let i = 0; i < members.length; i++) { + const member = members[i]; + const resolvedMember = resolvedMembers[i]; + + const { username: rawUsername, role } = member; + const { username: resolvedUsername } = resolvedMember; + + if (role && rawUsername) { + membersMap.set(rawUsername.toLowerCase(), member.id); } - }); + + if (resolvedUsername && resolvedUsername !== rawUsername) { + membersMap.set(resolvedUsername.toLowerCase(), member.id); + } + } return membersMap; } @@ -368,7 +382,7 @@ jsonPrint, matchList, parseList, - createMemberMapForUserMentions, + useMemberMapForUserMentions, matchUserMentions, parseUserMentions, stripSpoilersFromNotifications, diff --git a/native/markdown/rules.react.js b/native/markdown/rules.react.js --- a/native/markdown/rules.react.js +++ b/native/markdown/rules.react.js @@ -363,12 +363,19 @@ chatMentionCandidates: ChatMentionCandidates, ): (useDarkStyle: boolean) => MarkdownRules { const { members } = threadInfo; + const membersMap = SharedMarkdown.useMemberMapForUserMentions(members); + return React.useMemo( () => _memoize<[boolean], MarkdownRules>((useDarkStyle: boolean) => - textMessageRules(members, chatMentionCandidates, useDarkStyle), + textMessageRules( + members, + chatMentionCandidates, + useDarkStyle, + membersMap, + ), ), - [members, chatMentionCandidates], + [members, chatMentionCandidates, membersMap], ); } @@ -376,9 +383,9 @@ members: $ReadOnlyArray, chatMentionCandidates: ChatMentionCandidates, useDarkStyle: boolean, + membersMap: $ReadOnlyMap, ): MarkdownRules { const baseRules = fullMarkdownRules(useDarkStyle); - const membersMap = SharedMarkdown.createMemberMapForUserMentions(members); return { ...baseRules, @@ -428,15 +435,26 @@ } let defaultTextMessageRules = null; +const defaultMembersMap = new Map(); function getDefaultTextMessageRules( overrideDefaultChatMentionCandidates: ChatMentionCandidates = {}, ): MarkdownRules { if (Object.keys(overrideDefaultChatMentionCandidates).length > 0) { - return textMessageRules([], overrideDefaultChatMentionCandidates, false); + return textMessageRules( + [], + overrideDefaultChatMentionCandidates, + false, + defaultMembersMap, + ); } if (!defaultTextMessageRules) { - defaultTextMessageRules = textMessageRules([], {}, false); + defaultTextMessageRules = textMessageRules( + [], + {}, + false, + defaultMembersMap, + ); } return defaultTextMessageRules; } diff --git a/web/markdown/rules.react.js b/web/markdown/rules.react.js --- a/web/markdown/rules.react.js +++ b/web/markdown/rules.react.js @@ -169,12 +169,19 @@ chatMentionCandidates: ChatMentionCandidates, ): boolean => MarkdownRules { const { members } = threadInfo; + const membersMap = SharedMarkdown.useMemberMapForUserMentions(members); + return React.useMemo( () => _memoize<[boolean], MarkdownRules>((useDarkStyle: boolean) => - textMessageRules(members, chatMentionCandidates, useDarkStyle), + textMessageRules( + members, + chatMentionCandidates, + useDarkStyle, + membersMap, + ), ), - [chatMentionCandidates, members], + [chatMentionCandidates, members, membersMap], ); } @@ -182,9 +189,9 @@ members: $ReadOnlyArray, chatMentionCandidates: ChatMentionCandidates, useDarkStyle: boolean, + membersMap: $ReadOnlyMap, ): MarkdownRules { const baseRules = markdownRules(useDarkStyle); - const membersMap = SharedMarkdown.createMemberMapForUserMentions(members); return { ...baseRules, @@ -232,15 +239,26 @@ } let defaultTextMessageRules = null; +const defaultMembersMap = new Map(); function getDefaultTextMessageRules( overrideDefaultChatMentionCandidates: ChatMentionCandidates = {}, ): MarkdownRules { if (Object.keys(overrideDefaultChatMentionCandidates).length > 0) { - return textMessageRules([], overrideDefaultChatMentionCandidates, false); + return textMessageRules( + [], + overrideDefaultChatMentionCandidates, + false, + defaultMembersMap, + ); } if (!defaultTextMessageRules) { - defaultTextMessageRules = textMessageRules([], {}, false); + defaultTextMessageRules = textMessageRules( + [], + {}, + false, + defaultMembersMap, + ); } return defaultTextMessageRules; }