diff --git a/lib/hooks/child-threads.js b/lib/hooks/child-threads.js --- a/lib/hooks/child-threads.js +++ b/lib/hooks/child-threads.js @@ -102,14 +102,15 @@ ); }, [allSubchannelsList, searchResultIDs, searchTextExists]); + const messageStore = useSelector(state => state.messageStore); const threadIDsWithNoMessages = React.useMemo( () => new Set( filteredSubchannelsChatList - .filter(item => !item.mostRecentMessageInfo) - .map(item => item.threadInfo.id), + .map(item => item.threadInfo.id) + .filter(id => messageStore.threads[id]?.messageIDs.length === 0), ), - [filteredSubchannelsChatList], + [filteredSubchannelsChatList, messageStore], ); const dispatchActionPromise = useDispatchActionPromise(); const fetchSingleMostRecentMessages = diff --git a/lib/hooks/message-hooks.js b/lib/hooks/message-hooks.js --- a/lib/hooks/message-hooks.js +++ b/lib/hooks/message-hooks.js @@ -1,6 +1,11 @@ // @flow +import * as React from 'react'; + +import { messageInfoSelector } from '../selectors/chat-selectors.js'; import { getOldestNonLocalMessageID } from '../shared/message-utils.js'; +import type { MessageInfo } from '../types/message-types.js'; +import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { useSelector } from '../utils/redux-utils.js'; function useOldestMessageServerID(threadID: string): ?string { @@ -9,4 +14,42 @@ ); } -export { useOldestMessageServerID }; +function useGetMessageInfoForPreview(): ( + threadInfo: ThreadInfo, +) => Promise { + const messageInfos = useSelector(messageInfoSelector); + const messageStore = useSelector(state => state.messageStore); + return React.useCallback( + async threadInfo => { + const thread = messageStore.threads[threadInfo.id]; + if (!thread) { + return null; + } + for (const messageID of thread.messageIDs) { + const messageInfo = messageInfos[messageID]; + if (messageInfo) { + return messageInfo; + } + } + return null; + }, + [messageInfos, messageStore], + ); +} + +function useMessageInfoForPreview(threadInfo: ThreadInfo): ?MessageInfo { + const [messageInfo, setMessageInfo] = React.useState(); + + const getMessageInfoForPreview = useGetMessageInfoForPreview(); + React.useEffect(() => { + void (async () => { + const newMessageInfoForPreview = + await getMessageInfoForPreview(threadInfo); + setMessageInfo(newMessageInfoForPreview); + })(); + }, [threadInfo, getMessageInfoForPreview]); + + return messageInfo; +} + +export { useOldestMessageServerID, useMessageInfoForPreview }; 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 @@ -67,7 +67,6 @@ export type ChatThreadItem = { +type: 'chatThreadItem', +threadInfo: ThreadInfo, - +mostRecentMessageInfo: ?MessageInfo, +mostRecentNonLocalMessage: ?string, +lastUpdatedTime: number, +lastUpdatedTimeIncludingSidebars: number, @@ -196,7 +195,6 @@ return { type: 'chatThreadItem', threadInfo, - mostRecentMessageInfo, mostRecentNonLocalMessage, lastUpdatedTime, lastUpdatedTimeIncludingSidebars, 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 @@ -654,7 +654,6 @@ return { type: 'chatThreadItem', threadInfo, - mostRecentMessageInfo: null, mostRecentNonLocalMessage: null, lastUpdatedTime: threadInfo.creationTime, lastUpdatedTimeIncludingSidebars: threadInfo.creationTime, diff --git a/native/chat/chat-thread-list-item.react.js b/native/chat/chat-thread-list-item.react.js --- a/native/chat/chat-thread-list-item.react.js +++ b/native/chat/chat-thread-list-item.react.js @@ -155,10 +155,7 @@ - + {lastActivity} @@ -175,7 +172,6 @@ styles.row, styles.threadDetails, threadNameStyle, - data.mostRecentMessageInfo, ], ); 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 @@ -5,8 +5,8 @@ import { Text } from 'react-native'; import { useThreadChatMentionCandidates } from 'lib/hooks/chat-mention-hooks.js'; +import { useMessageInfoForPreview } from 'lib/hooks/message-hooks.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; -import { type MessageInfo } from 'lib/types/message-types.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import SingleLine from '../components/single-line.react.js'; @@ -14,15 +14,15 @@ import { useStyles } from '../themes/colors.js'; type Props = { - +messageInfo: ?MessageInfo, +threadInfo: ThreadInfo, }; function MessagePreview(props: Props): React.Node { - const { messageInfo, threadInfo } = props; + const { threadInfo } = props; const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); + const messageInfoForPreview = useMessageInfoForPreview(threadInfo); const messagePreviewResult = useMessagePreview( - messageInfo, + messageInfoForPreview, threadInfo, getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules, ); diff --git a/native/chat/subchannel-item.react.js b/native/chat/subchannel-item.react.js --- a/native/chat/subchannel-item.react.js +++ b/native/chat/subchannel-item.react.js @@ -16,8 +16,7 @@ +subchannelInfo: ChatThreadItem, }; function SubchannelItem(props: Props): React.Node { - const { lastUpdatedTime, threadInfo, mostRecentMessageInfo } = - props.subchannelInfo; + const { lastUpdatedTime, threadInfo } = props.subchannelInfo; const { uiName } = useResolvedThreadInfo(threadInfo); const lastActivity = shortAbsoluteDate(lastUpdatedTime); @@ -37,10 +36,7 @@ {uiName} - + {lastActivity} diff --git a/web/chat/chat-thread-list-item.react.js b/web/chat/chat-thread-list-item.react.js --- a/web/chat/chat-thread-list-item.react.js +++ b/web/chat/chat-thread-list-item.react.js @@ -39,7 +39,6 @@ threadInfo, lastUpdatedTimeIncludingSidebars, mostRecentNonLocalMessage, - mostRecentMessageInfo, } = item; const { id: threadID, currentUser } = threadInfo; @@ -156,10 +155,7 @@
{uiName}
- +
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,37 +5,33 @@ import * as React from 'react'; import { useThreadChatMentionCandidates } from 'lib/hooks/chat-mention-hooks.js'; +import { useMessageInfoForPreview } from 'lib/hooks/message-hooks.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; -import { type MessageInfo } from 'lib/types/message-types.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import css from './chat-thread-list.css'; import { getDefaultTextMessageRules } from '../markdown/rules.react.js'; type Props = { - +messageInfo: ?MessageInfo, +threadInfo: ThreadInfo, }; function MessagePreview(props: Props): React.Node { - const { messageInfo, threadInfo } = props; + const { threadInfo } = props; const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); + const messageInfoForPreview = useMessageInfoForPreview(threadInfo); const messagePreviewResult = useMessagePreview( - messageInfo, + messageInfoForPreview, threadInfo, getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules, ); - if (!messageInfo) { + if (!messagePreviewResult) { return (
No messages
); } - invariant( - messagePreviewResult, - 'useMessagePreview should only return falsey if pass null or undefined', - ); const { message, username } = messagePreviewResult; let usernameText = null; 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 @@ -5,6 +5,7 @@ import { useModalContext } from 'lib/components/modal-provider.react.js'; import { useThreadChatMentionCandidates } from 'lib/hooks/chat-mention-hooks.js'; +import { useMessageInfoForPreview } from 'lib/hooks/message-hooks.js'; import type { ChatThreadItem } from 'lib/selectors/chat-selectors.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; import { shortAbsoluteDate } from 'lib/utils/date-utils.js'; @@ -23,7 +24,7 @@ function Sidebar(props: Props): React.Node { const { sidebar, isLastItem } = props; - const { threadInfo, lastUpdatedTime, mostRecentMessageInfo } = sidebar; + const { threadInfo, lastUpdatedTime } = sidebar; const { unread } = threadInfo.currentUser; const { popModal } = useModalContext(); @@ -54,8 +55,9 @@ ); const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); + const messageInfoForPreview = useMessageInfoForPreview(threadInfo); const messagePreviewResult = useMessagePreview( - mostRecentMessageInfo, + messageInfoForPreview, threadInfo, getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules, ); 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 @@ -5,6 +5,7 @@ import { useModalContext } from 'lib/components/modal-provider.react.js'; import { useThreadChatMentionCandidates } from 'lib/hooks/chat-mention-hooks.js'; +import { useMessageInfoForPreview } from 'lib/hooks/message-hooks.js'; import { type ChatThreadItem } from 'lib/selectors/chat-selectors.js'; import { useMessagePreview } from 'lib/shared/message-utils.js'; import { shortAbsoluteDate } from 'lib/utils/date-utils.js'; @@ -22,11 +23,7 @@ function Subchannel(props: Props): React.Node { const { chatThreadItem } = props; - const { - threadInfo, - mostRecentMessageInfo, - lastUpdatedTimeIncludingSidebars, - } = chatThreadItem; + const { threadInfo, lastUpdatedTimeIncludingSidebars } = chatThreadItem; const { unread } = threadInfo.currentUser; @@ -52,8 +49,9 @@ [lastUpdatedTimeIncludingSidebars], ); const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo); + const messageInfoForPreview = useMessageInfoForPreview(threadInfo); const messagePreviewResult = useMessagePreview( - mostRecentMessageInfo, + messageInfoForPreview, threadInfo, getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules, );