diff --git a/lib/shared/dm-ops/dm-op-utils.js b/lib/shared/dm-ops/dm-op-utils.js --- a/lib/shared/dm-ops/dm-op-utils.js +++ b/lib/shared/dm-ops/dm-op-utils.js @@ -14,8 +14,10 @@ import { useFindUserIdentities } from '../../actions/user-actions.js'; import { useLoggedInUserInfo } from '../../hooks/account-hooks.js'; import { useGetLatestMessageEdit } from '../../hooks/latest-message-edit.js'; +import { useGetAndUpdateDeviceListsForUsers } from '../../hooks/peer-list-hooks.js'; import { mergeUpdatesWithMessageInfos } from '../../reducers/message-reducer.js'; import { getAllPeerUserIDAndDeviceIDs } from '../../selectors/user-selectors.js'; +import { type P2PMessageRecipient } from '../../tunnelbroker/peer-to-peer-context.js'; import type { CreateThickRawThreadInfoInput, DMAddMembersOperation, @@ -48,6 +50,7 @@ import { getContentSigningKey } from '../../utils/crypto-utils.js'; import { useSelector } from '../../utils/redux-utils.js'; import { messageSpecs } from '../messages/message-specs.js'; +import { userSupportsThickThreads } from '../thread-utils.js'; import { updateSpecs } from '../updates/update-specs.js'; function generateMessagesToPeers( @@ -127,6 +130,55 @@ ) => Promise<$ReadOnlyArray> { const allPeerUserIDAndDeviceIDs = useSelector(getAllPeerUserIDAndDeviceIDs); const utilities = useSendDMOperationUtils(); + const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos); + const getAndUpdateDeviceListsForUsers = useGetAndUpdateDeviceListsForUsers(); + + const getUsersWithoutDeviceList = React.useCallback( + (userIDs: $ReadOnlyArray) => { + const missingDeviceListsUserIDs: Array = []; + for (const userID of userIDs) { + const supportsThickThreads = userSupportsThickThreads( + userID, + auxUserInfos, + ); + if (!supportsThickThreads) { + missingDeviceListsUserIDs.push(userID); + } + } + return missingDeviceListsUserIDs; + }, + [auxUserInfos], + ); + + const getMissingPeers = React.useCallback( + async ( + userIDs: $ReadOnlyArray, + ): Promise<$ReadOnlyArray> => { + const missingDeviceListsUserIDs = getUsersWithoutDeviceList(userIDs); + if (missingDeviceListsUserIDs.length === 0) { + return []; + } + + const deviceLists = await getAndUpdateDeviceListsForUsers( + missingDeviceListsUserIDs, + true, + ); + + const updatedPeers: Array = []; + for (const userID of missingDeviceListsUserIDs) { + if (deviceLists[userID] && deviceLists[userID].devices.length > 0) { + updatedPeers.push( + ...deviceLists[userID].devices.map(deviceID => ({ + deviceID, + userID, + })), + ); + } + } + return updatedPeers; + }, + [getAndUpdateDeviceListsForUsers, getUsersWithoutDeviceList], + ); return React.useCallback( async ( @@ -144,8 +196,11 @@ peer => peer.userID === viewerID, ); } else if (recipients.type === 'some_users') { + const missingPeers = await getMissingPeers(recipients.userIDs); + const updatedPeers = [...allPeerUserIDAndDeviceIDs, ...missingPeers]; + const userIDs = new Set(recipients.userIDs); - peerUserIDAndDeviceIDs = allPeerUserIDAndDeviceIDs.filter(peer => + peerUserIDAndDeviceIDs = updatedPeers.filter(peer => userIDs.has(peer.userID), ); } else if (recipients.type === 'all_thread_members') { @@ -160,8 +215,11 @@ const members = threadInfos[recipients.threadID]?.members ?? []; const memberIDs = members.map(member => member.id); + const missingPeers = await getMissingPeers(memberIDs); + const updatedPeers = [...allPeerUserIDAndDeviceIDs, ...missingPeers]; + const userIDs = new Set(memberIDs); - peerUserIDAndDeviceIDs = allPeerUserIDAndDeviceIDs.filter(peer => + peerUserIDAndDeviceIDs = updatedPeers.filter(peer => userIDs.has(peer.userID), ); } else if (recipients.type === 'some_devices') { @@ -177,7 +235,7 @@ ); return generateMessagesToPeers(operation, targetPeers); }, - [allPeerUserIDAndDeviceIDs, utilities], + [allPeerUserIDAndDeviceIDs, getMissingPeers, utilities], ); }