diff --git a/web/chat/chat-message-list.react.js b/web/chat/chat-message-list.react.js --- a/web/chat/chat-message-list.react.js +++ b/web/chat/chat-message-list.react.js @@ -19,7 +19,10 @@ useMessageListData, } from 'lib/selectors/chat-selectors.js'; import { messageKey } from 'lib/shared/message-utils.js'; -import { threadIsPending } from 'lib/shared/thread-utils.js'; +import { + threadIsPending, + useThreadChatMentionCandidates, +} from 'lib/shared/thread-utils.js'; import type { FetchMessageInfosPayload } from 'lib/types/message-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import { type ThreadInfo } from 'lib/types/thread-types.js'; @@ -437,7 +440,11 @@ const { clearTooltip } = useTooltipContext(); - const getTextMessageMarkdownRules = useTextMessageRulesFunc(threadInfo); + const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); + const getTextMessageMarkdownRules = useTextMessageRulesFunc( + threadInfo, + chatMentionCandidates, + ); const messageListContext = React.useMemo(() => { if (!getTextMessageMarkdownRules) { return undefined; diff --git a/web/chat/message-preview.react.js b/web/chat/message-preview.react.js --- a/web/chat/message-preview.react.js +++ b/web/chat/message-preview.react.js @@ -5,6 +5,7 @@ import * as React from 'react'; import { useMessagePreview } from 'lib/shared/message-utils.js'; +import { useThreadChatMentionCandidates } from 'lib/shared/thread-utils.js'; import { type MessageInfo } from 'lib/types/message-types.js'; import { type ThreadInfo } from 'lib/types/thread-types.js'; @@ -17,10 +18,11 @@ }; function MessagePreview(props: Props): React.Node { const { messageInfo, threadInfo } = props; + const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); const messagePreviewResult = useMessagePreview( messageInfo, threadInfo, - getDefaultTextMessageRules().simpleMarkdownRules, + getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules, ); if (!messageInfo) { diff --git a/web/components/message-result.react.js b/web/components/message-result.react.js --- a/web/components/message-result.react.js +++ b/web/components/message-result.react.js @@ -5,6 +5,7 @@ import { useStringForUser } from 'lib/hooks/ens-cache.js'; import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js'; +import { useThreadChatMentionCandidates } from 'lib/shared/thread-utils.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; import { longAbsoluteDate } from 'lib/utils/date-utils.js'; @@ -22,7 +23,11 @@ function MessageResult(props: MessageResultProps): React.Node { const { item, threadInfo, scrollable } = props; - const getTextMessageMarkdownRules = useTextMessageRulesFunc(threadInfo); + const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); + const getTextMessageMarkdownRules = useTextMessageRulesFunc( + threadInfo, + chatMentionCandidates, + ); const messageListContext = React.useMemo(() => { if (!getTextMessageMarkdownRules) { return undefined; 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 @@ -5,7 +5,11 @@ import * as SimpleMarkdown from 'simple-markdown'; import * as SharedMarkdown from 'lib/shared/markdown.js'; -import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types.js'; +import type { + RelativeMemberInfo, + ThreadInfo, + ChatMentionCandidates, +} from 'lib/types/thread-types.js'; import MarkdownSpoiler from './markdown-spoiler.react.js'; @@ -159,19 +163,21 @@ function useTextMessageRulesFunc( threadInfo: ThreadInfo, + chatMentionCandidates: ChatMentionCandidates, ): boolean => MarkdownRules { const { members } = threadInfo; return React.useMemo( () => _memoize<[boolean], MarkdownRules>((useDarkStyle: boolean) => - textMessageRules(members, useDarkStyle), + textMessageRules(members, chatMentionCandidates, useDarkStyle), ), - [members], + [chatMentionCandidates, members], ); } function textMessageRules( members: $ReadOnlyArray, + chatMentionCandidates: ChatMentionCandidates, useDarkStyle: boolean, ): MarkdownRules { const baseRules = markdownRules(useDarkStyle); @@ -198,11 +204,16 @@ let defaultTextMessageRules = null; -function getDefaultTextMessageRules(): MarkdownRules { - if (!defaultTextMessageRules) { - defaultTextMessageRules = textMessageRules([], false); +function getDefaultTextMessageRules( + overrideDefaultChatMentionCandidates: ChatMentionCandidates = {}, +): MarkdownRules { + if (Object.keys(overrideDefaultChatMentionCandidates).length === 0) { + if (!defaultTextMessageRules) { + defaultTextMessageRules = textMessageRules([], {}, false); + } + return defaultTextMessageRules; } - return defaultTextMessageRules; + return textMessageRules([], overrideDefaultChatMentionCandidates, false); } export { linkRules, useTextMessageRulesFunc, getDefaultTextMessageRules }; diff --git a/web/modals/threads/sidebars/sidebar.react.js b/web/modals/threads/sidebars/sidebar.react.js --- a/web/modals/threads/sidebars/sidebar.react.js +++ b/web/modals/threads/sidebars/sidebar.react.js @@ -6,6 +6,7 @@ import { useModalContext } from 'lib/components/modal-provider.react.js'; import type { ChatThreadItem } from 'lib/selectors/chat-selectors.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; +import { useThreadChatMentionCandidates } from 'lib/shared/thread-utils.js'; import { shortAbsoluteDate } from 'lib/utils/date-utils.js'; import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; @@ -52,10 +53,11 @@ [lastUpdatedTime], ); + const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); const messagePreviewResult = useMessagePreview( mostRecentMessageInfo, threadInfo, - getDefaultTextMessageRules().simpleMarkdownRules, + getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules, ); const lastMessage = React.useMemo(() => { diff --git a/web/modals/threads/subchannels/subchannel.react.js b/web/modals/threads/subchannels/subchannel.react.js --- a/web/modals/threads/subchannels/subchannel.react.js +++ b/web/modals/threads/subchannels/subchannel.react.js @@ -6,6 +6,7 @@ import { useModalContext } from 'lib/components/modal-provider.react.js'; import { type ChatThreadItem } from 'lib/selectors/chat-selectors.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; +import { useThreadChatMentionCandidates } from 'lib/shared/thread-utils.js'; import { shortAbsoluteDate } from 'lib/utils/date-utils.js'; import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; @@ -50,11 +51,11 @@ () => shortAbsoluteDate(lastUpdatedTimeIncludingSidebars), [lastUpdatedTimeIncludingSidebars], ); - + const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); const messagePreviewResult = useMessagePreview( mostRecentMessageInfo, threadInfo, - getDefaultTextMessageRules().simpleMarkdownRules, + getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules, ); const lastMessage = React.useMemo(() => { diff --git a/web/selectors/thread-selectors.js b/web/selectors/thread-selectors.js --- a/web/selectors/thread-selectors.js +++ b/web/selectors/thread-selectors.js @@ -10,6 +10,7 @@ import { createPendingSidebar, threadInHomeChatList, + useThreadChatMentionCandidates, } from 'lib/shared/thread-utils.js'; import type { ComposableMessageInfo, @@ -72,6 +73,7 @@ const cacheContext = React.useContext(ENSCacheContext); const { getENSNames } = cacheContext; + const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); return React.useCallback( async (event: SyntheticEvent) => { event.preventDefault(); @@ -82,7 +84,8 @@ sourceMessageInfo: messageInfo, parentThreadInfo: threadInfo, loggedInUserInfo, - markdownRules: getDefaultTextMessageRules().simpleMarkdownRules, + markdownRules: getDefaultTextMessageRules(chatMentionCandidates) + .simpleMarkdownRules, getENSNames, }); dispatch({ @@ -93,7 +96,14 @@ }, }); }, - [loggedInUserInfo, messageInfo, threadInfo, dispatch, getENSNames], + [ + loggedInUserInfo, + chatMentionCandidates, + threadInfo, + messageInfo, + getENSNames, + dispatch, + ], ); }