Device manager - device type icon (#9355)
* record device client inforamtion events on app start * matrix-client-information -> matrix_client_information * fix types * remove another unused export * add docs link * display device client information in device details * update snapshots * integration-ish test client information in metadata * tests * fix tests * export helper * DeviceClientInformation type * Device manager - select all devices (#9330) * add device selection that does nothing * multi select and sign out of sessions * test multiple selection * fix type after rebase * select all sessions * rename type * use ExtendedDevice type everywhere * rename clientName to appName for less collision with UA parser * fix bad find and replace * rename ExtendedDeviceInfo to ExtendedDeviceAppInfo * rename DeviceType comp to DeviceTypeIcon * update tests for new required property deviceType * add stubbed user agent parsing * add icons * set device type icon * device type icon tets * update snapshots for device type icon changes * desktop icon viewbox * i18npull/28217/head
parent
8399b63e7a
commit
5e18abe7f7
|
@ -22,7 +22,7 @@ limitations under the License.
|
|||
padding: 0 $spacing-8 $spacing-8 0;
|
||||
}
|
||||
|
||||
.mx_DeviceTypeIcon_deviceIcon {
|
||||
.mx_DeviceTypeIcon_deviceIconWrapper {
|
||||
--background-color: $system;
|
||||
--icon-color: $secondary-content;
|
||||
|
||||
|
@ -36,11 +36,16 @@ limitations under the License.
|
|||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
.mx_DeviceTypeIcon_selected .mx_DeviceTypeIcon_deviceIcon {
|
||||
.mx_DeviceTypeIcon_selected .mx_DeviceTypeIcon_deviceIconWrapper {
|
||||
--background-color: $primary-content;
|
||||
--icon-color: $background;
|
||||
}
|
||||
|
||||
.mx_DeviceTypeIcon_deviceIcon {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.mx_DeviceTypeIcon_verificationIcon {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="22" height="19" viewBox="0 0 22 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 15.5C2.45 15.5 1.97933 15.3043 1.588 14.913C1.196 14.521 1 14.05 1 13.5V2.5C1 1.95 1.196 1.479 1.588 1.087C1.97933 0.695667 2.45 0.5 3 0.5H19C19.55 0.5 20.021 0.695667 20.413 1.087C20.8043 1.479 21 1.95 21 2.5V13.5C21 14.05 20.8043 14.521 20.413 14.913C20.021 15.3043 19.55 15.5 19 15.5H3ZM3 13.5H19V2.5H3V13.5ZM1 18.5C0.716667 18.5 0.479333 18.404 0.288 18.212C0.096 18.0207 0 17.7833 0 17.5C0 17.2167 0.096 16.9793 0.288 16.788C0.479333 16.596 0.716667 16.5 1 16.5H21C21.2833 16.5 21.5207 16.596 21.712 16.788C21.904 16.9793 22 17.2167 22 17.5C22 17.7833 21.904 18.0207 21.712 18.212C21.5207 18.404 21.2833 18.5 21 18.5H1ZM3 13.5V2.5V13.5Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 780 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="14" height="23" viewBox="0 0 14 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 0.51L2 0.5C0.9 0.5 0 1.4 0 2.5V20.5C0 21.6 0.9 22.5 2 22.5H12C13.1 22.5 14 21.6 14 20.5V2.5C14 1.4 13.1 0.51 12 0.51ZM12 18.5H2V4.5H12V18.5Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 280 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 16.5H2C1.45 16.5 0.979333 16.3043 0.588 15.913C0.196 15.521 0 15.05 0 14.5V2.5C0 1.95 0.196 1.47933 0.588 1.088C0.979333 0.696 1.45 0.5 2 0.5H18C18.55 0.5 19.021 0.696 19.413 1.088C19.8043 1.47933 20 1.95 20 2.5V14.5C20 15.05 19.8043 15.521 19.413 15.913C19.021 16.3043 18.55 16.5 18 16.5ZM2 4.5V14.5H18V4.5H2Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 450 B |
|
@ -18,6 +18,9 @@ import React from 'react';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { Icon as UnknownDeviceIcon } from '../../../../../res/img/element-icons/settings/unknown-device.svg';
|
||||
import { Icon as DesktopIcon } from '../../../../../res/img/element-icons/settings/desktop.svg';
|
||||
import { Icon as WebIcon } from '../../../../../res/img/element-icons/settings/web.svg';
|
||||
import { Icon as MobileIcon } from '../../../../../res/img/element-icons/settings/mobile.svg';
|
||||
import { Icon as VerifiedIcon } from '../../../../../res/img/e2e/verified.svg';
|
||||
import { Icon as UnverifiedIcon } from '../../../../../res/img/e2e/warning.svg';
|
||||
import { _t } from '../../../../languageHandler';
|
||||
|
@ -30,33 +33,51 @@ interface Props {
|
|||
deviceType?: DeviceType;
|
||||
}
|
||||
|
||||
const deviceTypeIcon: Record<DeviceType, React.FC<React.SVGProps<SVGSVGElement>>> = {
|
||||
[DeviceType.Desktop]: DesktopIcon,
|
||||
[DeviceType.Mobile]: MobileIcon,
|
||||
[DeviceType.Web]: WebIcon,
|
||||
[DeviceType.Unknown]: UnknownDeviceIcon,
|
||||
};
|
||||
const deviceTypeLabel: Record<DeviceType, string> = {
|
||||
[DeviceType.Desktop]: _t('Desktop session'),
|
||||
[DeviceType.Mobile]: _t('Mobile session'),
|
||||
[DeviceType.Web]: _t('Web session'),
|
||||
[DeviceType.Unknown]: _t('Unknown session type'),
|
||||
};
|
||||
|
||||
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_DeviceTypeIcon_deviceIcon'
|
||||
role='img'
|
||||
aria-label={_t('Unknown device type')}
|
||||
/>
|
||||
{
|
||||
isVerified
|
||||
? <VerifiedIcon
|
||||
className={classNames('mx_DeviceTypeIcon_verificationIcon', 'verified')}
|
||||
}) => {
|
||||
const Icon = deviceTypeIcon[deviceType] || deviceTypeIcon[DeviceType.Unknown];
|
||||
const label = deviceTypeLabel[deviceType] || deviceTypeLabel[DeviceType.Unknown];
|
||||
return (
|
||||
<div className={classNames('mx_DeviceTypeIcon', {
|
||||
mx_DeviceTypeIcon_selected: isSelected,
|
||||
})}
|
||||
>
|
||||
<div className='mx_DeviceTypeIcon_deviceIconWrapper'>
|
||||
<Icon
|
||||
className='mx_DeviceTypeIcon_deviceIcon'
|
||||
role='img'
|
||||
aria-label={_t('Verified')}
|
||||
aria-label={label}
|
||||
/>
|
||||
: <UnverifiedIcon
|
||||
className={classNames('mx_DeviceTypeIcon_verificationIcon', 'unverified')}
|
||||
role='img'
|
||||
aria-label={_t('Unverified')}
|
||||
/>
|
||||
}
|
||||
</div>);
|
||||
</div>
|
||||
{
|
||||
isVerified
|
||||
? <VerifiedIcon
|
||||
className={classNames('mx_DeviceTypeIcon_verificationIcon', 'verified')}
|
||||
role='img'
|
||||
aria-label={_t('Verified')}
|
||||
/>
|
||||
: <UnverifiedIcon
|
||||
className={classNames('mx_DeviceTypeIcon_verificationIcon', 'unverified')}
|
||||
role='img'
|
||||
aria-label={_t('Unverified')}
|
||||
/>
|
||||
}
|
||||
</div>);
|
||||
};
|
||||
|
||||
|
|
|
@ -1729,7 +1729,10 @@
|
|||
"Inactive for %(inactiveAgeDays)s+ days": "Inactive for %(inactiveAgeDays)s+ days",
|
||||
"Verified": "Verified",
|
||||
"Unverified": "Unverified",
|
||||
"Unknown device type": "Unknown device type",
|
||||
"Desktop session": "Desktop session",
|
||||
"Mobile session": "Mobile session",
|
||||
"Web session": "Web session",
|
||||
"Unknown session type": "Unknown session type",
|
||||
"Verified session": "Verified session",
|
||||
"This session is ready for secure messaging.": "This session is ready for secure messaging.",
|
||||
"Unverified session": "Unverified session",
|
||||
|
|
|
@ -115,10 +115,14 @@ exports[`<DevicesPanel /> renders device panel with devices 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -238,10 +242,14 @@ exports[`<DevicesPanel /> renders device panel with devices 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -320,10 +328,14 @@ exports[`<DevicesPanel /> renders device panel with devices 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -18,6 +18,7 @@ import { render } from '@testing-library/react';
|
|||
import React from 'react';
|
||||
|
||||
import { DeviceTypeIcon } from '../../../../../src/components/views/settings/devices/DeviceTypeIcon';
|
||||
import { DeviceType } from '../../../../../src/utils/device/parseUserAgent';
|
||||
|
||||
describe('<DeviceTypeIcon />', () => {
|
||||
const defaultProps = {
|
||||
|
@ -41,4 +42,33 @@ describe('<DeviceTypeIcon />', () => {
|
|||
const { container } = render(getComponent({ isSelected: true }));
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders an unknown device icon when no device type given', () => {
|
||||
const { getByLabelText } = render(getComponent());
|
||||
expect(getByLabelText('Unknown session type')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders a desktop device type', () => {
|
||||
const deviceType = DeviceType.Desktop;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Desktop session')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders a web device type', () => {
|
||||
const deviceType = DeviceType.Web;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Web session')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders a mobile device type', () => {
|
||||
const deviceType = DeviceType.Mobile;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Mobile session')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders an unknown device type', () => {
|
||||
const deviceType = DeviceType.Unknown;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Unknown session type')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -154,10 +154,14 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -270,10 +274,14 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -10,10 +10,14 @@ exports[`<DeviceTile /> renders a device with no metadata 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -61,10 +65,14 @@ exports[`<DeviceTile /> renders a verified device with no metadata 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -112,10 +120,14 @@ exports[`<DeviceTile /> renders display name with a tooltip 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -163,10 +175,14 @@ exports[`<DeviceTile /> separates metadata with a dot 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -6,10 +6,14 @@ exports[`<DeviceTypeIcon /> renders a verified device 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Verified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon verified"
|
||||
|
@ -25,10 +29,14 @@ exports[`<DeviceTypeIcon /> renders an unverified device 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -44,10 +52,14 @@ exports[`<DeviceTypeIcon /> renders correctly when selected 1`] = `
|
|||
class="mx_DeviceTypeIcon mx_DeviceTypeIcon_selected"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -42,10 +42,14 @@ exports[`<SelectableDeviceTile /> renders unselected device tile with checkbox 1
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -97,10 +97,14 @@ exports[`<SessionManagerTab /> renders current session section with a verified s
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Verified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon verified"
|
||||
|
@ -199,10 +203,14 @@ exports[`<SessionManagerTab /> renders current session section with an unverifie
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -301,10 +309,14 @@ exports[`<SessionManagerTab /> sets device verification status correctly 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Verified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon verified"
|
||||
|
|
Loading…
Reference in New Issue