Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(EXPERIMENTAL) Prototyping with to-device sender key distribution #2572

Draft
wants to merge 26 commits into
base: livekit
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
497b38b
Prototyping for to-device key distribution
hughns Aug 19, 2024
4c68122
Allow for null MatrixClient
hughns Sep 2, 2024
d060f85
Use branch of js-sdk
hughns Sep 3, 2024
9987a45
Prototyping for to-device key distribution
hughns Aug 19, 2024
a33b40e
Allow for null MatrixClient
hughns Sep 2, 2024
79d09e1
Use branch of js-sdk
hughns Sep 3, 2024
efcabe9
Merge branch 'hughns/do-device-key-distribution' of https://github.co…
hughns Sep 3, 2024
c5f50e0
Update yarn.lock
hughns Sep 3, 2024
38384c2
Bump js-sdk
hughns Sep 4, 2024
2afe179
Merge branch 'livekit' into hughns/do-device-key-distribution
hughns Sep 4, 2024
7e1fbdb
Bump js-sdk
hughns Sep 4, 2024
0a3dae0
Upgrade js-sdk to get forward secrecy
hughns Sep 4, 2024
cd2937c
Bump js-sdk
hughns Sep 4, 2024
d219f32
Bump js-sdk
hughns Sep 4, 2024
a5ac5b2
Merge branch 'livekit' into hughns/to-device-key-distribution
hughns Sep 6, 2024
20e3f67
Bump js-sdk
hughns Sep 6, 2024
e502cfb
Bump js-sdk
hughns Sep 9, 2024
102399a
Include the hostname of where EC is running in rageshakes (#2616)
hughns Sep 9, 2024
4cfdd15
Give user feedback if rageshake submission fails
hughns Sep 11, 2024
0c762fd
Rageshake logging improvements
hughns Sep 11, 2024
8e38d66
Merge branch 'livekit' into hughns/to-device-key-distribution
hughns Sep 11, 2024
55ea373
Intercept matrix_sdk logging via console
hughns Sep 11, 2024
c1161ed
Bump js-sdk to fix embedded mode
hughns Sep 11, 2024
cb89bd0
Merge branch 'livekit' into hughns/do-device-key-distribution
hughns Sep 11, 2024
8f73f81
Request widget permission to send encryption key to device messages
hughns Sep 11, 2024
01c2efc
Merge branch 'livekit' into hughns/to-device-key-distribution
hughns Oct 30, 2024
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
Prev Previous commit
Next Next commit
Bump js-sdk
hughns committed Sep 9, 2024
commit e502cfb7ce27ec32cebc04a0201f946405a27062
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -83,7 +83,7 @@
"livekit-client": "^2.0.2",
"lodash": "^4.17.21",
"loglevel": "^1.9.1",
"matrix-js-sdk": "matrix-org/matrix-js-sdk#54cbaa814698e57d20751faeeb3af5f847481409",
"matrix-js-sdk": "matrix-org/matrix-js-sdk#f1974b2090c10bdf51b717ce4995fc70cd482364",
"matrix-widget-api": "^1.8.2",
"normalize.css": "^8.0.1",
"observable-hooks": "^4.2.3",
13 changes: 6 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -1889,10 +1889,9 @@
dependencies:
"@bufbuild/protobuf" "^1.7.2"

"@matrix-org/matrix-sdk-crypto-wasm@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-8.0.0.tgz"
integrity sha512-s0q3O2dK8b6hOJ+SZFz+s/IiMabmVsNue6r17sTwbrRD8liBkCrpjYnxoMYvtC01GggJ9TZLQbeqpt8hQSPHAg==
"@matrix-org/matrix-sdk-crypto-wasm@https://floofy.netlify.app/matrix-org-matrix-sdk-crypto-wasm-v7.0.0-to-device.tgz":
version "7.0.0"
resolved "https://floofy.netlify.app/matrix-org-matrix-sdk-crypto-wasm-v7.0.0-to-device.tgz#cf0df87e75d8780e3756eb13dce817ae272cc071"

"@matrix-org/olm@3.2.15":
version "3.2.15"
@@ -5950,12 +5949,12 @@ matrix-events-sdk@0.0.1:
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd"
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==

"matrix-js-sdk@github:matrix-org/matrix-js-sdk#54cbaa814698e57d20751faeeb3af5f847481409":
matrix-js-sdk@matrix-org/matrix-js-sdk#f1974b2090c10bdf51b717ce4995fc70cd482364:
version "34.4.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/54cbaa814698e57d20751faeeb3af5f847481409"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/f1974b2090c10bdf51b717ce4995fc70cd482364"
dependencies:
"@babel/runtime" "^7.12.5"
"@matrix-org/matrix-sdk-crypto-wasm" "^8.0.0"
"@matrix-org/matrix-sdk-crypto-wasm" "https://floofy.netlify.app/matrix-org-matrix-sdk-crypto-wasm-v7.0.0-to-device.tgz"
"@matrix-org/olm" "3.2.15"
another-json "^0.2.0"
bs58 "^6.0.0"

Unchanged files with check annotations Beta

appVersion,
matrixBackend: widget ? "embedded" : "jssdk",
callBackend: "livekit",
cryptoVersion: widget
? undefined
: window.matrixclient?.getCrypto()?.getVersion(),

Check warning on line 190 in src/analytics/PosthogAnalytics.ts

Codecov / codecov/patch

src/analytics/PosthogAnalytics.ts#L188-L190

Added lines #L188 - L190 were not covered by tests
};
}
case E2eeType.NONE:
return "none";
case E2eeType.SHARED_KEY:
return "shared";

