diff --git a/lib/actions/message-actions.js b/lib/actions/message-actions.js --- a/lib/actions/message-actions.js +++ b/lib/actions/message-actions.js @@ -15,36 +15,59 @@ SearchMessagesResponse, } from '../types/message-types.js'; import type { MediaMessageServerDBContent } from '../types/messages/media.js'; -import type { - CallServerEndpoint, - CallServerEndpointResultInfo, -} from '../utils/call-server-endpoint.js'; +import { + extractKeyserverIDFromID, + sortThreadIDsPerKeyserver, +} from '../utils/action-utils.js'; +import type { CallServerEndpointResultInfo } from '../utils/call-server-endpoint.js'; +import { useKeyserverCall } from '../utils/keyserver-call.js'; +import type { CallKeyserverEndpoint } from '../utils/keyserver-call.js'; const fetchMessagesBeforeCursorActionTypes = Object.freeze({ started: 'FETCH_MESSAGES_BEFORE_CURSOR_STARTED', success: 'FETCH_MESSAGES_BEFORE_CURSOR_SUCCESS', failed: 'FETCH_MESSAGES_BEFORE_CURSOR_FAILED', }); +export type FetchMessagesBeforeCursorInput = { + +threadID: string, + +beforeMessageID: string, +}; const fetchMessagesBeforeCursor = ( - callServerEndpoint: CallServerEndpoint, + callKeyserverEndpoint: CallKeyserverEndpoint, ): (( - threadID: string, - beforeMessageID: string, + input: FetchMessagesBeforeCursorInput, ) => Promise) => - async (threadID, beforeMessageID) => { - const response = await callServerEndpoint('fetch_messages', { - cursors: { - [threadID]: beforeMessageID, + async input => { + const { threadID, beforeMessageID } = input; + + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { + [keyserverID]: { + cursors: { + [threadID]: beforeMessageID, + }, }, - }); + }; + + const responses = await callKeyserverEndpoint('fetch_messages', requests); return { threadID, - rawMessageInfos: response.rawMessageInfos, - truncationStatus: response.truncationStatuses[threadID], + rawMessageInfos: responses[keyserverID].rawMessageInfos, + truncationStatus: responses[keyserverID].truncationStatuses[threadID], }; }; +function useFetchMessagesBeforeCursor(): ( + input: FetchMessagesBeforeCursorInput, +) => Promise { + return useKeyserverCall(fetchMessagesBeforeCursor); +} + +export type FetchMostRecentMessagesInput = { + +threadID: string, +}; + const fetchMostRecentMessagesActionTypes = Object.freeze({ started: 'FETCH_MOST_RECENT_MESSAGES_STARTED', success: 'FETCH_MOST_RECENT_MESSAGES_SUCCESS', @@ -52,21 +75,36 @@ }); const fetchMostRecentMessages = ( - callServerEndpoint: CallServerEndpoint, - ): ((threadID: string) => Promise) => - async threadID => { - const response = await callServerEndpoint('fetch_messages', { - cursors: { - [threadID]: null, + callKeyserverEndpoint: CallKeyserverEndpoint, + ): (( + input: FetchMostRecentMessagesInput, + ) => Promise) => + async input => { + const { threadID } = input; + + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { + [keyserverID]: { + cursors: { + [threadID]: null, + }, }, - }); + }; + + const responses = await callKeyserverEndpoint('fetch_messages', requests); return { threadID, - rawMessageInfos: response.rawMessageInfos, - truncationStatus: response.truncationStatuses[threadID], + rawMessageInfos: responses[keyserverID].rawMessageInfos, + truncationStatus: responses[keyserverID].truncationStatuses[threadID], }; }; +function useFetchMostRecentMessages(): ( + input: FetchMostRecentMessagesInput, +) => Promise { + return useKeyserverCall(fetchMostRecentMessages); +} + const fetchSingleMostRecentMessagesFromThreadsActionTypes = Object.freeze({ started: 'FETCH_SINGLE_MOST_RECENT_MESSAGES_FROM_THREADS_STARTED', success: 'FETCH_SINGLE_MOST_RECENT_MESSAGES_FROM_THREADS_SUCCESS', @@ -74,22 +112,54 @@ }); const fetchSingleMostRecentMessagesFromThreads = ( - callServerEndpoint: CallServerEndpoint, + callKeyserverEndpoint: CallKeyserverEndpoint, ): ((threadIDs: $ReadOnlyArray) => Promise) => async threadIDs => { - const cursors = Object.fromEntries( - threadIDs.map(threadID => [threadID, null]), - ); - const response = await callServerEndpoint('fetch_messages', { - cursors, - numberPerThread: 1, - }); + const sortedThreadIDs = sortThreadIDsPerKeyserver(threadIDs); + + const requests = {}; + for (const keyserverID in sortedThreadIDs) { + const cursors = Object.fromEntries( + sortedThreadIDs[keyserverID].map(threadID => [threadID, null]), + ); + requests[keyserverID] = { + cursors, + numberPerThread: 1, + }; + } + + const responses = await callKeyserverEndpoint('fetch_messages', requests); + let rawMessageInfos = []; + let truncationStatuses = {}; + for (const keyserverID in responses) { + rawMessageInfos = rawMessageInfos.concat( + responses[keyserverID].rawMessageInfos, + ); + truncationStatuses = { + ...truncationStatuses, + ...responses[keyserverID].truncationStatuses, + }; + } + return { - rawMessageInfos: response.rawMessageInfos, - truncationStatuses: response.truncationStatuses, + rawMessageInfos, + truncationStatuses, }; }; +function useFetchSingleMostRecentMessagesFromThreads(): ( + threadIDs: $ReadOnlyArray, +) => Promise { + return useKeyserverCall(fetchSingleMostRecentMessagesFromThreads); +} + +export type SendTextMessageInput = { + +threadID: string, + +localID: string, + +text: string, + +sidebarCreation?: boolean, +}; + const sendTextMessageActionTypes = Object.freeze({ started: 'SEND_TEXT_MESSAGE_STARTED', success: 'SEND_TEXT_MESSAGE_SUCCESS', @@ -97,39 +167,56 @@ }); const sendTextMessage = ( - callServerEndpoint: CallServerEndpoint, - ): (( - threadID: string, - localID: string, - text: string, - sidebarCreation?: boolean, - ) => Promise) => - async (threadID, localID, text, sidebarCreation) => { + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: SendTextMessageInput) => Promise) => + async input => { let resultInfo; const getResultInfo = (passedResultInfo: CallServerEndpointResultInfo) => { resultInfo = passedResultInfo; }; + const { threadID, localID, text, sidebarCreation } = input; let payload = { threadID, localID, text }; if (sidebarCreation) { payload = { ...payload, sidebarCreation }; } - const response = await callServerEndpoint('create_text_message', payload, { - getResultInfo, - }); + + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: payload }; + + const responses = await callKeyserverEndpoint( + 'create_text_message', + requests, + { + getResultInfo, + }, + ); const resultInterface = resultInfo?.interface; invariant( resultInterface, - 'getResultInfo not called before callServerEndpoint resolves', + 'getResultInfo not called before callKeyserverEndpoint resolves', ); return { - id: response.newMessageInfo.id, - time: response.newMessageInfo.time, + id: responses[keyserverID].newMessageInfo.id, + time: responses[keyserverID].newMessageInfo.time, interface: resultInterface, }; }; +function useSendTextMessage(): ( + input: SendTextMessageInput, +) => Promise { + return useKeyserverCall(sendTextMessage); +} + const createLocalMessageActionType = 'CREATE_LOCAL_MESSAGE'; +export type SendMultimediaMessageInput = { + +threadID: string, + +localID: string, + +mediaMessageContents: $ReadOnlyArray, + +sidebarCreation?: boolean, +}; + const sendMultimediaMessageActionTypes = Object.freeze({ started: 'SEND_MULTIMEDIA_MESSAGE_STARTED', success: 'SEND_MULTIMEDIA_MESSAGE_SUCCESS', @@ -137,74 +224,95 @@ }); const sendMultimediaMessage = ( - callServerEndpoint: CallServerEndpoint, - ): (( - threadID: string, - localID: string, - mediaMessageContents: $ReadOnlyArray, - sidebarCreation?: boolean, - ) => Promise) => - async (threadID, localID, mediaMessageContents, sidebarCreation) => { + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: SendMultimediaMessageInput) => Promise) => + async input => { let resultInfo; const getResultInfo = (passedResultInfo: CallServerEndpointResultInfo) => { resultInfo = passedResultInfo; }; + const { threadID, localID, mediaMessageContents, sidebarCreation } = input; let payload = { threadID, localID, mediaMessageContents }; if (sidebarCreation) { payload = { ...payload, sidebarCreation }; } - const response = await callServerEndpoint( + + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: payload }; + + const responses = await callKeyserverEndpoint( 'create_multimedia_message', - payload, + requests, { getResultInfo }, ); const resultInterface = resultInfo?.interface; invariant( resultInterface, - 'getResultInfo not called before callServerEndpoint resolves', + 'getResultInfo not called before callKeyserverEndpoint resolves', ); return { - id: response.newMessageInfo.id, - time: response.newMessageInfo.time, + id: responses[keyserverID].newMessageInfo.id, + time: responses[keyserverID].newMessageInfo.time, interface: resultInterface, }; }; +function useSendMultimediaMessage(): ( + input: SendMultimediaMessageInput, +) => Promise { + return useKeyserverCall(sendMultimediaMessage); +} + +export type LegacySendMultimediaMessageInput = { + +threadID: string, + +localID: string, + +mediaIDs: $ReadOnlyArray, + +sidebarCreation?: boolean, +}; + const legacySendMultimediaMessage = ( - callServerEndpoint: CallServerEndpoint, + callKeyserverEndpoint: CallKeyserverEndpoint, ): (( - threadID: string, - localID: string, - mediaIDs: $ReadOnlyArray, - sidebarCreation?: boolean, + input: LegacySendMultimediaMessageInput, ) => Promise) => - async (threadID, localID, mediaIDs, sidebarCreation) => { + async input => { let resultInfo; const getResultInfo = (passedResultInfo: CallServerEndpointResultInfo) => { resultInfo = passedResultInfo; }; + const { threadID, localID, mediaIDs, sidebarCreation } = input; let payload = { threadID, localID, mediaIDs }; if (sidebarCreation) { payload = { ...payload, sidebarCreation }; } - const response = await callServerEndpoint( + + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: payload }; + + const responses = await callKeyserverEndpoint( 'create_multimedia_message', - payload, + requests, { getResultInfo }, ); const resultInterface = resultInfo?.interface; invariant( resultInterface, - 'getResultInfo not called before callServerEndpoint resolves', + 'getResultInfo not called before callKeyserverEndpoint resolves', ); return { - id: response.newMessageInfo.id, - time: response.newMessageInfo.time, + id: responses[keyserverID].newMessageInfo.id, + time: responses[keyserverID].newMessageInfo.time, interface: resultInterface, }; }; +function useLegacySendMultimediaMessage(): ( + input: LegacySendMultimediaMessageInput, +) => Promise { + return useKeyserverCall(legacySendMultimediaMessage); +} + const sendReactionMessageActionTypes = Object.freeze({ started: 'SEND_REACTION_MESSAGE_STARTED', success: 'SEND_REACTION_MESSAGE_SUCCESS', @@ -212,39 +320,50 @@ }); const sendReactionMessage = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: SendReactionMessageRequest) => Promise) => - async request => { + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: SendReactionMessageRequest) => Promise) => + async input => { let resultInfo; const getResultInfo = (passedResultInfo: CallServerEndpointResultInfo) => { resultInfo = passedResultInfo; }; - const response = await callServerEndpoint( - 'create_reaction_message', - { - threadID: request.threadID, - localID: request.localID, - targetMessageID: request.targetMessageID, - reaction: request.reaction, - action: request.action, + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { + [keyserverID]: { + threadID: input.threadID, + localID: input.localID, + targetMessageID: input.targetMessageID, + reaction: input.reaction, + action: input.action, }, + }; + + const responses = await callKeyserverEndpoint( + 'create_reaction_message', + requests, { getResultInfo }, ); const resultInterface = resultInfo?.interface; invariant( resultInterface, - 'getResultInfo not called before callServerEndpoint resolves', + 'getResultInfo not called before callKeyserverEndpoint resolves', ); return { - id: response.newMessageInfo.id, - time: response.newMessageInfo.time, + id: responses[keyserverID].newMessageInfo.id, + time: responses[keyserverID].newMessageInfo.time, interface: resultInterface, }; }; +function useSendReactionMessage(): ( + input: SendReactionMessageRequest, +) => Promise { + return useKeyserverCall(sendReactionMessage); +} + const sendEditMessageActionTypes = Object.freeze({ started: 'SEND_EDIT_MESSAGE_STARTED', success: 'SEND_EDIT_MESSAGE_SUCCESS', @@ -252,18 +371,30 @@ }); const sendEditMessage = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: SendEditMessageRequest) => Promise) => - async request => { - const response = await callServerEndpoint('edit_message', { - targetMessageID: request.targetMessageID, - text: request.text, - }); + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: SendEditMessageRequest) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.targetMessageID); + const requests = { + [keyserverID]: { + targetMessageID: input.targetMessageID, + text: input.text, + }, + }; + + const responses = await callKeyserverEndpoint('edit_message', requests); + return { - newMessageInfos: response.newMessageInfos, + newMessageInfos: responses[keyserverID].newMessageInfos, }; }; +function useSendEditMessage(): ( + input: SendEditMessageRequest, +) => Promise { + return useKeyserverCall(sendEditMessage); +} + const saveMessagesActionType = 'SAVE_MESSAGES'; const processMessagesActionType = 'PROCESS_MESSAGES'; const messageStorePruneActionType = 'MESSAGE_STORE_PRUNE'; @@ -275,15 +406,28 @@ }); const fetchPinnedMessages = ( - callServerEndpoint: CallServerEndpoint, + callKeyserverEndpoint: CallKeyserverEndpoint, ): (( - request: FetchPinnedMessagesRequest, + input: FetchPinnedMessagesRequest, ) => Promise) => - async request => { - const response = await callServerEndpoint('fetch_pinned_messages', request); - return { pinnedMessages: response.pinnedMessages }; + async input => { + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint( + 'fetch_pinned_messages', + requests, + ); + + return { pinnedMessages: responses[keyserverID].pinnedMessages }; }; +function useFetchPinnedMessages(): ( + input: FetchPinnedMessagesRequest, +) => Promise { + return useKeyserverCall(fetchPinnedMessages); +} + const searchMessagesActionTypes = Object.freeze({ started: 'SEARCH_MESSAGES_STARTED', success: 'SEARCH_MESSAGES_SUCCESS', @@ -292,38 +436,48 @@ const searchMessages = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: SearchMessagesRequest) => Promise) => - async request => { - const response = await callServerEndpoint('search_messages', request); + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: SearchMessagesRequest) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint('search_messages', requests); + return { - messages: response.messages, - endReached: response.endReached, + messages: responses[keyserverID].messages, + endReached: responses[keyserverID].endReached, }; }; +function useSearchMessages(): ( + input: SearchMessagesRequest, +) => Promise { + return useKeyserverCall(searchMessages); +} + export { fetchMessagesBeforeCursorActionTypes, - fetchMessagesBeforeCursor, + useFetchMessagesBeforeCursor, fetchMostRecentMessagesActionTypes, - fetchMostRecentMessages, + useFetchMostRecentMessages, fetchSingleMostRecentMessagesFromThreadsActionTypes, - fetchSingleMostRecentMessagesFromThreads, + useFetchSingleMostRecentMessagesFromThreads, sendTextMessageActionTypes, - sendTextMessage, + useSendTextMessage, createLocalMessageActionType, sendMultimediaMessageActionTypes, - sendMultimediaMessage, - legacySendMultimediaMessage, + useSendMultimediaMessage, + useLegacySendMultimediaMessage, searchMessagesActionTypes, - searchMessages, + useSearchMessages, sendReactionMessageActionTypes, - sendReactionMessage, + useSendReactionMessage, saveMessagesActionType, processMessagesActionType, messageStorePruneActionType, sendEditMessageActionTypes, - sendEditMessage, - fetchPinnedMessages, + useSendEditMessage, + useFetchPinnedMessages, fetchPinnedMessageActionTypes, }; 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 @@ -3,7 +3,7 @@ import * as React from 'react'; import { - fetchSingleMostRecentMessagesFromThreads, + useFetchSingleMostRecentMessagesFromThreads, fetchSingleMostRecentMessagesFromThreadsActionTypes, } from '../actions/message-actions.js'; import { @@ -15,10 +15,7 @@ import { threadInChatList } from '../shared/thread-utils.js'; import threadWatcher from '../shared/thread-watcher.js'; import type { ThreadInfo } from '../types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from '../utils/action-utils.js'; +import { useDispatchActionPromise } from '../utils/action-utils.js'; import { useSelector } from '../utils/redux-utils.js'; type ThreadFilter = { @@ -96,9 +93,8 @@ [filteredSubchannelsChatList], ); const dispatchActionPromise = useDispatchActionPromise(); - const fetchSingleMostRecentMessages = useServerCall( - fetchSingleMostRecentMessagesFromThreads, - ); + const fetchSingleMostRecentMessages = + useFetchSingleMostRecentMessagesFromThreads(); React.useEffect(() => { if (!threadIDsWithNoMessages.size) { diff --git a/lib/shared/edit-messages-utils.js b/lib/shared/edit-messages-utils.js --- a/lib/shared/edit-messages-utils.js +++ b/lib/shared/edit-messages-utils.js @@ -5,7 +5,7 @@ import { threadIsPending, threadHasPermission } from './thread-utils.js'; import { sendEditMessageActionTypes, - sendEditMessage, + useSendEditMessage, } from '../actions/message-actions.js'; import type { SendEditMessageResult, @@ -16,17 +16,14 @@ import { messageTypes } from '../types/message-types-enum.js'; import { threadPermissions } from '../types/thread-permission-types.js'; import { type ThreadInfo } from '../types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from '../utils/action-utils.js'; +import { useDispatchActionPromise } from '../utils/action-utils.js'; import { useSelector } from '../utils/redux-utils.js'; function useEditMessage(): ( messageID: string, newText: string, ) => Promise { - const callEditMessage = useServerCall(sendEditMessage); + const callEditMessage = useSendEditMessage(); const dispatchActionPromise = useDispatchActionPromise(); return React.useCallback( diff --git a/lib/shared/search-utils.js b/lib/shared/search-utils.js --- a/lib/shared/search-utils.js +++ b/lib/shared/search-utils.js @@ -10,7 +10,7 @@ getContainingThreadID, } from './thread-utils.js'; import { - searchMessages, + useSearchMessages as useSearchMessagesAction, searchMessagesActionTypes, } from '../actions/message-actions.js'; import { @@ -240,7 +240,7 @@ queryID: number, cursor?: string, ) => void { - const callSearchMessages = useServerCall(searchMessages); + const callSearchMessages = useSearchMessagesAction(); const dispatchActionPromise = useDispatchActionPromise(); return React.useCallback( 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 @@ -14,7 +14,7 @@ import threadWatcher from './thread-watcher.js'; import { fetchMostRecentMessagesActionTypes, - fetchMostRecentMessages, + useFetchMostRecentMessages, } from '../actions/message-actions.js'; import { changeThreadMemberRolesActionTypes, @@ -1109,7 +1109,7 @@ function useWatchThread(threadInfo: ?ThreadInfo) { const dispatchActionPromise = useDispatchActionPromise(); - const callFetchMostRecentMessages = useServerCall(fetchMostRecentMessages); + const callFetchMostRecentMessages = useFetchMostRecentMessages(); const threadID = threadInfo?.id; const threadNotInChatList = !threadInChatList(threadInfo); @@ -1118,7 +1118,7 @@ threadWatcher.watchID(threadID); dispatchActionPromise( fetchMostRecentMessagesActionTypes, - callFetchMostRecentMessages(threadID), + callFetchMostRecentMessages({ threadID }), ); } return () => { diff --git a/lib/utils/action-utils.js b/lib/utils/action-utils.js --- a/lib/utils/action-utils.js +++ b/lib/utils/action-utils.js @@ -458,6 +458,21 @@ socketAPIHandler = passedSocketAPIHandler; } +function sortThreadIDsPerKeyserver(threadIDs: $ReadOnlyArray): { + +[keyserverID: string]: $ReadOnlyArray, +} { + const results = {}; + for (const threadID of threadIDs) { + const keyserverID = extractKeyserverIDFromID(threadID); + invariant(keyserverID, 'keyserver data missing from thread id'); + if (results[keyserverID] === undefined) { + results[keyserverID] = []; + } + results[keyserverID].push(threadID); + } + return results; +} + export { useDispatchActionPromise, setNewSessionActionType, @@ -467,4 +482,5 @@ useServerCall, bindCookieAndUtilsIntoCallServerEndpoint, extractKeyserverIDFromID, + sortThreadIDsPerKeyserver, }; diff --git a/native/chat/message-list.react.js b/native/chat/message-list.react.js --- a/native/chat/message-list.react.js +++ b/native/chat/message-list.react.js @@ -8,9 +8,11 @@ import { fetchMessagesBeforeCursorActionTypes, - fetchMessagesBeforeCursor, + useFetchMessagesBeforeCursor, fetchMostRecentMessagesActionTypes, - fetchMostRecentMessages, + useFetchMostRecentMessages, + type FetchMostRecentMessagesInput, + type FetchMessagesBeforeCursorInput, } from 'lib/actions/message-actions.js'; import { useOldestMessageServerID } from 'lib/hooks/message-hooks.js'; import { registerFetchKey } from 'lib/reducers/loading-reducer.js'; @@ -21,7 +23,6 @@ import { type ThreadInfo } from 'lib/types/thread-types.js'; import { type DispatchActionPromise, - useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; @@ -66,11 +67,10 @@ +indicatorStyle: IndicatorStyle, +dispatchActionPromise: DispatchActionPromise, +fetchMessagesBeforeCursor: ( - threadID: string, - beforeMessageID: string, + input: FetchMessagesBeforeCursorInput, ) => Promise, +fetchMostRecentMessages: ( - threadID: string, + input: FetchMostRecentMessagesInput, ) => Promise, +overlayContext: ?OverlayContextType, +keyboardState: ?KeyboardState, @@ -292,15 +292,15 @@ if (oldestMessageServerID) { await this.props.dispatchActionPromise( fetchMessagesBeforeCursorActionTypes, - this.props.fetchMessagesBeforeCursor( + this.props.fetchMessagesBeforeCursor({ threadID, - oldestMessageServerID, - ), + beforeMessageID: oldestMessageServerID, + }), ); } else { await this.props.dispatchActionPromise( fetchMostRecentMessagesActionTypes, - this.props.fetchMostRecentMessages(threadID), + this.props.fetchMostRecentMessages({ threadID }), ); } } finally { @@ -344,10 +344,8 @@ const indicatorStyle = useIndicatorStyle(); const dispatchActionPromise = useDispatchActionPromise(); - const callFetchMessagesBeforeCursor = useServerCall( - fetchMessagesBeforeCursor, - ); - const callFetchMostRecentMessages = useServerCall(fetchMostRecentMessages); + const callFetchMessagesBeforeCursor = useFetchMessagesBeforeCursor(); + const callFetchMostRecentMessages = useFetchMostRecentMessages(); const oldestMessageServerID = useOldestMessageServerID(threadID); diff --git a/native/chat/message-results-screen.react.js b/native/chat/message-results-screen.react.js --- a/native/chat/message-results-screen.react.js +++ b/native/chat/message-results-screen.react.js @@ -5,14 +5,13 @@ import { View } from 'react-native'; import { ScrollView } from 'react-native-gesture-handler'; -import { fetchPinnedMessages } from 'lib/actions/message-actions.js'; +import { useFetchPinnedMessages } from 'lib/actions/message-actions.js'; import { messageListData } from 'lib/selectors/chat-selectors.js'; import { createMessageInfo, isInvalidPinSourceForThread, } from 'lib/shared/message-utils.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import { useServerCall } from 'lib/utils/action-utils.js'; import { useHeightMeasurer } from './chat-context.js'; import type { ChatNavigationProp } from './chat.react'; @@ -44,7 +43,7 @@ const [messageVerticalBounds, setMessageVerticalBounds] = React.useState(); const scrollViewContainerRef = React.useRef(); - const callFetchPinnedMessages = useServerCall(fetchPinnedMessages); + const callFetchPinnedMessages = useFetchPinnedMessages(); const userInfos = useSelector(state => state.userStore.userInfos); React.useEffect(() => { diff --git a/native/chat/reaction-message-utils.js b/native/chat/reaction-message-utils.js --- a/native/chat/reaction-message-utils.js +++ b/native/chat/reaction-message-utils.js @@ -4,16 +4,13 @@ import * as React from 'react'; import { - sendReactionMessage, + useSendReactionMessage, sendReactionMessageActionTypes, } from 'lib/actions/message-actions.js'; import type { ReactionInfo } from 'lib/selectors/chat-selectors.js'; import { messageTypes } from 'lib/types/message-types-enum.js'; import type { RawReactionMessageInfo } from 'lib/types/messages/reaction.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { cloneError } from 'lib/utils/errors.js'; import { useSelector } from '../redux/redux-utils.js'; @@ -33,7 +30,7 @@ state => state.currentUserInfo && state.currentUserInfo.id, ); - const callSendReactionMessage = useServerCall(sendReactionMessage); + const callSendReactionMessage = useSendReactionMessage(); const dispatchActionPromise = useDispatchActionPromise(); return React.useCallback( diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js --- a/native/input/input-state-container.react.js +++ b/native/input/input-state-container.react.js @@ -10,9 +10,13 @@ import { createLocalMessageActionType, sendMultimediaMessageActionTypes, - sendMultimediaMessage, + useSendMultimediaMessage, sendTextMessageActionTypes, - sendTextMessage, + useSendTextMessage, +} from 'lib/actions/message-actions.js'; +import type { + SendMultimediaMessageInput, + SendTextMessageInput, } from 'lib/actions/message-actions.js'; import { queueReportsActionType } from 'lib/actions/report-actions.js'; import { newThread } from 'lib/actions/thread-actions.js'; @@ -66,10 +70,7 @@ type SendMessagePayload, } from 'lib/types/message-types.js'; import type { RawImagesMessageInfo } from 'lib/types/messages/images.js'; -import type { - MediaMessageServerDBContent, - RawMediaMessageInfo, -} from 'lib/types/messages/media.js'; +import type { RawMediaMessageInfo } from 'lib/types/messages/media.js'; import { getMediaMessageServerDBContentsFromMedia } from 'lib/types/messages/media.js'; import type { RawTextMessageInfo } from 'lib/types/messages/text.js'; import type { Dispatch } from 'lib/types/redux-types.js'; @@ -149,17 +150,9 @@ ) => Promise, +blobServiceUpload: BlobServiceUploadAction, +sendMultimediaMessage: ( - threadID: string, - localID: string, - mediaMessageContents: $ReadOnlyArray, - sidebarCreation?: boolean, - ) => Promise, - +sendTextMessage: ( - threadID: string, - localID: string, - text: string, - sidebarCreation?: boolean, + input: SendMultimediaMessageInput, ) => Promise, + +sendTextMessage: (input: SendTextMessageInput) => Promise, +newThread: (request: ClientNewThreadRequest) => Promise, +textMessageCreationSideEffectsFunc: CreationSideEffectsFunc, }; @@ -375,12 +368,12 @@ messageInfo.media, ); try { - const result = await this.props.sendMultimediaMessage( + const result = await this.props.sendMultimediaMessage({ threadID, localID, mediaMessageContents, sidebarCreation, - ); + }); this.pendingSidebarCreationMessageLocalIDs.delete(localID); return { localID, @@ -574,12 +567,12 @@ ); const sidebarCreation = this.pendingSidebarCreationMessageLocalIDs.has(localID); - const result = await this.props.sendTextMessage( - messageInfo.threadID, + const result = await this.props.sendTextMessage({ + threadID: messageInfo.threadID, localID, - messageInfo.text, + text: messageInfo.text, sidebarCreation, - ); + }); this.pendingSidebarCreationMessageLocalIDs.delete(localID); return { localID, @@ -1702,8 +1695,8 @@ const callUploadMultimedia = useServerCall(uploadMultimedia); const callUploadMediaMetadata = useServerCall(uploadMediaMetadata); const callBlobServiceUpload = useServerCall(blobServiceUpload); - const callSendMultimediaMessage = useServerCall(sendMultimediaMessage); - const callSendTextMessage = useServerCall(sendTextMessage); + const callSendMultimediaMessage = useSendMultimediaMessage(); + const callSendTextMessage = useSendTextMessage(); const callNewThread = useServerCall(newThread); const dispatchActionPromise = useDispatchActionPromise(); const dispatch = useDispatch(); diff --git a/web/chat/chat-message-list.react.js b/web/chat/chat-message-list.react.js --- a/web/chat/chat-message-list.react.js +++ b/web/chat/chat-message-list.react.js @@ -8,9 +8,13 @@ import { fetchMessagesBeforeCursorActionTypes, - fetchMessagesBeforeCursor, + useFetchMessagesBeforeCursor, fetchMostRecentMessagesActionTypes, - fetchMostRecentMessages, + useFetchMostRecentMessages, +} from 'lib/actions/message-actions.js'; +import type { + FetchMostRecentMessagesInput, + FetchMessagesBeforeCursorInput, } from 'lib/actions/message-actions.js'; import { useThreadChatMentionCandidates } from 'lib/hooks/chat-mention-hooks.js'; import { useOldestMessageServerID } from 'lib/hooks/message-hooks.js'; @@ -26,7 +30,6 @@ import { type ThreadInfo } from 'lib/types/thread-types.js'; import { type DispatchActionPromise, - useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; @@ -62,11 +65,10 @@ +startReached: boolean, +dispatchActionPromise: DispatchActionPromise, +fetchMessagesBeforeCursor: ( - threadID: string, - beforeMessageID: string, + input: FetchMessagesBeforeCursorInput, ) => Promise, +fetchMostRecentMessages: ( - threadID: string, + input: FetchMostRecentMessagesInput, ) => Promise, +inputState: ?InputState, +clearTooltip: () => mixed, @@ -384,12 +386,15 @@ if (oldestMessageServerID) { await this.props.dispatchActionPromise( fetchMessagesBeforeCursorActionTypes, - this.props.fetchMessagesBeforeCursor(threadID, oldestMessageServerID), + this.props.fetchMessagesBeforeCursor({ + threadID, + beforeMessageID: oldestMessageServerID, + }), ); } else { await this.props.dispatchActionPromise( fetchMostRecentMessagesActionTypes, - this.props.fetchMostRecentMessages(threadID), + this.props.fetchMostRecentMessages({ threadID }), ); } } finally { @@ -429,10 +434,8 @@ }); const dispatchActionPromise = useDispatchActionPromise(); - const callFetchMessagesBeforeCursor = useServerCall( - fetchMessagesBeforeCursor, - ); - const callFetchMostRecentMessages = useServerCall(fetchMostRecentMessages); + const callFetchMessagesBeforeCursor = useFetchMessagesBeforeCursor(); + const callFetchMostRecentMessages = useFetchMostRecentMessages(); const inputState = React.useContext(InputStateContext); diff --git a/web/chat/reaction-message-utils.js b/web/chat/reaction-message-utils.js --- a/web/chat/reaction-message-utils.js +++ b/web/chat/reaction-message-utils.js @@ -4,17 +4,14 @@ import * as React from 'react'; import { - sendReactionMessage, + useSendReactionMessage, sendReactionMessageActionTypes, } from 'lib/actions/message-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import type { ReactionInfo } from 'lib/selectors/chat-selectors'; import { messageTypes } from 'lib/types/message-types-enum.js'; import type { RawReactionMessageInfo } from 'lib/types/messages/reaction.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { cloneError } from 'lib/utils/errors.js'; import Alert from '../modals/alert.react.js'; @@ -37,7 +34,7 @@ state => state.currentUserInfo && state.currentUserInfo.id, ); - const callSendReactionMessage = useServerCall(sendReactionMessage); + const callSendReactionMessage = useSendReactionMessage(); const dispatchActionPromise = useDispatchActionPromise(); return React.useCallback( diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js --- a/web/input/input-state-container.react.js +++ b/web/input/input-state-container.react.js @@ -14,9 +14,13 @@ import { createLocalMessageActionType, sendMultimediaMessageActionTypes, - legacySendMultimediaMessage, + useLegacySendMultimediaMessage, sendTextMessageActionTypes, - sendTextMessage, + useSendTextMessage, +} from 'lib/actions/message-actions.js'; +import type { + LegacySendMultimediaMessageInput, + SendTextMessageInput, } from 'lib/actions/message-actions.js'; import { queueReportsActionType } from 'lib/actions/report-actions.js'; import { newThread } from 'lib/actions/thread-actions.js'; @@ -134,17 +138,9 @@ ) => Promise, +deleteUpload: (id: string) => Promise, +sendMultimediaMessage: ( - threadID: string, - localID: string, - mediaIDs: $ReadOnlyArray, - sidebarCreation?: boolean, - ) => Promise, - +sendTextMessage: ( - threadID: string, - localID: string, - text: string, - sidebarCreation?: boolean, + input: LegacySendMultimediaMessageInput, ) => Promise, + +sendTextMessage: (input: SendTextMessageInput) => Promise, +newThread: (request: ClientNewThreadRequest) => Promise, +pushModal: PushModal, +sendCallbacks: $ReadOnlyArray<() => mixed>, @@ -508,12 +504,12 @@ mediaIDs.push(id); } try { - const result = await this.props.sendMultimediaMessage( + const result = await this.props.sendMultimediaMessage({ threadID, localID, mediaIDs, sidebarCreation, - ); + }); this.pendingSidebarCreationMessageLocalIDs.delete(localID); this.setState(prevState => { const newThreadID = this.getRealizedOrPendingThreadID(threadID); @@ -1318,12 +1314,12 @@ ); const sidebarCreation = this.pendingSidebarCreationMessageLocalIDs.has(localID); - const result = await this.props.sendTextMessage( - messageInfo.threadID, + const result = await this.props.sendTextMessage({ + threadID: messageInfo.threadID, localID, - messageInfo.text, + text: messageInfo.text, sidebarCreation, - ); + }); this.pendingSidebarCreationMessageLocalIDs.delete(localID); return { localID, @@ -1618,10 +1614,8 @@ const callBlobServiceUpload = useServerCall(blobServiceUpload); const callUploadMediaMetadata = useServerCall(uploadMediaMetadata); const callDeleteUpload = useServerCall(deleteUpload); - const callSendMultimediaMessage = useServerCall( - legacySendMultimediaMessage, - ); - const callSendTextMessage = useServerCall(sendTextMessage); + const callSendMultimediaMessage = useLegacySendMultimediaMessage(); + const callSendTextMessage = useSendTextMessage(); const callNewThread = useServerCall(newThread); const dispatch = useDispatch(); const dispatchActionPromise = useDispatchActionPromise(); diff --git a/web/modals/chat/message-results-modal.react.js b/web/modals/chat/message-results-modal.react.js --- a/web/modals/chat/message-results-modal.react.js +++ b/web/modals/chat/message-results-modal.react.js @@ -3,8 +3,8 @@ import * as React from 'react'; import { - fetchPinnedMessages, fetchPinnedMessageActionTypes, + useFetchPinnedMessages, } from 'lib/actions/message-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import { messageListData } from 'lib/selectors/chat-selectors.js'; @@ -15,10 +15,7 @@ modifyItemForResultScreen, } from 'lib/shared/message-utils.js'; import { type ThreadInfo } from 'lib/types/thread-types.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import css from './message-results-modal.css'; import MessageResult from '../../components/message-result.react.js'; @@ -41,7 +38,7 @@ const { popModal } = useModalContext(); const [rawMessageResults, setRawMessageResults] = React.useState([]); - const callFetchPinnedMessages = useServerCall(fetchPinnedMessages); + const callFetchPinnedMessages = useFetchPinnedMessages(); const dispatchActionPromise = useDispatchActionPromise(); const userInfos = useSelector(state => state.userStore.userInfos);