Merge pull request #1912 from robintown/unencrypted-indicator

Show a warning on unencrypted media
This commit is contained in:
fkwp
2023-11-21 16:22:12 +01:00
committed by GitHub
3 changed files with 48 additions and 10 deletions

View File

@@ -292,6 +292,7 @@ export const InCallView: FC<InCallViewProps> = ({
data={maximisedParticipant.data} data={maximisedParticipant.data}
showSpeakingIndicator={false} showSpeakingIndicator={false}
showConnectionStats={showConnectionStats} showConnectionStats={showConnectionStats}
matrixInfo={matrixInfo}
/> />
); );
} }
@@ -310,6 +311,7 @@ export const InCallView: FC<InCallViewProps> = ({
onToggleFullscreen={toggleFullscreen} onToggleFullscreen={toggleFullscreen}
showSpeakingIndicator={items.length > 2} showSpeakingIndicator={items.length > 2}
showConnectionStats={showConnectionStats} showConnectionStats={showConnectionStats}
matrixInfo={matrixInfo}
{...props} {...props}
ref={props.ref as Ref<HTMLDivElement>} ref={props.ref as Ref<HTMLDivElement>}
/> />

View File

@@ -88,11 +88,11 @@ limitations under the License.
flex-shrink: 0; flex-shrink: 0;
} }
.nameTag > svg[data-muted="true"] { .muteIcon[data-muted="true"] {
color: var(--cpd-color-icon-secondary); color: var(--cpd-color-icon-secondary);
} }
.nameTag > svg[data-muted="false"] { .muteIcon[data-muted="false"] {
color: var(--cpd-color-icon-primary); color: var(--cpd-color-icon-primary);
} }
@@ -103,6 +103,10 @@ limitations under the License.
padding-inline: var(--cpd-space-2x); padding-inline: var(--cpd-space-2x);
} }
.errorIcon {
color: var(--cpd-color-icon-critical-primary);
}
.toolbar { .toolbar {
position: absolute; position: absolute;
top: 0; top: 0;

View File

@@ -36,13 +36,15 @@ import {
} from "matrix-js-sdk/src/models/room-member"; } from "matrix-js-sdk/src/models/room-member";
import MicOnSolidIcon from "@vector-im/compound-design-tokens/icons/mic-on-solid.svg?react"; import MicOnSolidIcon from "@vector-im/compound-design-tokens/icons/mic-on-solid.svg?react";
import MicOffSolidIcon from "@vector-im/compound-design-tokens/icons/mic-off-solid.svg?react"; import MicOffSolidIcon from "@vector-im/compound-design-tokens/icons/mic-off-solid.svg?react";
import { Text } from "@vector-im/compound-web"; import ErrorIcon from "@vector-im/compound-design-tokens/icons/error.svg?react";
import { Text, Tooltip } from "@vector-im/compound-web";
import { Avatar } from "../Avatar"; import { Avatar } from "../Avatar";
import styles from "./VideoTile.module.css"; import styles from "./VideoTile.module.css";
import { useReactiveState } from "../useReactiveState"; import { useReactiveState } from "../useReactiveState";
import { AudioButton, FullscreenButton } from "../button/Button"; import { AudioButton, FullscreenButton } from "../button/Button";
import { VideoTileSettingsModal } from "./VideoTileSettingsModal"; import { VideoTileSettingsModal } from "./VideoTileSettingsModal";
import { MatrixInfo } from "../room/VideoPreview";
export interface ItemData { export interface ItemData {
id: string; id: string;
@@ -68,6 +70,9 @@ interface Props {
style?: ComponentProps<typeof animated.div>["style"]; style?: ComponentProps<typeof animated.div>["style"];
showSpeakingIndicator: boolean; showSpeakingIndicator: boolean;
showConnectionStats: boolean; showConnectionStats: boolean;
// TODO: This dependency in particular should probably not be here. We can fix
// this with a view model.
matrixInfo: MatrixInfo;
} }
export const VideoTile = forwardRef<HTMLDivElement, Props>( export const VideoTile = forwardRef<HTMLDivElement, Props>(
@@ -83,6 +88,7 @@ export const VideoTile = forwardRef<HTMLDivElement, Props>(
targetHeight, targetHeight,
showSpeakingIndicator, showSpeakingIndicator,
showConnectionStats, showConnectionStats,
matrixInfo,
}, },
tileRef, tileRef,
) => { ) => {
@@ -108,13 +114,22 @@ export const VideoTile = forwardRef<HTMLDivElement, Props>(
} }
}, [member, setDisplayName]); }, [member, setDisplayName]);
const muted = const audioInfo = useMediaTrack(
useMediaTrack(
content === TileContent.UserMedia content === TileContent.UserMedia
? Track.Source.Microphone ? Track.Source.Microphone
: Track.Source.ScreenShareAudio, : Track.Source.ScreenShareAudio,
sfuParticipant, sfuParticipant,
).isMuted !== false; );
const videoInfo = useMediaTrack(
content === TileContent.UserMedia
? Track.Source.Camera
: Track.Source.ScreenShare,
sfuParticipant,
);
const muted = audioInfo.isMuted !== false;
const encrypted =
audioInfo.publication?.isEncrypted !== false &&
videoInfo.publication?.isEncrypted !== false;
const MicIcon = muted ? MicOffSolidIcon : MicOnSolidIcon; const MicIcon = muted ? MicOffSolidIcon : MicOnSolidIcon;
@@ -202,12 +217,29 @@ export const VideoTile = forwardRef<HTMLDivElement, Props>(
height={20} height={20}
aria-label={muted ? t("microphone_off") : t("microphone_on")} aria-label={muted ? t("microphone_off") : t("microphone_on")}
data-muted={muted} data-muted={muted}
className={styles.muteIcon}
/> />
<Text as="span" size="sm" weight="medium"> <Text as="span" size="sm" weight="medium">
{sfuParticipant.isLocal {sfuParticipant.isLocal
? t("video_tile.sfu_participant_local") ? t("video_tile.sfu_participant_local")
: displayName} : displayName}
</Text> </Text>
{matrixInfo.roomEncrypted && !encrypted && (
<Tooltip label={t("common.unencrypted")} side="bottom">
<ErrorIcon
width={20}
height={20}
aria-label={t("common.unencrypted")}
className={styles.errorIcon}
// Make the icon focusable so that the tooltip can be opened
// with keyboard navigation
// TODO: Replace this with the solution from
// https://github.com/vector-im/compound-web/pull/130 once it
// lands
tabIndex={0}
/>
</Tooltip>
)}
{showConnectionStats && ( {showConnectionStats && (
<ConnectionQualityIndicator participant={sfuParticipant} /> <ConnectionQualityIndicator participant={sfuParticipant} />
)} )}