Check warning on line 26 in src/analytics/PosthogEvents.ts

Codecov / codecov/patch

src/analytics/PosthogEvents.ts#L26

Added line #L26 was not covered by tests
case E2eeType.PER_PARTICIPANT:
return "per_sender";

Check warning on line 28 in src/analytics/PosthogEvents.ts

Codecov / codecov/patch

src/analytics/PosthogEvents.ts#L28

Added line #L28 was not covered by tests
}
}
interface CallEnded extends IPosthogEvent {
public track(
callId: string,
callParticipantsNow: number,
e2eeType: E2eeType,
rtcSession: MatrixRTCSession,

Check warning on line 67 in src/analytics/PosthogEvents.ts

Codecov / codecov/patch

src/analytics/PosthogEvents.ts#L66-L67

Added lines #L66 - L67 were not covered by tests
sendInstantly: boolean,
): void {
PosthogAnalytics.instance.trackEvent<CallEnded>(
callParticipantsMax: this.cache.maxParticipantsCount,
callParticipantsOnLeave: callParticipantsNow,
callDuration: (Date.now() - this.cache.startTime.getTime()) / 1000,
encryption: mapE2eeType(e2eeType),
toDeviceEncryptionKeysSent:
rtcSession.statistics.counters.toDeviceEncryptionKeysSent,
toDeviceEncryptionKeysReceived:
rtcSession.statistics.counters.toDeviceEncryptionKeysReceived,
toDeviceEncryptionKeysReceivedAverageAge:
rtcSession.statistics.counters.toDeviceEncryptionKeysReceived > 0
? rtcSession.statistics.totals
.toDeviceEncryptionKeysReceivedTotalAge /
rtcSession.statistics.counters.toDeviceEncryptionKeysReceived
: 0,
roomEventEncryptionKeysSent:
rtcSession.statistics.counters.roomEventEncryptionKeysSent,
roomEventEncryptionKeysReceived:
rtcSession.statistics.counters.roomEventEncryptionKeysReceived,
roomEventEncryptionKeysReceivedAverageAge:
rtcSession.statistics.counters.roomEventEncryptionKeysReceived > 0
? rtcSession.statistics.totals
.roomEventEncryptionKeysReceivedTotalAge /
rtcSession.statistics.counters.roomEventEncryptionKeysReceived
: 0,

Check warning on line 97 in src/analytics/PosthogEvents.ts

Codecov / codecov/patch

src/analytics/PosthogEvents.ts#L77-L97

Added lines #L77 - L97 were not covered by tests
},
{ send_instantly: sendInstantly },
);
import { useHistory } from "react-router-dom";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { useTranslation } from "react-i18next";
import { Dropdown, Heading } from "@vector-im/compound-web";

Check warning on line 12 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L12

Added line #L12 was not covered by tests
import { logger } from "matrix-js-sdk/src/logger";
import { Button } from "@vector-im/compound-web";
interface Props {
client: MatrixClient;
}
const encryptionOptions = {
shared: {
label: "Shared key",
e2eeType: E2eeType.SHARED_KEY,
},
sender: {
label: "Per-participant key",
e2eeType: E2eeType.PER_PARTICIPANT,
},
none: { label: "None", e2eeType: E2eeType.NONE },
};

Check warning on line 49 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L39-L49

Added lines #L39 - L49 were not covered by tests
export const RegisteredView: FC<Props> = ({ client }) => {
const [loading, setLoading] = useState(false);
[setJoinExistingCallModalOpen],
);
const [encryption, setEncryption] =
useState<keyof typeof encryptionOptions>("shared");

Check warning on line 65 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L64-L65

Added lines #L64 - L65 were not covered by tests
const onSubmit: FormEventHandler<HTMLFormElement> = useCallback(
(e: FormEvent) => {
setError(undefined);
setLoading(true);
const { roomId, encryptionSystem } = await createRoom(

Check warning on line 81 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L81

Added line #L81 was not covered by tests
client,
roomName,
encryptionOptions[encryption].e2eeType,

Check warning on line 84 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L84

Added line #L84 was not covered by tests
);
history.push(getRelativeRoomUrl(roomId, encryptionSystem, roomName));

Check warning on line 87 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L87

Added line #L87 was not covered by tests
}
submit().catch((error) => {
}
});
},
[client, history, setJoinExistingCallModalOpen, encryption],

