Page MenuHomePhabricator

D8833.id30613.diff
No OneTemporary

D8833.id30613.diff

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
@@ -77,6 +77,9 @@
type ClientNewThreadRequest,
type NewThreadResult,
type ChangeThreadSettingsPayload,
+ type ResolvedThreadInfo,
+ type ChatMentionCandidatesObj,
+ type ChatMentionCandidates,
} from '../types/thread-types.js';
import { updateTypes } from '../types/update-types-enum.js';
import { type ClientUpdateInfo } from '../types/update-types.js';
@@ -92,6 +95,7 @@
} from '../utils/action-utils.js';
import type { DispatchActionPromise } from '../utils/action-utils.js';
import type { GetENSNames } from '../utils/ens-helpers.js';
+import { useResolvedThreadInfosObj } from '../utils/entity-helpers.js';
import {
ET,
entityTextToRawString,
@@ -1621,6 +1625,154 @@
} within this ${communityOrThreadNoun(threadInfo)}`;
}
+function getChatMentionCandidates(threadInfos: {
+ +[id: string]: ResolvedThreadInfo,
+}): {
+ chatMentionCandidatesObj: ChatMentionCandidatesObj,
+ communityThreadIDForGenesisThreads: { +[id: string]: string },
+} {
+ const result = {};
+ const visitedGenesisThreads = new Set();
+ const communityThreadIDForGenesisThreads = {};
+ for (const currentThreadID in threadInfos) {
+ const currentThreadInfo = threadInfos[currentThreadID];
+ const { community: currentThreadCommunity } = currentThreadInfo;
+ if (!currentThreadCommunity) {
+ if (!result[currentThreadID]) {
+ result[currentThreadID] = { [currentThreadID]: currentThreadInfo };
+ }
+ continue;
+ }
+ if (!result[currentThreadCommunity]) {
+ result[currentThreadCommunity] = {
+ [currentThreadCommunity]: threadInfos[currentThreadCommunity],
+ };
+ }
+ // Handle GENESIS community case: mentioning inside GENESIS should only
+ // show chats and threads inside the top level that is below GENESIS.
+ if (threadInfos[currentThreadCommunity].type === threadTypes.GENESIS) {
+ if (visitedGenesisThreads.has(currentThreadID)) {
+ continue;
+ }
+ const threadTraversePath = [currentThreadInfo];
+ visitedGenesisThreads.add(currentThreadID);
+ let currentlySelectedThreadID = currentThreadInfo.parentThreadID;
+ while (currentlySelectedThreadID) {
+ const currentlySelectedThreadInfo =
+ threadInfos[currentlySelectedThreadID];
+ if (
+ visitedGenesisThreads.has(currentlySelectedThreadID) ||
+ !currentlySelectedThreadInfo ||
+ currentlySelectedThreadInfo.type === threadTypes.GENESIS
+ ) {
+ break;
+ }
+ threadTraversePath.push(currentlySelectedThreadInfo);
+ visitedGenesisThreads.add(currentlySelectedThreadID);
+ currentlySelectedThreadID = currentlySelectedThreadInfo.parentThreadID;
+ }
+ const lastThreadInTraversePath =
+ threadTraversePath[threadTraversePath.length - 1];
+ let lastThreadInTraversePathParentID;
+ if (lastThreadInTraversePath.parentThreadID) {
+ lastThreadInTraversePathParentID = threadInfos[
+ lastThreadInTraversePath.parentThreadID
+ ]
+ ? lastThreadInTraversePath.parentThreadID
+ : lastThreadInTraversePath.id;
+ } else {
+ lastThreadInTraversePathParentID = lastThreadInTraversePath.id;
+ }
+ if (
+ threadInfos[lastThreadInTraversePathParentID].type ===
+ threadTypes.GENESIS
+ ) {
+ if (!result[lastThreadInTraversePath.id]) {
+ result[lastThreadInTraversePath.id] = {};
+ }
+ for (const threadInfo of threadTraversePath) {
+ result[lastThreadInTraversePath.id][threadInfo.id] = threadInfo;
+ communityThreadIDForGenesisThreads[threadInfo.id] =
+ lastThreadInTraversePath.id;
+ }
+ } else {
+ if (
+ !communityThreadIDForGenesisThreads[lastThreadInTraversePathParentID]
+ ) {
+ result[lastThreadInTraversePathParentID] = {};
+ communityThreadIDForGenesisThreads[lastThreadInTraversePathParentID] =
+ lastThreadInTraversePathParentID;
+ }
+ const lastThreadInTraversePathParentCommunityThreadID =
+ communityThreadIDForGenesisThreads[lastThreadInTraversePathParentID];
+ for (const threadInfo of threadTraversePath) {
+ result[lastThreadInTraversePathParentCommunityThreadID][
+ threadInfo.id
+ ] = threadInfo;
+ communityThreadIDForGenesisThreads[threadInfo.id] =
+ lastThreadInTraversePathParentCommunityThreadID;
+ }
+ }
+ continue;
+ }
+ result[currentThreadCommunity][currentThreadID] = currentThreadInfo;
+ }
+ return {
+ chatMentionCandidatesObj: result,
+ communityThreadIDForGenesisThreads,
+ };
+}
+
+function useChatMentionCandidatesObjAndUtils(): {
+ chatMentionCandidatesObj: ChatMentionCandidatesObj,
+ resolvedThreadInfos: ChatMentionCandidates,
+ communityThreadIDForGenesisThreads: { +[id: string]: string },
+} {
+ const threadInfos = useSelector(threadInfoSelector);
+ const resolvedThreadInfos = useResolvedThreadInfosObj(threadInfos);
+ const { chatMentionCandidatesObj, communityThreadIDForGenesisThreads } =
+ React.useMemo(
+ () => getChatMentionCandidates(resolvedThreadInfos),
+ [resolvedThreadInfos],
+ );
+ return {
+ chatMentionCandidatesObj,
+ resolvedThreadInfos,
+ communityThreadIDForGenesisThreads,
+ };
+}
+
+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,
+ ]);
+}
+
export {
threadHasPermission,
viewerIsMember,
@@ -1689,4 +1841,6 @@
useRoleMemberCountsForCommunity,
useRoleUserSurfacedPermissions,
getThreadsToDeleteText,
+ useChatMentionCandidatesObj,
+ useThreadChatMentionCandidates,
};
diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js
--- a/lib/types/thread-types.js
+++ b/lib/types/thread-types.js
@@ -456,3 +456,8 @@
export const maxUnreadSidebars = 5;
export type ThreadStoreThreadInfos = { +[id: string]: RawThreadInfo };
+
+export type ChatMentionCandidates = { +[id: string]: ResolvedThreadInfo };
+export type ChatMentionCandidatesObj = {
+ +[id: string]: ChatMentionCandidates,
+};

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 6, 9:26 AM (22 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2248286
Default Alt Text
D8833.id30613.diff (7 KB)

Event Timeline