Skip to content

Commit 7202484

Browse files
authored
Include pending events in thread summary and count again (#2922)
* Include pending events in thread summary and count again * Pass through pending event status
1 parent 43bfa0c commit 7202484

File tree

3 files changed

+71
-6
lines changed

3 files changed

+71
-6
lines changed

spec/unit/models/thread.spec.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import { MatrixClient } from "../../../src/client";
17+
import { MatrixClient, PendingEventOrdering } from "../../../src/client";
1818
import { Room } from "../../../src/models/room";
19-
import { Thread } from "../../../src/models/thread";
19+
import { Thread, THREAD_RELATION_TYPE, ThreadEvent } from "../../../src/models/thread";
2020
import { mkThread } from "../../test-utils/thread";
2121
import { TestClient } from "../../TestClient";
22+
import { emitPromise, mkMessage } from "../../test-utils/test-utils";
23+
import { EventStatus } from "../../../src";
2224

2325
describe('Thread', () => {
2426
describe("constructor", () => {
@@ -30,6 +32,50 @@ describe('Thread', () => {
3032
});
3133
});
3234

35+
it("includes pending events in replyCount", async () => {
36+
const myUserId = "@bob:example.org";
37+
const testClient = new TestClient(
38+
myUserId,
39+
"DEVICE",
40+
"ACCESS_TOKEN",
41+
undefined,
42+
{ timelineSupport: false },
43+
);
44+
const client = testClient.client;
45+
const room = new Room("123", client, myUserId, {
46+
pendingEventOrdering: PendingEventOrdering.Detached,
47+
});
48+
49+
jest.spyOn(client, "getRoom").mockReturnValue(room);
50+
51+
const { thread } = mkThread({
52+
room,
53+
client,
54+
authorId: myUserId,
55+
participantUserIds: ["@alice:example.org"],
56+
length: 3,
57+
});
58+
await emitPromise(thread, ThreadEvent.Update);
59+
expect(thread.length).toBe(2);
60+
61+
const event = mkMessage({
62+
room: room.roomId,
63+
user: myUserId,
64+
msg: "thread reply",
65+
relatesTo: {
66+
rel_type: THREAD_RELATION_TYPE.name,
67+
event_id: thread.id,
68+
},
69+
event: true,
70+
});
71+
await thread.processEvent(event);
72+
event.setStatus(EventStatus.SENDING);
73+
room.addPendingEvent(event, "txn01");
74+
75+
await emitPromise(thread, ThreadEvent.Update);
76+
expect(thread.length).toBe(3);
77+
});
78+
3379
describe("hasUserReadEvent", () => {
3480
const myUserId = "@bob:example.org";
3581
let client: MatrixClient;

src/models/room.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
20172017
const thread = new Thread(threadId, rootEvent, {
20182018
room: this,
20192019
client: this.client,
2020+
pendingEventOrdering: this.opts.pendingEventOrdering,
20202021
});
20212022

20222023
// This is necessary to be able to jump to events in threads:

src/models/thread.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ limitations under the License.
1616

1717
import { Optional } from "matrix-events-sdk";
1818

19-
import { MatrixClient } from "../client";
19+
import { MatrixClient, PendingEventOrdering } from "../client";
2020
import { TypedReEmitter } from "../ReEmitter";
2121
import { RelationType } from "../@types/event";
22-
import { IThreadBundledRelationship, MatrixEvent, MatrixEventEvent } from "./event";
22+
import { EventStatus, IThreadBundledRelationship, MatrixEvent, MatrixEventEvent } from "./event";
2323
import { EventTimeline } from "./event-timeline";
2424
import { EventTimelineSet, EventTimelineSetHandlerMap } from './event-timeline-set';
2525
import { NotificationCountType, Room, RoomEvent } from './room';
@@ -51,6 +51,7 @@ export type EventHandlerMap = {
5151
interface IThreadOpts {
5252
room: Room;
5353
client: MatrixClient;
54+
pendingEventOrdering?: PendingEventOrdering;
5455
}
5556

5657
export enum FeatureSupport {
@@ -88,9 +89,12 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
8889

8990
private lastEvent: MatrixEvent | undefined;
9091
private replyCount = 0;
92+
private lastPendingEvent: MatrixEvent | undefined;
93+
private pendingReplyCount = 0;
9194

9295
public readonly room: Room;
9396
public readonly client: MatrixClient;
97+
private readonly pendingEventOrdering: PendingEventOrdering;
9498

9599
public initialEventsFetched = !Thread.hasServerSideSupport;
96100

@@ -109,6 +113,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
109113

110114
this.room = opts.room;
111115
this.client = opts.client;
116+
this.pendingEventOrdering = opts.pendingEventOrdering ?? PendingEventOrdering.Chronological;
112117
this.timelineSet = new EventTimelineSet(this.room, {
113118
timelineSupport: true,
114119
pendingEvents: true,
@@ -300,6 +305,19 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
300305
bundledRelationship = this.getRootEventBundledRelationship();
301306
}
302307

308+
let pendingEvents: MatrixEvent[];
309+
if (this.pendingEventOrdering === PendingEventOrdering.Detached) {
310+
pendingEvents = this.room.getPendingEvents()
311+
.filter(ev => ev.isRelation(THREAD_RELATION_TYPE.name) && this.id === ev.threadRootId);
312+
await Promise.all(pendingEvents.map(ev => this.processEvent(ev)));
313+
} else {
314+
pendingEvents = this.events
315+
.filter(ev => ev.isRelation(THREAD_RELATION_TYPE.name))
316+
.filter(ev => ev.status !== EventStatus.SENT && ev.status !== EventStatus.CANCELLED);
317+
}
318+
this.lastPendingEvent = pendingEvents.length ? pendingEvents[pendingEvents.length - 1] : undefined;
319+
this.pendingReplyCount = pendingEvents.length;
320+
303321
if (Thread.hasServerSideSupport && bundledRelationship) {
304322
this.replyCount = bundledRelationship.count;
305323
this._currentUserParticipated = !!bundledRelationship.current_user_participated;
@@ -393,14 +411,14 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
393411
* exclude annotations from that number
394412
*/
395413
public get length(): number {
396-
return this.replyCount;
414+
return this.replyCount + this.pendingReplyCount;
397415
}
398416

399417
/**
400418
* A getter for the last event added to the thread, if known.
401419
*/
402420
public get replyToEvent(): Optional<MatrixEvent> {
403-
return this.lastEvent ?? this.lastReply();
421+
return this.lastPendingEvent ?? this.lastEvent ?? this.lastReply();
404422
}
405423

406424
public get events(): MatrixEvent[] {

0 commit comments

Comments
 (0)