Check warning on line 103 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L103

Added line #L103 was not covered by tests
);
const recentRooms = useGroupCallRooms(client);
data-testid="home_callName"
/>
<Dropdown
label="Encryption"
defaultValue={encryption}
onValueChange={(x) =>
setEncryption(x as keyof typeof encryptionOptions)

Check warning on line 146 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L142-L146

Added lines #L142 - L146 were not covered by tests
}
values={Object.keys(encryptionOptions).map((value) => [
value,
encryptionOptions[value as keyof typeof encryptionOptions]
.label,
])}
placeholder=""
/>

Check warning on line 154 in src/home/RegisteredView.tsx

Codecov / codecov/patch

src/home/RegisteredView.tsx#L148-L154

Added lines #L148 - L154 were not covered by tests
<Button
type="submit"
size="lg"
import { useHistory } from "react-router-dom";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { Trans, useTranslation } from "react-i18next";
import { Button, Dropdown, Heading } from "@vector-im/compound-web";

Check warning on line 12 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L12

Added line #L12 was not covered by tests
import { logger } from "matrix-js-sdk/src/logger";
import { useClient } from "../ClientContext";
import { E2eeType } from "../e2ee/e2eeType";
import { useOptInAnalytics } from "../settings/settings";
const encryptionOptions = {
shared: {
label: "Shared key",
e2eeType: E2eeType.SHARED_KEY,
},
sender: {
label: "Per-participant key",
e2eeType: E2eeType.PER_PARTICIPANT,
},
none: { label: "None", e2eeType: E2eeType.NONE },
};

Check warning on line 48 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L38-L48

Added lines #L38 - L48 were not covered by tests
export const UnauthenticatedView: FC = () => {
const { setClient } = useClient();
const { recaptchaKey, register } = useInteractiveRegistration();
const { execute, reset, recaptchaId } = useRecaptcha(recaptchaKey);
const [encryption, setEncryption] =
useState<keyof typeof encryptionOptions>("shared");

Check warning on line 59 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L58-L59

Added lines #L58 - L59 were not covered by tests
const [joinExistingCallModalOpen, setJoinExistingCallModalOpen] =
useState(false);
true,
);
let roomId;
let encryptionSystem;

Check warning on line 92 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L91-L92

Added lines #L91 - L92 were not covered by tests
try {
const res = await createRoom(

Check warning on line 94 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L94

Added line #L94 was not covered by tests
client,
roomName,
encryptionOptions[encryption].e2eeType,

Check warning on line 97 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L97

Added line #L97 was not covered by tests
);
roomId = res.roomId;
encryptionSystem = res.encryptionSystem;

Check warning on line 100 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L99-L100

Added lines #L99 - L100 were not covered by tests
} catch (error) {
if (!setClient) {
throw error;
// throw new Error("Failed to create room with shared secret");
setClient({ client, session });
history.push(getRelativeRoomUrl(roomId, encryptionSystem, roomName));

Check warning on line 131 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L131

Added line #L131 was not covered by tests
}
submit().catch((error) => {
history,
setJoinExistingCallModalOpen,
setClient,
encryption,

Check warning on line 148 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L148

Added line #L148 was not covered by tests
],
);
<ErrorMessage error={error} />
</FieldRow>
)}
<Dropdown
label="Encryption"
defaultValue={encryption}
onValueChange={(x) =>
setEncryption(x as keyof typeof encryptionOptions)

Check warning on line 215 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L211-L215

Added lines #L211 - L215 were not covered by tests
}
values={Object.keys(encryptionOptions).map((value) => [
value,
encryptionOptions[value as keyof typeof encryptionOptions]
.label,
])}
placeholder=""
/>

