diff --git a/lib/hooks/peer-list-hooks.js b/lib/hooks/peer-list-hooks.js --- a/lib/hooks/peer-list-hooks.js +++ b/lib/hooks/peer-list-hooks.js @@ -6,10 +6,16 @@ import { setPeerDeviceListsActionType } from '../actions/aux-user-actions.js'; import { getRelativeUserIDs } from '../selectors/user-selectors.js'; import { IdentityClientContext } from '../shared/identity-client-context.js'; +import { useTunnelbroker } from '../tunnelbroker/tunnelbroker-context.js'; import type { UsersRawDeviceLists, UsersDevicesPlatformDetails, + SignedDeviceList, } from '../types/identity-service-types.js'; +import { + type DeviceListUpdated, + peerToPeerMessageTypes, +} from '../types/tunnelbroker/peer-to-peer-message-types.js'; import { convertSignedDeviceListsToRawDeviceLists } from '../utils/device-list-utils.js'; import { useDispatch, useSelector } from '../utils/redux-utils.js'; @@ -68,4 +74,46 @@ ); } -export { useCreateInitialPeerList, useGetDeviceListsForUsers }; +function useBroadcastDeviceListUpdates(): ( + deviceIDs: $ReadOnlyArray, + signedDeviceList?: SignedDeviceList, +) => Promise { + const { sendMessage } = useTunnelbroker(); + const identityContext = React.useContext(IdentityClientContext); + invariant(identityContext, 'identity context not set'); + + return React.useCallback( + async ( + deviceIDs: $ReadOnlyArray, + signedDeviceList?: SignedDeviceList, + ) => { + const { getAuthMetadata } = identityContext; + + const { userID } = await getAuthMetadata(); + if (!userID) { + throw new Error('missing auth metadata'); + } + const messageToPeer: DeviceListUpdated = { + type: peerToPeerMessageTypes.DEVICE_LIST_UPDATED, + userID, + signedDeviceList, + }; + const payload = JSON.stringify(messageToPeer); + + const promises = deviceIDs.map((deviceID: string) => + sendMessage({ + deviceID, + payload, + }), + ); + await Promise.all(promises); + }, + [identityContext, sendMessage], + ); +} + +export { + useCreateInitialPeerList, + useGetDeviceListsForUsers, + useBroadcastDeviceListUpdates, +}; diff --git a/native/profile/secondary-device-qr-code-scanner.react.js b/native/profile/secondary-device-qr-code-scanner.react.js --- a/native/profile/secondary-device-qr-code-scanner.react.js +++ b/native/profile/secondary-device-qr-code-scanner.react.js @@ -7,6 +7,7 @@ import { View } from 'react-native'; import { parseDataFromDeepLink } from 'lib/facts/links.js'; +import { useBroadcastDeviceListUpdates } from 'lib/hooks/peer-list-hooks.js'; import { addDeviceToDeviceList } from 'lib/shared/device-list-utils.js'; import { IdentityClientContext } from 'lib/shared/identity-client-context.js'; import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js'; @@ -59,33 +60,7 @@ const aes256Key = React.useRef(null); const secondaryDeviceID = React.useRef(null); - const broadcastDeviceListUpdate = React.useCallback(async () => { - invariant(identityContext, 'identity context not set'); - const { getAuthMetadata, identityClient } = identityContext; - const { userID } = await getAuthMetadata(); - if (!userID) { - throw new Error('missing auth metadata'); - } - - const deviceLists = - await identityClient.getDeviceListHistoryForUser(userID); - invariant(deviceLists.length > 0, 'received empty device list history'); - - const lastSignedDeviceList = deviceLists[deviceLists.length - 1]; - const deviceList = rawDeviceListFromSignedList(lastSignedDeviceList); - - const promises = deviceList.devices.map(recipient => - tunnelbrokerContext.sendMessage({ - deviceID: recipient, - payload: JSON.stringify({ - type: peerToPeerMessageTypes.DEVICE_LIST_UPDATED, - userID, - signedDeviceList: lastSignedDeviceList, - }), - }), - ); - await Promise.all(promises); - }, [identityContext, tunnelbrokerContext]); + const broadcastDeviceListUpdates = useBroadcastDeviceListUpdates(); const tunnelbrokerMessageListener = React.useCallback( async (message: TunnelbrokerMessage) => { @@ -122,7 +97,24 @@ return; } - void broadcastDeviceListUpdate(); + invariant(identityContext, 'identity context not set'); + const { getAuthMetadata, identityClient } = identityContext; + const { userID } = await getAuthMetadata(); + if (!userID) { + throw new Error('missing auth metadata'); + } + + const deviceLists = + await identityClient.getDeviceListHistoryForUser(userID); + invariant(deviceLists.length > 0, 'received empty device list history'); + + const lastSignedDeviceList = deviceLists[deviceLists.length - 1]; + const deviceList = rawDeviceListFromSignedList(lastSignedDeviceList); + + await broadcastDeviceListUpdates( + deviceList.devices, + lastSignedDeviceList, + ); const backupSecret = await getBackupSecret(); const backupKeysResponse = @@ -148,7 +140,7 @@ { text: 'OK' }, ]); }, - [tunnelbrokerContext, broadcastDeviceListUpdate], + [identityContext, broadcastDeviceListUpdates, tunnelbrokerContext], ); React.useEffect(() => {