diff --git a/lib/shared/farcaster/farcaster-hooks.js b/lib/shared/farcaster/farcaster-hooks.js --- a/lib/shared/farcaster/farcaster-hooks.js +++ b/lib/shared/farcaster/farcaster-hooks.js @@ -80,6 +80,89 @@ ); } +function useFetchMessagesForConversation(): ( + conversationID: string, + messagesNumberLimit?: number, +) => Promise { + const fetchFarcasterMessages = useFetchFarcasterMessages(); + const dispatch = useDispatch(); + + return React.useCallback( + async ( + conversationID: string, + messagesNumberLimit: number = 20, + ): Promise => { + try { + let cursor: ?string = null; + let totalMessagesFetched = 0; + + do { + const batchLimit = Math.min( + 20, + messagesNumberLimit - totalMessagesFetched, + ); + + if (batchLimit <= 0) { + break; + } + + const messagesInput = { + conversationId: conversationID, + limit: batchLimit, + ...(cursor ? { cursor } : {}), + }; + + const messagesResult = await fetchFarcasterMessages(messagesInput); + + if (messagesResult) { + const farcasterMessages = messagesResult.result.messages; + const rawMessageInfos = farcasterMessages.flatMap( + convertFarcasterMessageToCommMessages, + ); + + if (rawMessageInfos.length > 0) { + const payload = + totalMessagesFetched === 0 + ? { rawMessageInfos, updateInfos: [] } + : { + rawMessageInfos: [], + updateInfos: [], + additionalMessageInfos: rawMessageInfos, + }; + dispatch({ + type: processFarcasterOpsActionType, + payload, + }); + totalMessagesFetched += farcasterMessages.length; + } + + cursor = messagesResult.next?.cursor; + } else { + cursor = null; + } + } while (cursor && totalMessagesFetched < messagesNumberLimit); + } catch (e) { + console.error(`Failed fetching messages for ${conversationID}:`, e); + } + }, + [fetchFarcasterMessages, dispatch], + ); +} + +function useRefreshFarcasterConversation(): ( + conversationID: string, +) => Promise { + const fetchConversation = useFetchConversation(); + const fetchMessagesForConversation = useFetchMessagesForConversation(); + return React.useCallback( + async (conversationID: string) => { + await fetchConversation(conversationID); + await fetchMessagesForConversation(conversationID); + }, + [fetchConversation, fetchMessagesForConversation], + ); +} + function useFarcasterConversationsSync(): (limit: number) => Promise { const [fullInbox, setFullInbox] = React.useState(false); const [conversations, setConversations] = React.useState< @@ -88,11 +171,11 @@ const [messagesNumberLimit, setMessagesNumberLimit] = React.useState(20); const fetchFarcasterInbox = useFetchFarcasterInbox(); - const fetchFarcasterMessages = useFetchFarcasterMessages(); const sendFarcasterTextMessage = useSendFarcasterTextMessage(); const dispatch = useDispatch(); const utils = useSendDMOperationUtils(); - const fetchConversationCallback = useFetchConversation(); + const fetchConversation = useFetchConversation(); + const fetchMessagesForConversation = useFetchMessagesForConversation(); const fetchInboxes: (cursor: ?string) => Promise = React.useCallback( async (cursor: ?string) => { @@ -138,75 +221,16 @@ const conversationResults = await processInBatches( conversations, 20, - fetchConversationCallback, + fetchConversation, ); farcasterConversations.push(...conversationResults.filter(Boolean)); - const fetchMessagesForConversation = async ( - farcasterConversation: FarcasterConversation, - ): Promise => { - try { - let cursor: ?string = null; - let totalMessagesFetched = 0; - - do { - const batchLimit = Math.min( - 20, - messagesNumberLimit - totalMessagesFetched, - ); - - if (batchLimit <= 0) { - break; - } - - const messagesInput = { - conversationId: farcasterConversation.conversationId, - limit: batchLimit, - ...(cursor ? { cursor } : {}), - }; - - const messagesResult = await fetchFarcasterMessages(messagesInput); - - if (messagesResult) { - const farcasterMessages = messagesResult.result.messages; - const rawMessageInfos = farcasterMessages.flatMap( - convertFarcasterMessageToCommMessages, - ); - - if (rawMessageInfos.length > 0) { - const payload = - totalMessagesFetched === 0 - ? { rawMessageInfos, updateInfos: [] } - : { - rawMessageInfos: [], - updateInfos: [], - additionalMessageInfos: rawMessageInfos, - }; - dispatch({ - type: processFarcasterOpsActionType, - payload, - }); - totalMessagesFetched += farcasterMessages.length; - } - - cursor = messagesResult.next?.cursor; - } else { - cursor = null; - } - } while (cursor && totalMessagesFetched < messagesNumberLimit); - } catch (e) { - console.error( - `Failed fetching messages for ${farcasterConversation.conversationId}:`, - e, - ); - } - }; - - await processInBatches( - farcasterConversations, - 20, - fetchMessagesForConversation, + await processInBatches(farcasterConversations, 20, conversation => + fetchMessagesForConversation( + conversation.conversationId, + messagesNumberLimit, + ), ); setConversations([]); @@ -216,8 +240,8 @@ }, [ conversations, dispatch, - fetchConversationCallback, - fetchFarcasterMessages, + fetchConversation, + fetchMessagesForConversation, fullInbox, inProgress, messagesNumberLimit, @@ -236,4 +260,9 @@ ); } -export { useFarcasterConversationsSync, useFetchConversation }; +export { + useFarcasterConversationsSync, + useFetchConversation, + useFetchMessagesForConversation, + useRefreshFarcasterConversation, +}; diff --git a/lib/shared/threads/protocols/farcaster-thread-protocol.js b/lib/shared/threads/protocols/farcaster-thread-protocol.js --- a/lib/shared/threads/protocols/farcaster-thread-protocol.js +++ b/lib/shared/threads/protocols/farcaster-thread-protocol.js @@ -371,7 +371,7 @@ utils: OnOpenThreadUtils, ) => { const conversationID = conversationIDFromFarcasterThreadID(input.threadID); - void utils.farcasterFetchConversation(conversationID); + void utils.farcasterRefreshConversation(conversationID); }, threadIDMatchesProtocol: (threadID: string): boolean => { diff --git a/lib/shared/threads/thread-spec.js b/lib/shared/threads/thread-spec.js --- a/lib/shared/threads/thread-spec.js +++ b/lib/shared/threads/thread-spec.js @@ -309,7 +309,7 @@ +threadID: string, }; export type OnOpenThreadUtils = { - +farcasterFetchConversation: (conversationID: string) => Promise, + +farcasterRefreshConversation: (conversationID: string) => Promise, }; export type ThreadProtocol< diff --git a/native/chat/message-list-container.react.js b/native/chat/message-list-container.react.js --- a/native/chat/message-list-container.react.js +++ b/native/chat/message-list-container.react.js @@ -10,7 +10,7 @@ import { useUsersSupportThickThreads } from 'lib/hooks/user-identities-hooks.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js'; -import { useFetchConversation } from 'lib/shared/farcaster/farcaster-hooks.js'; +import { useRefreshFarcasterConversation } from 'lib/shared/farcaster/farcaster-hooks.js'; import { usePotentialMemberItems, useSearchUsers, @@ -458,18 +458,18 @@ ]); const prevActiveThreadID = React.useRef(threadInfo.id); - const farcasterFetchConversation = useFetchConversation(); + const farcasterRefreshConversation = useRefreshFarcasterConversation(); React.useEffect(() => { if (prevActiveThreadID !== threadInfo.id) { threadSpecs[threadInfo.type] .protocol() .onOpenThread?.( { threadID: threadInfo.id }, - { farcasterFetchConversation }, + { farcasterRefreshConversation }, ); prevActiveThreadID.current = threadInfo.id; } - }, [farcasterFetchConversation, threadInfo.id, threadInfo.type]); + }, [farcasterRefreshConversation, threadInfo.id, threadInfo.type]); return ( diff --git a/web/chat/chat-message-list-container.react.js b/web/chat/chat-message-list-container.react.js --- a/web/chat/chat-message-list-container.react.js +++ b/web/chat/chat-message-list-container.react.js @@ -6,7 +6,7 @@ import { useDrop } from 'react-dnd'; import { NativeTypes } from 'react-dnd-html5-backend'; -import { useFetchConversation } from 'lib/shared/farcaster/farcaster-hooks.js'; +import { useRefreshFarcasterConversation } from 'lib/shared/farcaster/farcaster-hooks.js'; import { threadIsPending } from 'lib/shared/thread-utils.js'; import { threadSpecs } from 'lib/shared/threads/thread-specs.js'; import { useWatchThread } from 'lib/shared/watch-thread-utils.js'; @@ -146,18 +146,18 @@ }, [inputState, isChatCreation, selectedUserInfos, threadInfo]); const prevActiveThreadID = React.useRef(activeChatThreadID); - const farcasterFetchConversation = useFetchConversation(); + const farcasterRefreshConversation = useRefreshFarcasterConversation(); React.useEffect(() => { if (prevActiveThreadID !== activeChatThreadID && activeChatThreadID) { threadSpecs[threadInfo.type] .protocol() .onOpenThread?.( { threadID: activeChatThreadID }, - { farcasterFetchConversation }, + { farcasterRefreshConversation }, ); prevActiveThreadID.current = activeChatThreadID; } - }, [farcasterFetchConversation, activeChatThreadID, threadInfo.type]); + }, [farcasterRefreshConversation, activeChatThreadID, threadInfo.type]); return connectDropTarget(