Check warning on line 223 in src/home/UnauthenticatedView.tsx

Codecov / codecov/patch

src/home/UnauthenticatedView.tsx#L217-L223

Added lines #L217 - L223 were not covered by tests
<Button
type="submit"
const { displayName, avatarUrl } = useProfile(client);
const roomName = useRoomName(rtcSession.room);
const roomAvatar = useRoomAvatar(rtcSession.room);
const { returnToLobby } = useUrlParams();

Check warning on line 91 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L91

Added line #L91 was not covered by tests
const e2eeSystem = useRoomEncryptionSystem(rtcSession.room.roomId);
const matrixInfo = useMemo((): MatrixInfo => {
ev: CustomEvent<IWidgetApiRequest>,
): Promise<void> => {
await defaultDeviceSetup(ev.detail.data as unknown as JoinCallData);
await enterRTCSession(rtcSession, e2eeSystem.kind);

Check warning on line 185 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L185

Added line #L185 was not covered by tests
await widget!.api.transport.reply(ev.detail, {});
};
widget.lazyActions.on(ElementWidgetActions.JoinCall, onJoin);
} else if (widget && !preload && skipLobby) {
const join = async (): Promise<void> => {
await defaultDeviceSetup({ audioInput: null, videoInput: null });
await enterRTCSession(rtcSession, e2eeSystem.kind);

Check warning on line 195 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L195

Added line #L195 was not covered by tests
};
// No lobby and no preload: we enter the RTC Session right away.
join();
}
}, [rtcSession, preload, skipLobby, e2eeSystem]);

Check warning on line 200 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L200

Added line #L200 was not covered by tests
const [left, setLeft] = useState(false);
const [leaveError, setLeaveError] = useState<Error | undefined>(undefined);
PosthogAnalytics.instance.eventCallEnded.track(
rtcSession.room.roomId,
rtcSession.memberships.length,
matrixInfo.e2eeSystem.kind,
rtcSession,

Check warning on line 218 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L217-L218

Added lines #L217 - L218 were not covered by tests
sendInstantly,
);
history.push("/");
}
},
[rtcSession, isPasswordlessUser, confineToRoom, history, matrixInfo],

Check warning on line 233 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L233

