show unverified tab indicator on sidebar (#1862)

This commit is contained in:
Ajay Bura 2024-08-04 09:49:37 +05:30 committed by GitHub
parent 9cb5c70d51
commit 681287c46a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 123 additions and 33 deletions

View file

@ -1,31 +0,0 @@
/* eslint-disable import/prefer-default-export */
import { useState, useEffect } from 'react';
import { useMatrixClient } from './useMatrixClient';
export function useDeviceList() {
const mx = useMatrixClient();
const [deviceList, setDeviceList] = useState(null);
useEffect(() => {
let isMounted = true;
const updateDevices = () => mx.getDevices().then((data) => {
if (!isMounted) return;
setDeviceList(data.devices || []);
});
updateDevices();
const handleDevicesUpdate = (users) => {
if (users.includes(mx.getUserId())) {
updateDevices();
}
};
mx.on('crypto.devicesUpdated', handleDevicesUpdate);
return () => {
mx.removeListener('crypto.devicesUpdated', handleDevicesUpdate);
isMounted = false;
};
}, [mx]);
return deviceList;
}

View file

@ -0,0 +1,35 @@
/* eslint-disable import/prefer-default-export */
import { useState, useEffect } from 'react';
import { CryptoEvent, IMyDevice } from 'matrix-js-sdk';
import { CryptoEventHandlerMap } from 'matrix-js-sdk/lib/crypto';
import { useMatrixClient } from './useMatrixClient';
export function useDeviceList() {
const mx = useMatrixClient();
const [deviceList, setDeviceList] = useState<IMyDevice[] | null>(null);
useEffect(() => {
let isMounted = true;
const updateDevices = () =>
mx.getDevices().then((data) => {
if (!isMounted) return;
setDeviceList(data.devices || []);
});
updateDevices();
const handleDevicesUpdate: CryptoEventHandlerMap[CryptoEvent.DevicesUpdated] = (users) => {
const userId = mx.getUserId();
if (userId && users.includes(userId)) {
updateDevices();
}
};
mx.on(CryptoEvent.DevicesUpdated, handleDevicesUpdate);
return () => {
mx.removeListener(CryptoEvent.DevicesUpdated, handleDevicesUpdate);
isMounted = false;
};
}, [mx]);
return deviceList;
}

View file

@ -10,7 +10,15 @@ import {
SidebarItemTooltip,
SidebarItem,
} from '../../components/sidebar';
import { DirectTab, HomeTab, SpaceTabs, InboxTab, ExploreTab, UserTab } from './sidebar';
import {
DirectTab,
HomeTab,
SpaceTabs,
InboxTab,
ExploreTab,
UserTab,
UnverifiedTab,
} from './sidebar';
import { openCreateRoom, openSearch } from '../../../client/action/navigation';
export function SidebarNav() {
@ -65,6 +73,8 @@ export function SidebarNav() {
</SidebarItemTooltip>
</SidebarItem>
<UnverifiedTab />
<InboxTab />
<UserTab />
</SidebarStack>

View file

@ -0,0 +1,24 @@
import { keyframes, style } from '@vanilla-extract/css';
import { color, toRem } from 'folds';
const pushRight = keyframes({
from: {
transform: `translateX(${toRem(2)}) scale(1)`,
},
to: {
transform: 'translateX(0) scale(1)',
},
});
export const UnverifiedTab = style({
animationName: pushRight,
animationDuration: '400ms',
animationIterationCount: 30,
animationDirection: 'alternate',
});
export const UnverifiedAvatar = style({
backgroundColor: color.Critical.Container,
color: color.Critical.OnContainer,
borderColor: color.Critical.ContainerLine,
});

View file

@ -0,0 +1,51 @@
import React from 'react';
import { Badge, color, Icon, Icons, Text } from 'folds';
import { openSettings } from '../../../../client/action/navigation';
import { isCrossVerified } from '../../../../util/matrixUtil';
import {
SidebarAvatar,
SidebarItem,
SidebarItemBadge,
SidebarItemTooltip,
} from '../../../components/sidebar';
import { useDeviceList } from '../../../hooks/useDeviceList';
import { tabText } from '../../../organisms/settings/Settings';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import * as css from './UnverifiedTab.css';
export function UnverifiedTab() {
const mx = useMatrixClient();
const deviceList = useDeviceList();
console.log(deviceList);
const unverified = deviceList?.filter(
(device) => isCrossVerified(mx, device.device_id) === false
);
console.log(unverified);
if (!unverified?.length) return null;
return (
<SidebarItem className={css.UnverifiedTab}>
<SidebarItemTooltip tooltip="Unverified Sessions">
{(triggerRef) => (
<SidebarAvatar
className={css.UnverifiedAvatar}
as="button"
ref={triggerRef}
outlined
onClick={() => openSettings(tabText.SECURITY)}
>
<Icon style={{ color: color.Critical.Main }} src={Icons.ShieldUser} />
</SidebarAvatar>
)}
</SidebarItemTooltip>
<SidebarItemBadge hasCount>
<Badge variant="Critical" size="400" fill="Solid" radii="Pill" outlined={false}>
<Text as="span" size="L400">
{unverified.length}
</Text>
</Badge>
</SidebarItemBadge>
</SidebarItem>
);
}

View file

@ -4,3 +4,4 @@ export * from './SpaceTabs';
export * from './InboxTab';
export * from './ExploreTab';
export * from './UserTab';
export * from './UnverifiedTab';

View file

@ -106,7 +106,7 @@ export function isCrossVerified(mx, deviceId) {
const deviceInfo = mx.getStoredDevice(mx.getUserId(), deviceId);
const deviceTrust = crossSignInfo.checkDeviceTrust(crossSignInfo, deviceInfo, false, true);
return deviceTrust.isCrossSigningVerified();
} catch {
} catch (e) {
// device does not support encryption
return null;
}