Changeset View
Changeset View
Standalone View
Standalone View
lib/components/chat-mention-provider.react.js
Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | function ChatMentionContextProvider(props: Props): React.Node { | ||||
return ( | return ( | ||||
<ChatMentionContext.Provider value={value}> | <ChatMentionContext.Provider value={value}> | ||||
{children} | {children} | ||||
</ChatMentionContext.Provider> | </ChatMentionContext.Provider> | ||||
); | ); | ||||
} | } | ||||
function getChatMentionCandidates(threadInfos: { | function getChatMentionCandidates(resolvedThreadInfos: { | ||||
+[id: string]: ResolvedThreadInfo, | +[id: string]: ResolvedThreadInfo, | ||||
}): { | }): { | ||||
chatMentionCandidatesObj: ChatMentionCandidatesObj, | chatMentionCandidatesObj: ChatMentionCandidatesObj, | ||||
communityThreadIDForGenesisThreads: { +[id: string]: string }, | communityThreadIDForGenesisThreads: { +[id: string]: string }, | ||||
} { | } { | ||||
const result: { | const result: { | ||||
[string]: { | [string]: { | ||||
[string]: ResolvedThreadInfo, | [string]: ResolvedThreadInfo, | ||||
}, | }, | ||||
} = {}; | } = {}; | ||||
const visitedGenesisThreads = new Set<string>(); | const visitedGenesisThreads = new Set<string>(); | ||||
const communityThreadIDForGenesisThreads: { [string]: string } = {}; | const communityThreadIDForGenesisThreads: { [string]: string } = {}; | ||||
for (const currentThreadID in threadInfos) { | for (const currentThreadID in resolvedThreadInfos) { | ||||
const currentThreadInfo = threadInfos[currentThreadID]; | const currentResolvedThreadInfo = resolvedThreadInfos[currentThreadID]; | ||||
const { community: currentThreadCommunity } = currentThreadInfo; | const { community: currentThreadCommunity } = currentResolvedThreadInfo; | ||||
if (!currentThreadCommunity) { | if (!currentThreadCommunity) { | ||||
if (!result[currentThreadID]) { | if (!result[currentThreadID]) { | ||||
result[currentThreadID] = { [currentThreadID]: currentThreadInfo }; | result[currentThreadID] = { | ||||
[currentThreadID]: currentResolvedThreadInfo, | |||||
}; | |||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
if (!result[currentThreadCommunity]) { | if (!result[currentThreadCommunity]) { | ||||
result[currentThreadCommunity] = {}; | result[currentThreadCommunity] = {}; | ||||
result[currentThreadCommunity][currentThreadCommunity] = | result[currentThreadCommunity][currentThreadCommunity] = | ||||
threadInfos[currentThreadCommunity]; | resolvedThreadInfos[currentThreadCommunity]; | ||||
} | } | ||||
// Handle GENESIS community case: mentioning inside GENESIS should only | // Handle GENESIS community case: mentioning inside GENESIS should only | ||||
// show chats and threads inside the top level that is below GENESIS. | // show chats and threads inside the top level that is below GENESIS. | ||||
if (threadInfos[currentThreadCommunity].type === threadTypes.GENESIS) { | if ( | ||||
resolvedThreadInfos[currentThreadCommunity].type === threadTypes.GENESIS | |||||
) { | |||||
if (visitedGenesisThreads.has(currentThreadID)) { | if (visitedGenesisThreads.has(currentThreadID)) { | ||||
continue; | continue; | ||||
} | } | ||||
const threadTraversePath = [currentThreadInfo]; | const threadTraversePath = [currentResolvedThreadInfo]; | ||||
visitedGenesisThreads.add(currentThreadID); | visitedGenesisThreads.add(currentThreadID); | ||||
let currentlySelectedThreadID = currentThreadInfo.parentThreadID; | let currentlySelectedThreadID = currentResolvedThreadInfo.parentThreadID; | ||||
while (currentlySelectedThreadID) { | while (currentlySelectedThreadID) { | ||||
const currentlySelectedThreadInfo = | const currentlySelectedThreadInfo = | ||||
threadInfos[currentlySelectedThreadID]; | resolvedThreadInfos[currentlySelectedThreadID]; | ||||
if ( | if ( | ||||
visitedGenesisThreads.has(currentlySelectedThreadID) || | visitedGenesisThreads.has(currentlySelectedThreadID) || | ||||
!currentlySelectedThreadInfo || | !currentlySelectedThreadInfo || | ||||
currentlySelectedThreadInfo.type === threadTypes.GENESIS | currentlySelectedThreadInfo.type === threadTypes.GENESIS | ||||
) { | ) { | ||||
break; | break; | ||||
} | } | ||||
threadTraversePath.push(currentlySelectedThreadInfo); | threadTraversePath.push(currentlySelectedThreadInfo); | ||||
visitedGenesisThreads.add(currentlySelectedThreadID); | visitedGenesisThreads.add(currentlySelectedThreadID); | ||||
currentlySelectedThreadID = currentlySelectedThreadInfo.parentThreadID; | currentlySelectedThreadID = currentlySelectedThreadInfo.parentThreadID; | ||||
} | } | ||||
const lastThreadInTraversePath = | const lastThreadInTraversePath = | ||||
threadTraversePath[threadTraversePath.length - 1]; | threadTraversePath[threadTraversePath.length - 1]; | ||||
let lastThreadInTraversePathParentID; | let lastThreadInTraversePathParentID; | ||||
if (lastThreadInTraversePath.parentThreadID) { | if (lastThreadInTraversePath.parentThreadID) { | ||||
lastThreadInTraversePathParentID = threadInfos[ | lastThreadInTraversePathParentID = resolvedThreadInfos[ | ||||
lastThreadInTraversePath.parentThreadID | lastThreadInTraversePath.parentThreadID | ||||
] | ] | ||||
? lastThreadInTraversePath.parentThreadID | ? lastThreadInTraversePath.parentThreadID | ||||
: lastThreadInTraversePath.id; | : lastThreadInTraversePath.id; | ||||
} else { | } else { | ||||
lastThreadInTraversePathParentID = lastThreadInTraversePath.id; | lastThreadInTraversePathParentID = lastThreadInTraversePath.id; | ||||
} | } | ||||
if ( | if ( | ||||
threadInfos[lastThreadInTraversePathParentID].type === | resolvedThreadInfos[lastThreadInTraversePathParentID].type === | ||||
threadTypes.GENESIS | threadTypes.GENESIS | ||||
) { | ) { | ||||
if (!result[lastThreadInTraversePath.id]) { | if (!result[lastThreadInTraversePath.id]) { | ||||
result[lastThreadInTraversePath.id] = {}; | result[lastThreadInTraversePath.id] = {}; | ||||
} | } | ||||
for (const threadInfo of threadTraversePath) { | for (const threadInfo of threadTraversePath) { | ||||
result[lastThreadInTraversePath.id][threadInfo.id] = threadInfo; | result[lastThreadInTraversePath.id][threadInfo.id] = threadInfo; | ||||
communityThreadIDForGenesisThreads[threadInfo.id] = | communityThreadIDForGenesisThreads[threadInfo.id] = | ||||
Show All 21 Lines | ) { | ||||
threadInfo.id | threadInfo.id | ||||
] = threadInfo; | ] = threadInfo; | ||||
communityThreadIDForGenesisThreads[threadInfo.id] = | communityThreadIDForGenesisThreads[threadInfo.id] = | ||||
lastThreadInTraversePathParentCommunityThreadID; | lastThreadInTraversePathParentCommunityThreadID; | ||||
} | } | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
result[currentThreadCommunity][currentThreadID] = currentThreadInfo; | result[currentThreadCommunity][currentThreadID] = currentResolvedThreadInfo; | ||||
} | } | ||||
return { | return { | ||||
chatMentionCandidatesObj: result, | chatMentionCandidatesObj: result, | ||||
communityThreadIDForGenesisThreads, | communityThreadIDForGenesisThreads, | ||||
}; | }; | ||||
} | } | ||||
// Without allAtOnce, useChatMentionCandidatesObjAndUtils is very expensive. | // Without allAtOnce, useChatMentionCandidatesObjAndUtils is very expensive. | ||||
▲ Show 20 Lines • Show All 57 Lines • Show Last 20 Lines |