mirror of
https://github.com/vector-im/element-call.git
synced 2026-04-03 07:10:26 +00:00
Prototyping for to-device key distribution
Show participant ID and some encryption status message Allow encryption system to be chosen at point of room creation Send cryptoVersion platform data to Posthog Send key distribution stats to posthog Send encryption type for CallStarted and CallEnded events Update js-sdk
This commit is contained in:
@@ -19,6 +19,7 @@ import {
|
||||
ReactNode,
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import { animated } from "@react-spring/web";
|
||||
@@ -88,6 +89,12 @@ const UserMediaTile = forwardRef<HTMLDivElement, UserMediaTileProps>(
|
||||
const { t } = useTranslation();
|
||||
const video = useObservableEagerState(vm.video);
|
||||
const unencryptedWarning = useObservableEagerState(vm.unencryptedWarning);
|
||||
const encryptionKeyMissing = useObservableEagerState(
|
||||
vm.encryptionKeyMissing,
|
||||
);
|
||||
const encryptionKeyInvalid = useObservableEagerState(
|
||||
vm.encryptionKeyInvalid,
|
||||
);
|
||||
const audioEnabled = useObservableEagerState(vm.audioEnabled);
|
||||
const videoEnabled = useObservableEagerState(vm.videoEnabled);
|
||||
const speaking = useObservableEagerState(vm.speaking);
|
||||
@@ -100,6 +107,8 @@ const UserMediaTile = forwardRef<HTMLDivElement, UserMediaTileProps>(
|
||||
[vm],
|
||||
);
|
||||
|
||||
const participantId = useMemo(() => vm.participant.identity, [vm]);
|
||||
|
||||
const MicIcon = audioEnabled ? MicOnSolidIcon : MicOffSolidIcon;
|
||||
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
@@ -122,6 +131,9 @@ const UserMediaTile = forwardRef<HTMLDivElement, UserMediaTileProps>(
|
||||
video={video}
|
||||
member={vm.member}
|
||||
unencryptedWarning={unencryptedWarning}
|
||||
encryptionKeyMissing={encryptionKeyMissing}
|
||||
encryptionKeyInvalid={encryptionKeyInvalid}
|
||||
participantId={participantId}
|
||||
videoEnabled={videoEnabled && showVideo}
|
||||
videoFit={cropVideo ? "cover" : "contain"}
|
||||
className={classNames(className, styles.tile, {
|
||||
|
||||
@@ -94,7 +94,7 @@ unconditionally select the container so we can use cqmin units */
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-rows: 1fr auto;
|
||||
grid-template-areas: ". ." "nameTag button";
|
||||
grid-template-areas: "status status" "nameTag button";
|
||||
gap: var(--cpd-space-1x);
|
||||
place-items: start;
|
||||
}
|
||||
@@ -115,6 +115,24 @@ unconditionally select the container so we can use cqmin units */
|
||||
max-inline-size: 100%;
|
||||
}
|
||||
|
||||
.status {
|
||||
grid-area: status;
|
||||
justify-self: center;
|
||||
align-self: start;
|
||||
padding: var(--cpd-space-1x);
|
||||
padding-block: var(--cpd-space-1x);
|
||||
color: var(--cpd-color-text-primary);
|
||||
background-color: var(--cpd-color-bg-canvas-default);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: var(--cpd-radius-pill-effect);
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--small-drop-shadow);
|
||||
box-sizing: border-box;
|
||||
max-inline-size: 100%;
|
||||
}
|
||||
|
||||
.nameTag > svg,
|
||||
.nameTag > span {
|
||||
flex-shrink: 0;
|
||||
|
||||
@@ -38,8 +38,11 @@ interface Props extends ComponentProps<typeof animated.div> {
|
||||
member: RoomMember | undefined;
|
||||
videoEnabled: boolean;
|
||||
unencryptedWarning: boolean;
|
||||
encryptionKeyMissing: boolean;
|
||||
encryptionKeyInvalid: boolean;
|
||||
nameTagLeadingIcon?: ReactNode;
|
||||
displayName: string;
|
||||
participantId: string;
|
||||
primaryButton?: ReactNode;
|
||||
}
|
||||
|
||||
@@ -59,6 +62,9 @@ export const MediaView = forwardRef<HTMLDivElement, Props>(
|
||||
nameTagLeadingIcon,
|
||||
displayName,
|
||||
primaryButton,
|
||||
encryptionKeyMissing,
|
||||
encryptionKeyInvalid,
|
||||
participantId,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
@@ -69,7 +75,8 @@ export const MediaView = forwardRef<HTMLDivElement, Props>(
|
||||
<animated.div
|
||||
className={classNames(styles.media, className, {
|
||||
[styles.mirror]: mirror,
|
||||
[styles.videoMuted]: !videoEnabled,
|
||||
[styles.videoMuted]:
|
||||
!videoEnabled || encryptionKeyInvalid || encryptionKeyMissing,
|
||||
})}
|
||||
style={style}
|
||||
ref={ref}
|
||||
@@ -95,10 +102,24 @@ export const MediaView = forwardRef<HTMLDivElement, Props>(
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.fg}>
|
||||
<div className={styles.nameTag}>
|
||||
{encryptionKeyMissing && (
|
||||
<div className={styles.status}>
|
||||
<Text as="span" size="sm" weight="medium" className={styles.name}>
|
||||
Encryption key missing
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
{encryptionKeyInvalid && (
|
||||
<div className={styles.status}>
|
||||
<Text as="span" size="sm" weight="medium" className={styles.name}>
|
||||
Encryption key invalid
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.nameTag} title={participantId}>
|
||||
{nameTagLeadingIcon}
|
||||
<Text as="span" size="sm" weight="medium" className={styles.name}>
|
||||
{displayName}
|
||||
{displayName} ({participantId})
|
||||
</Text>
|
||||
{unencryptedWarning && (
|
||||
<Tooltip
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
@@ -60,7 +61,10 @@ interface SpotlightItemBaseProps {
|
||||
video: TrackReferenceOrPlaceholder;
|
||||
member: RoomMember | undefined;
|
||||
unencryptedWarning: boolean;
|
||||
encryptionKeyMissing: boolean;
|
||||
encryptionKeyInvalid: boolean;
|
||||
displayName: string;
|
||||
participantId: string;
|
||||
}
|
||||
|
||||
interface SpotlightUserMediaItemBaseProps extends SpotlightItemBaseProps {
|
||||
@@ -127,6 +131,17 @@ const SpotlightItem = forwardRef<HTMLDivElement, SpotlightItemProps>(
|
||||
const displayName = useDisplayName(vm);
|
||||
const video = useObservableEagerState(vm.video);
|
||||
const unencryptedWarning = useObservableEagerState(vm.unencryptedWarning);
|
||||
const encryptionKeyMissing = useObservableEagerState(
|
||||
vm.encryptionKeyMissing,
|
||||
);
|
||||
const encryptionKeyInvalid = useObservableEagerState(
|
||||
vm.encryptionKeyInvalid,
|
||||
);
|
||||
|
||||
const participantId = useMemo(
|
||||
() => vm.participant.identity,
|
||||
[vm.participant],
|
||||
);
|
||||
|
||||
// Hook this item up to the intersection observer
|
||||
useEffect(() => {
|
||||
@@ -153,6 +168,9 @@ const SpotlightItem = forwardRef<HTMLDivElement, SpotlightItemProps>(
|
||||
member: vm.member,
|
||||
unencryptedWarning,
|
||||
displayName,
|
||||
encryptionKeyMissing,
|
||||
encryptionKeyInvalid,
|
||||
participantId,
|
||||
};
|
||||
|
||||
return vm instanceof ScreenShareViewModel ? (
|
||||
|
||||
Reference in New Issue
Block a user