diff --git a/lib/components/chat-mention-context.react.js b/lib/components/chat-mention-context.react.js
new file mode 100644
--- /dev/null
+++ b/lib/components/chat-mention-context.react.js
@@ -0,0 +1,111 @@
+// @flow
+
+import invariant from 'invariant';
+import * as React from 'react';
+
+import genesis from '../facts/genesis.js';
+import SentencePrefixSearchIndex from '../shared/sentence-prefix-search-index.js';
+import {
+ useChatMentionCandidatesObjAndUtils,
+ useChatMentionSearchIndex,
+} from '../shared/thread-utils.js';
+import type {
+ ChatMentionCandidates,
+ ChatMentionCandidatesObj,
+ ThreadInfo,
+} from '../types/thread-types.js';
+
+type Props = {
+ +children: React.Node,
+};
+type ChatMentionContextType = {
+ +getChatMentionSearchIndex: (
+ threadInfo: ThreadInfo,
+ ) => SentencePrefixSearchIndex,
+ communityThreadIDForGenesisThreads: { +[id: string]: string },
+ chatMentionCandidatesObj: ChatMentionCandidatesObj,
+};
+
+const emptySearchIndex = new SentencePrefixSearchIndex();
+const ChatMentionContext: React.Context =
+ React.createContext({
+ getChatMentionSearchIndex: () => emptySearchIndex,
+ communityThreadIDForGenesisThreads: {},
+ chatMentionCandidatesObj: {},
+ });
+
+function ChatMentionProvider(props: Props): React.Node {
+ const { children } = props;
+
+ const { communityThreadIDForGenesisThreads, chatMentionCandidatesObj } =
+ useChatMentionCandidatesObjAndUtils();
+ const searchIndices = useChatMentionSearchIndex(chatMentionCandidatesObj);
+
+ const getChatMentionSearchIndex = React.useCallback(
+ (threadInfo: ThreadInfo) => {
+ if (threadInfo.community === genesis.id) {
+ return searchIndices[communityThreadIDForGenesisThreads[threadInfo.id]];
+ }
+ return searchIndices[threadInfo.community ?? threadInfo.id];
+ },
+ [communityThreadIDForGenesisThreads, searchIndices],
+ );
+
+ const value = React.useMemo(
+ () => ({
+ getChatMentionSearchIndex,
+ communityThreadIDForGenesisThreads,
+ chatMentionCandidatesObj,
+ }),
+ [
+ getChatMentionSearchIndex,
+ communityThreadIDForGenesisThreads,
+ chatMentionCandidatesObj,
+ ],
+ );
+
+ return (
+
+ {children}
+
+ );
+}
+
+function useChatMentionContext(): ChatMentionContextType {
+ const context = React.useContext(ChatMentionContext);
+ invariant(context, 'ChatMentionContext not found');
+
+ return context;
+}
+
+function useThreadChatMentionCandidates(
+ threadInfo: ThreadInfo,
+): ChatMentionCandidates {
+ const { communityThreadIDForGenesisThreads, chatMentionCandidatesObj } =
+ useChatMentionContext();
+ return React.useMemo(() => {
+ let communityID,
+ result = {};
+ if (threadInfo.community === genesis.id) {
+ communityID = communityThreadIDForGenesisThreads[threadInfo.id];
+ } else {
+ communityID = threadInfo.community ?? threadInfo.id;
+ }
+ if (chatMentionCandidatesObj[communityID]) {
+ result = { ...chatMentionCandidatesObj[communityID] };
+ }
+ delete result[threadInfo.id];
+ return result;
+ }, [
+ chatMentionCandidatesObj,
+ communityThreadIDForGenesisThreads,
+ threadInfo.community,
+ threadInfo.id,
+ ]);
+}
+
+export {
+ ChatMentionProvider,
+ useChatMentionContext,
+ useThreadChatMentionCandidates,
+};
diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js
--- a/lib/shared/thread-utils.js
+++ b/lib/shared/thread-utils.js
@@ -1763,37 +1763,6 @@
};
}
-function useChatMentionCandidatesObj(): ChatMentionCandidatesObj {
- const { chatMentionCandidatesObj } = useChatMentionCandidatesObjAndUtils();
- return chatMentionCandidatesObj;
-}
-
-function useThreadChatMentionCandidates(
- threadInfo: ThreadInfo,
-): ChatMentionCandidates {
- const { chatMentionCandidatesObj, communityThreadIDForGenesisThreads } =
- useChatMentionCandidatesObjAndUtils();
- return React.useMemo(() => {
- let communityID,
- result = {};
- if (threadInfo.community === genesis.id) {
- communityID = communityThreadIDForGenesisThreads[threadInfo.id];
- } else {
- communityID = threadInfo.community ?? threadInfo.id;
- }
- if (chatMentionCandidatesObj[communityID]) {
- result = { ...chatMentionCandidatesObj[communityID] };
- }
- delete result[threadInfo.id];
- return result;
- }, [
- chatMentionCandidatesObj,
- communityThreadIDForGenesisThreads,
- threadInfo.community,
- threadInfo.id,
- ]);
-}
-
function useUserProfileThreadInfo(userInfo: ?UserInfo): ?UserProfileThreadInfo {
const userID = userInfo?.id;
const username = userInfo?.username;
@@ -1852,10 +1821,11 @@
]);
}
-function useChatMentionSearchIndex(): {
+function useChatMentionSearchIndex(
+ chatMentionCandidatesObj: ChatMentionCandidatesObj,
+): {
+[id: string]: SentencePrefixSearchIndex,
} {
- const { chatMentionCandidatesObj } = useChatMentionCandidatesObjAndUtils();
return React.useMemo(() => {
const result = {};
for (const communityThreadID in chatMentionCandidatesObj) {
@@ -1880,22 +1850,6 @@
}, [chatMentionCandidatesObj]);
}
-function useThreadChatMentionSearchIndex(
- threadInfo: ThreadInfo,
-): SentencePrefixSearchIndex {
- const chatMentionCandidatesSearchIndex = useChatMentionSearchIndex();
- const { communityThreadIDForGenesisThreads } =
- useChatMentionCandidatesObjAndUtils();
- if (threadInfo.community === genesis.id) {
- return chatMentionCandidatesSearchIndex[
- communityThreadIDForGenesisThreads[threadInfo.id]
- ];
- }
- return chatMentionCandidatesSearchIndex[
- threadInfo.community ?? threadInfo.id
- ];
-}
-
export {
threadHasPermission,
viewerIsMember,
@@ -1961,8 +1915,7 @@
useRoleMemberCountsForCommunity,
useRoleUserSurfacedPermissions,
getThreadsToDeleteText,
- useChatMentionCandidatesObj,
- useThreadChatMentionCandidates,
useUserProfileThreadInfo,
- useThreadChatMentionSearchIndex,
+ useChatMentionCandidatesObjAndUtils,
+ useChatMentionSearchIndex,
};
diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js
--- a/native/chat/chat-input-bar.react.js
+++ b/native/chat/chat-input-bar.react.js
@@ -31,6 +31,10 @@
joinThread,
newThreadActionTypes,
} from 'lib/actions/thread-actions.js';
+import {
+ useChatMentionContext,
+ useThreadChatMentionCandidates,
+} from 'lib/components/chat-mention-context.react.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import { threadInfoSelector } from 'lib/selectors/thread-selectors.js';
import { userStoreMentionSearchIndex } from 'lib/selectors/user-selectors.js';
@@ -58,8 +62,6 @@
threadActualMembers,
checkIfDefaultMembersAreVoiced,
draftKeyFromThreadID,
- useThreadChatMentionCandidates,
- useThreadChatMentionSearchIndex,
} from 'lib/shared/thread-utils.js';
import type { CalendarQuery } from 'lib/types/entry-types.js';
import type { LoadingStatus } from 'lib/types/loading-types.js';
@@ -1266,9 +1268,8 @@
const userSearchIndex = useSelector(userStoreMentionSearchIndex);
- const chatMentionSearchIndex = useThreadChatMentionSearchIndex(
- props.threadInfo,
- );
+ const { getChatMentionSearchIndex } = useChatMentionContext();
+ const chatMentionSearchIndex = getChatMentionSearchIndex(props.threadInfo);
const { parentThreadID } = props.threadInfo;
const parentThreadInfo = useSelector(state =>
diff --git a/native/chat/message-list-types.js b/native/chat/message-list-types.js
--- a/native/chat/message-list-types.js
+++ b/native/chat/message-list-types.js
@@ -4,7 +4,7 @@
import invariant from 'invariant';
import * as React from 'react';
-import { useThreadChatMentionCandidates } from 'lib/shared/thread-utils.js';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
import { type UserInfo } from 'lib/types/user-types.js';
diff --git a/native/chat/message-preview.react.js b/native/chat/message-preview.react.js
--- a/native/chat/message-preview.react.js
+++ b/native/chat/message-preview.react.js
@@ -4,8 +4,8 @@
import * as React from 'react';
import { Text } from 'react-native';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
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';
diff --git a/native/chat/sidebar-input-bar-height-measurer.react.js b/native/chat/sidebar-input-bar-height-measurer.react.js
--- a/native/chat/sidebar-input-bar-height-measurer.react.js
+++ b/native/chat/sidebar-input-bar-height-measurer.react.js
@@ -3,8 +3,8 @@
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js';
-import { useThreadChatMentionCandidates } from 'lib/shared/thread-utils.js';
import { DummyChatInputBar } from './chat-input-bar.react.js';
import { useMessageListScreenWidth } from './composed-message-width.js';
diff --git a/native/chat/sidebar-navigation.js b/native/chat/sidebar-navigation.js
--- a/native/chat/sidebar-navigation.js
+++ b/native/chat/sidebar-navigation.js
@@ -3,12 +3,12 @@
import invariant from 'invariant';
import * as React from 'react';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
import { ENSCacheContext } from 'lib/components/ens-cache-provider.react.js';
import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js';
import {
createPendingSidebar,
createUnresolvedPendingSidebar,
- useThreadChatMentionCandidates,
} from 'lib/shared/thread-utils.js';
import type {
ThreadInfo,
diff --git a/native/chat/utils.js b/native/chat/utils.js
--- a/native/chat/utils.js
+++ b/native/chat/utils.js
@@ -4,13 +4,11 @@
import * as React from 'react';
import Animated from 'react-native-reanimated';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js';
import { colorIsDark } from 'lib/shared/color-utils.js';
import { messageKey } from 'lib/shared/message-utils.js';
-import {
- viewerIsMember,
- useThreadChatMentionCandidates,
-} from 'lib/shared/thread-utils.js';
+import { viewerIsMember } from 'lib/shared/thread-utils.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
import { clusterEndHeight } from './chat-constants.js';
diff --git a/native/root.react.js b/native/root.react.js
--- a/native/root.react.js
+++ b/native/root.react.js
@@ -19,6 +19,7 @@
import { Provider } from 'react-redux';
import { PersistGate as ReduxPersistGate } from 'redux-persist/es/integration/react.js';
+import { ChatMentionProvider } from 'lib/components/chat-mention-context.react.js';
import { EditUserAvatarProvider } from 'lib/components/edit-user-avatar-provider.react.js';
import { ENSCacheProvider } from 'lib/components/ens-cache-provider.react.js';
import IntegrityHandler from 'lib/components/integrity-handler.react.js';
@@ -259,7 +260,9 @@
-
+
+
+
diff --git a/web/chat/chat-input-bar.react.js b/web/chat/chat-input-bar.react.js
--- a/web/chat/chat-input-bar.react.js
+++ b/web/chat/chat-input-bar.react.js
@@ -9,6 +9,10 @@
joinThread,
newThreadActionTypes,
} from 'lib/actions/thread-actions.js';
+import {
+ useChatMentionContext,
+ useThreadChatMentionCandidates,
+} from 'lib/components/chat-mention-context.react.js';
import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import { threadInfoSelector } from 'lib/selectors/thread-selectors.js';
@@ -28,8 +32,6 @@
threadFrozenDueToViewerBlock,
threadActualMembers,
checkIfDefaultMembersAreVoiced,
- useThreadChatMentionCandidates,
- useThreadChatMentionSearchIndex,
} from 'lib/shared/thread-utils.js';
import type { CalendarQuery } from 'lib/types/entry-types.js';
import type { LoadingStatus } from 'lib/types/loading-types.js';
@@ -581,9 +583,8 @@
const dispatchActionPromise = useDispatchActionPromise();
const callJoinThread = useServerCall(joinThread);
const userSearchIndex = useSelector(userStoreMentionSearchIndex);
- const chatMentionSearchIndex = useThreadChatMentionSearchIndex(
- props.threadInfo,
- );
+ const { getChatMentionSearchIndex } = useChatMentionContext();
+ const chatMentionSearchIndex = getChatMentionSearchIndex(props.threadInfo);
const { parentThreadID } = props.threadInfo;
const parentThreadInfo = useSelector(state =>
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
@@ -12,6 +12,7 @@
fetchMostRecentMessagesActionTypes,
fetchMostRecentMessages,
} from 'lib/actions/message-actions.js';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
import { useOldestMessageServerID } from 'lib/hooks/message-hooks.js';
import { registerFetchKey } from 'lib/reducers/loading-reducer.js';
import {
@@ -19,10 +20,7 @@
useMessageListData,
} from 'lib/selectors/chat-selectors.js';
import { messageKey } from 'lib/shared/message-utils.js';
-import {
- threadIsPending,
- useThreadChatMentionCandidates,
-} from 'lib/shared/thread-utils.js';
+import { threadIsPending } 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';
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
@@ -4,8 +4,8 @@
import invariant from 'invariant';
import * as React from 'react';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
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';
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
@@ -3,9 +3,9 @@
import classNames from 'classnames';
import * as React from 'react';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
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';
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
@@ -3,10 +3,10 @@
import classNames from 'classnames';
import * as React from 'react';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
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';
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
@@ -3,10 +3,10 @@
import classNames from 'classnames';
import * as React from 'react';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
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';
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
@@ -5,12 +5,12 @@
import { useDispatch } from 'react-redux';
import { createSelector } from 'reselect';
+import { useThreadChatMentionCandidates } from 'lib/components/chat-mention-context.react.js';
import { ENSCacheContext } from 'lib/components/ens-cache-provider.react.js';
import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js';
import {
createPendingSidebar,
threadInHomeChatList,
- useThreadChatMentionCandidates,
} from 'lib/shared/thread-utils.js';
import type {
ComposableMessageInfo,