Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions res/css/_components.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
@import "./components/views/location/_ZoomButtons.pcss";
@import "./components/views/messages/_MBeaconBody.pcss";
@import "./components/views/messages/shared/_MediaProcessingError.pcss";
@import "./components/views/settings/devices/_DeviceDetails.pcss";
@import "./components/views/settings/devices/_DeviceTile.pcss";
@import "./components/views/settings/devices/_SelectableDeviceTile.pcss";
@import "./components/views/settings/shared/_SettingsSubsection.pcss";
Expand Down
70 changes: 70 additions & 0 deletions res/css/components/views/settings/devices/_DeviceDetails.pcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

.mx_DeviceDetails {
display: flex;
flex-direction: column;

width: 100%;

padding: $spacing-16;
border-radius: 8px;
border: 1px solid $system;
}

.mx_DeviceDetails_section {
padding-bottom: $spacing-16;
margin-bottom: $spacing-16;
border-bottom: 1px solid $system;

&:last-child {
padding-bottom: 0;
border-bottom: 0;
margin-bottom: 0;
}
}

.mx_DeviceDetails_sectionHeading {
margin: 0;
}

.mxDeviceDetails_metadataTable {
font-size: $font-12px;
color: $secondary-content;

width: 100%;
margin-top: $spacing-20;

border-spacing: 0;

th {
text-transform: uppercase;
font-weight: normal;
text-align: left;
}

td {
padding-top: $spacing-8;
}

.mxDeviceDetails_metadataLabel {
width: 160px;
}

.mxDeviceDetails_metadataValue {
color: $primary-content;
}
}
7 changes: 3 additions & 4 deletions src/components/views/settings/DevicesPanelEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
import React from 'react';
import { IMyDevice } from 'matrix-js-sdk/src/client';
import { logger } from "matrix-js-sdk/src/logger";
import classNames from 'classnames';

import { _t } from '../../../languageHandler';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
Expand Down Expand Up @@ -113,8 +114,6 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
};

public render(): JSX.Element {
const myDeviceClass = this.props.isOwnDevice ? " mx_DevicesPanel_myDevice" : '';

let iconClass = '';
let verifyButton: JSX.Element;
if (this.props.verified !== null) {
Expand Down Expand Up @@ -160,7 +159,7 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
};

if (this.props.isOwnDevice) {
return <div className={"mx_DevicesPanel_device" + myDeviceClass}>
return <div className={classNames("mx_DevicesPanel_device", "mx_DevicesPanel_myDevice")}>
<div className="mx_DevicesPanel_deviceTrust">
<span className={"mx_DevicesPanel_icon mx_E2EIcon " + iconClass} />
</div>
Expand All @@ -171,7 +170,7 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
}

return (
<div className={"mx_DevicesPanel_device" + myDeviceClass}>
<div className="mx_DevicesPanel_device">
<SelectableDeviceTile device={deviceWithVerification} onClick={this.onDeviceToggled} isSelected={this.props.selected}>
{ buttons }
</SelectableDeviceTile>
Expand Down
79 changes: 79 additions & 0 deletions src/components/views/settings/devices/DeviceDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import { IMyDevice } from 'matrix-js-sdk/src/matrix';

import { formatDate } from '../../../../DateUtils';
import { _t } from '../../../../languageHandler';
import Heading from '../../typography/Heading';

interface Props {
device: IMyDevice;
}

interface MetadataTable {
heading?: string;
values: { label: string, value?: string | React.ReactNode }[];
}

const DeviceDetails: React.FC<Props> = ({ device }) => {
const metadata: MetadataTable[] = [
{
values: [
{ label: _t('Session ID'), value: device.device_id },
{
label: _t('Last activity'),
value: device.last_seen_ts && formatDate(new Date(device.last_seen_ts)),
},
],
},
{
heading: _t('Device'),
values: [
{ label: _t('IP address'), value: device.last_seen_ip },
],
},
];
return <div className='mx_DeviceDetails'>
<section className='mx_DeviceDetails_section'>
<Heading size='h3'>{ device.display_name ?? device.device_id }</Heading>
</section>
<section className='mx_DeviceDetails_section'>
<p className='mx_DeviceDetails_sectionHeading'>{ _t('Session details') }</p>
{ metadata.map(({ heading, values }, index) => <table
className='mxDeviceDetails_metadataTable'
key={index}
>
{ heading &&
<thead>
<tr><th>{ heading }</th></tr>
</thead>
}
<tbody>

{ values.map(({ label, value }) => <tr key={label}>
<td className='mxDeviceDetails_metadataLabel'>{ label }</td>
<td className='mxDeviceDetails_metadataValue'>{ value }</td>
</tr>) }
</tbody>
</table>,
) }
</section>
</div>;
};

export default DeviceDetails;
5 changes: 4 additions & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1692,7 +1692,11 @@
"Sign out devices|other": "Sign out devices",
"Sign out devices|one": "Sign out device",
"Authentication": "Authentication",
"Session ID": "Session ID",
"Last activity": "Last activity",
"Device": "Device",
"IP address": "IP address",
"Session details": "Session details",
"Verified": "Verified",
"Unverified": "Unverified",
"Unable to remove contact information": "Unable to remove contact information",
Expand Down Expand Up @@ -2720,7 +2724,6 @@
"Confirm by comparing the following with the User Settings in your other session:": "Confirm by comparing the following with the User Settings in your other session:",
"Confirm this user's session by comparing the following with their User Settings:": "Confirm this user's session by comparing the following with their User Settings:",
"Session name": "Session name",
"Session ID": "Session ID",
"Session key": "Session key",
"If they don't match, the security of your communication may be compromised.": "If they don't match, the security of your communication may be compromised.",
"Verify session": "Verify session",
Expand Down
53 changes: 53 additions & 0 deletions test/components/views/settings/devices/DeviceDetails-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

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

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

describe('<DeviceDetails />', () => {
const baseDevice = {
device_id: 'my-device',
};
const defaultProps = {
device: baseDevice,
};
const getComponent = (props = {}) => <DeviceDetails {...defaultProps} {...props} />;
// 14.03.2022 16:15
const now = 1647270879403;
jest.useFakeTimers();

beforeEach(() => {
jest.setSystemTime(now);
});

it('renders device without metadata', () => {
const { container } = render(getComponent());
expect(container).toMatchSnapshot();
});

it('renders device with metadata', () => {
const device = {
...baseDevice,
display_name: 'My Device',
last_seen_ip: '123.456.789',
last_seen_ts: now - 60000000,
};
const { container } = render(getComponent({ device }));
expect(container).toMatchSnapshot();
});
});
Loading