From 903a157de2bbf6c61545cccfbb91468199c7f2e5 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 31 Jan 2023 16:48:48 +0530 Subject: [PATCH 1/4] Don't show toast if room is not available --- src/domain/session/toast/ToastCollectionViewModel.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/domain/session/toast/ToastCollectionViewModel.ts b/src/domain/session/toast/ToastCollectionViewModel.ts index 709f5b81..78961029 100644 --- a/src/domain/session/toast/ToastCollectionViewModel.ts +++ b/src/domain/session/toast/ToastCollectionViewModel.ts @@ -39,6 +39,9 @@ export class ToastCollectionViewModel extends ViewModel { onAdd(_, call: GroupCall) { if (this._shouldShowNotification(call)) { const room = this._findRoomForCall(call); + if (!room) { + return; + } const dismiss = () => { const idx = this.toastViewModels.array.findIndex(vm => vm.call === call); if (idx !== -1) { From 9a6d15a72b64c7a93af73319b494833d92fc09c8 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 31 Jan 2023 16:49:58 +0530 Subject: [PATCH 2/4] Fix unwanted toast appearing when opening client --- src/matrix/calls/CallHandler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/matrix/calls/CallHandler.ts b/src/matrix/calls/CallHandler.ts index af01beef..b4a1c5cf 100644 --- a/src/matrix/calls/CallHandler.ts +++ b/src/matrix/calls/CallHandler.ts @@ -229,7 +229,8 @@ export class CallHandler implements RoomStateHandler { this._calls.remove(call.id); txn.calls.remove(call.intent, roomId, call.id); } - } else { + } else if(!event.content["m.terminated"]) { + // We don't have this call already and it isn't terminated, so create the call: call = new GroupCall( event.state_key, // id false, // isLoadedFromStorage From de57e0798269b87c899528f78c0375677cde67a3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 2 Feb 2023 15:26:38 +0530 Subject: [PATCH 3/4] Wait for room to come through sync --- .../session/toast/ToastCollectionViewModel.ts | 20 ++++++++------ src/matrix/Session.js | 26 ++++++++++++------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/domain/session/toast/ToastCollectionViewModel.ts b/src/domain/session/toast/ToastCollectionViewModel.ts index 78961029..d1595b2d 100644 --- a/src/domain/session/toast/ToastCollectionViewModel.ts +++ b/src/domain/session/toast/ToastCollectionViewModel.ts @@ -21,6 +21,7 @@ import type {GroupCall} from "../../../matrix/calls/group/GroupCall"; import type {Room} from "../../../matrix/room/Room.js"; import type {Session} from "../../../matrix/Session.js"; import type {SegmentType} from "../../navigation"; +import { RoomStatus } from "../../../lib"; type Options = { session: Session; @@ -36,12 +37,9 @@ export class ToastCollectionViewModel extends ViewModel { this.track(callsObservableMap.subscribe(this)); } - onAdd(_, call: GroupCall) { + async onAdd(_, call: GroupCall) { if (this._shouldShowNotification(call)) { - const room = this._findRoomForCall(call); - if (!room) { - return; - } + const room = await this._findRoomForCall(call); const dismiss = () => { const idx = this.toastViewModels.array.findIndex(vm => vm.call === call); if (idx !== -1) { @@ -74,10 +72,16 @@ export class ToastCollectionViewModel extends ViewModel { } } - private _findRoomForCall(call: GroupCall): Room { + private async _findRoomForCall(call: GroupCall): Promise { const id = call.roomId; - const rooms = this.getOption("session").rooms; - return rooms.get(id); + const session = this.getOption("session"); + const rooms = session.rooms; + // Make sure that we know of this room, + // otherwise wait for it to come through sync + const observable = await session.observeRoomStatus(id); + await observable.waitFor(s => s === RoomStatus.Joined).promise; + const room = rooms.get(id); + return room; } private _shouldShowNotification(call: GroupCall): boolean { diff --git a/src/matrix/Session.js b/src/matrix/Session.js index d640e2df..87680a49 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -132,6 +132,7 @@ export class Session { this._createRoomEncryption = this._createRoomEncryption.bind(this); this._forgetArchivedRoom = this._forgetArchivedRoom.bind(this); this.needsKeyBackup = new ObservableValue(false); + this._pendingObserveCalls = []; } get fingerprintKey() { @@ -776,7 +777,7 @@ export class Session { } } - applyRoomCollectionChangesAfterSync(inviteStates, roomStates, archivedRoomStates, log) { + async applyRoomCollectionChangesAfterSync(inviteStates, roomStates, archivedRoomStates, log) { // update the collections after sync for (const rs of roomStates) { if (rs.shouldAdd) { @@ -796,6 +797,8 @@ export class Session { // now all the collections are updated, update the room status // so any listeners to the status will find the collections // completely up to date + await Promise.all(this._pendingObserveCalls); + this._pendingObserveCalls = []; if (this._observedRoomStatus.size !== 0) { for (const ars of archivedRoomStates) { if (ars.shouldAdd) { @@ -938,16 +941,21 @@ export class Session { } async observeRoomStatus(roomId) { - let observable = this._observedRoomStatus.get(roomId); - if (!observable) { - const status = await this.getRoomStatus(roomId); - observable = new RetainedObservableValue(status, () => { - this._observedRoomStatus.delete(roomId); - }); + const op = async () => { + let observable = this._observedRoomStatus.get(roomId); + if (!observable) { + const status = await this.getRoomStatus(roomId); + observable = new RetainedObservableValue(status, () => { + this._observedRoomStatus.delete(roomId); + }); - this._observedRoomStatus.set(roomId, observable); + this._observedRoomStatus.set(roomId, observable); + } + return observable; } - return observable; + const promise = op(); + this._pendingObserveCalls.push(promise); + return await promise; } observeRoomState(roomStateHandler) { From 09e67ec21c42783bc847a8592cd4bd2bd3e618f5 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 2 Feb 2023 18:39:19 +0530 Subject: [PATCH 4/4] Deal with race in a better way --- src/matrix/Session.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 87680a49..f1b273ff 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -132,7 +132,6 @@ export class Session { this._createRoomEncryption = this._createRoomEncryption.bind(this); this._forgetArchivedRoom = this._forgetArchivedRoom.bind(this); this.needsKeyBackup = new ObservableValue(false); - this._pendingObserveCalls = []; } get fingerprintKey() { @@ -797,8 +796,6 @@ export class Session { // now all the collections are updated, update the room status // so any listeners to the status will find the collections // completely up to date - await Promise.all(this._pendingObserveCalls); - this._pendingObserveCalls = []; if (this._observedRoomStatus.size !== 0) { for (const ars of archivedRoomStates) { if (ars.shouldAdd) { @@ -941,21 +938,24 @@ export class Session { } async observeRoomStatus(roomId) { - const op = async () => { - let observable = this._observedRoomStatus.get(roomId); - if (!observable) { - const status = await this.getRoomStatus(roomId); - observable = new RetainedObservableValue(status, () => { - this._observedRoomStatus.delete(roomId); - }); - - this._observedRoomStatus.set(roomId, observable); + let observable = this._observedRoomStatus.get(roomId); + if (!observable) { + let status = undefined; + // Create and set the observable with value = undefined, so that + // we don't loose any sync changes that come in while we are busy + // calculating the current room status. + observable = new RetainedObservableValue(status, () => { + this._observedRoomStatus.delete(roomId); + }); + this._observedRoomStatus.set(roomId, observable); + status = await this.getRoomStatus(roomId); + // If observable.value is not undefined anymore, then some + // change has come through the sync. + if (observable.get() === undefined) { + observable.set(status); } - return observable; } - const promise = op(); - this._pendingObserveCalls.push(promise); - return await promise; + return observable; } observeRoomState(roomStateHandler) {