vojo/src/app/features/settings/devices/Devices.tsx

134 lines
4.5 KiB
TypeScript

import React from 'react';
import { useTranslation } from 'react-i18next';
import { Box, Text } from 'folds';
import { SectionLabel, SettingFlatRow } from '../styles.css';
import { SettingTile } from '../../../components/setting-tile';
import { SettingsPage } from '../SettingsPage';
import { SettingsSection } from '../SettingsSection';
import { useDeviceIds, useDeviceList, useSplitCurrentDevice } from '../../../hooks/useDeviceList';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { LocalBackup } from './LocalBackup';
import { DeviceLogoutBtn, DeviceKeyDetails, DeviceTile, DeviceTilePlaceholder } from './DeviceTile';
import { OtherDevices } from './OtherDevices';
import {
DeviceVerificationOptions,
EnableVerification,
VerificationStatusBadge,
VerifyCurrentDeviceTile,
} from './Verification';
import {
useDeviceVerificationStatus,
useUnverifiedDeviceCount,
VerificationStatus,
} from '../../../hooks/useDeviceVerificationStatus';
import {
useSecretStorageDefaultKeyId,
useSecretStorageKeyContent,
} from '../../../hooks/useSecretStorage';
import { useCrossSigningActive } from '../../../hooks/useCrossSigning';
import { BackupRestoreTile } from '../../../components/BackupRestore';
function DevicesPlaceholder() {
return (
<Box direction="Column" gap="100">
<DeviceTilePlaceholder />
<DeviceTilePlaceholder />
</Box>
);
}
type DevicesProps = {
requestClose: () => void;
};
export function Devices({ requestClose }: DevicesProps) {
const { t } = useTranslation();
const mx = useMatrixClient();
const crypto = mx.getCrypto();
const crossSigningActive = useCrossSigningActive();
const [devices, refreshDeviceList] = useDeviceList();
const [currentDevice, otherDevices] = useSplitCurrentDevice(devices);
const verificationStatus = useDeviceVerificationStatus(
crypto,
mx.getSafeUserId(),
currentDevice?.device_id
);
const otherDevicesId = useDeviceIds(otherDevices);
const unverifiedDeviceCount = useUnverifiedDeviceCount(
crypto,
mx.getSafeUserId(),
otherDevicesId
);
const defaultSecretStorageKeyId = useSecretStorageDefaultKeyId();
const defaultSecretStorageKeyContent = useSecretStorageKeyContent(
defaultSecretStorageKeyId ?? ''
);
return (
<SettingsPage title={t('Settings.devices_title')} requestClose={requestClose}>
<SettingsSection label={t('Settings.security')}>
<SettingTile
title={t('Settings.device_verification')}
description={t('Settings.device_verification_desc')}
after={
<>
<EnableVerification visible={!crossSigningActive} />
{crossSigningActive && (
<Box gap="200" alignItems="Center">
<VerificationStatusBadge
verificationStatus={verificationStatus}
otherUnverifiedCount={unverifiedDeviceCount}
/>
<DeviceVerificationOptions />
</Box>
)}
</>
}
/>
</SettingsSection>
<Box direction="Column" gap="200">
<Text as="span" className={SectionLabel}>
{t('Settings.current')}
</Text>
{currentDevice ? (
<Box className={SettingFlatRow} direction="Column" gap="400">
<DeviceTile
device={currentDevice}
refreshDeviceList={refreshDeviceList}
options={<DeviceLogoutBtn />}
>
{crypto && <DeviceKeyDetails crypto={crypto} />}
</DeviceTile>
{crossSigningActive &&
verificationStatus === VerificationStatus.Unverified &&
defaultSecretStorageKeyId &&
defaultSecretStorageKeyContent && (
<VerifyCurrentDeviceTile
secretStorageKeyId={defaultSecretStorageKeyId}
secretStorageKeyContent={defaultSecretStorageKeyContent}
/>
)}
{crypto && verificationStatus === VerificationStatus.Verified && (
<BackupRestoreTile crypto={crypto} />
)}
</Box>
) : (
<DeviceTilePlaceholder />
)}
</Box>
{devices === undefined && <DevicesPlaceholder />}
{otherDevices && (
<OtherDevices
devices={otherDevices}
refreshDeviceList={refreshDeviceList}
showVerification={
crossSigningActive && verificationStatus === VerificationStatus.Verified
}
/>
)}
<LocalBackup />
</SettingsPage>
);
}