Skip to content

Commit 43a5406

Browse files
committed
Add room.getLastLiveEvent and remove room.lastThread
1 parent cfffa9c commit 43a5406

File tree

2 files changed

+109
-11
lines changed

2 files changed

+109
-11
lines changed

spec/unit/room.spec.ts

+83-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import { Crypto } from "../../src/crypto";
5454
import { mkThread } from "../test-utils/thread";
5555
import { getMockClientWithEventEmitter, mockClientMethodsUser } from "../test-utils/client";
5656
import { logger } from "../../src/logger";
57+
import { IMessageOpts } from "../test-utils/test-utils";
5758

5859
describe("Room", function () {
5960
const roomId = "!foo:bar";
@@ -63,9 +64,10 @@ describe("Room", function () {
6364
const userD = "@dorothy:bar";
6465
let room: Room;
6566

66-
const mkMessage = () =>
67+
const mkMessage = (opts?: Partial<IMessageOpts>) =>
6768
utils.mkMessage(
6869
{
70+
...opts,
6971
event: true,
7072
user: userA,
7173
room: roomId,
@@ -113,9 +115,10 @@ describe("Room", function () {
113115
room.client,
114116
);
115117

116-
const mkThreadResponse = (root: MatrixEvent) =>
118+
const mkThreadResponse = (root: MatrixEvent, opts?: Partial<IMessageOpts>) =>
117119
utils.mkEvent(
118120
{
121+
...opts,
119122
event: true,
120123
type: EventType.RoomMessage,
121124
user: userA,
@@ -165,6 +168,32 @@ describe("Room", function () {
165168
room.client,
166169
);
167170

171+
const addRoomMainAndThreadMessages = (
172+
room: Room,
173+
tsMain?: number,
174+
tsThread?: number,
175+
): { mainEvent?: MatrixEvent; threadEvent?: MatrixEvent } => {
176+
const result: { mainEvent?: MatrixEvent; threadEvent?: MatrixEvent } = {};
177+
178+
if (tsMain) {
179+
result.mainEvent = mkMessage({ ts: tsMain });
180+
room.addLiveEvents([result.mainEvent]);
181+
}
182+
183+
if (tsThread) {
184+
const { rootEvent, thread } = mkThread({
185+
room,
186+
client: new TestClient().client,
187+
authorId: "@bob:example.org",
188+
participantUserIds: ["@bob:example.org"],
189+
});
190+
result.threadEvent = mkThreadResponse(rootEvent, { ts: tsThread });
191+
thread.liveTimeline.addEvent(result.threadEvent, true);
192+
}
193+
194+
return result;
195+
};
196+
168197
beforeEach(function () {
169198
room = new Room(roomId, new TestClient(userA, "device").client, userA);
170199
// mock RoomStates
@@ -3475,4 +3504,56 @@ describe("Room", function () {
34753504
expect(room.findPredecessor()).toBeNull();
34763505
});
34773506
});
3507+
3508+
describe("getLastLiveEvent", () => {
3509+
let lastEventInMainTimeline: MatrixEvent;
3510+
let lastEventInThread: MatrixEvent;
3511+
3512+
it("when there are no events, it should return undefined", () => {
3513+
expect(room.getLastLiveEvent()).toBeUndefined();
3514+
});
3515+
3516+
describe("when there is only an event in the main timeline and there are no threads", () => {
3517+
beforeEach(() => {
3518+
lastEventInMainTimeline = addRoomMainAndThreadMessages(room, 23).mainEvent!;
3519+
room.addLiveEvents([lastEventInMainTimeline]);
3520+
});
3521+
3522+
it("should return the last event from the main timeline", () => {
3523+
expect(room.getLastLiveEvent()).toBe(lastEventInMainTimeline);
3524+
});
3525+
});
3526+
3527+
describe("when there is no event in the room live timeline, but in a thread", () => {
3528+
beforeEach(() => {
3529+
lastEventInThread = addRoomMainAndThreadMessages(room, undefined, 42).threadEvent!;
3530+
});
3531+
3532+
it("should return the last event from the thread", () => {
3533+
expect(room.getLastLiveEvent()).toBe(lastEventInThread);
3534+
});
3535+
});
3536+
3537+
describe("when there are events in both, the main timeline and threads", () => {
3538+
describe("and the last event is in a thread", () => {
3539+
beforeEach(() => {
3540+
lastEventInThread = addRoomMainAndThreadMessages(room, 23, 42).threadEvent!;
3541+
});
3542+
3543+
it("should return the last event from the thread", () => {
3544+
expect(room.getLastLiveEvent()).toBe(lastEventInThread);
3545+
});
3546+
});
3547+
3548+
describe("and the last event is in the main timeline", () => {
3549+
beforeEach(() => {
3550+
lastEventInMainTimeline = addRoomMainAndThreadMessages(room, 42, 23).mainEvent!;
3551+
});
3552+
3553+
it("should return the last event from the main timeline", () => {
3554+
expect(room.getLastLiveEvent()).toBe(lastEventInMainTimeline);
3555+
});
3556+
});
3557+
});
3558+
});
34783559
});

src/models/room.ts

+26-9
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,6 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
396396
* This is not a comprehensive list of the threads that exist in this room
397397
*/
398398
private threads = new Map<string, Thread>();
399-
public lastThread?: Thread;
400399

401400
/**
402401
* A mapping of eventId to all visibility changes to apply
@@ -785,6 +784,32 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
785784
}
786785
}
787786

787+
/**
788+
* Returns the last live event of this room.
789+
* "last" means latest timestamp.
790+
* "live of this room" means from all live timelines: the room and the threads.
791+
*
792+
* @returns MatrixEvent if there is a last event; else undefined.
793+
*/
794+
public getLastLiveEvent(): MatrixEvent | undefined {
795+
const roomEvents = this.getLiveTimeline().getEvents();
796+
const lastRoomEvent = roomEvents[roomEvents.length - 1] as MatrixEvent | undefined;
797+
798+
return this.getThreads().reduce<MatrixEvent | undefined>(
799+
(lastEventSoFar: MatrixEvent | undefined, thread: Thread) => {
800+
const lastThreadEvent = thread.events[thread.events.length - 1];
801+
802+
if (!lastEventSoFar || (lastThreadEvent?.getTs() ?? 0) > (lastEventSoFar?.getTs() ?? 0)) {
803+
// no last-event-so-far or last thread event is newer than the last-event-so-far
804+
return lastThreadEvent;
805+
}
806+
807+
return lastEventSoFar;
808+
},
809+
lastRoomEvent,
810+
);
811+
}
812+
788813
/**
789814
* @returns the membership type (join | leave | invite) for the logged in user
790815
*/
@@ -2212,14 +2237,6 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
22122237
RoomEvent.Timeline,
22132238
RoomEvent.TimelineReset,
22142239
]);
2215-
const isNewer =
2216-
this.lastThread?.rootEvent &&
2217-
rootEvent?.localTimestamp &&
2218-
this.lastThread.rootEvent?.localTimestamp < rootEvent?.localTimestamp;
2219-
2220-
if (!this.lastThread || isNewer) {
2221-
this.lastThread = thread;
2222-
}
22232240

22242241
if (this.threadsReady) {
22252242
this.updateThreadRootEvents(thread, toStartOfTimeline, false);

0 commit comments

Comments
 (0)