diff --git a/lib/handlers/user-infos-handler.react.js b/lib/handlers/user-infos-handler.react.js --- a/lib/handlers/user-infos-handler.react.js +++ b/lib/handlers/user-infos-handler.react.js @@ -80,7 +80,7 @@ } void (async () => { try { - await getAndUpdateDeviceListsForUsers(usersWithMissingDeviceList); + await getAndUpdateDeviceListsForUsers(usersWithMissingDeviceList, true); } catch (e) { console.log( `Error getting and setting peer device list: ${ 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 @@ -4,19 +4,25 @@ import * as React from 'react'; import { setPeerDeviceListsActionType } from '../actions/aux-user-actions.js'; -import { getRelativeUserIDs } from '../selectors/user-selectors.js'; +import { + getAllPeerDevices, + 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, + RawDeviceList, } from '../types/identity-service-types.js'; import { type DeviceListUpdated, peerToPeerMessageTypes, } from '../types/tunnelbroker/peer-to-peer-message-types.js'; +import { getContentSigningKey } from '../utils/crypto-utils.js'; import { convertSignedDeviceListsToRawDeviceLists } from '../utils/device-list-utils.js'; +import { values } from '../utils/objects.js'; import { useDispatch, useSelector } from '../utils/redux-utils.js'; function useCreateInitialPeerList(): () => Promise { @@ -76,11 +82,16 @@ function useGetAndUpdateDeviceListsForUsers(): ( userIDs: $ReadOnlyArray, + broadcastUpdates: ?boolean, ) => Promise { const getDeviceListsForUsers = useGetDeviceListsForUsers(); const dispatch = useDispatch(); + const broadcastDeviceListUpdates = useBroadcastDeviceListUpdates(); + + const allPeerDevices = useSelector(getAllPeerDevices); + return React.useCallback( - async (userIDs: $ReadOnlyArray) => { + async (userIDs: $ReadOnlyArray, broadcastUpdates: ?boolean) => { const { deviceLists, usersPlatformDetails } = await getDeviceListsForUsers(userIDs); if (Object.keys(deviceLists).length === 0) { @@ -90,8 +101,29 @@ type: setPeerDeviceListsActionType, payload: { deviceLists, usersPlatformDetails }, }); + + if (!broadcastUpdates) { + return; + } + + const thisDeviceID = await getContentSigningKey(); + + const newDevices = values(deviceLists) + .map((deviceList: RawDeviceList) => deviceList.devices) + .flat() + .filter( + deviceID => + !allPeerDevices.includes(deviceID) && deviceID !== thisDeviceID, + ); + + await broadcastDeviceListUpdates(newDevices); }, - [dispatch, getDeviceListsForUsers], + [ + allPeerDevices, + broadcastDeviceListUpdates, + dispatch, + getDeviceListsForUsers, + ], ); } diff --git a/lib/selectors/user-selectors.js b/lib/selectors/user-selectors.js --- a/lib/selectors/user-selectors.js +++ b/lib/selectors/user-selectors.js @@ -28,7 +28,7 @@ AccountUserInfo, CurrentUserInfo, } from '../types/user-types.js'; -import { entries } from '../utils/objects.js'; +import { entries, values } from '../utils/objects.js'; // Used for specific message payloads that include an array of user IDs, ie. // array of initial users, array of added users @@ -242,6 +242,17 @@ .flat(), ); +const getAllPeerDevices: (state: BaseAppState<>) => $ReadOnlyArray = + createSelector( + (state: BaseAppState<>) => state.auxUserStore.auxUserInfos, + (auxUserInfos: AuxUserInfos): $ReadOnlyArray => + values(auxUserInfos) + .map( + (auxUserInfo: AuxUserInfo) => auxUserInfo.deviceList?.devices ?? [], + ) + .flat(), + ); + export { userIDsToRelativeUserInfos, getRelativeMemberInfos, @@ -254,4 +265,5 @@ getRelativeUserIDs, usersWithMissingDeviceListSelector, getForeignPeerDevices, + getAllPeerDevices, };