From 02b2f9aa629906aa60c0a0443535647d41f4ae00 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Wed, 2 Feb 2022 16:24:55 +0000 Subject: [PATCH] Fix initial sync fail when event fetching unsuccessful --- src/models/room.ts | 53 ++++++++++++++++++++++++++++---------------- src/models/thread.ts | 28 +++++++++++++---------- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/models/room.ts b/src/models/room.ts index 6619c5bb9ef..b5633b3ef50 100644 --- a/src/models/room.ts +++ b/src/models/room.ts @@ -1372,13 +1372,24 @@ export class Room extends EventEmitter { let rootEvent = this.findEventById(event.threadRootId); // If the rootEvent does not exist in the current sync, then look for // it over the network - const eventData = await this.client.fetchRoomEvent(this.roomId, event.threadRootId); - if (!rootEvent) { - rootEvent = new MatrixEvent(eventData); - } else { - rootEvent.setUnsigned(eventData.unsigned); + try { + let eventData; + if (event.threadRootId) { + eventData = await this.client.fetchRoomEvent(this.roomId, event.threadRootId); + } + + if (!rootEvent) { + rootEvent = new MatrixEvent(eventData); + } else { + rootEvent.setUnsigned(eventData.unsigned); + } + } finally { + // The root event might be not be visible to the person requesting + // it. If it wasn't fetched successfully the thread will work + // in "limited" mode and won't benefit from all the APIs a homeserver + // can provide to enhance the thread experience + thread = this.createThread(rootEvent, events); } - thread = this.createThread(rootEvent, events); } if (event.getUnsigned().transaction_id) { @@ -1393,26 +1404,30 @@ export class Room extends EventEmitter { this.emit(ThreadEvent.Update, thread); } - public createThread(rootEvent: MatrixEvent, events?: MatrixEvent[]): Thread { + public createThread(rootEvent: MatrixEvent, events?: MatrixEvent[]): Thread | undefined { const thread = new Thread(rootEvent, { initialEvents: events, room: this, client: this.client, }); - this.threads.set(thread.id, thread); - this.reEmitter.reEmit(thread, [ - ThreadEvent.Update, - ThreadEvent.Ready, - "Room.timeline", - "Room.timelineReset", - ]); + // If we managed to create a thread and figure out its `id` + // then we can use it + if (thread.id) { + this.threads.set(thread.id, thread); + this.reEmitter.reEmit(thread, [ + ThreadEvent.Update, + ThreadEvent.Ready, + "Room.timeline", + "Room.timelineReset", + ]); + + if (!this.lastThread || this.lastThread.rootEvent.localTimestamp < rootEvent.localTimestamp) { + this.lastThread = thread; + } - if (!this.lastThread || this.lastThread.rootEvent.localTimestamp < rootEvent.localTimestamp) { - this.lastThread = thread; + this.emit(ThreadEvent.New, thread); + return thread; } - - this.emit(ThreadEvent.New, thread); - return thread; } /** diff --git a/src/models/thread.ts b/src/models/thread.ts index 50459766d41..b882f79044f 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -60,8 +60,10 @@ export class Thread extends TypedEventEmitter { public initialEventsFetched = false; + public readonly id: string; + constructor( - public readonly rootEvent: MatrixEvent, + public readonly rootEvent: MatrixEvent | undefined, opts: IThreadOpts, ) { super(); @@ -82,6 +84,15 @@ export class Thread extends TypedEventEmitter { "Room.timelineReset", ]); + // If we weren't able to find the root event, it's probably missing + // and we define the thread ID from one of the thread relation + if (!rootEvent) { + this.id = opts?.initialEvents + ?.find(event => event.isThreadRelation)?.relationEventId; + } else { + this.id = rootEvent.getId(); + } + opts?.initialEvents?.forEach(event => this.addEvent(event)); this.room.on("Room.localEchoUpdated", this.onEcho); @@ -177,9 +188,9 @@ export class Thread extends TypedEventEmitter { this.emit(ThreadEvent.Update, this); } - private initialiseThread(rootEvent: MatrixEvent): void { + private initialiseThread(rootEvent: MatrixEvent | undefined): void { const bundledRelationship = rootEvent - .getServerAggregatedRelation(RelationType.Thread); + ?.getServerAggregatedRelation(RelationType.Thread); if (this.hasServerSideSupport && bundledRelationship) { this.replyCount = bundledRelationship.count; @@ -190,7 +201,7 @@ export class Thread extends TypedEventEmitter { this.lastEvent = event; } - if (!bundledRelationship) { + if (!bundledRelationship && rootEvent) { this.addEvent(rootEvent); } } @@ -229,15 +240,8 @@ export class Thread extends TypedEventEmitter { } } - /** - * The thread ID, which is the same as the root event ID - */ - public get id(): string { - return this.rootEvent.getId(); - } - public get roomId(): string { - return this.rootEvent.getRoomId(); + return this.room.roomId; } /**