Merge branch 'livekit' into toger5/sdk-improvements

This commit is contained in:
Valere
2026-02-03 16:32:36 +01:00
4 changed files with 25 additions and 32 deletions

View File

@@ -5,10 +5,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details. Please see LICENSE in the repository root for full details.
*/ */
import {
type ICallNotifyContent,
type IRTCNotificationContent,
} from "matrix-js-sdk/lib/matrixrtc";
import { describe, it } from "vitest"; import { describe, it } from "vitest";
import { import {
EventType, EventType,
@@ -25,23 +21,23 @@ import {
localRtcMember, localRtcMember,
} from "../../utils/test-fixtures"; } from "../../utils/test-fixtures";
import { import {
type CallNotificationWrapper,
createCallNotificationLifecycle$, createCallNotificationLifecycle$,
type Props as CallNotificationLifecycleProps, type Props as CallNotificationLifecycleProps,
} from "./CallNotificationLifecycle"; } from "./CallNotificationLifecycle";
import { trackEpoch } from "../ObservableScope"; import { trackEpoch } from "../ObservableScope";
const mockLegacyRingEvent = {} as { event_id: string } & ICallNotifyContent;
function mockRingEvent( function mockRingEvent(
eventId: string, eventId: string,
lifetimeMs: number | undefined, lifetimeMs: number | undefined,
sender = local.userId, sender = local.userId,
): { event_id: string } & IRTCNotificationContent { ): CallNotificationWrapper {
return { return {
event_id: eventId, event_id: eventId,
...(lifetimeMs === undefined ? {} : { lifetime: lifetimeMs }), ...(lifetimeMs === undefined ? {} : { lifetime: lifetimeMs }),
notification_type: "ring", notification_type: "ring",
sender, sender,
} as unknown as { event_id: string } & IRTCNotificationContent; } as unknown as CallNotificationWrapper;
} }
describe("waitForCallPickup$", () => { describe("waitForCallPickup$", () => {
@@ -54,7 +50,7 @@ describe("waitForCallPickup$", () => {
behavior("a", { a: [] }).pipe(trackEpoch()), behavior("a", { a: [] }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("10ms a", { sentCallNotification$: hot("10ms a", {
a: [mockRingEvent("$notif1", 30), mockLegacyRingEvent], a: mockRingEvent("$notif1", 30),
}), }),
receivedDecline$: hot(""), receivedDecline$: hot(""),
options: { options: {
@@ -86,7 +82,7 @@ describe("waitForCallPickup$", () => {
}).pipe(trackEpoch()), }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("5ms a", { sentCallNotification$: hot("5ms a", {
a: [mockRingEvent("$notif2", 100), mockLegacyRingEvent], a: mockRingEvent("$notif2", 100),
}), }),
receivedDecline$: hot(""), receivedDecline$: hot(""),
options: { options: {
@@ -115,7 +111,7 @@ describe("waitForCallPickup$", () => {
}).pipe(trackEpoch()), }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("20ms a", { sentCallNotification$: hot("20ms a", {
a: [mockRingEvent("$notif2", 50), mockLegacyRingEvent], a: mockRingEvent("$notif2", 50),
}), }),
receivedDecline$: hot(""), receivedDecline$: hot(""),
options: { options: {
@@ -142,7 +138,7 @@ describe("waitForCallPickup$", () => {
}).pipe(trackEpoch()), }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("10ms a", { sentCallNotification$: hot("10ms a", {
a: [mockRingEvent("$notif2", undefined), mockLegacyRingEvent], a: mockRingEvent("$notif2", undefined),
}), }),
receivedDecline$: hot(""), receivedDecline$: hot(""),
options: { options: {
@@ -171,7 +167,7 @@ describe("waitForCallPickup$", () => {
}).pipe(trackEpoch()), }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("10ms a", { sentCallNotification$: hot("10ms a", {
a: [mockRingEvent("$notif5", 30), mockLegacyRingEvent], a: mockRingEvent("$notif5", 30),
}), }),
receivedDecline$: hot(""), receivedDecline$: hot(""),
options: { options: {
@@ -210,7 +206,7 @@ describe("waitForCallPickup$", () => {
}).pipe(trackEpoch()), }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("10ms a", { sentCallNotification$: hot("10ms a", {
a: [mockRingEvent("$decl1", 50), mockLegacyRingEvent], a: mockRingEvent("$decl1", 50),
}), }),
receivedDecline$: hot("40ms d", { receivedDecline$: hot("40ms d", {
d: [ d: [
@@ -254,7 +250,7 @@ describe("waitForCallPickup$", () => {
}).pipe(trackEpoch()), }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("10ms a", { sentCallNotification$: hot("10ms a", {
a: [mockRingEvent("$decl", 20), mockLegacyRingEvent], a: mockRingEvent("$decl", 20),
}), }),
receivedDecline$: hot("40ms d", { receivedDecline$: hot("40ms d", {
d: [ d: [
@@ -305,7 +301,7 @@ describe("waitForCallPickup$", () => {
}).pipe(trackEpoch()), }).pipe(trackEpoch()),
), ),
sentCallNotification$: hot("10ms a", { sentCallNotification$: hot("10ms a", {
a: [mockRingEvent("$right", 50), mockLegacyRingEvent], a: mockRingEvent("$right", 50),
}), }),
receivedDecline$: hot("20ms d", { receivedDecline$: hot("20ms d", {
d: [ d: [

View File

@@ -7,9 +7,9 @@ Please see LICENSE in the repository root for full details.
import { import {
type CallMembership, type CallMembership,
type IRTCNotificationContent,
type MatrixRTCSession, type MatrixRTCSession,
MatrixRTCSessionEvent, MatrixRTCSessionEvent,
type MatrixRTCSessionEventHandlerMap,
} from "matrix-js-sdk/lib/matrixrtc"; } from "matrix-js-sdk/lib/matrixrtc";
import { import {
combineLatest, combineLatest,
@@ -38,6 +38,7 @@ import {
import { type Behavior } from "../Behavior"; import { type Behavior } from "../Behavior";
import { type Epoch, mapEpoch, type ObservableScope } from "../ObservableScope"; import { type Epoch, mapEpoch, type ObservableScope } from "../ObservableScope";
export type AutoLeaveReason = "allOthersLeft" | "timeout" | "decline"; export type AutoLeaveReason = "allOthersLeft" | "timeout" | "decline";
export type CallPickupState = export type CallPickupState =
| "unknown" | "unknown"
@@ -46,9 +47,11 @@ export type CallPickupState =
| "decline" | "decline"
| "success" | "success"
| null; | null;
export type CallNotificationWrapper = Parameters<
MatrixRTCSessionEventHandlerMap[MatrixRTCSessionEvent.DidSendCallNotification] export type CallNotificationWrapper = {
>; event_id: string;
} & IRTCNotificationContent;
export function createSentCallNotification$( export function createSentCallNotification$(
scope: ObservableScope, scope: ObservableScope,
matrixRTCSession: MatrixRTCSession, matrixRTCSession: MatrixRTCSession,
@@ -80,6 +83,7 @@ export interface Props {
options: { waitForCallPickup?: boolean; autoLeaveWhenOthersLeft?: boolean }; options: { waitForCallPickup?: boolean; autoLeaveWhenOthersLeft?: boolean };
localUser: { deviceId: string; userId: string }; localUser: { deviceId: string; userId: string };
} }
/** /**
* @returns two observables: * @returns two observables:
* `callPickupState$` The current call pickup state of the call. * `callPickupState$` The current call pickup state of the call.
@@ -140,12 +144,12 @@ export function createCallNotificationLifecycle$({
scope.behavior( scope.behavior(
sentCallNotification$.pipe( sentCallNotification$.pipe(
filter( filter(
(newAndLegacyEvents) => (notificationEventArgs: CallNotificationWrapper | null) =>
// only care about new events (legacy do not have decline pattern) // only care about new events (legacy do not have decline pattern)
newAndLegacyEvents?.[0].notification_type === "ring", notificationEventArgs?.notification_type === "ring",
), ),
map((e) => e as CallNotificationWrapper), map((e) => e as CallNotificationWrapper),
switchMap(([notificationEvent]) => { switchMap((notificationEvent) => {
const lifetimeMs = notificationEvent?.lifetime ?? 0; const lifetimeMs = notificationEvent?.lifetime ?? 0;
return concat( return concat(
lifetimeMs === 0 lifetimeMs === 0

View File

@@ -29,7 +29,6 @@ import {
Status, Status,
type CallMembership, type CallMembership,
type IRTCNotificationContent, type IRTCNotificationContent,
type ICallNotifyContent,
MatrixRTCSessionEvent, MatrixRTCSessionEvent,
type LivekitTransport, type LivekitTransport,
} from "matrix-js-sdk/lib/matrixrtc"; } from "matrix-js-sdk/lib/matrixrtc";
@@ -232,10 +231,6 @@ function mockRingEvent(
} as unknown as { event_id: string } & IRTCNotificationContent; } as unknown as { event_id: string } & IRTCNotificationContent;
} }
// The app doesn't really care about the content of these legacy events, we just
// need a value to fill in for them when emitting notifications
const mockLegacyRingEvent = {} as { event_id: string } & ICallNotifyContent;
describe.each([ describe.each([
[MatrixRTCMode.Legacy], [MatrixRTCMode.Legacy],
[MatrixRTCMode.Compatibility], [MatrixRTCMode.Compatibility],
@@ -1109,7 +1104,6 @@ describe.each([
rtcSession.emit( rtcSession.emit(
MatrixRTCSessionEvent.DidSendCallNotification, MatrixRTCSessionEvent.DidSendCallNotification,
mockRingEvent("$notif1", 30), mockRingEvent("$notif1", 30),
mockLegacyRingEvent,
); );
}, },
}); });
@@ -1151,7 +1145,6 @@ describe.each([
rtcSession.emit( rtcSession.emit(
MatrixRTCSessionEvent.DidSendCallNotification, MatrixRTCSessionEvent.DidSendCallNotification,
mockRingEvent("$notif2", 100), mockRingEvent("$notif2", 100),
mockLegacyRingEvent,
); );
}, },
d: () => { d: () => {

View File

@@ -11452,9 +11452,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"matrix-js-sdk@matrix-org/matrix-js-sdk#toger5/make-empty-string-room-m.call-constraint": "matrix-js-sdk@matrix-org/matrix-js-sdk#develop":
version: 40.1.0 version: 40.1.0
resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=55cdd22d83e2d92900c4981a769ad02bb2f64451" resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=f2157f28bbadf2898fe21991f69ccb2af40df326"
dependencies: dependencies:
"@babel/runtime": "npm:^7.12.5" "@babel/runtime": "npm:^7.12.5"
"@matrix-org/matrix-sdk-crypto-wasm": "npm:^17.0.0" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^17.0.0"
@@ -11470,7 +11470,7 @@ __metadata:
sdp-transform: "npm:^3.0.0" sdp-transform: "npm:^3.0.0"
unhomoglyph: "npm:^1.0.6" unhomoglyph: "npm:^1.0.6"
uuid: "npm:13" uuid: "npm:13"
checksum: 10c0/23ede2482a345d0b44dff08d7f0977e99a5efa2c21e2df12f0b3543e7f5f14bf8130f2549218c4164227a3d3301cb64d8588d199845a62a283d588750dae871f checksum: 10c0/d646b9214abbf0b9126760105edd9c57be7ffe8b53ae4acd5fefe841a51ad7d78fa57130922b3eac65ff2266b43f31ea60b4bdda9481e6bf8f1808d96726ed8a
languageName: node languageName: node
linkType: hard linkType: hard