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) {