diff --git a/lib/hooks/search-threads.js b/lib/hooks/search-threads.js --- a/lib/hooks/search-threads.js +++ b/lib/hooks/search-threads.js @@ -2,12 +2,12 @@ import * as React from 'react'; +import { useSidebarInfos } from './sidebar-hooks.js'; import { type ChatThreadItem, useFilteredChatListData, } from '../selectors/chat-selectors.js'; import { useThreadSearchIndex } from '../selectors/nav-selectors.js'; -import { sidebarInfoSelector } from '../selectors/sidebar-selectors.js'; import { threadIsChannel } from '../shared/thread-utils.js'; import type { SetState } from '../types/hook-types.js'; import type { @@ -15,7 +15,6 @@ RawThreadInfo, } from '../types/minimally-encoded-thread-permissions-types.js'; import type { SidebarInfo } from '../types/thread-types.js'; -import { useSelector } from '../utils/redux-utils.js'; export type ThreadSearchState = { +text: string, @@ -90,12 +89,13 @@ ); } +const emptyArray: $ReadOnlyArray = []; + function useSearchSidebars( threadInfo: ThreadInfo, ): SearchThreadsResult { - const childThreadInfos = useSelector( - state => sidebarInfoSelector(state)[threadInfo.id] ?? [], - ); + const sidebarsByParentID = useSidebarInfos(); + const childThreadInfos = sidebarsByParentID[threadInfo.id] ?? emptyArray; return useSearchThreads(threadInfo, childThreadInfos); } diff --git a/lib/hooks/sidebar-hooks.js b/lib/hooks/sidebar-hooks.js new file mode 100644 --- /dev/null +++ b/lib/hooks/sidebar-hooks.js @@ -0,0 +1,67 @@ +// @flow + +import _orderBy from 'lodash/fp/orderBy.js'; +import * as React from 'react'; + +import { childThreadInfos } from '../selectors/thread-selectors.js'; +import { getMostRecentNonLocalMessageID } from '../shared/message-utils.js'; +import { threadInChatList } from '../shared/thread-utils.js'; +import type { MessageStore, RawMessageInfo } from '../types/message-types.js'; +import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; +import { threadTypeIsSidebar } from '../types/thread-types-enum.js'; +import type { SidebarInfo } from '../types/thread-types.js'; +import { useSelector } from '../utils/redux-utils.js'; + +function getMostRecentRawMessageInfo( + threadInfo: ThreadInfo, + messageStore: MessageStore, +): ?RawMessageInfo { + const thread = messageStore.threads[threadInfo.id]; + if (!thread) { + return null; + } + for (const messageID of thread.messageIDs) { + return messageStore.messages[messageID]; + } + return null; +} + +function useSidebarInfos(): { +[id: string]: $ReadOnlyArray } { + const childThreadInfoByParentID = useSelector(childThreadInfos); + const messageStore = useSelector(state => state.messageStore); + + return React.useMemo(() => { + const result: { [id: string]: $ReadOnlyArray } = {}; + for (const parentID in childThreadInfoByParentID) { + const childThreads = childThreadInfoByParentID[parentID]; + const sidebarInfos = []; + for (const childThreadInfo of childThreads) { + if ( + !threadInChatList(childThreadInfo) || + !threadTypeIsSidebar(childThreadInfo.type) + ) { + continue; + } + const mostRecentRawMessageInfo = getMostRecentRawMessageInfo( + childThreadInfo, + messageStore, + ); + const lastUpdatedTime = + mostRecentRawMessageInfo?.time ?? childThreadInfo.creationTime; + const mostRecentNonLocalMessage = getMostRecentNonLocalMessageID( + childThreadInfo.id, + messageStore, + ); + sidebarInfos.push({ + threadInfo: childThreadInfo, + lastUpdatedTime, + mostRecentNonLocalMessage, + }); + } + result[parentID] = _orderBy('lastUpdatedTime')('desc')(sidebarInfos); + } + return result; + }, [childThreadInfoByParentID, messageStore]); +} + +export { useSidebarInfos }; diff --git a/lib/selectors/chat-selectors.js b/lib/selectors/chat-selectors.js --- a/lib/selectors/chat-selectors.js +++ b/lib/selectors/chat-selectors.js @@ -13,7 +13,7 @@ threadInfoFromSourceMessageIDSelector, threadInfoSelector, } from './thread-selectors.js'; -import { sidebarInfoSelector } from '../selectors/sidebar-selectors.js'; +import { useSidebarInfos } from '../hooks/sidebar-hooks.js'; import { createMessageInfo, getMostRecentNonLocalMessageID, @@ -113,7 +113,7 @@ function useCreateChatThreadItem(): ThreadInfo => ChatThreadItem { const messageInfos = useSelector(messageInfoSelector); - const sidebarInfos = useSelector(sidebarInfoSelector); + const sidebarInfos = useSidebarInfos(); const messageStore = useSelector(state => state.messageStore); return React.useCallback( threadInfo => { diff --git a/lib/selectors/sidebar-selectors.js b/lib/selectors/sidebar-selectors.js deleted file mode 100644 --- a/lib/selectors/sidebar-selectors.js +++ /dev/null @@ -1,63 +0,0 @@ -// @flow - -import _orderBy from 'lodash/fp/orderBy.js'; -import { createObjectSelector } from 'reselect-map'; - -import { childThreadInfos } from './thread-selectors.js'; -import { getMostRecentNonLocalMessageID } from '../shared/message-utils.js'; -import { threadInChatList } from '../shared/thread-utils.js'; -import type { MessageStore, RawMessageInfo } from '../types/message-types.js'; -import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; -import type { BaseAppState } from '../types/redux-types.js'; -import { threadTypeIsSidebar } from '../types/thread-types-enum.js'; -import type { SidebarInfo } from '../types/thread-types.js'; - -function getMostRecentRawMessageInfo( - threadInfo: ThreadInfo, - messageStore: MessageStore, -): ?RawMessageInfo { - const thread = messageStore.threads[threadInfo.id]; - if (!thread) { - return null; - } - for (const messageID of thread.messageIDs) { - return messageStore.messages[messageID]; - } - return null; -} - -const sidebarInfoSelector: (state: BaseAppState<>) => { - +[id: string]: $ReadOnlyArray, -} = createObjectSelector( - childThreadInfos, - (state: BaseAppState<>) => state.messageStore, - (childThreads: $ReadOnlyArray, messageStore: MessageStore) => { - const sidebarInfos = []; - for (const childThreadInfo of childThreads) { - if ( - !threadInChatList(childThreadInfo) || - !threadTypeIsSidebar(childThreadInfo.type) - ) { - continue; - } - const mostRecentRawMessageInfo = getMostRecentRawMessageInfo( - childThreadInfo, - messageStore, - ); - const lastUpdatedTime = - mostRecentRawMessageInfo?.time ?? childThreadInfo.creationTime; - const mostRecentNonLocalMessage = getMostRecentNonLocalMessageID( - childThreadInfo.id, - messageStore, - ); - sidebarInfos.push({ - threadInfo: childThreadInfo, - lastUpdatedTime, - mostRecentNonLocalMessage, - }); - } - return _orderBy('lastUpdatedTime')('desc')(sidebarInfos); - }, -); - -export { sidebarInfoSelector };