From 43dea3bfdc1af23df1efc43808715c8b5ba733c2 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 27 Jan 2023 10:01:53 +0100 Subject: [PATCH 1/6] detect calls using a foci --- src/matrix/calls/callEventTypes.ts | 6 ++++++ src/matrix/calls/group/GroupCall.ts | 9 +++++++++ src/matrix/calls/group/Member.ts | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/src/matrix/calls/callEventTypes.ts b/src/matrix/calls/callEventTypes.ts index a0eb986c..879d0c11 100644 --- a/src/matrix/calls/callEventTypes.ts +++ b/src/matrix/calls/callEventTypes.ts @@ -22,11 +22,17 @@ export enum EventType { // TODO: Change to "sdp_stream_metadata" when MSC3077 is merged export const SDPStreamMetadataKey = "org.matrix.msc3077.sdp_stream_metadata"; +export interface FocusConfig { + user_id: string, + device_id: string +} + export interface CallDeviceMembership { device_id: string, session_id: string, ["expires_ts"]?: number, feeds?: Array<{purpose: string}> + ["m.foci.active"]?: Array } export interface CallMembership { diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index e0099f4e..16f09dd2 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -145,6 +145,15 @@ export class GroupCall extends EventEmitter<{change: never}> { return !!this.callContent?.["m.terminated"]; } + get usesFoci(): boolean { + for (const member of this._members.values()) { + if (member.usesFoci) { + return true; + } + } + return false; + } + get duration(): number | undefined { if (typeof this.startTime === "number") { return (this.options.clock.now() - this.startTime); diff --git a/src/matrix/calls/group/Member.ts b/src/matrix/calls/group/Member.ts index e097804c..ab99c6b8 100644 --- a/src/matrix/calls/group/Member.ts +++ b/src/matrix/calls/group/Member.ts @@ -117,6 +117,11 @@ export class Member { return this.errorBoundary.error; } + get usesFoci(): boolean { + const activeFoci = this.callDeviceMembership["m.foci.active"]; + return Array.isArray(activeFoci) && activeFoci.length > 0; + } + private _renewExpireTimeout(log: ILogItem) { this.expireTimeout?.dispose(); this.expireTimeout = undefined; From 365157449e9e052c6045f6a8693dadcdc42566be Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 27 Jan 2023 10:02:13 +0100 Subject: [PATCH 2/6] cleanup loops here to not get keys --- src/matrix/calls/group/GroupCall.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index 16f09dd2..90c4d982 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -226,7 +226,7 @@ export class GroupCall extends EventEmitter<{change: never}> { this.emitChange(); }); // send invite to all members that are < my userId - for (const [,member] of this._members) { + for (const member of this._members.values()) { this.connectToMember(member, joinedData, log); } }); @@ -530,7 +530,7 @@ export class GroupCall extends EventEmitter<{change: never}> { disconnect(log: ILogItem): boolean { return this.errorBoundary.try(() => { if (this.hasJoined) { - for (const [,member] of this._members) { + for (const member of this._members.values()) { const disconnectLogItem = member.disconnect(true); if (disconnectLogItem) { log.refDetached(disconnectLogItem); From c8bb5fffb0fa7cce87a9d02fd4dbb6f8826af2a6 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 27 Jan 2023 10:12:22 +0100 Subject: [PATCH 3/6] don't allow to join a call using a foci --- src/domain/session/room/timeline/tiles/CallTile.js | 2 +- src/matrix/calls/group/GroupCall.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/domain/session/room/timeline/tiles/CallTile.js b/src/domain/session/room/timeline/tiles/CallTile.js index ffb9ef59..37be05be 100644 --- a/src/domain/session/room/timeline/tiles/CallTile.js +++ b/src/domain/session/room/timeline/tiles/CallTile.js @@ -94,7 +94,7 @@ export class CallTile extends SimpleTile { } get canJoin() { - return this._call && !this._call.hasJoined; + return this._call && !this._call.hasJoined && !this._call.usesFoci; } get canLeave() { diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index 90c4d982..9ef2e068 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -190,7 +190,7 @@ export class GroupCall extends EventEmitter<{change: never}> { join(localMedia: LocalMedia, log?: ILogItem): Promise { return this.options.logger.wrapOrRun(log, "Call.join", async joinLog => { - if (this._state !== GroupCallState.Created || this.joinedData) { + if (this._state !== GroupCallState.Created || this.joinedData || this.usesFoci) { return; } const logItem = this.options.logger.child({ From 825602a04a2d89dd6cb7ec75cab3de821a6b77fc Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 27 Jan 2023 10:12:36 +0100 Subject: [PATCH 4/6] dispose local media here when returning early as join takes ownership --- src/matrix/calls/group/GroupCall.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index 9ef2e068..0460c212 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -191,6 +191,7 @@ export class GroupCall extends EventEmitter<{change: never}> { join(localMedia: LocalMedia, log?: ILogItem): Promise { return this.options.logger.wrapOrRun(log, "Call.join", async joinLog => { if (this._state !== GroupCallState.Created || this.joinedData || this.usesFoci) { + localMedia.dispose(); return; } const logItem = this.options.logger.child({ From f5838b21baae8fed048af4e8aa376a00f1c8d50f Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 27 Jan 2023 10:12:51 +0100 Subject: [PATCH 5/6] show message in tile when call uses foci, explaining we can't join --- src/domain/session/room/timeline/tiles/CallTile.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/domain/session/room/timeline/tiles/CallTile.js b/src/domain/session/room/timeline/tiles/CallTile.js index 37be05be..05762bc0 100644 --- a/src/domain/session/room/timeline/tiles/CallTile.js +++ b/src/domain/session/room/timeline/tiles/CallTile.js @@ -118,11 +118,14 @@ export class CallTile extends SimpleTile { } get typeLabel() { + if (this._call && this._call.usesFoci) { + return `This call uses a stream-forwarding unit, which isn't supported yet, so you can't join this call.`; + } if (this.type === CallType.Video) { - return `Video call`; - } else { - return `Voice call`; - } + return `Video call`; + } else { + return `Voice call`; + } } get type() { From 1d7db53f30cb4f6ff438fe86936df84fee797737 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 27 Jan 2023 10:22:01 +0100 Subject: [PATCH 6/6] don't show toast for foci calls --- src/domain/session/toast/ToastCollectionViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/session/toast/ToastCollectionViewModel.ts b/src/domain/session/toast/ToastCollectionViewModel.ts index 18b58b76..709f5b81 100644 --- a/src/domain/session/toast/ToastCollectionViewModel.ts +++ b/src/domain/session/toast/ToastCollectionViewModel.ts @@ -79,7 +79,7 @@ export class ToastCollectionViewModel extends ViewModel { private _shouldShowNotification(call: GroupCall): boolean { const currentlyOpenedRoomId = this.navigation.path.get("room")?.value; - if (!call.isLoadedFromStorage && call.roomId !== currentlyOpenedRoomId) { + if (!call.isLoadedFromStorage && call.roomId !== currentlyOpenedRoomId && !call.usesFoci) { return true; } return false;