Merge branch 'livekit' into toger5/track-processor-blur

This commit is contained in:
Robin
2025-04-18 12:32:03 +02:00
36 changed files with 1660 additions and 200 deletions

View File

@@ -55,11 +55,14 @@ export function useLiveKit(
if (e2eeSystem.kind === E2eeType.NONE) return undefined;
if (e2eeSystem.kind === E2eeType.PER_PARTICIPANT) {
logger.info("Created MatrixKeyProvider (per participant)");
return {
keyProvider: new MatrixKeyProvider(),
worker: new E2EEWorker(),
};
} else if (e2eeSystem.kind === E2eeType.SHARED_KEY && e2eeSystem.secret) {
logger.info("Created ExternalE2EEKeyProvider (shared key)");
return {
keyProvider: new ExternalE2EEKeyProvider(),
worker: new E2EEWorker(),

View File

@@ -62,6 +62,7 @@ import {
} from "../utils/errors.ts";
import { GroupCallErrorBoundary } from "./GroupCallErrorBoundary.tsx";
import {
useExperimentalToDeviceTransportSetting,
useNewMembershipManagerSetting as useNewMembershipManagerSetting,
useSetting,
} from "../settings/settings";
@@ -151,6 +152,9 @@ export const GroupCallView: FC<Props> = ({
const { perParticipantE2EE, returnToLobby } = useUrlParams();
const e2eeSystem = useRoomEncryptionSystem(room.roomId);
const [useNewMembershipManager] = useSetting(useNewMembershipManagerSetting);
const [useExperimentalToDeviceTransport] = useSetting(
useExperimentalToDeviceTransportSetting,
);
usePageTitle(roomName);
@@ -178,16 +182,13 @@ export const GroupCallView: FC<Props> = ({
const latestMuteStates = useLatest(muteStates);
const enterRTCSessionOrError = useCallback(
async (
rtcSession: MatrixRTCSession,
perParticipantE2EE: boolean,
newMembershipManager: boolean,
): Promise<void> => {
async (rtcSession: MatrixRTCSession): Promise<void> => {
try {
await enterRTCSession(
rtcSession,
perParticipantE2EE,
newMembershipManager,
useNewMembershipManager,
useExperimentalToDeviceTransport,
);
} catch (e) {
if (e instanceof ElementCallError) {
@@ -201,7 +202,11 @@ export const GroupCallView: FC<Props> = ({
}
}
},
[setExternalError],
[
perParticipantE2EE,
useExperimentalToDeviceTransport,
useNewMembershipManager,
],
);
useEffect(() => {
@@ -253,11 +258,7 @@ export const GroupCallView: FC<Props> = ({
await defaultDeviceSetup(
ev.detail.data as unknown as JoinCallData,
);
await enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
);
await enterRTCSessionOrError(rtcSession);
widget.api.transport.reply(ev.detail, {});
})().catch((e) => {
logger.error("Error joining RTC session", e);
@@ -270,21 +271,13 @@ export const GroupCallView: FC<Props> = ({
} else {
// No lobby and no preload: we enter the rtc session right away
(async (): Promise<void> => {
await enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
);
await enterRTCSessionOrError(rtcSession);
})().catch((e) => {
logger.error("Error joining RTC session", e);
});
}
} else {
void enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
);
void enterRTCSessionOrError(rtcSession);
}
}
}, [
@@ -407,13 +400,7 @@ export const GroupCallView: FC<Props> = ({
client={client}
matrixInfo={matrixInfo}
muteStates={muteStates}
onEnter={() =>
void enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
)
}
onEnter={() => void enterRTCSessionOrError(rtcSession)}
confineToRoom={confineToRoom}
hideHeader={hideHeader}
participantCount={participantCount}
@@ -491,11 +478,7 @@ export const GroupCallView: FC<Props> = ({
recoveryActionHandler={(action) => {
if (action == "reconnect") {
setLeft(false);
enterRTCSessionOrError(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
).catch((e) => {
enterRTCSessionOrError(rtcSession).catch((e) => {
logger.error("Error re-entering RTC session", e);
});
}

View File

@@ -10,6 +10,7 @@ import {
RoomContext,
useLocalParticipant,
} from "@livekit/components-react";
import { Text } from "@vector-im/compound-web";
import { ConnectionState, type Room } from "livekit-client";
import { type MatrixClient } from "matrix-js-sdk";
import {
@@ -31,6 +32,7 @@ import classNames from "classnames";
import { BehaviorSubject, map } from "rxjs";
import { useObservable, useObservableEagerState } from "observable-hooks";
import { logger } from "matrix-js-sdk/lib/logger";
import { RoomAndToDeviceEvents } from "matrix-js-sdk/lib/matrixrtc/RoomAndToDeviceKeyTransport";
import LogoMark from "../icons/LogoMark.svg?react";
import LogoType from "../icons/LogoType.svg?react";
@@ -94,10 +96,12 @@ import { ReactionsOverlay } from "./ReactionsOverlay";
import { CallEventAudioRenderer } from "./CallEventAudioRenderer";
import {
debugTileLayout as debugTileLayoutSetting,
useExperimentalToDeviceTransportSetting,
useSetting,
} from "../settings/settings";
import { ReactionsReader } from "../reactions/ReactionsReader";
import { ConnectionLostError } from "../utils/errors.ts";
import { useTypedEventEmitter } from "../useEvents.ts";
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
@@ -216,6 +220,21 @@ export const InCallView: FC<InCallViewProps> = ({
room: livekitRoom,
});
const [toDeviceEncryptionSetting] = useSetting(
useExperimentalToDeviceTransportSetting,
);
const [showToDeviceEncryption, setShowToDeviceEncryption] = useState(
() => toDeviceEncryptionSetting,
);
useEffect(() => {
setShowToDeviceEncryption(toDeviceEncryptionSetting);
}, [toDeviceEncryptionSetting]);
useTypedEventEmitter(
rtcSession,
RoomAndToDeviceEvents.EnabledTransportsChanged,
(enabled) => setShowToDeviceEncryption(enabled.to_device),
);
const toggleMicrophone = useCallback(
() => muteStates.audio.setEnabled?.((e) => !e),
[muteStates],
@@ -662,6 +681,18 @@ export const InCallView: FC<InCallViewProps> = ({
</RightNav>
</Header>
))}
{
// TODO: remove this once we remove the developer flag gets removed and we have shipped to
// device transport as the default.
showToDeviceEncryption && (
<Text
style={{ height: 0, zIndex: 1, alignSelf: "center", margin: 0 }}
size="sm"
>
using to Device key transport
</Text>
)
}
<RoomAudioRenderer />
{renderContent()}
<CallEventAudioRenderer vm={vm} />

View File

@@ -112,6 +112,7 @@ test("It joins the correct Session", async () => {
manageMediaKeys: false,
useLegacyMemberEvents: false,
useNewMembershipManager: true,
useExperimentalToDeviceTransport: false,
},
);
});

View File

@@ -98,6 +98,7 @@ export async function enterRTCSession(
rtcSession: MatrixRTCSession,
encryptMedia: boolean,
useNewMembershipManager = true,
useExperimentalToDeviceTransport = false,
): Promise<void> {
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId);
@@ -125,6 +126,7 @@ export async function enterRTCSession(
membershipKeepAlivePeriod:
matrixRtcSessionConfig?.membership_keep_alive_period,
makeKeyDelay: matrixRtcSessionConfig?.key_rotation_on_leave_delay,
useExperimentalToDeviceTransport,
},
);
if (widget) {

View File

@@ -16,6 +16,7 @@ import {
showNonMemberTiles as showNonMemberTilesSetting,
showConnectionStats as showConnectionStatsSetting,
useNewMembershipManagerSetting,
useExperimentalToDeviceTransportSetting,
} from "./settings";
import type { MatrixClient } from "matrix-js-sdk";
import type { Room as LivekitRoom } from "livekit-client";
@@ -44,6 +45,10 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
useNewMembershipManagerSetting,
);
const [
useExperimentalToDeviceTransport,
setUseExperimentalToDeviceTransport,
] = useSetting(useExperimentalToDeviceTransportSetting);
const urlParams = useUrlParams();
const sfuUrl = useMemo((): URL | null => {
@@ -156,6 +161,20 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
)}
/>
</FieldRow>
<FieldRow>
<InputField
id="useToDeviceKeyTransport"
type="checkbox"
label={t("developer_mode.use_to_device_key_transport")}
checked={!!useExperimentalToDeviceTransport}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
setUseExperimentalToDeviceTransport(event.target.checked);
},
[setUseExperimentalToDeviceTransport],
)}
/>
</FieldRow>
{livekitRoom ? (
<>
<p>

View File

@@ -119,4 +119,10 @@ export const useNewMembershipManagerSetting = new Setting<boolean>(
"new-membership-manager",
true,
);
export const useExperimentalToDeviceTransportSetting = new Setting<boolean>(
"experimental-to-device-transport",
true,
);
export const alwaysShowSelf = new Setting<boolean>("always-show-self", true);