diff --git a/lib/hooks/message-hooks.js b/lib/hooks/message-hooks.js index ebdb7d18e..39601a7ce 100644 --- a/lib/hooks/message-hooks.js +++ b/lib/hooks/message-hooks.js @@ -1,78 +1,108 @@ // @flow import * as React from 'react'; import { useGetLatestMessageEdit } from './latest-message-edit.js'; import { messageInfoSelector } from '../selectors/chat-selectors.js'; import { getOldestNonLocalMessageID } from '../shared/message-utils.js'; import { messageSpecs } from '../shared/messages/message-specs.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 { return useSelector(state => getOldestNonLocalMessageID(threadID, state.messageStore), ); } +type MessageInfoForPreview = { + +messageInfoForPreview: ?MessageInfo, + // If showInMessagePreview rejects all of the messages in the local store, + // then we'll ignore it and return the most recent message (if there is one) + // as messageInfoForPreview. In this case, we'll also set + // shouldFetchOlderMessages to tell the caller to fetch more messages. + +shouldFetchOlderMessages: boolean, +}; + +const emptyMessageInfoForPreview = { + messageInfoForPreview: undefined, + shouldFetchOlderMessages: false, +}; + function useGetMessageInfoForPreview(): ( threadInfo: ThreadInfo, -) => Promise { +) => Promise { const messageInfos = useSelector(messageInfoSelector); const messageStore = useSelector(state => state.messageStore); const viewerID = useSelector(state => state.currentUserInfo?.id); const fetchMessage = useGetLatestMessageEdit(); return React.useCallback( async threadInfo => { if (!viewerID) { - return null; + return emptyMessageInfoForPreview; } const thread = messageStore.threads[threadInfo.id]; if (!thread) { - return null; + return emptyMessageInfoForPreview; } const showInMessagePreviewParams = { threadInfo, viewerID, fetchMessage, }; + let mostRecentMessageInfo; for (const messageID of thread.messageIDs) { const messageInfo = messageInfos[messageID]; if (!messageInfo) { continue; } + if (!mostRecentMessageInfo) { + mostRecentMessageInfo = messageInfo; + } const { showInMessagePreview } = messageSpecs[messageInfo.type]; if (!showInMessagePreview) { - return messageInfo; + return { + messageInfoForPreview: messageInfo, + shouldFetchOlderMessages: false, + }; } const shouldShow = await showInMessagePreview( messageInfo, showInMessagePreviewParams, ); if (shouldShow) { - return messageInfo; + return { + messageInfoForPreview: messageInfo, + shouldFetchOlderMessages: false, + }; } } - return null; + // If we get here, that means showInMessagePreview rejected all of the + // messages in the local store + return { + messageInfoForPreview: mostRecentMessageInfo, + shouldFetchOlderMessages: true, + }; }, [messageInfos, messageStore, viewerID, fetchMessage], ); } function useMessageInfoForPreview(threadInfo: ThreadInfo): ?MessageInfo { - const [messageInfo, setMessageInfo] = React.useState(); + const [messageInfoForPreview, setMessageInfoForPreview] = + React.useState(); const getMessageInfoForPreview = useGetMessageInfoForPreview(); React.useEffect(() => { void (async () => { const newMessageInfoForPreview = await getMessageInfoForPreview(threadInfo); - setMessageInfo(newMessageInfoForPreview); + setMessageInfoForPreview(newMessageInfoForPreview); })(); }, [threadInfo, getMessageInfoForPreview]); - return messageInfo; + return messageInfoForPreview?.messageInfoForPreview; } export { useOldestMessageServerID, useMessageInfoForPreview };