Split MatrixLivekitMembers more verbosely into two types
This commit is contained in:
@@ -116,7 +116,7 @@ import { createConnectionManager$ } from "./remoteMembers/ConnectionManager.ts";
|
|||||||
import {
|
import {
|
||||||
createMatrixLivekitMembers$,
|
createMatrixLivekitMembers$,
|
||||||
type TaggedParticipant,
|
type TaggedParticipant,
|
||||||
type MatrixLivekitMember,
|
type LocalMatrixLivekitMember,
|
||||||
} from "./remoteMembers/MatrixLivekitMembers.ts";
|
} from "./remoteMembers/MatrixLivekitMembers.ts";
|
||||||
import {
|
import {
|
||||||
type AutoLeaveReason,
|
type AutoLeaveReason,
|
||||||
@@ -510,7 +510,7 @@ export function createCallViewModel$(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const localMatrixLivekitMember$: Behavior<MatrixLivekitMember<"local"> | null> =
|
const localMatrixLivekitMember$: Behavior<LocalMatrixLivekitMember | null> =
|
||||||
scope.behavior(
|
scope.behavior(
|
||||||
localRtcMembership$.pipe(
|
localRtcMembership$.pipe(
|
||||||
filterBehavior((membership) => membership !== null),
|
filterBehavior((membership) => membership !== null),
|
||||||
@@ -682,10 +682,8 @@ export function createCallViewModel$(
|
|||||||
let localParticipantId: string | undefined = undefined;
|
let localParticipantId: string | undefined = undefined;
|
||||||
// add local member if available
|
// add local member if available
|
||||||
if (localMatrixLivekitMember) {
|
if (localMatrixLivekitMember) {
|
||||||
const { userId, connection$, membership$ } =
|
const { userId, participant, connection$, membership$ } =
|
||||||
localMatrixLivekitMember;
|
localMatrixLivekitMember;
|
||||||
const participant: TaggedParticipant =
|
|
||||||
localMatrixLivekitMember.participant; // Widen the type
|
|
||||||
localParticipantId = `${userId}:${membership$.value.deviceId}`; // should be membership$.value.membershipID which is not optional
|
localParticipantId = `${userId}:${membership$.value.deviceId}`; // should be membership$.value.membershipID which is not optional
|
||||||
// const participantId = membership$.value.membershipID;
|
// const participantId = membership$.value.membershipID;
|
||||||
if (localParticipantId) {
|
if (localParticipantId) {
|
||||||
@@ -695,7 +693,7 @@ export function createCallViewModel$(
|
|||||||
dup,
|
dup,
|
||||||
localParticipantId,
|
localParticipantId,
|
||||||
userId,
|
userId,
|
||||||
participant,
|
participant satisfies TaggedParticipant as TaggedParticipant, // Widen the type safely
|
||||||
connection$,
|
connection$,
|
||||||
],
|
],
|
||||||
data: undefined,
|
data: undefined,
|
||||||
@@ -727,7 +725,7 @@ export function createCallViewModel$(
|
|||||||
dup,
|
dup,
|
||||||
participantId,
|
participantId,
|
||||||
userId,
|
userId,
|
||||||
participant$,
|
participant,
|
||||||
connection$,
|
connection$,
|
||||||
) => {
|
) => {
|
||||||
const livekitRoom$ = scope.behavior(
|
const livekitRoom$ = scope.behavior(
|
||||||
@@ -746,7 +744,7 @@ export function createCallViewModel$(
|
|||||||
scope,
|
scope,
|
||||||
`${participantId}:${dup}`,
|
`${participantId}:${dup}`,
|
||||||
userId,
|
userId,
|
||||||
participant$,
|
participant,
|
||||||
options.encryptionSystem,
|
options.encryptionSystem,
|
||||||
livekitRoom$,
|
livekitRoom$,
|
||||||
focusUrl$,
|
focusUrl$,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { combineLatest, map, type Observable } from "rxjs";
|
|||||||
|
|
||||||
import { type IConnectionManager } from "./ConnectionManager.ts";
|
import { type IConnectionManager } from "./ConnectionManager.ts";
|
||||||
import {
|
import {
|
||||||
type MatrixLivekitMember,
|
type RemoteMatrixLivekitMember,
|
||||||
createMatrixLivekitMembers$,
|
createMatrixLivekitMembers$,
|
||||||
} from "./MatrixLivekitMembers.ts";
|
} from "./MatrixLivekitMembers.ts";
|
||||||
import {
|
import {
|
||||||
@@ -100,7 +100,7 @@ test("should signal participant not yet connected to livekit", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", {
|
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", {
|
||||||
a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => {
|
a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => {
|
||||||
expect(data.length).toEqual(1);
|
expect(data.length).toEqual(1);
|
||||||
expectObservable(data[0].membership$).toBe("a", {
|
expectObservable(data[0].membership$).toBe("a", {
|
||||||
a: bobMembership,
|
a: bobMembership,
|
||||||
@@ -180,7 +180,7 @@ test("should signal participant on a connection that is publishing", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", {
|
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", {
|
||||||
a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => {
|
a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => {
|
||||||
expect(data.length).toEqual(1);
|
expect(data.length).toEqual(1);
|
||||||
expectObservable(data[0].membership$).toBe("a", {
|
expectObservable(data[0].membership$).toBe("a", {
|
||||||
a: bobMembership,
|
a: bobMembership,
|
||||||
@@ -231,7 +231,7 @@ test("should signal participant on a connection that is not publishing", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", {
|
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", {
|
||||||
a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => {
|
a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => {
|
||||||
expect(data.length).toEqual(1);
|
expect(data.length).toEqual(1);
|
||||||
expectObservable(data[0].membership$).toBe("a", {
|
expectObservable(data[0].membership$).toBe("a", {
|
||||||
a: bobMembership,
|
a: bobMembership,
|
||||||
@@ -296,7 +296,7 @@ describe("Publication edge case", () => {
|
|||||||
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe(
|
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe(
|
||||||
"a",
|
"a",
|
||||||
{
|
{
|
||||||
a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => {
|
a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => {
|
||||||
expect(data.length).toEqual(2);
|
expect(data.length).toEqual(2);
|
||||||
expectObservable(data[0].membership$).toBe("a", {
|
expectObservable(data[0].membership$).toBe("a", {
|
||||||
a: bobMembership,
|
a: bobMembership,
|
||||||
@@ -362,7 +362,7 @@ describe("Publication edge case", () => {
|
|||||||
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe(
|
expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe(
|
||||||
"a",
|
"a",
|
||||||
{
|
{
|
||||||
a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => {
|
a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => {
|
||||||
expect(data.length).toEqual(2);
|
expect(data.length).toEqual(2);
|
||||||
expectObservable(data[0].membership$).toBe("a", {
|
expectObservable(data[0].membership$).toBe("a", {
|
||||||
a: bobMembership,
|
a: bobMembership,
|
||||||
|
|||||||
@@ -21,30 +21,44 @@ import { generateItemsWithEpoch } from "../../../utils/observable";
|
|||||||
|
|
||||||
const logger = rootLogger.getChild("[MatrixLivekitMembers]");
|
const logger = rootLogger.getChild("[MatrixLivekitMembers]");
|
||||||
|
|
||||||
/**
|
interface LocalTaggedParticipant {
|
||||||
* A dynamic participant value with a static tag to tell what kind of
|
type: "local";
|
||||||
* participant it can be (local vs. remote).
|
value$: Behavior<LocalParticipant | null>;
|
||||||
*/
|
}
|
||||||
|
interface RemoteTaggedParticipant {
|
||||||
|
type: "remote";
|
||||||
|
value$: Behavior<RemoteParticipant | null>;
|
||||||
|
}
|
||||||
export type TaggedParticipant =
|
export type TaggedParticipant =
|
||||||
| { type: "local"; value$: Behavior<LocalParticipant | null> }
|
| LocalTaggedParticipant
|
||||||
| { type: "remote"; value$: Behavior<RemoteParticipant | null> };
|
| RemoteTaggedParticipant;
|
||||||
|
|
||||||
/**
|
interface MatrixLivekitMember {
|
||||||
* Represents a Matrix call member and their associated LiveKit participation.
|
|
||||||
* `livekitParticipant` can be undefined if the member is not yet connected to the livekit room
|
|
||||||
* or if it has no livekit transport at all.
|
|
||||||
*/
|
|
||||||
export interface MatrixLivekitMember<
|
|
||||||
ParticipantType extends TaggedParticipant["type"],
|
|
||||||
> {
|
|
||||||
membership$: Behavior<CallMembership>;
|
membership$: Behavior<CallMembership>;
|
||||||
participant: TaggedParticipant & { type: ParticipantType };
|
|
||||||
connection$: Behavior<Connection | null>;
|
connection$: Behavior<Connection | null>;
|
||||||
// participantId: string; We do not want a participantId here since it will be generated by the jwt
|
// participantId: string; We do not want a participantId here since it will be generated by the jwt
|
||||||
// TODO decide if we can also drop the userId. Its in the matrix membership anyways.
|
// TODO decide if we can also drop the userId. Its in the matrix membership anyways.
|
||||||
userId: string;
|
userId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the local Matrix call member and their associated LiveKit participation.
|
||||||
|
* `livekitParticipant` can be null if the member is not yet connected to the livekit room
|
||||||
|
* or if it has no livekit transport at all.
|
||||||
|
*/
|
||||||
|
export interface LocalMatrixLivekitMember extends MatrixLivekitMember {
|
||||||
|
participant: LocalTaggedParticipant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a remote Matrix call member and their associated LiveKit participation.
|
||||||
|
* `livekitParticipant` can be null if the member is not yet connected to the livekit room
|
||||||
|
* or if it has no livekit transport at all.
|
||||||
|
*/
|
||||||
|
export interface RemoteMatrixLivekitMember extends MatrixLivekitMember {
|
||||||
|
participant: RemoteTaggedParticipant;
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
scope: ObservableScope;
|
scope: ObservableScope;
|
||||||
membershipsWithTransport$: Behavior<
|
membershipsWithTransport$: Behavior<
|
||||||
@@ -66,7 +80,7 @@ export function createMatrixLivekitMembers$({
|
|||||||
scope,
|
scope,
|
||||||
membershipsWithTransport$,
|
membershipsWithTransport$,
|
||||||
connectionManager,
|
connectionManager,
|
||||||
}: Props): Behavior<Epoch<MatrixLivekitMember<"remote">[]>> {
|
}: Props): Behavior<Epoch<RemoteMatrixLivekitMember[]>> {
|
||||||
/**
|
/**
|
||||||
* Stream of all the call members and their associated livekit data (if available).
|
* Stream of all the call members and their associated livekit data (if available).
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import { type ProcessorState } from "../../../livekit/TrackProcessorContext.tsx"
|
|||||||
import {
|
import {
|
||||||
areLivekitTransportsEqual,
|
areLivekitTransportsEqual,
|
||||||
createMatrixLivekitMembers$,
|
createMatrixLivekitMembers$,
|
||||||
type MatrixLivekitMember,
|
type RemoteMatrixLivekitMember,
|
||||||
} from "./MatrixLivekitMembers.ts";
|
} from "./MatrixLivekitMembers.ts";
|
||||||
import { createConnectionManager$ } from "./ConnectionManager.ts";
|
import { createConnectionManager$ } from "./ConnectionManager.ts";
|
||||||
import { membershipsAndTransports$ } from "../../SessionBehaviors.ts";
|
import { membershipsAndTransports$ } from "../../SessionBehaviors.ts";
|
||||||
@@ -132,7 +132,7 @@ test("bob, carl, then bob joining no tracks yet", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expectObservable(matrixLivekitItems$).toBe(vMarble, {
|
expectObservable(matrixLivekitItems$).toBe(vMarble, {
|
||||||
a: expect.toSatisfy((e: Epoch<MatrixLivekitMember<"remote">[]>) => {
|
a: expect.toSatisfy((e: Epoch<RemoteMatrixLivekitMember[]>) => {
|
||||||
const items = e.value;
|
const items = e.value;
|
||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
const item = items[0]!;
|
const item = items[0]!;
|
||||||
@@ -152,7 +152,7 @@ test("bob, carl, then bob joining no tracks yet", () => {
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
b: expect.toSatisfy((e: Epoch<MatrixLivekitMember<"remote">[]>) => {
|
b: expect.toSatisfy((e: Epoch<RemoteMatrixLivekitMember[]>) => {
|
||||||
const items = e.value;
|
const items = e.value;
|
||||||
expect(items.length).toBe(2);
|
expect(items.length).toBe(2);
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ test("bob, carl, then bob joining no tracks yet", () => {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
c: expect.toSatisfy((e: Epoch<MatrixLivekitMember<"remote">[]>) => {
|
c: expect.toSatisfy((e: Epoch<RemoteMatrixLivekitMember[]>) => {
|
||||||
const items = e.value;
|
const items = e.value;
|
||||||
expect(items.length).toBe(3);
|
expect(items.length).toBe(3);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user