Added line #L233 was not covered by tests
);
useEffect(() => {
const onReconnect = useCallback(() => {
setLeft(false);
setLeaveError(undefined);
enterRTCSession(rtcSession, e2eeSystem.kind);
}, [rtcSession, e2eeSystem]);

Check warning on line 259 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L258-L259

Added lines #L258 - L259 were not covered by tests
const joinRule = useJoinRule(rtcSession.room);
client={client}
matrixInfo={matrixInfo}
muteStates={muteStates}
onEnter={() => void enterRTCSession(rtcSession, e2eeSystem.kind)}

Check warning on line 312 in src/room/GroupCallView.tsx

Codecov / codecov/patch

src/room/GroupCallView.tsx#L312

Added line #L312 was not covered by tests
confineToRoom={confineToRoom}
hideHeader={hideHeader}
participantCount={participantCount}
member: RoomMember | undefined,
participant: LocalParticipant | RemoteParticipant,
callEncrypted: boolean,
livekitRoom: LivekitRoom,

Check warning on line 167 in src/state/CallViewModel.ts

Codecov / codecov/patch

src/state/CallViewModel.ts#L167

Added line #L167 was not covered by tests
) {
this.vm =
participant instanceof LocalParticipant
? new LocalUserMediaViewModel(
id,
member,
participant,
callEncrypted,
livekitRoom,
)
: new RemoteUserMediaViewModel(
id,
member,
participant,
callEncrypted,
livekitRoom,
);

Check warning on line 184 in src/state/CallViewModel.ts

Codecov / codecov/patch

src/state/CallViewModel.ts#L171-L184

Added lines #L171 - L184 were not covered by tests
this.speaker = this.vm.speaking.pipe(
// Require 1 s of continuous speaking to become a speaker, and 60 s of
member: RoomMember | undefined,
participant: LocalParticipant | RemoteParticipant,
callEncrypted: boolean,
liveKitRoom: LivekitRoom,

Check warning on line 226 in src/state/CallViewModel.ts

Codecov / codecov/patch

src/state/CallViewModel.ts#L226

Added line #L226 was not covered by tests
) {
this.vm = new ScreenShareViewModel(
id,
member,
participant,
callEncrypted,
liveKitRoom,
);

Check warning on line 234 in src/state/CallViewModel.ts

Codecov / codecov/patch

src/state/CallViewModel.ts#L228-L234

Added lines #L228 - L234 were not covered by tests
}
public destroy(): void {
yield [
userMediaId,
prevItems.get(userMediaId) ??
new UserMedia(
userMediaId,
member,
p,
this.encrypted,
this.livekitRoom,
),

Check warning on line 373 in src/state/CallViewModel.ts

Codecov / codecov/patch

src/state/CallViewModel.ts#L367-L373

Added lines #L367 - L373 were not covered by tests
];
if (p.isScreenShareEnabled) {
yield [
screenShareId,
prevItems.get(screenShareId) ??
new ScreenShare(
screenShareId,
member,
p,
this.encrypted,
this.livekitRoom,
),

Check warning on line 387 in src/state/CallViewModel.ts

Codecov / codecov/patch

src/state/CallViewModel.ts#L381-L387

Added lines #L381 - L387 were not covered by tests
];
}
}
).pipe(
map((e) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const [err, participantIdentity] = e as any; // FIXME: fudge for type error during build
return (
(participantIdentity == participant.identity &&
err?.message.includes(criteria)) ??
false

Check warning on line 102 in src/state/MediaViewModel.ts

Codecov / codecov/patch

src/state/MediaViewModel.ts#L98-L102

Added lines #L98 - L102 were not covered by tests
);
}),
throttleTime(1000), // Throttle to avoid spamming the UI
member: RoomMember | undefined,
participant: LocalParticipant | RemoteParticipant,
callEncrypted: boolean,
livekitRoom: LivekitRoom,

Check warning on line 340 in src/state/MediaViewModel.ts

Codecov / codecov/patch

src/state/MediaViewModel.ts#L340

Added line #L340 was not covered by tests
) {
super(
id,
callEncrypted,
Track.Source.ScreenShareAudio,
Track.Source.ScreenShare,
livekitRoom,

Check warning on line 349 in src/state/MediaViewModel.ts

Codecov / codecov/patch

src/state/MediaViewModel.ts#L349

Added line #L349 was not covered by tests
);
}
}
const { t } = useTranslation();
const video = useObservableEagerState(vm.video);
const unencryptedWarning = useObservableEagerState(vm.unencryptedWarning);
const encryptionKeyMissing = useObservableEagerState(
vm.encryptionKeyMissing,
);
const encryptionKeyInvalid = useObservableEagerState(
vm.encryptionKeyInvalid,
);

Check warning on line 88 in src/tile/GridTile.tsx

Codecov / codecov/patch

src/tile/GridTile.tsx#L83-L88

Added lines #L83 - L88 were not covered by tests
const audioEnabled = useObservableEagerState(vm.audioEnabled);
const videoEnabled = useObservableEagerState(vm.videoEnabled);
const speaking = useObservableEagerState(vm.speaking);
[vm],
);
const participantId = useMemo(() => vm.participant.identity, [vm]);

Check warning on line 101 in src/tile/GridTile.tsx

Codecov / codecov/patch

src/tile/GridTile.tsx#L101

Added line #L101 was not covered by tests
const MicIcon = audioEnabled ? MicOnSolidIcon : MicOffSolidIcon;
video={video}
member={vm.member}
unencryptedWarning={unencryptedWarning}
encryptionKeyMissing={encryptionKeyMissing}
encryptionKeyInvalid={encryptionKeyInvalid}
participantId={participantId}

Check warning on line 127 in src/tile/GridTile.tsx

Codecov / codecov/patch

src/tile/GridTile.tsx#L125-L127

