diff --git a/lib/hooks/input-state-container-hooks.js b/lib/hooks/input-state-container-hooks.js --- a/lib/hooks/input-state-container-hooks.js +++ b/lib/hooks/input-state-container-hooks.js @@ -4,16 +4,25 @@ import * as React from 'react'; import uuid from 'uuid'; -import { useSendTextMessage } from '../actions/message-actions.js'; +import { + useLegacySendMultimediaMessage, + useSendMultimediaMessage, + useSendTextMessage, +} from '../actions/message-actions.js'; import { dmOperationSpecificationTypes } from '../shared/dm-ops/dm-op-utils.js'; import { useSendComposableDMOperation } from '../shared/dm-ops/process-dm-ops.js'; -import type { SendMessagePayload } from '../types/message-types.js'; +import type { + RawMultimediaMessageInfo, + SendMessagePayload, +} from '../types/message-types.js'; +import { getMediaMessageServerDBContentsFromMedia } from '../types/messages/media.js'; import type { RawTextMessageInfo } from '../types/messages/text.js'; import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { thickThreadTypes, threadTypeIsThick, } from '../types/thread-types-enum.js'; +import { useSelector } from '../utils/redux-utils.js'; function useInputStateContainerSendTextMessage(): ( messageInfo: RawTextMessageInfo, @@ -97,4 +106,114 @@ ); } -export { useInputStateContainerSendTextMessage }; +function useInputStateContainerSendMultimediaMessage(): ( + messageInfo: RawMultimediaMessageInfo, + sidebarCreation: boolean, + isLegacy: boolean, +) => Promise { + const sendMultimediaMessage = useSendMultimediaMessage(); + const legacySendMultimediaMessage = useLegacySendMultimediaMessage(); + const sendComposableDMOperation = useSendComposableDMOperation(); + const threadInfos = useSelector(state => state.threadStore.threadInfos); + + return React.useCallback( + async ( + messageInfo: RawMultimediaMessageInfo, + sidebarCreation: boolean, + isLegacy: boolean, + ) => { + const { localID } = messageInfo; + invariant( + localID !== null && localID !== undefined, + 'localID should be set', + ); + + const threadInfo = threadInfos[messageInfo.threadID]; + + if (!threadTypeIsThick(threadInfo.type) && isLegacy) { + const mediaIDs = []; + for (const { id } of messageInfo.media) { + mediaIDs.push(id); + } + const result = await legacySendMultimediaMessage({ + threadID: messageInfo.threadID, + localID, + mediaIDs, + sidebarCreation, + }); + return { + localID, + serverID: result.id, + threadID: messageInfo.threadID, + time: result.time, + }; + } + + if (!threadTypeIsThick(threadInfo.type) && !isLegacy) { + const mediaMessageContents = getMediaMessageServerDBContentsFromMedia( + messageInfo.media, + ); + const result = await sendMultimediaMessage({ + threadID: messageInfo.threadID, + localID, + mediaMessageContents, + sidebarCreation, + }); + return { + localID, + serverID: result.id, + threadID: messageInfo.threadID, + time: result.time, + }; + } + + const messageID = uuid.v4(); + const time = Date.now(); + + const messageIDs = await sendComposableDMOperation({ + type: dmOperationSpecificationTypes.OUTBOUND, + op: { + type: 'send_multimedia_message', + threadID: threadInfo.id, + creatorID: messageInfo.creatorID, + time: Date.now(), + messageID, + media: messageInfo.media, + }, + recipients: { + type: 'all_thread_members', + threadID: + threadInfo.type === thickThreadTypes.THICK_SIDEBAR && + threadInfo.parentThreadID + ? threadInfo.parentThreadID + : threadInfo.id, + }, + sendOnly: true, + composableMessageID: localID, + }); + + if (messageIDs.length > 0) { + const e: any = new Error('Failed to send message to all peers'); + e.failedOutboundP2PMessageIDs = messageIDs; + throw e; + } + return { + localID, + serverID: messageID, + threadID: messageInfo.threadID, + time, + }; + }, + [ + legacySendMultimediaMessage, + sendComposableDMOperation, + sendMultimediaMessage, + threadInfos, + ], + ); +} + +export { + useInputStateContainerSendTextMessage, + useInputStateContainerSendMultimediaMessage, +};