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
Show all changes
31 commits
Select commit Hold shift + click to select a range
a37682e
record device client inforamtion events on app start
Sep 23, 2022
94b027b
matrix-client-information -> matrix_client_information
Sep 26, 2022
593465a
fix types
Sep 26, 2022
3f616af
Merge branch 'develop' into psg-633/save-device-client-info
Sep 26, 2022
c858656
remove another unused export
Sep 26, 2022
950f61c
add docs link
Sep 27, 2022
fb95964
Merge branch 'develop' into psg-633/save-device-client-info
Sep 27, 2022
258d364
display device client information in device details
Sep 23, 2022
a3cf263
update snapshots
Sep 23, 2022
d316ec6
integration-ish test client information in metadata
Sep 23, 2022
f24e983
tests
Sep 23, 2022
e79934f
fix tests
Sep 26, 2022
9e86e9e
export helper
Sep 26, 2022
ad81d2c
DeviceClientInformation type
Sep 26, 2022
b97ff34
Merge branch 'develop' into psg-682/display-client-info
Sep 30, 2022
d1e3b73
Merge branch 'develop' into psg-682/display-client-info
Oct 4, 2022
0e273d9
Device manager - select all devices (#9330)
Oct 4, 2022
ae76c77
rename type
Oct 4, 2022
295c6d7
use ExtendedDevice type everywhere
Oct 4, 2022
b733f61
rename clientName to appName for less collision with UA parser
Oct 4, 2022
605019c
fix bad find and replace
Oct 4, 2022
0bec4bd
Merge branch 'psg-632/device-man-type-shuffle' into psg-632/device-ma…
Oct 4, 2022
b8c3ea1
rename ExtendedDeviceInfo to ExtendedDeviceAppInfo
Oct 4, 2022
a01c3ca
Merge branch 'psg-632/device-man-type-shuffle' into psg-632/device-ma…
Oct 4, 2022
2569c0c
rename DeviceType comp to DeviceTypeIcon
Oct 4, 2022
82dbfb6
update tests for new required property deviceType
Oct 4, 2022
b10c197
add stubbed user agent parsing
Oct 4, 2022
680fb21
Merge branch 'develop' into psg-682/display-client-info
Oct 4, 2022
eef014a
Merge branch 'psg-682/display-client-info' into psg-632/device-man-pa…
Oct 4, 2022
6766985
Merge branch 'develop' into psg-632/device-man-parse-ua
Oct 4, 2022
6ab22d3
Merge branch 'develop' into psg-632/device-man-parse-ua
Oct 5, 2022
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
2 changes: 1 addition & 1 deletion res/css/_components.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
@import "./components/views/settings/devices/_DeviceExpandDetailsButton.pcss";
@import "./components/views/settings/devices/_DeviceSecurityCard.pcss";
@import "./components/views/settings/devices/_DeviceTile.pcss";
@import "./components/views/settings/devices/_DeviceType.pcss";
@import "./components/views/settings/devices/_DeviceTypeIcon.pcss";
@import "./components/views/settings/devices/_FilteredDeviceList.pcss";
@import "./components/views/settings/devices/_FilteredDeviceListHeader.pcss";
@import "./components/views/settings/devices/_SecurityRecommendations.pcss";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

.mx_DeviceType {
.mx_DeviceTypeIcon {
flex: 0 0 auto;
position: relative;
margin-right: $spacing-8;
/* creates space for verification icon to overlap */
padding: 0 $spacing-8 $spacing-8 0;
}

.mx_DeviceType_deviceIcon {
.mx_DeviceTypeIcon_deviceIcon {
--background-color: $system;
--icon-color: $secondary-content;

Expand All @@ -36,12 +36,12 @@ limitations under the License.
background-color: var(--background-color);
}

.mx_DeviceType_selected .mx_DeviceType_deviceIcon {
.mx_DeviceTypeIcon_selected .mx_DeviceTypeIcon_deviceIcon {
--background-color: $primary-content;
--icon-color: $background;
}

.mx_DeviceType_verificationIcon {
.mx_DeviceTypeIcon_verificationIcon {
position: absolute;
bottom: 0;
right: 0;
Expand Down
2 changes: 1 addition & 1 deletion res/css/views/settings/_DevicesPanel.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ limitations under the License.
min-height: 35px;
padding: 0 $spacing-8;

.mx_DeviceType {
.mx_DeviceTypeIcon {
/* hide the new device type in legacy device list
for backwards compat reasons */
display: none;
Expand Down
8 changes: 5 additions & 3 deletions src/components/views/settings/DevicesPanelEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import VerificationRequestDialog from '../../views/dialogs/VerificationRequestDi
import LogoutDialog from '../dialogs/LogoutDialog';
import DeviceTile from './devices/DeviceTile';
import SelectableDeviceTile from './devices/SelectableDeviceTile';
import { DeviceType } from '../../../utils/device/parseUserAgent';

interface IProps {
device: IMyDevice;
Expand Down Expand Up @@ -153,25 +154,26 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
</AccessibleButton>
</React.Fragment>;

const deviceWithVerification = {
const extendedDevice = {
...this.props.device,
isVerified: this.props.verified,
deviceType: DeviceType.Unknown,
};

if (this.props.isOwnDevice) {
return <div className={classNames("mx_DevicesPanel_device", "mx_DevicesPanel_myDevice")}>
<div className="mx_DevicesPanel_deviceTrust">
<span className={"mx_DevicesPanel_icon mx_E2EIcon " + iconClass} />
</div>
<DeviceTile device={deviceWithVerification}>
<DeviceTile device={extendedDevice}>
{ buttons }
</DeviceTile>
</div>;
}

return (
<div className="mx_DevicesPanel_device">
<SelectableDeviceTile device={deviceWithVerification} onClick={this.onDeviceToggled} isSelected={this.props.selected}>
<SelectableDeviceTile device={extendedDevice} onClick={this.onDeviceToggled} isSelected={this.props.selected}>
{ buttons }
</SelectableDeviceTile>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import DeviceDetails from './DeviceDetails';
import DeviceExpandDetailsButton from './DeviceExpandDetailsButton';
import DeviceTile from './DeviceTile';
import { DeviceVerificationStatusCard } from './DeviceVerificationStatusCard';
import { DeviceWithVerification } from './types';
import { ExtendedDevice } from './types';

interface Props {
device?: DeviceWithVerification;
device?: ExtendedDevice;
isLoading: boolean;
isSigningOut: boolean;
localNotificationSettings?: LocalNotificationSettings | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import Field from '../../elements/Field';
import Spinner from '../../elements/Spinner';
import { Caption } from '../../typography/Caption';
import Heading from '../../typography/Heading';
import { DeviceWithVerification } from './types';
import { ExtendedDevice } from './types';

interface Props {
device: DeviceWithVerification;
device: ExtendedDevice;
saveDeviceName: (deviceName: string) => Promise<void>;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/views/settings/devices/DeviceDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ const DeviceDetails: React.FC<Props> = ({
id: 'application',
heading: _t('Application'),
values: [
{ label: _t('Name'), value: device.clientName },
{ label: _t('Version'), value: device.clientVersion },
{ label: _t('Name'), value: device.appName },
{ label: _t('Version'), value: device.appVersion },
{ label: _t('URL'), value: device.url },
],
},
Expand Down
16 changes: 10 additions & 6 deletions src/components/views/settings/devices/DeviceTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ import { _t } from "../../../../languageHandler";
import { formatDate, formatRelativeTime } from "../../../../DateUtils";
import Heading from "../../typography/Heading";
import { INACTIVE_DEVICE_AGE_DAYS, isDeviceInactive } from "./filter";
import { DeviceWithVerification } from "./types";
import { DeviceType } from "./DeviceType";
import { ExtendedDevice } from "./types";
import { DeviceTypeIcon } from "./DeviceTypeIcon";
export interface DeviceTileProps {
device: DeviceWithVerification;
device: ExtendedDevice;
isSelected?: boolean;
children?: React.ReactNode;
onClick?: () => void;
}

const DeviceTileName: React.FC<{ device: DeviceWithVerification }> = ({ device }) => {
const DeviceTileName: React.FC<{ device: ExtendedDevice }> = ({ device }) => {
return <Heading size='h4'>
{ device.display_name || device.device_id }
</Heading>;
Expand All @@ -48,7 +48,7 @@ const formatLastActivity = (timestamp: number, now = new Date().getTime()): stri
return formatRelativeTime(new Date(timestamp));
};

const getInactiveMetadata = (device: DeviceWithVerification): { id: string, value: React.ReactNode } | undefined => {
const getInactiveMetadata = (device: ExtendedDevice): { id: string, value: React.ReactNode } | undefined => {
const isInactive = isDeviceInactive(device);

if (!isInactive) {
Expand Down Expand Up @@ -89,7 +89,11 @@ const DeviceTile: React.FC<DeviceTileProps> = ({
];

return <div className="mx_DeviceTile" data-testid={`device-tile-${device.device_id}`}>
<DeviceType isVerified={device.isVerified} isSelected={isSelected} />
<DeviceTypeIcon
isVerified={device.isVerified}
isSelected={isSelected}
deviceType={device.deviceType}
/>
<div className="mx_DeviceTile_info" onClick={onClick}>
<DeviceTileName device={device} />
<div className="mx_DeviceTile_metadata">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,39 @@ import { Icon as UnknownDeviceIcon } from '../../../../../res/img/element-icons/
import { Icon as VerifiedIcon } from '../../../../../res/img/e2e/verified.svg';
import { Icon as UnverifiedIcon } from '../../../../../res/img/e2e/warning.svg';
import { _t } from '../../../../languageHandler';
import { DeviceWithVerification } from './types';
import { ExtendedDevice } from './types';
import { DeviceType } from '../../../../utils/device/parseUserAgent';

interface Props {
isVerified?: DeviceWithVerification['isVerified'];
isVerified?: ExtendedDevice['isVerified'];
isSelected?: boolean;
deviceType?: DeviceType;
}

export const DeviceType: React.FC<Props> = ({ isVerified, isSelected }) => (
<div className={classNames('mx_DeviceType', {
mx_DeviceType_selected: isSelected,
export const DeviceTypeIcon: React.FC<Props> = ({
isVerified,
isSelected,
deviceType,
}) => (
<div className={classNames('mx_DeviceTypeIcon', {
mx_DeviceTypeIcon_selected: isSelected,
})}
>
{ /* TODO(kerrya) all devices have an unknown type until PSG-650 */ }
<UnknownDeviceIcon
className='mx_DeviceType_deviceIcon'
className='mx_DeviceTypeIcon_deviceIcon'
role='img'
aria-label={_t('Unknown device type')}
/>
{
isVerified
? <VerifiedIcon
className={classNames('mx_DeviceType_verificationIcon', 'verified')}
className={classNames('mx_DeviceTypeIcon_verificationIcon', 'verified')}
role='img'
aria-label={_t('Verified')}
/>
: <UnverifiedIcon
className={classNames('mx_DeviceType_verificationIcon', 'unverified')}
className={classNames('mx_DeviceTypeIcon_verificationIcon', 'unverified')}
role='img'
aria-label={_t('Unverified')}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import AccessibleButton from '../../elements/AccessibleButton';
import DeviceSecurityCard from './DeviceSecurityCard';
import {
DeviceSecurityVariation,
DeviceWithVerification,
ExtendedDevice,
} from './types';

interface Props {
device: DeviceWithVerification;
device: ExtendedDevice;
onVerifyDevice?: () => void;
}

Expand Down
28 changes: 14 additions & 14 deletions src/components/views/settings/devices/FilteredDeviceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import SelectableDeviceTile from './SelectableDeviceTile';
import {
DevicesDictionary,
DeviceSecurityVariation,
DeviceWithVerification,
ExtendedDevice,
} from './types';
import { DevicesState } from './useOwnDevices';
import FilteredDeviceListHeader from './FilteredDeviceListHeader';
Expand All @@ -42,27 +42,27 @@ interface Props {
devices: DevicesDictionary;
pushers: IPusher[];
localNotificationSettings: Map<string, LocalNotificationSettings>;
expandedDeviceIds: DeviceWithVerification['device_id'][];
signingOutDeviceIds: DeviceWithVerification['device_id'][];
selectedDeviceIds: DeviceWithVerification['device_id'][];
expandedDeviceIds: ExtendedDevice['device_id'][];
signingOutDeviceIds: ExtendedDevice['device_id'][];
selectedDeviceIds: ExtendedDevice['device_id'][];
filter?: DeviceSecurityVariation;
onFilterChange: (filter: DeviceSecurityVariation | undefined) => void;
onDeviceExpandToggle: (deviceId: DeviceWithVerification['device_id']) => void;
onSignOutDevices: (deviceIds: DeviceWithVerification['device_id'][]) => void;
onDeviceExpandToggle: (deviceId: ExtendedDevice['device_id']) => void;
onSignOutDevices: (deviceIds: ExtendedDevice['device_id'][]) => void;
saveDeviceName: DevicesState['saveDeviceName'];
onRequestDeviceVerification?: (deviceId: DeviceWithVerification['device_id']) => void;
onRequestDeviceVerification?: (deviceId: ExtendedDevice['device_id']) => void;
setPushNotifications: (deviceId: string, enabled: boolean) => Promise<void>;
setSelectedDeviceIds: (deviceIds: DeviceWithVerification['device_id'][]) => void;
setSelectedDeviceIds: (deviceIds: ExtendedDevice['device_id'][]) => void;
supportsMSC3881?: boolean | undefined;
}

const isDeviceSelected = (
deviceId: DeviceWithVerification['device_id'],
selectedDeviceIds: DeviceWithVerification['device_id'][],
deviceId: ExtendedDevice['device_id'],
selectedDeviceIds: ExtendedDevice['device_id'][],
) => selectedDeviceIds.includes(deviceId);

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

const getFilteredSortedDevices = (devices: DevicesDictionary, filter?: DeviceSecurityVariation) =>
Expand Down Expand Up @@ -149,7 +149,7 @@ const NoResults: React.FC<NoResultsProps> = ({ filter, clearFilter }) =>
</div>;

const DeviceListItem: React.FC<{
device: DeviceWithVerification;
device: ExtendedDevice;
pusher?: IPusher | undefined;
localNotificationSettings?: LocalNotificationSettings | undefined;
isExpanded: boolean;
Expand Down Expand Up @@ -227,11 +227,11 @@ export const FilteredDeviceList =
}: Props, ref: ForwardedRef<HTMLDivElement>) => {
const sortedDevices = getFilteredSortedDevices(devices, filter);

function getPusherForDevice(device: DeviceWithVerification): IPusher | undefined {
function getPusherForDevice(device: ExtendedDevice): IPusher | undefined {
return pushers.find(pusher => pusher[PUSHER_DEVICE_ID.name] === device.device_id);
}

const toggleSelection = (deviceId: DeviceWithVerification['device_id']): void => {
const toggleSelection = (deviceId: ExtendedDevice['device_id']): void => {
if (isDeviceSelected(deviceId, selectedDeviceIds)) {
// remove from selection
setSelectedDeviceIds(selectedDeviceIds.filter(id => id !== deviceId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ import DeviceSecurityCard from './DeviceSecurityCard';
import { filterDevicesBySecurityRecommendation, INACTIVE_DEVICE_AGE_DAYS } from './filter';
import {
DeviceSecurityVariation,
DeviceWithVerification,
ExtendedDevice,
DevicesDictionary,
} from './types';

interface Props {
devices: DevicesDictionary;
currentDeviceId: DeviceWithVerification['device_id'];
currentDeviceId: ExtendedDevice['device_id'];
goToFilteredList: (filter: DeviceSecurityVariation) => void;
}

Expand All @@ -38,7 +38,7 @@ const SecurityRecommendations: React.FC<Props> = ({
currentDeviceId,
goToFilteredList,
}) => {
const devicesArray = Object.values<DeviceWithVerification>(devices);
const devicesArray = Object.values<ExtendedDevice>(devices);

const unverifiedDevicesCount = filterDevicesBySecurityRecommendation(
devicesArray,
Expand Down
6 changes: 3 additions & 3 deletions src/components/views/settings/devices/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { DeviceWithVerification, DeviceSecurityVariation } from "./types";
import { ExtendedDevice, DeviceSecurityVariation } from "./types";

type DeviceFilterCondition = (device: DeviceWithVerification) => boolean;
type DeviceFilterCondition = (device: ExtendedDevice) => boolean;

const MS_DAY = 24 * 60 * 60 * 1000;
export const INACTIVE_DEVICE_AGE_MS = 7.776e+9; // 90 days
Expand All @@ -32,7 +32,7 @@ const filters: Record<DeviceSecurityVariation, DeviceFilterCondition> = {
};

export const filterDevicesBySecurityRecommendation = (
devices: DeviceWithVerification[],
devices: ExtendedDevice[],
securityVariations: DeviceSecurityVariation[],
) => {
const activeFilters = securityVariations.map(variation => filters[variation]);
Expand Down
13 changes: 8 additions & 5 deletions src/components/views/settings/devices/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ limitations under the License.

import { IMyDevice } from "matrix-js-sdk/src/matrix";

import { ExtendedDeviceInformation } from "../../../../utils/device/parseUserAgent";

export type DeviceWithVerification = IMyDevice & { isVerified: boolean | null };
export type ExtendedDeviceInfo = {
clientName?: string;
clientVersion?: string;
export type ExtendedDeviceAppInfo = {
// eg Element Web
appName?: string;
appVersion?: string;
url?: string;
};
export type ExtendedDevice = DeviceWithVerification & ExtendedDeviceInfo;
export type DevicesDictionary = Record<DeviceWithVerification['device_id'], ExtendedDevice>;
export type ExtendedDevice = DeviceWithVerification & ExtendedDeviceAppInfo & ExtendedDeviceInformation;
export type DevicesDictionary = Record<ExtendedDevice['device_id'], ExtendedDevice>;

export enum DeviceSecurityVariation {
Verified = 'Verified',
Expand Down
Loading