Added lines #L125 - L127 were not covered by tests
videoEnabled={videoEnabled && showVideo}
videoFit={cropVideo ? "cover" : "contain"}
className={classNames(className, styles.tile, {
nameTagLeadingIcon,
displayName,
primaryButton,
encryptionKeyMissing,
encryptionKeyInvalid,
participantId,

Check warning on line 58 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L56-L58

Added lines #L56 - L58 were not covered by tests
...props
},
ref,
<animated.div
className={classNames(styles.media, className, {
[styles.mirror]: mirror,
[styles.videoMuted]:
!videoEnabled || encryptionKeyInvalid || encryptionKeyMissing,

Check warning on line 70 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L69-L70

Added lines #L69 - L70 were not covered by tests
})}
style={style}
ref={ref}
)}
</div>
<div className={styles.fg}>
{encryptionKeyMissing && (
<div className={styles.status}>
<Text as="span" size="sm" weight="medium" className={styles.name}>

Check warning on line 98 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L96-L98

Added lines #L96 - L98 were not covered by tests
Encryption key missing
</Text>
</div>

Check warning on line 101 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L100-L101

Added lines #L100 - L101 were not covered by tests
)}
{encryptionKeyInvalid && (
<div className={styles.status}>
<Text as="span" size="sm" weight="medium" className={styles.name}>

Check warning on line 105 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L103-L105

Added lines #L103 - L105 were not covered by tests
Encryption key invalid
</Text>
</div>

Check warning on line 108 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L107-L108

Added lines #L107 - L108 were not covered by tests
)}
<div className={styles.nameTag} title={participantId}>

Check warning on line 110 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L110

Added line #L110 was not covered by tests
{nameTagLeadingIcon}
<Text as="span" size="sm" weight="medium" className={styles.name}>
{displayName} ({participantId})

Check warning on line 113 in src/tile/MediaView.tsx

Codecov / codecov/patch

src/tile/MediaView.tsx#L113

Added line #L113 was not covered by tests
</Text>
{unencryptedWarning && (
<Tooltip
const displayName = useDisplayName(vm);
const video = useObservableEagerState(vm.video);
const unencryptedWarning = useObservableEagerState(vm.unencryptedWarning);
const encryptionKeyMissing = useObservableEagerState(
vm.encryptionKeyMissing,
);
const encryptionKeyInvalid = useObservableEagerState(
vm.encryptionKeyInvalid,
);

Check warning on line 130 in src/tile/SpotlightTile.tsx

Codecov / codecov/patch

src/tile/SpotlightTile.tsx#L125-L130

Added lines #L125 - L130 were not covered by tests
const participantId = useMemo(
() => vm.participant.identity,
[vm.participant],
);

Check warning on line 135 in src/tile/SpotlightTile.tsx

Codecov / codecov/patch

src/tile/SpotlightTile.tsx#L132-L135

Added lines #L132 - L135 were not covered by tests
// Hook this item up to the intersection observer
useEffect(() => {
member: vm.member,
unencryptedWarning,
displayName,
encryptionKeyMissing,
encryptionKeyInvalid,
participantId,

Check warning on line 164 in src/tile/SpotlightTile.tsx

Codecov / codecov/patch

src/tile/SpotlightTile.tsx#L162-L164

Added lines #L162 - L164 were not covered by tests
};
return vm instanceof ScreenShareViewModel ? (
[client.getUserId()!]: 100,
},
},
initial_state:
e2ee === E2eeType.PER_PARTICIPANT
? [
{
type: EventType.RoomEncryption,
state_key: "",
content: {
algorithm: "m.megolm.v1.aes-sha2",
},
},
]
: undefined,

Check warning on line 272 in src/utils/matrix.ts

Codecov / codecov/patch

src/utils/matrix.ts#L261-L272

Added lines #L261 - L272 were not covered by tests
});
// Wait for the room to arrive
const result = await createPromise;
let encryptionSystem: EncryptionSystem;

Check warning on line 296 in src/utils/matrix.ts

Codecov / codecov/patch

src/utils/matrix.ts#L296

Added line #L296 was not covered by tests
if (e2ee == E2eeType.SHARED_KEY) {
const password = secureRandomBase64Url(16);

Check warning on line 298 in src/utils/matrix.ts

Codecov / codecov/patch

src/utils/matrix.ts#L298

Added line #L298 was not covered by tests
saveKeyForRoom(result.room_id, password);
encryptionSystem = {
kind: E2eeType.SHARED_KEY,
secret: password,
};
} else {
encryptionSystem = { kind: e2ee };

Check warning on line 305 in src/utils/matrix.ts

Codecov / codecov/patch

src/utils/matrix.ts#L300-L305

Added lines #L300 - L305 were not covered by tests
}
return {
roomId: result.room_id,
alias: e2ee ? undefined : fullAliasFromRoomName(name, client),
encryptionSystem,

Check warning on line 311 in src/utils/matrix.ts

Codecov / codecov/patch

src/utils/matrix.ts#L311

Added line #L311 was not covered by tests
};
}