From 1e32b355ce2640990abae4a87b5f3c100295d011 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 5 Sep 2025 21:22:32 +0200 Subject: [PATCH] Ignore decline events from the local user --- src/state/CallViewModel.test.ts | 29 ++++++++++++++++++++++++----- src/state/CallViewModel.ts | 3 ++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/state/CallViewModel.test.ts b/src/state/CallViewModel.test.ts index 938109cb..4b5e603f 100644 --- a/src/state/CallViewModel.test.ts +++ b/src/state/CallViewModel.test.ts @@ -26,6 +26,7 @@ import { MatrixEvent, type IRoomTimelineData, EventType, + type IEvent, } from "matrix-js-sdk"; import { ConnectionState, @@ -248,12 +249,14 @@ function summarizeLayout$(l$: Observable): Observable { function mockRingEvent( eventId: string, lifetimeMs: number | undefined, + sender = local.userId, ): { event_id: string } & IRTCNotificationContent { return { event_id: eventId, ...(lifetimeMs === undefined ? {} : { lifetime: lifetimeMs }), notification_type: "ring", - } as { event_id: string } & IRTCNotificationContent; + sender, + } as unknown as { event_id: string } & IRTCNotificationContent; } // The app doesn't really care about the content of these legacy events, we just @@ -1436,7 +1439,7 @@ describe("waitForCallPickup$", () => { }); test("decline after timeout window ends -> stays timeout", () => { - withTestScheduler(({ hot, schedule, expectObservable, scope }) => { + withTestScheduler(({ schedule, expectObservable }) => { withCallViewModel( {}, (vm, rtcSession) => { @@ -1475,8 +1478,8 @@ describe("waitForCallPickup$", () => { }); }); - test("decline with wrong id is ignored (stays ringing)", () => { - withTestScheduler(({ hot, schedule, expectObservable, scope }) => { + function testStaysRinging(declineEvent: Partial): void { + withTestScheduler(({ schedule, expectObservable }) => { withCallViewModel( {}, (vm, rtcSession) => { @@ -1492,7 +1495,7 @@ describe("waitForCallPickup$", () => { d: () => { rtcSession.room.emit( MatrixRoomEvent.Timeline, - new MatrixEvent({ event_id: "$wrong", type: "m.rtc.decline" }), + new MatrixEvent(declineEvent), rtcSession.room, undefined, false, @@ -1512,6 +1515,22 @@ describe("waitForCallPickup$", () => { }, ); }); + } + + test("decline with wrong id is ignored (stays ringing)", () => { + testStaysRinging({ + event_id: "$wrong", + type: "m.rtc.decline", + sender: local.userId, + }); + }); + + test("decline with sender being the local user is ignored (stays ringing)", () => { + testStaysRinging({ + event_id: "$right", + type: "m.rtc.decline", + sender: alice.userId, + }); }); }); diff --git a/src/state/CallViewModel.ts b/src/state/CallViewModel.ts index 5dbb0b9c..3802d6dd 100644 --- a/src/state/CallViewModel.ts +++ b/src/state/CallViewModel.ts @@ -936,7 +936,8 @@ export class CallViewModel extends ViewModel { ([event]) => event.getType() === EventType.RTCDecline && event.getRelation()?.rel_type === "m.reference" && - event.getRelation()?.event_id === notificationEvent.event_id, + event.getRelation()?.event_id === notificationEvent.event_id && + event.getSender() !== this.userId, ), ), ),