Device manager - logout of other session (PSG-744) (#9280)
* add sign out of current device section in device details * lint * add sign out cta for other sessions * test other device sign out * add pending sign out loader * tidy * fix strict error * use gap instead of nbsp * use more specific assertions in tests, tweak formatting * tweak test
This commit is contained in:
parent
0c22b15bba
commit
10bb10539b
13 changed files with 371 additions and 49 deletions
|
@ -28,6 +28,7 @@ import { DeviceWithVerification } from './types';
|
|||
interface Props {
|
||||
device?: DeviceWithVerification;
|
||||
isLoading: boolean;
|
||||
isSigningOut: boolean;
|
||||
onVerifyCurrentDevice: () => void;
|
||||
onSignOutCurrentDevice: () => void;
|
||||
}
|
||||
|
@ -35,6 +36,7 @@ interface Props {
|
|||
const CurrentDeviceSection: React.FC<Props> = ({
|
||||
device,
|
||||
isLoading,
|
||||
isSigningOut,
|
||||
onVerifyCurrentDevice,
|
||||
onSignOutCurrentDevice,
|
||||
}) => {
|
||||
|
@ -58,6 +60,7 @@ const CurrentDeviceSection: React.FC<Props> = ({
|
|||
{ isExpanded &&
|
||||
<DeviceDetails
|
||||
device={device}
|
||||
isSigningOut={isSigningOut}
|
||||
onSignOutDevice={onSignOutCurrentDevice}
|
||||
/>
|
||||
}
|
||||
|
|
|
@ -19,16 +19,16 @@ import React from 'react';
|
|||
import { formatDate } from '../../../../DateUtils';
|
||||
import { _t } from '../../../../languageHandler';
|
||||
import AccessibleButton from '../../elements/AccessibleButton';
|
||||
import Spinner from '../../elements/Spinner';
|
||||
import Heading from '../../typography/Heading';
|
||||
import { DeviceVerificationStatusCard } from './DeviceVerificationStatusCard';
|
||||
import { DeviceWithVerification } from './types';
|
||||
|
||||
interface Props {
|
||||
device: DeviceWithVerification;
|
||||
isSigningOut: boolean;
|
||||
onVerifyDevice?: () => void;
|
||||
// @TODO(kerry) optional while signout only implemented
|
||||
// for current device (PSG-744)
|
||||
onSignOutDevice?: () => void;
|
||||
onSignOutDevice: () => void;
|
||||
}
|
||||
|
||||
interface MetadataTable {
|
||||
|
@ -38,6 +38,7 @@ interface MetadataTable {
|
|||
|
||||
const DeviceDetails: React.FC<Props> = ({
|
||||
device,
|
||||
isSigningOut,
|
||||
onVerifyDevice,
|
||||
onSignOutDevice,
|
||||
}) => {
|
||||
|
@ -87,15 +88,19 @@ const DeviceDetails: React.FC<Props> = ({
|
|||
</table>,
|
||||
) }
|
||||
</section>
|
||||
{ !!onSignOutDevice && <section className='mx_DeviceDetails_section'>
|
||||
<section className='mx_DeviceDetails_section'>
|
||||
<AccessibleButton
|
||||
onClick={onSignOutDevice}
|
||||
kind='danger_inline'
|
||||
disabled={isSigningOut}
|
||||
data-testid='device-detail-sign-out-cta'
|
||||
>
|
||||
{ _t('Sign out of this session') }
|
||||
<span className='mx_DeviceDetails_signOutButtonContent'>
|
||||
{ _t('Sign out of this session') }
|
||||
{ isSigningOut && <Spinner w={16} h={16} /> }
|
||||
</span>
|
||||
</AccessibleButton>
|
||||
</section> }
|
||||
</section>
|
||||
</div>;
|
||||
};
|
||||
|
||||
|
|
|
@ -36,9 +36,11 @@ import {
|
|||
interface Props {
|
||||
devices: DevicesDictionary;
|
||||
expandedDeviceIds: DeviceWithVerification['device_id'][];
|
||||
signingOutDeviceIds: DeviceWithVerification['device_id'][];
|
||||
filter?: DeviceSecurityVariation;
|
||||
onFilterChange: (filter: DeviceSecurityVariation | undefined) => void;
|
||||
onDeviceExpandToggle: (deviceId: DeviceWithVerification['device_id']) => void;
|
||||
onSignOutDevices: (deviceIds: DeviceWithVerification['device_id'][]) => void;
|
||||
onRequestDeviceVerification?: (deviceId: DeviceWithVerification['device_id']) => void;
|
||||
}
|
||||
|
||||
|
@ -132,10 +134,16 @@ const NoResults: React.FC<NoResultsProps> = ({ filter, clearFilter }) =>
|
|||
const DeviceListItem: React.FC<{
|
||||
device: DeviceWithVerification;
|
||||
isExpanded: boolean;
|
||||
isSigningOut: boolean;
|
||||
onDeviceExpandToggle: () => void;
|
||||
onSignOutDevice: () => void;
|
||||
onRequestDeviceVerification?: () => void;
|
||||
}> = ({
|
||||
device, isExpanded, onDeviceExpandToggle,
|
||||
device,
|
||||
isExpanded,
|
||||
isSigningOut,
|
||||
onDeviceExpandToggle,
|
||||
onSignOutDevice,
|
||||
onRequestDeviceVerification,
|
||||
}) => <li className='mx_FilteredDeviceList_listItem'>
|
||||
<DeviceTile
|
||||
|
@ -146,7 +154,15 @@ const DeviceListItem: React.FC<{
|
|||
onClick={onDeviceExpandToggle}
|
||||
/>
|
||||
</DeviceTile>
|
||||
{ isExpanded && <DeviceDetails device={device} onVerifyDevice={onRequestDeviceVerification} /> }
|
||||
{
|
||||
isExpanded &&
|
||||
<DeviceDetails
|
||||
device={device}
|
||||
isSigningOut={isSigningOut}
|
||||
onVerifyDevice={onRequestDeviceVerification}
|
||||
onSignOutDevice={onSignOutDevice}
|
||||
/>
|
||||
}
|
||||
</li>;
|
||||
|
||||
/**
|
||||
|
@ -158,8 +174,10 @@ export const FilteredDeviceList =
|
|||
devices,
|
||||
filter,
|
||||
expandedDeviceIds,
|
||||
signingOutDeviceIds,
|
||||
onFilterChange,
|
||||
onDeviceExpandToggle,
|
||||
onSignOutDevices,
|
||||
onRequestDeviceVerification,
|
||||
}: Props, ref: ForwardedRef<HTMLDivElement>) => {
|
||||
const sortedDevices = getFilteredSortedDevices(devices, filter);
|
||||
|
@ -213,7 +231,9 @@ export const FilteredDeviceList =
|
|||
key={device.device_id}
|
||||
device={device}
|
||||
isExpanded={expandedDeviceIds.includes(device.device_id)}
|
||||
isSigningOut={signingOutDeviceIds.includes(device.device_id)}
|
||||
onDeviceExpandToggle={() => onDeviceExpandToggle(device.device_id)}
|
||||
onSignOutDevice={() => onSignOutDevices([device.device_id])}
|
||||
onRequestDeviceVerification={
|
||||
onRequestDeviceVerification
|
||||
? () => onRequestDeviceVerification(device.device_id)
|
||||
|
|
|
@ -18,7 +18,6 @@ import { useCallback, useContext, useEffect, useState } from "react";
|
|||
import { IMyDevice, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { CrossSigningInfo } from "matrix-js-sdk/src/crypto/CrossSigning";
|
||||
import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
||||
import { User } from "matrix-js-sdk/src/models/user";
|
||||
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
|
@ -74,10 +73,9 @@ export enum OwnDevicesError {
|
|||
Unsupported = 'Unsupported',
|
||||
Default = 'Default',
|
||||
}
|
||||
type DevicesState = {
|
||||
export type DevicesState = {
|
||||
devices: DevicesDictionary;
|
||||
currentDeviceId: string;
|
||||
currentUserMember?: User;
|
||||
isLoading: boolean;
|
||||
// not provided when current session cannot request verification
|
||||
requestDeviceVerification?: (deviceId: DeviceWithVerification['device_id']) => Promise<VerificationRequest>;
|
||||
|
@ -135,7 +133,6 @@ export const useOwnDevices = (): DevicesState => {
|
|||
return {
|
||||
devices,
|
||||
currentDeviceId,
|
||||
currentUserMember: userId && matrixClient.getUser(userId) || undefined,
|
||||
requestDeviceVerification,
|
||||
refreshDevices,
|
||||
isLoading,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue