mirror of
https://github.com/vector-im/element-call.git
synced 2026-08-20 20:49:20 +00:00
Compare commits
28 Commits
v0.23.0
...
SimonBrand
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28035b5028 | ||
|
|
d14d1e10c5 | ||
|
|
fce220c55f | ||
|
|
645b123bea | ||
|
|
a0f1184c40 | ||
|
|
ff9982683e | ||
|
|
2f6b1ea37c | ||
|
|
3a62eccdea | ||
|
|
8bae276fab | ||
|
|
3d57faca26 | ||
|
|
3a16dbe54e | ||
|
|
ba5c0424bf | ||
|
|
6bc6d50bce | ||
|
|
0ac651b03a | ||
|
|
18185be49c | ||
|
|
8516e528cb | ||
|
|
5862f911bc | ||
|
|
2ec75571d0 | ||
|
|
720e138199 | ||
|
|
ae04cfc53e | ||
|
|
912ed55f1e | ||
|
|
1a7b7c9470 | ||
|
|
ee304fb4b3 | ||
|
|
b57454fbc1 | ||
|
|
127e8c9103 | ||
|
|
f279bd69d7 | ||
|
|
b45c8924a6 | ||
|
|
fa5b014abe |
@@ -59,7 +59,7 @@
|
||||
"i18next-http-backend": "^1.4.4",
|
||||
"livekit-client": "^1.12.3",
|
||||
"lodash": "^4.17.21",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#6836720e1e1c2cb01d49d6e5fcfc01afc14834ca",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#0b72baada1dc9c14fb4ebe1b0595cef0acf4f2c8",
|
||||
"matrix-widget-api": "^1.3.1",
|
||||
"mermaid": "^9.0.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
|
||||
@@ -19,10 +19,10 @@ import { Trans } from "react-i18next";
|
||||
import { Banner } from "./Banner";
|
||||
import styles from "./E2EEBanner.module.css";
|
||||
import { ReactComponent as LockOffIcon } from "./icons/LockOff.svg";
|
||||
import { useEnableE2EE } from "./settings/useSetting";
|
||||
import { useEnableE2EE } from "./e2ee/e2eeHooks";
|
||||
|
||||
export const E2EEBanner = () => {
|
||||
const [e2eeEnabled] = useEnableE2EE();
|
||||
const e2eeEnabled = useEnableE2EE();
|
||||
if (e2eeEnabled) return null;
|
||||
|
||||
return (
|
||||
|
||||
@@ -92,6 +92,10 @@ interface UrlParams {
|
||||
* E2EE password
|
||||
*/
|
||||
password: string | null;
|
||||
/**
|
||||
* Whether we the app should use per participant keys for E2EE.
|
||||
*/
|
||||
perParticipantE2EE: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,6 +194,7 @@ export const getUrlParams = (
|
||||
fontScale: Number.isNaN(fontScale) ? null : fontScale,
|
||||
analyticsID: getParam("analyticsID"),
|
||||
allowIceFallback: hasParam("allowIceFallback"),
|
||||
perParticipantE2EE: hasParam("perParticipantE2EE"),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,9 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { isE2EESupported } from "livekit-client";
|
||||
|
||||
import { useEnableE2EE } from "../settings/useSetting";
|
||||
import { useEnableSPAE2EE } from "../settings/useSetting";
|
||||
import { useLocalStorage } from "../useLocalStorage";
|
||||
import { useClient } from "../ClientContext";
|
||||
import { PASSWORD_STRING, useUrlParams } from "../UrlParams";
|
||||
@@ -28,7 +29,7 @@ export const useInternalRoomSharedKey = (
|
||||
roomId: string
|
||||
): [string | null, (value: string) => void] => {
|
||||
const key = useMemo(() => getRoomSharedKeyLocalStorageKey(roomId), [roomId]);
|
||||
const [e2eeEnabled] = useEnableE2EE();
|
||||
const [e2eeEnabled] = useEnableSPAE2EE();
|
||||
const [roomSharedKey, setRoomSharedKey] = useLocalStorage(key);
|
||||
|
||||
return [e2eeEnabled ? roomSharedKey : null, setRoomSharedKey];
|
||||
@@ -67,7 +68,7 @@ export const useManageRoomSharedKey = (roomId: string): string | null => {
|
||||
};
|
||||
|
||||
export const useIsRoomE2EE = (roomId: string): boolean | null => {
|
||||
const { isEmbedded } = useUrlParams();
|
||||
const { isEmbedded, perParticipantE2EE } = useUrlParams();
|
||||
const client = useClient();
|
||||
const room = useMemo(
|
||||
() => client.client?.getRoom(roomId) ?? null,
|
||||
@@ -75,11 +76,32 @@ export const useIsRoomE2EE = (roomId: string): boolean | null => {
|
||||
);
|
||||
const isE2EE = useMemo(() => {
|
||||
if (isEmbedded) {
|
||||
return false;
|
||||
return perParticipantE2EE;
|
||||
} else {
|
||||
return room ? !room?.getCanonicalAlias() : null;
|
||||
}
|
||||
}, [isEmbedded, room]);
|
||||
}, [room, isEmbedded, perParticipantE2EE]);
|
||||
|
||||
return isE2EE;
|
||||
};
|
||||
|
||||
export const useEnableEmbeddedE2EE = (): boolean => {
|
||||
const { isEmbedded, perParticipantE2EE } = useUrlParams();
|
||||
|
||||
if (!isEmbedded) return false;
|
||||
if (!isE2EESupported()) return false;
|
||||
|
||||
return perParticipantE2EE;
|
||||
};
|
||||
|
||||
export const useEnableE2EE = (): boolean => {
|
||||
const [spaE2EEEnabled] = useEnableSPAE2EE();
|
||||
const embeddedE2EEEnabled = useEnableEmbeddedE2EE();
|
||||
|
||||
const e2eeEnabled = useMemo(
|
||||
() => spaE2EEEnabled || embeddedE2EEEnabled,
|
||||
[spaE2EEEnabled, embeddedE2EEEnabled]
|
||||
);
|
||||
|
||||
return e2eeEnabled;
|
||||
};
|
||||
69
src/e2ee/matrixKeyProvider.ts
Normal file
69
src/e2ee/matrixKeyProvider.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2023 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { BaseKeyProvider, createKeyMaterialFromString } from "livekit-client";
|
||||
import {
|
||||
MatrixRTCSession,
|
||||
MatrixRTCSessionEvent,
|
||||
} from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
|
||||
|
||||
export class MatrixKeyProvider extends BaseKeyProvider {
|
||||
private rtcSession?: MatrixRTCSession;
|
||||
|
||||
public setRTCSession(rtcSession: MatrixRTCSession) {
|
||||
if (this.rtcSession) {
|
||||
this.rtcSession.off(
|
||||
MatrixRTCSessionEvent.EncryptionKeyChanged,
|
||||
this.onEncryptionKeyChanged
|
||||
);
|
||||
}
|
||||
|
||||
this.rtcSession = rtcSession;
|
||||
|
||||
this.rtcSession.on(
|
||||
MatrixRTCSessionEvent.EncryptionKeyChanged,
|
||||
this.onEncryptionKeyChanged
|
||||
);
|
||||
|
||||
// The new session could be aware of keys of which the old session wasn't,
|
||||
// so emit a key changed event.
|
||||
for (const [
|
||||
participant,
|
||||
encryptionKeys,
|
||||
] of this.rtcSession.getEncryptionKeys()) {
|
||||
for (const [index, encryptionKey] of encryptionKeys.entries()) {
|
||||
this.onEncryptionKeyChanged(encryptionKey, index, participant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onEncryptionKeyChanged = async (
|
||||
encryptionKey: string,
|
||||
encryptionKeyIndex: number,
|
||||
participantId: string
|
||||
) => {
|
||||
this.onSetEncryptionKey(
|
||||
await createKeyMaterialFromString(encryptionKey),
|
||||
participantId,
|
||||
encryptionKeyIndex
|
||||
);
|
||||
|
||||
console.log(
|
||||
`Embedded-E2EE-LOG onEncryptionKeyChanged participantId=${participantId} encryptionKeyIndex=${encryptionKeyIndex} encryptionKey=${encryptionKey}`,
|
||||
this.getKeys()
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import styles from "./CallList.module.css";
|
||||
import { getRoomUrl } from "../matrix-utils";
|
||||
import { Body } from "../typography/Typography";
|
||||
import { GroupCallRoom } from "./useGroupCallRooms";
|
||||
import { useRoomSharedKey } from "../e2ee/sharedKeyManagement";
|
||||
import { useRoomSharedKey } from "../e2ee/e2eeHooks";
|
||||
|
||||
interface CallListProps {
|
||||
rooms: GroupCallRoom[];
|
||||
|
||||
@@ -38,11 +38,11 @@ import { JoinExistingCallModal } from "./JoinExistingCallModal";
|
||||
import { Caption, Title } from "../typography/Typography";
|
||||
import { Form } from "../form/Form";
|
||||
import { CallType, CallTypeDropdown } from "./CallTypeDropdown";
|
||||
import { useEnableE2EE, useOptInAnalytics } from "../settings/useSetting";
|
||||
import { useEnableSPAE2EE, useOptInAnalytics } from "../settings/useSetting";
|
||||
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
|
||||
import { E2EEBanner } from "../E2EEBanner";
|
||||
import { setLocalStorageItem } from "../useLocalStorage";
|
||||
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement";
|
||||
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/e2eeHooks";
|
||||
|
||||
interface Props {
|
||||
client: MatrixClient;
|
||||
@@ -57,7 +57,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
const { modalState, modalProps } = useModalTriggerState();
|
||||
const [e2eeEnabled] = useEnableE2EE();
|
||||
const [e2eeEnabled] = useEnableSPAE2EE();
|
||||
|
||||
const onSubmit: FormEventHandler<HTMLFormElement> = useCallback(
|
||||
(e: FormEvent) => {
|
||||
|
||||
@@ -40,10 +40,10 @@ import styles from "./UnauthenticatedView.module.css";
|
||||
import commonStyles from "./common.module.css";
|
||||
import { generateRandomName } from "../auth/generateRandomName";
|
||||
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
|
||||
import { useEnableE2EE, useOptInAnalytics } from "../settings/useSetting";
|
||||
import { useEnableSPAE2EE, useOptInAnalytics } from "../settings/useSetting";
|
||||
import { Config } from "../config/Config";
|
||||
import { E2EEBanner } from "../E2EEBanner";
|
||||
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement";
|
||||
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/e2eeHooks";
|
||||
import { setLocalStorageItem } from "../useLocalStorage";
|
||||
|
||||
export const UnauthenticatedView: FC = () => {
|
||||
@@ -60,7 +60,7 @@ export const UnauthenticatedView: FC = () => {
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [e2eeEnabled] = useEnableE2EE();
|
||||
const [e2eeEnabled] = useEnableSPAE2EE();
|
||||
|
||||
const onSubmit: FormEventHandler<HTMLFormElement> = useCallback(
|
||||
(e) => {
|
||||
|
||||
@@ -16,7 +16,6 @@ limitations under the License.
|
||||
|
||||
import {
|
||||
ConnectionState,
|
||||
E2EEOptions,
|
||||
ExternalE2EEKeyProvider,
|
||||
Room,
|
||||
RoomOptions,
|
||||
@@ -26,6 +25,7 @@ import { useLiveKitRoom } from "@livekit/components-react";
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import E2EEWorker from "livekit-client/e2ee-worker?worker";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
|
||||
|
||||
import { defaultLiveKitOptions } from "./options";
|
||||
import { SFUConfig } from "./openIDSFU";
|
||||
@@ -39,9 +39,16 @@ import {
|
||||
ECConnectionState,
|
||||
useECConnectionState,
|
||||
} from "./useECConnectionState";
|
||||
import { MatrixKeyProvider } from "../e2ee/matrixKeyProvider";
|
||||
|
||||
export enum E2EEMode {
|
||||
PerParticipantKey = "per_participant_key",
|
||||
SharedKey = "shared_key",
|
||||
}
|
||||
|
||||
export type E2EEConfig = {
|
||||
sharedKey: string;
|
||||
mode: E2EEMode;
|
||||
sharedKey?: string;
|
||||
};
|
||||
|
||||
setLogLevel("debug");
|
||||
@@ -53,25 +60,38 @@ interface UseLivekitResult {
|
||||
|
||||
export function useLiveKit(
|
||||
muteStates: MuteStates,
|
||||
rtcSession: MatrixRTCSession,
|
||||
sfuConfig?: SFUConfig,
|
||||
e2eeConfig?: E2EEConfig
|
||||
): UseLivekitResult {
|
||||
const e2eeOptions = useMemo(() => {
|
||||
if (!e2eeConfig?.sharedKey) return undefined;
|
||||
if (!e2eeConfig) return undefined;
|
||||
|
||||
return {
|
||||
keyProvider: new ExternalE2EEKeyProvider(),
|
||||
worker: new E2EEWorker(),
|
||||
} as E2EEOptions;
|
||||
if (e2eeConfig.mode === E2EEMode.PerParticipantKey) {
|
||||
return {
|
||||
keyProvider: new MatrixKeyProvider(),
|
||||
worker: new E2EEWorker(),
|
||||
};
|
||||
} else if (e2eeConfig.mode === E2EEMode.SharedKey && e2eeConfig.sharedKey) {
|
||||
return {
|
||||
keyProvider: new ExternalE2EEKeyProvider(),
|
||||
worker: new E2EEWorker(),
|
||||
};
|
||||
}
|
||||
}, [e2eeConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!e2eeConfig?.sharedKey || !e2eeOptions) return;
|
||||
if (!e2eeOptions) return;
|
||||
if (!e2eeConfig) return;
|
||||
|
||||
(e2eeOptions.keyProvider as ExternalE2EEKeyProvider).setKey(
|
||||
e2eeConfig?.sharedKey
|
||||
);
|
||||
}, [e2eeOptions, e2eeConfig?.sharedKey]);
|
||||
if (e2eeConfig.mode === E2EEMode.PerParticipantKey) {
|
||||
(e2eeOptions.keyProvider as MatrixKeyProvider).setRTCSession(rtcSession);
|
||||
} else if (e2eeConfig.mode === E2EEMode.SharedKey && e2eeConfig.sharedKey) {
|
||||
(e2eeOptions.keyProvider as ExternalE2EEKeyProvider).setKey(
|
||||
e2eeConfig.sharedKey
|
||||
);
|
||||
}
|
||||
}, [e2eeOptions, e2eeConfig, rtcSession]);
|
||||
|
||||
const initialMuteStates = useRef<MuteStates>(muteStates);
|
||||
const devices = useMediaDevices();
|
||||
|
||||
@@ -41,13 +41,17 @@ import { useMatrixRTCSessionJoinState } from "../useMatrixRTCSessionJoinState";
|
||||
import {
|
||||
useManageRoomSharedKey,
|
||||
useIsRoomE2EE,
|
||||
} from "../e2ee/sharedKeyManagement";
|
||||
import { useEnableE2EE } from "../settings/useSetting";
|
||||
useEnableE2EE,
|
||||
} from "../e2ee/e2eeHooks";
|
||||
import { useEnableSPAE2EE } from "../settings/useSetting";
|
||||
import { useRoomAvatar } from "./useRoomAvatar";
|
||||
import { useRoomName } from "./useRoomName";
|
||||
import { useModalTriggerState } from "../Modal";
|
||||
import { useJoinRule } from "./useJoinRule";
|
||||
import { ShareModal } from "./ShareModal";
|
||||
import { E2EEConfig, E2EEMode } from "../livekit/useLiveKit";
|
||||
import { useEnableEmbeddedE2EE } from "../e2ee/e2eeHooks";
|
||||
import { useUrlParams } from "../UrlParams";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -77,6 +81,10 @@ export function GroupCallView({
|
||||
|
||||
const e2eeSharedKey = useManageRoomSharedKey(rtcSession.room.roomId);
|
||||
const isRoomE2EE = useIsRoomE2EE(rtcSession.room.roomId);
|
||||
const [spaE2EEEnabled] = useEnableSPAE2EE();
|
||||
const embeddedE2EEEnabled = useEnableEmbeddedE2EE();
|
||||
const e2eeEnabled = useEnableE2EE();
|
||||
const { perParticipantE2EE } = useUrlParams();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -187,7 +195,7 @@ export function GroupCallView({
|
||||
}
|
||||
}
|
||||
|
||||
enterRTCSession(rtcSession);
|
||||
enterRTCSession(rtcSession, embeddedE2EEEnabled);
|
||||
|
||||
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
|
||||
// we only have room sessions right now, so call ID is the emprty string - we use the room ID
|
||||
@@ -206,18 +214,18 @@ export function GroupCallView({
|
||||
widget!.lazyActions.off(ElementWidgetActions.JoinCall, onJoin);
|
||||
};
|
||||
}
|
||||
}, [rtcSession, preload]);
|
||||
}, [rtcSession, preload, embeddedE2EEEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isEmbedded && !preload) {
|
||||
// In embedded mode, bypass the lobby and just enter the call straight away
|
||||
enterRTCSession(rtcSession);
|
||||
enterRTCSession(rtcSession, embeddedE2EEEnabled);
|
||||
|
||||
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
|
||||
// use the room ID as above
|
||||
PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId);
|
||||
}
|
||||
}, [rtcSession, isEmbedded, preload]);
|
||||
}, [rtcSession, isEmbedded, preload, embeddedE2EEEnabled]);
|
||||
|
||||
const [left, setLeft] = useState(false);
|
||||
const [leaveError, setLeaveError] = useState<Error | undefined>(undefined);
|
||||
@@ -271,18 +279,19 @@ export function GroupCallView({
|
||||
}
|
||||
}, [isJoined, rtcSession]);
|
||||
|
||||
const [e2eeEnabled] = useEnableE2EE();
|
||||
|
||||
const e2eeConfig = useMemo(
|
||||
() => (e2eeSharedKey ? { sharedKey: e2eeSharedKey } : undefined),
|
||||
[e2eeSharedKey]
|
||||
);
|
||||
const e2eeConfig = useMemo((): E2EEConfig | undefined => {
|
||||
if (perParticipantE2EE) {
|
||||
return { mode: E2EEMode.PerParticipantKey };
|
||||
} else if (e2eeSharedKey) {
|
||||
return { mode: E2EEMode.SharedKey, sharedKey: e2eeSharedKey };
|
||||
}
|
||||
}, [perParticipantE2EE, e2eeSharedKey]);
|
||||
|
||||
const onReconnect = useCallback(() => {
|
||||
setLeft(false);
|
||||
setLeaveError(undefined);
|
||||
enterRTCSession(rtcSession);
|
||||
}, [rtcSession]);
|
||||
enterRTCSession(rtcSession, embeddedE2EEEnabled);
|
||||
}, [rtcSession, embeddedE2EEEnabled]);
|
||||
|
||||
const joinRule = useJoinRule(rtcSession.room);
|
||||
|
||||
@@ -295,7 +304,7 @@ export function GroupCallView({
|
||||
);
|
||||
const onShareClick = joinRule === JoinRule.Public ? onShareClickFn : null;
|
||||
|
||||
if (e2eeEnabled && isRoomE2EE && !e2eeSharedKey) {
|
||||
if (spaE2EEEnabled && isRoomE2EE && !e2eeSharedKey) {
|
||||
return (
|
||||
<ErrorView
|
||||
error={
|
||||
@@ -376,7 +385,7 @@ export function GroupCallView({
|
||||
client={client}
|
||||
matrixInfo={matrixInfo}
|
||||
muteStates={muteStates}
|
||||
onEnter={() => enterRTCSession(rtcSession)}
|
||||
onEnter={() => enterRTCSession(rtcSession, embeddedE2EEEnabled)}
|
||||
isEmbedded={isEmbedded}
|
||||
hideHeader={hideHeader}
|
||||
participatingMembers={participatingMembers}
|
||||
|
||||
@@ -70,11 +70,11 @@ import { useLayoutStates } from "../video-grid/Layout";
|
||||
import { useWakeLock } from "../useWakeLock";
|
||||
import { useMergedRefs } from "../useMergedRefs";
|
||||
import { MuteStates } from "./MuteStates";
|
||||
import { useOpenIDSFU } from "../livekit/openIDSFU";
|
||||
import { MatrixInfo } from "./VideoPreview";
|
||||
import { ShareButton } from "../button/ShareButton";
|
||||
import { LayoutToggle } from "./LayoutToggle";
|
||||
import { ECConnectionState } from "../livekit/useECConnectionState";
|
||||
import { useOpenIDSFU } from "../livekit/openIDSFU";
|
||||
|
||||
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
||||
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
|
||||
@@ -91,6 +91,7 @@ export function ActiveCall(props: ActiveCallProps) {
|
||||
const sfuConfig = useOpenIDSFU(props.client, props.rtcSession);
|
||||
const { livekitRoom, connState } = useLiveKit(
|
||||
props.muteStates,
|
||||
props.rtcSession,
|
||||
sfuConfig,
|
||||
props.e2eeConfig
|
||||
);
|
||||
@@ -174,14 +175,12 @@ export function InCallView({
|
||||
room: livekitRoom,
|
||||
});
|
||||
|
||||
const toggleMicrophone = useCallback(
|
||||
() => muteStates.audio.setEnabled?.((e) => !e),
|
||||
[muteStates]
|
||||
);
|
||||
const toggleCamera = useCallback(
|
||||
() => muteStates.video.setEnabled?.((e) => !e),
|
||||
[muteStates]
|
||||
);
|
||||
const toggleMicrophone = useCallback(() => {
|
||||
muteStates.audio.setEnabled?.((e) => !e);
|
||||
}, [muteStates]);
|
||||
const toggleCamera = useCallback(() => {
|
||||
muteStates.video.setEnabled?.((e) => !e);
|
||||
}, [muteStates]);
|
||||
|
||||
// This function incorrectly assumes that there is a camera and microphone, which is not always the case.
|
||||
// TODO: Make sure that this module is resilient when it comes to camera/microphone availability!
|
||||
|
||||
@@ -26,7 +26,7 @@ import { Body, Link } from "../typography/Typography";
|
||||
import { useLocationNavigation } from "../useLocationNavigation";
|
||||
import { MatrixInfo, VideoPreview } from "./VideoPreview";
|
||||
import { MuteStates } from "./MuteStates";
|
||||
import { useRoomSharedKey } from "../e2ee/sharedKeyManagement";
|
||||
import { useRoomSharedKey } from "../e2ee/e2eeHooks";
|
||||
import { ShareButton } from "../button/ShareButton";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Modal, ModalContent, ModalProps } from "../Modal";
|
||||
import { CopyButton } from "../button";
|
||||
import { getRoomUrl } from "../matrix-utils";
|
||||
import styles from "./ShareModal.module.css";
|
||||
import { useRoomSharedKey } from "../e2ee/sharedKeyManagement";
|
||||
import { useRoomSharedKey } from "../e2ee/e2eeHooks";
|
||||
|
||||
interface Props extends Omit<ModalProps, "title" | "children"> {
|
||||
roomId: string;
|
||||
|
||||
@@ -26,8 +26,8 @@ import type { Room } from "matrix-js-sdk/src/models/room";
|
||||
import type { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall";
|
||||
import { setLocalStorageItem } from "../useLocalStorage";
|
||||
import { isLocalRoomId, createRoom, roomNameFromRoomId } from "../matrix-utils";
|
||||
import { useEnableE2EE } from "../settings/useSetting";
|
||||
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement";
|
||||
import { useEnableSPAE2EE } from "../settings/useSetting";
|
||||
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/e2eeHooks";
|
||||
|
||||
export type GroupCallLoaded = {
|
||||
kind: "loaded";
|
||||
@@ -62,7 +62,7 @@ export const useLoadGroupCall = (
|
||||
const { t } = useTranslation();
|
||||
const [state, setState] = useState<GroupCallStatus>({ kind: "loading" });
|
||||
|
||||
const [e2eeEnabled] = useEnableE2EE();
|
||||
const [e2eeEnabled] = useEnableSPAE2EE();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchOrCreateRoom = async (): Promise<Room> => {
|
||||
|
||||
@@ -33,7 +33,10 @@ function makeFocus(livekitAlias: string): LivekitFocus {
|
||||
};
|
||||
}
|
||||
|
||||
export function enterRTCSession(rtcSession: MatrixRTCSession) {
|
||||
export function enterRTCSession(
|
||||
rtcSession: MatrixRTCSession,
|
||||
encryptMedia: boolean
|
||||
) {
|
||||
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
|
||||
PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId);
|
||||
|
||||
@@ -44,7 +47,7 @@ export function enterRTCSession(rtcSession: MatrixRTCSession) {
|
||||
// right now we asume everything is a room-scoped call
|
||||
const livekitAlias = rtcSession.room.roomId;
|
||||
|
||||
rtcSession.joinRoomSession([makeFocus(livekitAlias)]);
|
||||
rtcSession.joinRoomSession([makeFocus(livekitAlias)], encryptMedia);
|
||||
}
|
||||
|
||||
export function leaveRTCSession(rtcSession: MatrixRTCSession) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
useOptInAnalytics,
|
||||
useDeveloperSettingsTab,
|
||||
useShowConnectionStats,
|
||||
useEnableE2EE,
|
||||
useEnableSPAE2EE,
|
||||
} from "./useSetting";
|
||||
import { FieldRow, InputField } from "../input/Input";
|
||||
import { Button } from "../button";
|
||||
@@ -69,7 +69,7 @@ export const SettingsModal = (props: Props) => {
|
||||
useDeveloperSettingsTab();
|
||||
const [showConnectionStats, setShowConnectionStats] =
|
||||
useShowConnectionStats();
|
||||
const [enableE2EE, setEnableE2EE] = useEnableE2EE();
|
||||
const [enableE2EE, setEnableE2EE] = useEnableSPAE2EE();
|
||||
|
||||
const downloadDebugLog = useDownloadDebugLog();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
setLocalStorageItem,
|
||||
useLocalStorage,
|
||||
} from "../useLocalStorage";
|
||||
import { useEnableEmbeddedE2EE } from "../e2ee/e2eeHooks";
|
||||
|
||||
type Setting<T> = [T, (value: T) => void];
|
||||
type DisableableSetting<T> = [T, ((value: T) => void) | null];
|
||||
@@ -89,14 +90,17 @@ export const useOptInAnalytics = (): DisableableSetting<boolean | null> => {
|
||||
return [false, null];
|
||||
};
|
||||
|
||||
export const useEnableE2EE = (): DisableableSetting<boolean | null> => {
|
||||
export const useEnableSPAE2EE = (): DisableableSetting<boolean | null> => {
|
||||
const embeddedE2EEEnabled = useEnableEmbeddedE2EE();
|
||||
const settingVal = useSetting<boolean | null>(
|
||||
"enable-end-to-end-encryption",
|
||||
true
|
||||
);
|
||||
if (isE2EESupported()) return settingVal;
|
||||
|
||||
return [false, null];
|
||||
if (embeddedE2EEEnabled) return [false, null];
|
||||
if (!isE2EESupported()) return [false, null];
|
||||
|
||||
return settingVal;
|
||||
};
|
||||
|
||||
export const useDeveloperSettingsTab = () =>
|
||||
|
||||
@@ -23,7 +23,6 @@ import type { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import type { IWidgetApiRequest } from "matrix-widget-api";
|
||||
import { LazyEventEmitter } from "./LazyEventEmitter";
|
||||
import { getUrlParams } from "./UrlParams";
|
||||
import { Config } from "./config/Config";
|
||||
|
||||
// Subset of the actions in matrix-react-sdk
|
||||
export enum ElementWidgetActions {
|
||||
@@ -79,6 +78,8 @@ export const widget: WidgetHelpers | null = (() => {
|
||||
logger.info("Widget API is available");
|
||||
const api = new WidgetApi(widgetId, parentOrigin);
|
||||
api.requestCapability(MatrixCapabilities.AlwaysOnScreen);
|
||||
api.requestCapabilityToSendEvent(EventType.CallEncryptionPrefix);
|
||||
api.requestCapabilityToReceiveEvent(EventType.CallEncryptionPrefix);
|
||||
|
||||
// Set up the lazy action emitter, but only for select actions that we
|
||||
// intend for the app to handle
|
||||
@@ -162,9 +163,6 @@ export const widget: WidgetHelpers | null = (() => {
|
||||
|
||||
const clientPromise = new Promise<MatrixClient>((resolve) => {
|
||||
(async () => {
|
||||
// wait for the config file to be ready (we load very early on so it might not
|
||||
// be otherwise)
|
||||
await Config.init();
|
||||
await client.startClient();
|
||||
resolve(client);
|
||||
})();
|
||||
|
||||
13
yarn.lock
13
yarn.lock
@@ -11624,9 +11624,9 @@ 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#6836720e1e1c2cb01d49d6e5fcfc01afc14834ca":
|
||||
version "28.0.0"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/6836720e1e1c2cb01d49d6e5fcfc01afc14834ca"
|
||||
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#0b72baada1dc9c14fb4ebe1b0595cef0acf4f2c8":
|
||||
version "28.1.0"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/0b72baada1dc9c14fb4ebe1b0595cef0acf4f2c8"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@matrix-org/matrix-sdk-crypto-wasm" "^1.2.3-alpha.0"
|
||||
@@ -15772,7 +15772,7 @@ utils-merge@1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
|
||||
|
||||
uuid@9, uuid@^9.0.0:
|
||||
uuid@9:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
||||
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||
@@ -15787,6 +15787,11 @@ uuid@^8.3.2:
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
||||
uuid@^9.0.0:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||
|
||||
v8-compile-cache@^2.0.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||
|
||||
Reference in New Issue
Block a user