mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-16 23:45:50 +00:00
renames + rewriting docs
This commit is contained in:
@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
|
||||
|
||||
import { type BaseKeyProvider, ExternalE2EEKeyProvider } from "livekit-client";
|
||||
import { type Logger } from "matrix-js-sdk/lib/logger";
|
||||
import { type MatrixRTCSession as JsSdkRtcSession } from "matrix-js-sdk/lib/matrixrtc";
|
||||
import { type MatrixRTCSession as JsSdkRTCSession } from "matrix-js-sdk/lib/matrixrtc";
|
||||
|
||||
import { E2eeType } from "../../../src/e2ee/e2eeType";
|
||||
import { MatrixKeyProvider } from "../../../src/e2ee/matrixKeyProvider";
|
||||
@@ -16,7 +16,7 @@ import { type EncryptionSystem } from "../../../src/e2ee/sharedKeyManagement";
|
||||
/** The LiveKit key provider for the encryption the host asked for, or none. */
|
||||
export function createKeyProvider(
|
||||
encryptionSystem: EncryptionSystem,
|
||||
session: JsSdkRtcSession,
|
||||
session: JsSdkRTCSession,
|
||||
logger: Logger,
|
||||
): BaseKeyProvider | undefined {
|
||||
switch (encryptionSystem.kind) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { type Logger } from "matrix-js-sdk/lib/logger";
|
||||
import {
|
||||
type LivekitTransport,
|
||||
type MatrixRTCSession as JsSdkRtcSession,
|
||||
type MatrixRTCSession as JsSdkRTCSession,
|
||||
type Status as RTCSessionStatus,
|
||||
} from "matrix-js-sdk/lib/matrixrtc";
|
||||
import { deepCompare } from "matrix-js-sdk/lib/utils";
|
||||
@@ -41,8 +41,8 @@ import {
|
||||
ConnectionState,
|
||||
} from "../../../src/state/CallViewModel/remoteMembers/Connection";
|
||||
import { type IConnectionManager } from "../../../src/state/CallViewModel/remoteMembers/ConnectionManager";
|
||||
import { type RtcSessionError } from "../api";
|
||||
import { toRtcSessionError } from "../utils/errors";
|
||||
import { type MatrixRTCError } from "../api";
|
||||
import { toMatrixRTCError } from "../utils/errors";
|
||||
import { type LocalTransport } from "./LocalTransport";
|
||||
import { type Publisher } from "./Publisher";
|
||||
|
||||
@@ -56,16 +56,16 @@ export enum PublishState {
|
||||
}
|
||||
|
||||
export type LocalMemberMediaState =
|
||||
| { connection: ConnectionState | RtcSessionError }
|
||||
| { connection: ConnectionState | MatrixRTCError }
|
||||
| PublishState
|
||||
| RtcSessionError;
|
||||
| MatrixRTCError;
|
||||
|
||||
export type LocalMemberState =
|
||||
| RtcSessionError
|
||||
| MatrixRTCError
|
||||
| TransportState.Waiting
|
||||
| {
|
||||
media: LocalMemberMediaState;
|
||||
matrix: RtcSessionError | RTCSessionStatus;
|
||||
matrix: MatrixRTCError | RTCSessionStatus;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
@@ -78,7 +78,7 @@ interface Props {
|
||||
/** The membership manager giving up on keeping the membership alive. */
|
||||
membershipManagerError$: Observable<unknown>;
|
||||
matrixRTCSession: Pick<
|
||||
JsSdkRtcSession,
|
||||
JsSdkRTCSession,
|
||||
"updateCallIntent" | "leaveRoomSession"
|
||||
>;
|
||||
cameraEnabled$: Behavior<boolean>;
|
||||
@@ -121,10 +121,10 @@ export function createLocalMembership$({
|
||||
}: Props): LocalMembership {
|
||||
const logger = parentLogger.getChild("[LocalMember]");
|
||||
|
||||
const fatalTransportError$ = new Subject<RtcSessionError>();
|
||||
const fatalTransportError$ = new Subject<MatrixRTCError>();
|
||||
const localTransport$ = localTransportWithErrors$.pipe(
|
||||
catchError((e: unknown) => {
|
||||
fatalTransportError$.next(toRtcSessionError(e));
|
||||
fatalTransportError$.next(toMatrixRTCError(e));
|
||||
return NEVER;
|
||||
}),
|
||||
);
|
||||
@@ -147,8 +147,8 @@ export function createLocalMembership$({
|
||||
|
||||
const joinRequested$ = new BehaviorSubject(false);
|
||||
const publisher$ = new BehaviorSubject<Publisher | null>(null);
|
||||
const publishError$ = new BehaviorSubject<RtcSessionError | null>(null);
|
||||
const matrixError$ = new BehaviorSubject<RtcSessionError | null>(null);
|
||||
const publishError$ = new BehaviorSubject<MatrixRTCError | null>(null);
|
||||
const matrixError$ = new BehaviorSubject<MatrixRTCError | null>(null);
|
||||
|
||||
scope.reconcile(connection$, async (connection) => {
|
||||
if (connection === null) return;
|
||||
@@ -171,7 +171,7 @@ export function createLocalMembership$({
|
||||
} else if (publisher.shouldPublish) await publisher.stopPublishing();
|
||||
} catch (e) {
|
||||
if (publishError$.value === null)
|
||||
publishError$.next(toRtcSessionError(e));
|
||||
publishError$.next(toMatrixRTCError(e));
|
||||
else logger.error("Another publish error", e);
|
||||
}
|
||||
},
|
||||
@@ -185,8 +185,7 @@ export function createLocalMembership$({
|
||||
joinMatrixRTC(transport.transport);
|
||||
} catch (e) {
|
||||
logger.error("Failed to enter the session", e);
|
||||
if (matrixError$.value === null)
|
||||
matrixError$.next(toRtcSessionError(e));
|
||||
if (matrixError$.value === null) matrixError$.next(toMatrixRTCError(e));
|
||||
}
|
||||
return Promise.resolve(async (): Promise<void> => {
|
||||
try {
|
||||
@@ -200,7 +199,7 @@ export function createLocalMembership$({
|
||||
|
||||
membershipManagerError$.pipe(scope.bind()).subscribe((e) => {
|
||||
logger.error("The membership manager stopped", e);
|
||||
if (matrixError$.value === null) matrixError$.next(toRtcSessionError(e));
|
||||
if (matrixError$.value === null) matrixError$.next(toMatrixRTCError(e));
|
||||
});
|
||||
|
||||
cameraEnabled$.pipe(scope.bind()).subscribe((videoEnabled) => {
|
||||
@@ -224,7 +223,7 @@ export function createLocalMembership$({
|
||||
return {
|
||||
connection:
|
||||
connectionState instanceof Error
|
||||
? toRtcSessionError(connectionState)
|
||||
? toMatrixRTCError(connectionState)
|
||||
: (connectionState ?? ConnectionState.Initialized),
|
||||
};
|
||||
return shouldPublish
|
||||
|
||||
@@ -6,8 +6,11 @@ Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type MatrixClient, type Room } from "matrix-js-sdk";
|
||||
import { logger as rootLogger } from "matrix-js-sdk/lib/logger";
|
||||
import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc";
|
||||
import { type Logger, logger as rootLogger } from "matrix-js-sdk/lib/logger";
|
||||
import {
|
||||
MatrixRTCSessionEvent,
|
||||
MatrixRTCSessionManager,
|
||||
} from "matrix-js-sdk/lib/matrixrtc";
|
||||
import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { combineLatest, from, fromEvent, map } from "rxjs";
|
||||
@@ -29,20 +32,20 @@ import {
|
||||
import { filterBehavior, generateItems } from "../../../src/utils/observable";
|
||||
import {
|
||||
type LocalMediaInputs,
|
||||
type LocalRtcMember,
|
||||
type RemoteRtcMember,
|
||||
type RtcSession,
|
||||
RtcSessionError,
|
||||
type RtcSessionOptions,
|
||||
type LocalRTCMember,
|
||||
type RemoteRTCMember,
|
||||
type MatrixRTCClient,
|
||||
MatrixRTCError,
|
||||
type MatrixRTCClientOptions,
|
||||
} from "../api";
|
||||
import { LivekitConnectionFactory } from "./ConnectionFactory";
|
||||
import { joinRtcSession, sessionTimings } from "./joinRtcSession";
|
||||
import { joinJsSdkSession, sessionTimings } from "./joinJsSdkSession";
|
||||
import { createKeyProvider } from "./KeyProvider";
|
||||
import { createLocalMembership$ } from "./LocalMember";
|
||||
import { getLocalTransport } from "./LocalTransport";
|
||||
import {
|
||||
createLocalRtcMember,
|
||||
createRemoteRtcMember,
|
||||
createLocalRTCMember,
|
||||
createRemoteRTCMember,
|
||||
membershipKeys,
|
||||
} from "./Members";
|
||||
import { Publisher } from "./Publisher";
|
||||
@@ -57,21 +60,26 @@ import { createTransportRegistry } from "./Transports";
|
||||
* js-sdk client, and only the SDK knows what that bridge needs. Holding the
|
||||
* client keeps that change inside the SDK.
|
||||
*/
|
||||
export function createRtcSession(
|
||||
export function createMatrixRTCClient(
|
||||
scope: ObservableScope,
|
||||
client: MatrixClient,
|
||||
room: Room,
|
||||
localMedia: LocalMediaInputs,
|
||||
options: RtcSessionOptions,
|
||||
): RtcSession {
|
||||
const logger = rootLogger.getChild("[RtcSession]");
|
||||
options: MatrixRTCClientOptions,
|
||||
): MatrixRTCClient {
|
||||
const logger = rootLogger.getChild("[MatrixRTCClient]");
|
||||
const userId = client.getUserId();
|
||||
const deviceId = client.getDeviceId();
|
||||
if (!(userId && deviceId))
|
||||
throw new RtcSessionError("The client has to be logged in");
|
||||
throw new MatrixRTCError("The client has to be logged in");
|
||||
const { encryptionSystem, matrixRTCMode } = options;
|
||||
|
||||
const jsSdkSession = client.matrixRTC.getRoomSession(room);
|
||||
const jsSdkSession = sessionManager(
|
||||
scope,
|
||||
client,
|
||||
options,
|
||||
logger,
|
||||
).getRoomSession(room);
|
||||
const keyProvider = createKeyProvider(encryptionSystem, jsSdkSession, logger);
|
||||
|
||||
const ownMembershipIdentity: CallMembershipIdentityParts = {
|
||||
@@ -136,11 +144,11 @@ export function createRtcSession(
|
||||
),
|
||||
),
|
||||
joinMatrixRTC: (transport) =>
|
||||
joinRtcSession(jsSdkSession, ownMembershipIdentity, transport, {
|
||||
joinJsSdkSession(jsSdkSession, ownMembershipIdentity, transport, {
|
||||
encryptMedia: keyProvider !== undefined,
|
||||
matrixRTCMode,
|
||||
sendNotificationType: options.sendNotificationType,
|
||||
callIntent: options.callIntent,
|
||||
applicationData: options.applicationData,
|
||||
}),
|
||||
membershipManagerError$: fromEvent(
|
||||
jsSdkSession,
|
||||
@@ -161,7 +169,7 @@ export function createRtcSession(
|
||||
encryptionSystem,
|
||||
};
|
||||
|
||||
const remoteMembers$ = scope.behavior<RemoteRtcMember[]>(
|
||||
const remoteMembers$ = scope.behavior<RemoteRTCMember[]>(
|
||||
createRemoteMatrixLivekitMembers$({
|
||||
scope,
|
||||
membershipsWithTransport$,
|
||||
@@ -170,7 +178,7 @@ export function createRtcSession(
|
||||
}).pipe(
|
||||
map(({ value }) => value),
|
||||
generateItems(
|
||||
"RtcSession remoteMembers",
|
||||
"MatrixRTCClient remoteMembers",
|
||||
function* (members) {
|
||||
for (const member of members)
|
||||
yield {
|
||||
@@ -179,7 +187,7 @@ export function createRtcSession(
|
||||
};
|
||||
},
|
||||
(memberScope, member$) =>
|
||||
createRemoteRtcMember(memberScope, member$.value, context),
|
||||
createRemoteRTCMember(memberScope, member$.value, context),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -196,9 +204,9 @@ export function createRtcSession(
|
||||
filterBehavior((membership) => membership !== null),
|
||||
),
|
||||
);
|
||||
const localMember$ = scope.behavior<LocalRtcMember | null>(
|
||||
const localMember$ = scope.behavior<LocalRTCMember | null>(
|
||||
mapScoped(scope, localMembership$, (memberScope, membership$) =>
|
||||
createLocalRtcMember(memberScope, membership$, localMembership, context),
|
||||
createLocalRTCMember(memberScope, membership$, localMembership, context),
|
||||
).pipe(map((member) => member ?? null)),
|
||||
);
|
||||
|
||||
@@ -233,3 +241,24 @@ export function createRtcSession(
|
||||
connectedTransports$: transports.connected$,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The js-sdk keeps one session manager per slot. The client comes with the
|
||||
* manager for the default slot; any other slot gets a manager of its own,
|
||||
* which lives as long as the scope.
|
||||
*/
|
||||
function sessionManager(
|
||||
scope: ObservableScope,
|
||||
client: MatrixClient,
|
||||
{ application = "m.call", slot = "ROOM" }: MatrixRTCClientOptions,
|
||||
logger: Logger,
|
||||
): MatrixRTCSessionManager {
|
||||
if (application === "m.call" && slot === "ROOM") return client.matrixRTC;
|
||||
const manager = new MatrixRTCSessionManager(logger, client, {
|
||||
application,
|
||||
id: slot,
|
||||
});
|
||||
manager.start();
|
||||
scope.onEnd(() => manager.stop());
|
||||
return manager;
|
||||
}
|
||||
+11
-11
@@ -20,10 +20,10 @@ import { type createMatrixMemberMetadata$ } from "../../../src/state/CallViewMod
|
||||
import { type RemoteMatrixLivekitMember } from "../../../src/state/CallViewModel/remoteMembers/MatrixLivekitMembers";
|
||||
import { type EncryptionSystem } from "../../../src/e2ee/sharedKeyManagement";
|
||||
import {
|
||||
type LocalRtcMember,
|
||||
type LocalRTCMember,
|
||||
type MemberMedia,
|
||||
type RemoteRtcMember,
|
||||
type RtcMember,
|
||||
type RemoteRTCMember,
|
||||
type RTCMember,
|
||||
} from "../api";
|
||||
import {
|
||||
createLivekitMemberMedia,
|
||||
@@ -51,13 +51,13 @@ export function membershipKeys(
|
||||
];
|
||||
}
|
||||
|
||||
export function createRemoteRtcMember(
|
||||
export function createRemoteRTCMember(
|
||||
scope: ObservableScope,
|
||||
member: RemoteMatrixLivekitMember,
|
||||
context: MemberContext,
|
||||
): RemoteRtcMember {
|
||||
): RemoteRTCMember {
|
||||
return {
|
||||
...createRtcMember(scope, member.membership$, context),
|
||||
...createRTCMember(scope, member.membership$, context),
|
||||
local: false,
|
||||
media$: mediaFor(
|
||||
scope,
|
||||
@@ -74,14 +74,14 @@ export function createRemoteRtcMember(
|
||||
};
|
||||
}
|
||||
|
||||
export function createLocalRtcMember(
|
||||
export function createLocalRTCMember(
|
||||
scope: ObservableScope,
|
||||
membership$: Behavior<CallMembership>,
|
||||
localMembership: LocalMembership,
|
||||
context: MemberContext,
|
||||
): LocalRtcMember {
|
||||
): LocalRTCMember {
|
||||
return {
|
||||
...createRtcMember(scope, membership$, context),
|
||||
...createRTCMember(scope, membership$, context),
|
||||
local: true,
|
||||
media$: mediaFor(
|
||||
scope,
|
||||
@@ -102,11 +102,11 @@ export function createLocalRtcMember(
|
||||
};
|
||||
}
|
||||
|
||||
function createRtcMember(
|
||||
function createRTCMember(
|
||||
scope: ObservableScope,
|
||||
membership$: Behavior<CallMembership>,
|
||||
{ metadata, transports }: MemberContext,
|
||||
): Omit<RtcMember, "local" | "media$"> {
|
||||
): Omit<RTCMember, "local" | "media$"> {
|
||||
const { userId, deviceId, rtcBackendIdentity } = membership$.value;
|
||||
return {
|
||||
id: rtcBackendIdentity,
|
||||
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
|
||||
|
||||
import {
|
||||
type LivekitTransport,
|
||||
type MatrixRTCSession as JsSdkRtcSession,
|
||||
type MatrixRTCSession as JsSdkRTCSession,
|
||||
type RTCCallIntent,
|
||||
type RTCNotificationType,
|
||||
} from "matrix-js-sdk/lib/matrixrtc";
|
||||
@@ -22,7 +22,7 @@ interface Options {
|
||||
encryptMedia: boolean;
|
||||
matrixRTCMode: MatrixRTCMode;
|
||||
sendNotificationType?: RTCNotificationType;
|
||||
callIntent?: RTCCallIntent;
|
||||
applicationData?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/** The session's timing defaults; a later slice makes them an input. */
|
||||
@@ -36,12 +36,21 @@ export const sessionTimings = {
|
||||
* alive and retries on failure.
|
||||
* @throws If the join could not be started.
|
||||
*/
|
||||
export function joinRtcSession(
|
||||
session: JsSdkRtcSession,
|
||||
export function joinJsSdkSession(
|
||||
session: JsSdkRTCSession,
|
||||
ownMembershipIdentity: CallMembershipIdentityParts,
|
||||
transport: LivekitTransport,
|
||||
{ encryptMedia, matrixRTCMode, sendNotificationType, callIntent }: Options,
|
||||
{
|
||||
encryptMedia,
|
||||
matrixRTCMode,
|
||||
sendNotificationType,
|
||||
applicationData,
|
||||
}: Options,
|
||||
): void {
|
||||
// The one piece of application data the js-sdk can put in a membership
|
||||
const intent = applicationData?.["m.call.intent"];
|
||||
const callIntent =
|
||||
typeof intent === "string" ? (intent as RTCCallIntent) : undefined;
|
||||
const timings = sessionTimings.delayed_leave;
|
||||
// Give up on the network as soon as either the sync has been down for the
|
||||
// grace period or the delayed leave has probably been sent, whichever is
|
||||
@@ -9,7 +9,7 @@ import { describe, expect, it } from "vitest";
|
||||
import { Status } from "matrix-js-sdk/lib/matrixrtc";
|
||||
|
||||
import { ConnectionState } from "../../../src/state/CallViewModel/remoteMembers/Connection";
|
||||
import { RtcSessionError } from "../api";
|
||||
import { MatrixRTCError } from "../api";
|
||||
import {
|
||||
type LocalMemberState,
|
||||
PublishState,
|
||||
@@ -25,7 +25,7 @@ const connecting: LocalMemberState = {
|
||||
media: { connection: ConnectionState.LivekitConnecting },
|
||||
matrix: Status.Connecting,
|
||||
};
|
||||
const error = new RtcSessionError("gone");
|
||||
const error = new MatrixRTCError("gone");
|
||||
|
||||
describe("sessionStatus", () => {
|
||||
it.each<[string, LocalMemberState, boolean, boolean, boolean, string]>([
|
||||
|
||||
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type RtcSessionError, type SessionConnectionStatus } from "../api";
|
||||
import { type MatrixRTCError, type ConnectionStatus } from "../api";
|
||||
import { type LocalMemberState, TransportState } from "./LocalMember";
|
||||
|
||||
/** The local member's state, collapsed to what a host shows. */
|
||||
@@ -14,7 +14,7 @@ export function sessionStatus(
|
||||
joinRequested: boolean,
|
||||
connected: boolean,
|
||||
reconnecting: boolean,
|
||||
): SessionConnectionStatus {
|
||||
): ConnectionStatus {
|
||||
if (fatalError(state) !== null) return "disconnected";
|
||||
if (state === TransportState.Waiting) return "waitingForTransport";
|
||||
if (connected) return "connected";
|
||||
@@ -23,7 +23,7 @@ export function sessionStatus(
|
||||
}
|
||||
|
||||
/** The error that stops the session, if the state holds one. */
|
||||
export function fatalError(state: LocalMemberState): RtcSessionError | null {
|
||||
export function fatalError(state: LocalMemberState): MatrixRTCError | null {
|
||||
if (state === TransportState.Waiting) return null;
|
||||
if (state instanceof Error) return state;
|
||||
if (state.matrix instanceof Error) return state.matrix;
|
||||
|
||||
Reference in New Issue
Block a user