Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
exclude current device session from other sessions list
Browse files Browse the repository at this point in the history
  • Loading branch information
Kerry Archibald committed Aug 9, 2022
1 parent 707076b commit 6d4d405
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 36 deletions.
42 changes: 19 additions & 23 deletions src/components/views/settings/devices/FilteredDeviceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,39 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { useEffect, useState } from 'react';
import React from 'react';

import DeviceTile from './DeviceTile';
import { DevicesDictionary, DeviceWithVerification } from './useOwnDevices';

export enum DeviceSortOrder {
LatestActivity = 'LatestActivity',
}

interface Props {
devices: DevicesDictionary;
}

// devices without timestamp metadata should be sorted last
const sortDevicesByLatestActivity = (left: DeviceWithVerification, right: DeviceWithVerification) =>
left.last_seen_ts - right.last_seen_ts;
(right.last_seen_ts || 0) - (left.last_seen_ts || 0);

const getSortedDeviceIds = (devices: DevicesDictionary) =>
Object.values(devices).sort(sortDevicesByLatestActivity).map(device => device.device_id);
const getSortedDevices = (devices: DevicesDictionary) =>
Object.values(devices).sort(sortDevicesByLatestActivity);

/**
* Filtered list of devices
* Sorted by latest activity descending
* TODO(kerrya) Filtering to added as part of PSG-648
*/
const FilteredDeviceList: React.FC<Props> = ({ devices }) => {
const [sortedIds, setSortedIds] = useState([]);

useEffect(() => {
setSortedIds(getSortedDeviceIds(devices));
}, [devices]);
const sortedDevices = getSortedDevices(devices);

return <ol className='mx_FilteredDeviceList'>
{ sortedIds.map((deviceId) =>
<li key={deviceId}>

<DeviceTile

device={devices[deviceId]}
/>
</li>

)}
{ sortedDevices.map((device) =>
<li key={device.device_id}>
<DeviceTile
device={device}
/>
</li>,

) }
</ol>;
};

Expand Down
12 changes: 6 additions & 6 deletions src/components/views/settings/tabs/user/SessionManagerTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import { useOwnDevices } from '../../devices/useOwnDevices';
import DeviceTile from '../../devices/DeviceTile';
import SettingsSubsection from '../../shared/SettingsSubsection';
import SettingsTab from '../SettingsTab';
import FilteredDeviceList, { DeviceSortOrder } from '../../devices/FilteredDeviceList';
import FilteredDeviceList from '../../devices/FilteredDeviceList';

const SessionManagerTab: React.FC = () => {
const { devices, currentDeviceId, isLoading } = useOwnDevices();

const currentDevice = devices[currentDeviceId];
const shouldShowOtherSessions = Object.keys(devices).length > 1;
const { [currentDeviceId]: currentDevice, ...otherDevices } = devices;
const shouldShowOtherSessions = Object.keys(otherDevices).length > 0;

return <SettingsTab heading={_t('Sessions')}>
<SettingsSubsection
Expand All @@ -45,11 +45,11 @@ const SessionManagerTab: React.FC = () => {
<SettingsSubsection
heading={_t('Other sessions')}
description={_t(
`For best security, verify your sessions and sign out` +
`from any session that you don't recognize or use anymore.`
`For best security, verify your sessions and sign out ` +
`from any session that you don't recognize or use anymore.`,
)}
>
<FilteredDeviceList devices={devices} sortOrder={DeviceSortOrder.LatestActivity} />
<FilteredDeviceList devices={otherDevices} />
</SettingsSubsection>
}
</SettingsTab>;
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,7 @@
"Sessions": "Sessions",
"Current session": "Current session",
"Other sessions": "Other sessions",
"For best security, verify your sessions and sign outfrom any session that you don't recognize or use anymore.": "For best security, verify your sessions and sign outfrom any session that you don't recognize or use anymore.",
"For best security, verify your sessions and sign out from any session that you don't recognize or use anymore.": "For best security, verify your sessions and sign out from any session that you don't recognize or use anymore.",
"Sidebar": "Sidebar",
"Spaces to show": "Spaces to show",
"Spaces are ways to group rooms and people. Alongside the spaces you're in, you can use some pre-built ones too.": "Spaces are ways to group rooms and people. Alongside the spaces you're in, you can use some pre-built ones too.",
Expand Down
46 changes: 40 additions & 6 deletions test/components/views/settings/devices/FilteredDeviceList-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,51 @@ limitations under the License.
*/

import React from 'react';
import { mount } from 'enzyme';
import { render } from '@testing-library/react';

import FilteredDeviceList from '../../../../../src/components/views/settings/devices/FilteredDeviceList';

describe('<FilteredDeviceList />', () => {
const defaultProps = {};
const noMetaDevice = { device_id: 'no-meta-device', isVerified: true };
const oldDevice = { device_id: 'old', last_seen_ts: new Date(1993, 7, 3, 4).getTime(), isVerified: true };
const newDevice = {
device_id: 'new',
last_seen_ts: new Date().getTime() - 500,
last_seen_ip: '123.456.789',
display_name: 'My Device',
isVerified: true,
};
const defaultProps = {
devices: {
[noMetaDevice.device_id]: noMetaDevice,
[oldDevice.device_id]: oldDevice,
[newDevice.device_id]: newDevice,
},
};
const getComponent = (props = {}) =>
mount(<FilteredDeviceList {...defaultProps} {...props} />);
(<FilteredDeviceList {...defaultProps} {...props} />);

it('renders', () => {
const component = getComponent();
expect(component).toBeTruthy();
it('renders devices in correct order', () => {
const { container } = render(getComponent());
const tiles = container.querySelectorAll('.mx_DeviceTile');
expect(tiles[0].getAttribute('data-testid')).toEqual(`device-tile-${newDevice.device_id}`);
expect(tiles[1].getAttribute('data-testid')).toEqual(`device-tile-${oldDevice.device_id}`);
expect(tiles[2].getAttribute('data-testid')).toEqual(`device-tile-${noMetaDevice.device_id}`);
});

it('updates list order when devices change', () => {
const updatedOldDevice = { ...oldDevice, last_seen_ts: new Date().getTime() };
const updatedDevices = {
[oldDevice.device_id]: updatedOldDevice,
[newDevice.device_id]: newDevice,
};
const { container, rerender } = render(getComponent());

rerender(getComponent({ devices: updatedDevices }));

const tiles = container.querySelectorAll('.mx_DeviceTile');
expect(tiles.length).toBe(2);
expect(tiles[0].getAttribute('data-testid')).toEqual(`device-tile-${oldDevice.device_id}`);
expect(tiles[1].getAttribute('data-testid')).toEqual(`device-tile-${newDevice.device_id}`);
});
});

0 comments on commit 6d4d405

Please sign in to comment.