diff --git a/src/domain/session/toast/ToastCollectionViewModel.ts b/src/domain/session/toast/ToastCollectionViewModel.ts index 709f5b81..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,9 +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); + const room = await this._findRoomForCall(call); const dismiss = () => { const idx = this.toastViewModels.array.findIndex(vm => vm.call === call); if (idx !== -1) { @@ -71,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..f1b273ff 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -776,7 +776,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) { @@ -940,12 +940,20 @@ export class Session { async observeRoomStatus(roomId) { let observable = this._observedRoomStatus.get(roomId); if (!observable) { - const status = await this.getRoomStatus(roomId); + 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; } 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