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 @@ -194,6 +194,9 @@ }, ); +const getRelativeUserIDs = (state: BaseAppState<>): $ReadOnlyArray => + Object.keys(state.userStore.userInfos); + export { userIDsToRelativeUserInfos, getRelativeMemberInfos, @@ -203,4 +206,5 @@ isLoggedInToKeyserver, usersWithPersonalThreadSelector, savedEmojiAvatarSelectorForCurrentUser, + getRelativeUserIDs, }; diff --git a/lib/types/identity-service-types.js b/lib/types/identity-service-types.js --- a/lib/types/identity-service-types.js +++ b/lib/types/identity-service-types.js @@ -220,6 +220,11 @@ +devices: $ReadOnlyArray, +timestamp: number, }; +export const rawDeviceListValidator: TInterface = + tShape({ + devices: t.list(t.String), + timestamp: t.Number, + }); export type UsersRawDeviceLists = { +[userID: string]: RawDeviceList, diff --git a/lib/utils/device-list-utils.js b/lib/utils/device-list-utils.js new file mode 100644 --- /dev/null +++ b/lib/utils/device-list-utils.js @@ -0,0 +1,26 @@ +// @flow + +import { assertWithValidator } from './validation-utils.js'; +import type { + UsersRawDeviceLists, + UsersSignedDeviceLists, +} from '../types/identity-service-types.js'; +import { rawDeviceListValidator } from '../types/identity-service-types.js'; + +function convertSignedDeviceListsToRawDeviceLists( + signedDeviceLists: UsersSignedDeviceLists, +): UsersRawDeviceLists { + let usersRawDeviceLists: UsersRawDeviceLists = {}; + for (const userID in signedDeviceLists) { + usersRawDeviceLists = { + ...usersRawDeviceLists, + [userID]: assertWithValidator( + JSON.parse(signedDeviceLists[userID].rawDeviceList), + rawDeviceListValidator, + ), + }; + } + return usersRawDeviceLists; +} + +export { convertSignedDeviceListsToRawDeviceLists }; diff --git a/web/settings/account-settings.react.js b/web/settings/account-settings.react.js --- a/web/settings/account-settings.react.js +++ b/web/settings/account-settings.react.js @@ -2,10 +2,12 @@ import * as React from 'react'; +import { setPeerDeviceListsActionType } from 'lib/actions/aux-user-actions.js'; import { useLogOut, logOutActionTypes } from 'lib/actions/user-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/swmansion-icon.react.js'; import { useStringForUser } from 'lib/hooks/ens-cache.js'; +import { getRelativeUserIDs } from 'lib/selectors/user-selectors.js'; import { accountHasPassword } from 'lib/shared/account-utils.js'; import { IdentityClientContext } from 'lib/shared/identity-client-context.js'; import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js'; @@ -13,7 +15,9 @@ createOlmSessionsWithOwnDevices, getContentSigningKey, } from 'lib/utils/crypto-utils.js'; +import { convertSignedDeviceListsToRawDeviceLists } from 'lib/utils/device-list-utils.js'; import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; +import { useDispatch } from 'lib/utils/redux-utils.js'; import css from './account-settings.css'; import AppearanceChangeModal from './appearance-change-modal.react.js'; @@ -109,6 +113,30 @@ } }, [identityContext, sendMessage]); + const dispatch = useDispatch(); + const relativeUserIDs = useSelector(getRelativeUserIDs); + + const onCreateInitialPeerList = React.useCallback(async () => { + if (!identityContext) { + return; + } + + try { + const userDeviceLists = + await identityContext.identityClient.getDeviceListsForUsers( + relativeUserIDs, + ); + const usersRawDeviceLists = + convertSignedDeviceListsToRawDeviceLists(userDeviceLists); + dispatch({ + type: setPeerDeviceListsActionType, + payload: { deviceLists: usersRawDeviceLists }, + }); + } catch (e) { + console.log(`Error creating initial peer list: ${e.message}`); + } + }, [dispatch, identityContext, relativeUserIDs]); + const openBackupTestRestoreModal = React.useCallback( () => pushModal(), [popModal, pushModal], @@ -185,6 +213,12 @@

Create

+
  • + Create initial peer list + +