/* * Wire * Copyright (C) 2021 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ import {useEffect, useMemo, useState} from 'react'; import {ClientClassification} from '@wireapp/api-client/lib/client/'; import {partition} from 'Util/ArrayUtil'; import {t} from 'Util/LocalizerUtil'; import {getLogger} from 'Util/Logger'; import {capitalizeFirstChar} from 'Util/StringUtil'; import {DeviceDetails} from './components/DeviceDetails'; import {DeviceList} from './components/DeviceList'; import {NoDevicesFound} from './components/NoDevicesFound'; import {SelfFingerprint} from './components/SelfFingerprint'; import {FIND_MODE, UserDevicesState} from './UserDevices.types'; import {ClientRepository, ClientEntity} from '../../client'; import {MessageRepository} from '../../conversation/MessageRepository'; import {CryptographyRepository} from '../../cryptography/CryptographyRepository'; import {User} from '../../entity/User'; import {useUserIdentity} from '../../hooks/useDeviceIdentities'; export interface UserDevicesHistoryEntry { headline: string; state: UserDevicesState; } const sortUserDevices = (devices: ClientEntity[]): ClientEntity[] => { const [legalholdDevices, otherDevices] = partition( devices, device => device.class === ClientClassification.LEGAL_HOLD, ); return legalholdDevices.concat(otherDevices); }; interface UserDevicesProps { clientRepository: ClientRepository; cryptographyRepository: CryptographyRepository; current: UserDevicesHistoryEntry; goTo: (state: UserDevicesState, headline: string) => void; messageRepository: MessageRepository; noPadding?: boolean; user: User; groupId?: string; } export const UserDevices = ({ noPadding = false, current, user, clientRepository, goTo, messageRepository, cryptographyRepository, groupId, }: UserDevicesProps) => { const [selectedClient, setSelectedClient] = useState(); const {getDeviceIdentity} = useUserIdentity(user.qualifiedId, groupId); const [deviceMode, setDeviceMode] = useState(FIND_MODE.REQUESTING); const [clients, setClients] = useState([]); const logger = useMemo(() => getLogger('UserDevicesComponent'), []); useEffect(() => { (async () => { try { const qualifiedUsersMap = Object.values(await clientRepository.getClientsByUserIds([user], true)); for (const qualifiedUsersMaps of qualifiedUsersMap) { for (const clientEntities of Object.values(qualifiedUsersMaps)) { setClients(sortUserDevices(clientEntities)); const hasDevices = clientEntities.length > 0; const deviceMode = hasDevices ? FIND_MODE.FOUND : FIND_MODE.NOT_FOUND; setDeviceMode(deviceMode); } } } catch (error) { logger.error(`Unable to retrieve clients for user '${user.id}': ${(error as Error).message || error}`); } })(); }, [user]); const clickOnDevice = (clientEntity: ClientEntity) => { setSelectedClient(clientEntity); const headline = user.isMe ? clientEntity.label || clientEntity.model : capitalizeFirstChar(clientEntity.class); goTo(UserDevicesState.DEVICE_DETAILS, headline || ''); }; const clickToShowSelfFingerprint = () => { goTo(UserDevicesState.SELF_FINGERPRINT, t('participantDevicesSelfFingerprint')); }; const showDeviceList = current.state === UserDevicesState.DEVICE_LIST; return (
{showDeviceList && deviceMode === FIND_MODE.FOUND && ( )} {showDeviceList && deviceMode === FIND_MODE.NOT_FOUND && } {current.state === UserDevicesState.DEVICE_DETAILS && selectedClient && ( )} {current.state === UserDevicesState.SELF_FINGERPRINT && ( )}
); };