From 2b3d33d8f3c7c8cd202c1b97e7e9af65e7e50bb7 Mon Sep 17 00:00:00 2001 From: Germain Date: Wed, 26 Oct 2022 15:24:07 +0100 Subject: [PATCH 1/4] Make thread replies trigger a room list re-ordering --- .../algorithms/tag-sorting/RecentAlgorithm.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts index 9466a35940a..1066ee38a1a 100644 --- a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts +++ b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts @@ -73,7 +73,7 @@ export const sortRooms = (rooms: Room[]): Room[] => { }; const getLastTs = (r: Room, userId: string) => { - const ts = (() => { + const mainTimelineLastTs = (() => { // Apparently we can have rooms without timelines, at least under testing // environments. Just return MAX_INT when this happens. if (!r?.timeline) { @@ -108,7 +108,13 @@ const getLastTs = (r: Room, userId: string) => { // This is better than just assuming the last event was forever ago. return r.timeline[0]?.getTs() ?? Number.MAX_SAFE_INTEGER; })(); - return ts; + + const threadLastEventTimestamps = r.getThreads().map(thread => { + const event = thread.replyToEvent ?? thread.rootEvent; + return event?.getTs() ?? 0; + }); + + return Math.max(mainTimelineLastTs, ...threadLastEventTimestamps); }; /** From c473ad387f9c60e9703fd12cd00300e19912aab9 Mon Sep 17 00:00:00 2001 From: Germain Date: Wed, 26 Oct 2022 16:45:12 +0100 Subject: [PATCH 2/4] Add recent algorithm test --- .../algorithms/RecentAlgorithm-test.ts | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/test/stores/room-list/algorithms/RecentAlgorithm-test.ts b/test/stores/room-list/algorithms/RecentAlgorithm-test.ts index 40ce53f2251..fd0ffb0c955 100644 --- a/test/stores/room-list/algorithms/RecentAlgorithm-test.ts +++ b/test/stores/room-list/algorithms/RecentAlgorithm-test.ts @@ -21,6 +21,7 @@ import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import "../../../../src/stores/room-list/RoomListStore"; import { RecentAlgorithm } from "../../../../src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; import { EffectiveMembership } from "../../../../src/utils/membership"; +import { makeThreadEvent, mkThread } from "../../../test-utils/threads"; describe("RecentAlgorithm", () => { let algorithm; @@ -122,6 +123,60 @@ describe("RecentAlgorithm", () => { room1.addLiveEvents([evt]); expect(algorithm.sortRooms([room2, room1])).toEqual([room2, room1]); + + const { events } = mkThread({ + room: room1, + client: cli, + authorId: "@bob:matrix.org", + participantUserIds: ["@bob:matrix.org"], + ts: 12, + }); + + room1.addLiveEvents(events); + }); + + it("orders rooms based on thread replies too", () => { + const room1 = new Room("room1", cli, "@bob:matrix.org"); + const room2 = new Room("room2", cli, "@bob:matrix.org"); + + room1.getMyMembership = () => "join"; + room2.getMyMembership = () => "join"; + + const { rootEvent, events: events1 } = mkThread({ + room: room1, + client: cli, + authorId: "@bob:matrix.org", + participantUserIds: ["@bob:matrix.org"], + ts: 12, + length: 5, + }); + room1.addLiveEvents(events1); + + const { events: events2 } = mkThread({ + room: room2, + client: cli, + authorId: "@bob:matrix.org", + participantUserIds: ["@bob:matrix.org"], + ts: 14, + length: 10, + }); + room2.addLiveEvents(events2); + + expect(algorithm.sortRooms([room1, room2])).toEqual([room2, room1]); + + const threadReply = makeThreadEvent({ + user: "@bob:matrix.org", + room: room1.roomId, + event: true, + msg: `hello world`, + rootEventId: rootEvent.getId(), + replyToEventId: rootEvent.getId(), + // replies are 1ms after each other + ts: 50, + }); + room2.addLiveEvents([threadReply]); + + expect(algorithm.sortRooms([room1, room2])).toEqual([room1, room2]); }); }); }); From 5ea7db41a31cc5583afda81a9ae71966e0781263 Mon Sep 17 00:00:00 2001 From: Germain Date: Wed, 26 Oct 2022 17:28:19 +0100 Subject: [PATCH 3/4] fix infinite loop --- test/stores/room-list/algorithms/RecentAlgorithm-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/stores/room-list/algorithms/RecentAlgorithm-test.ts b/test/stores/room-list/algorithms/RecentAlgorithm-test.ts index fd0ffb0c955..45dd89d7b5e 100644 --- a/test/stores/room-list/algorithms/RecentAlgorithm-test.ts +++ b/test/stores/room-list/algorithms/RecentAlgorithm-test.ts @@ -174,7 +174,7 @@ describe("RecentAlgorithm", () => { // replies are 1ms after each other ts: 50, }); - room2.addLiveEvents([threadReply]); + room1.addLiveEvents([threadReply]); expect(algorithm.sortRooms([room1, room2])).toEqual([room1, room2]); }); From 47da28281c106681b70c47d1e1fb8035c084b0e1 Mon Sep 17 00:00:00 2001 From: Germain Date: Thu, 27 Oct 2022 11:14:56 +0100 Subject: [PATCH 4/4] remove uneeded clause --- src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts index 1066ee38a1a..fe469d39ff3 100644 --- a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts +++ b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts @@ -111,7 +111,7 @@ const getLastTs = (r: Room, userId: string) => { const threadLastEventTimestamps = r.getThreads().map(thread => { const event = thread.replyToEvent ?? thread.rootEvent; - return event?.getTs() ?? 0; + return event!.getTs(); }); return Math.max(mainTimelineLastTs, ...threadLastEventTimestamps);