From 892175daafcff7fc731fc508bf2652b2c132f26b Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 7 Dec 2022 13:55:39 -0500 Subject: [PATCH 01/11] Check each thread for unread messages. --- src/Unread.ts | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/Unread.ts b/src/Unread.ts index 60ef9ca19ed..8254dd338fb 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { Room } from "matrix-js-sdk/src/models/room"; +import { Thread } from "matrix-js-sdk/src/models/thread"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { EventType } from "matrix-js-sdk/src/@types/event"; import { M_BEACON } from "matrix-js-sdk/src/@types/beacon"; @@ -59,34 +60,34 @@ export function doesRoomHaveUnreadMessages(room: Room): boolean { return false; } + for (const timeline of [room, ...room.getThreads()]) { + // If the current timeline has unread messages, we're done. + if (doesRoomOrThreadHaveUnreadMessages(timeline)) { + return true; + } + } + // If we got here then no timelines were found with unread messages. + return false; +} + +function doesRoomOrThreadHaveUnreadMessages(room: Room | Thread): boolean { const myUserId = MatrixClientPeg.get().getUserId(); + // as we don't send RRs for our own messages, make sure we special case that + // if *we* sent the last message into the room, we consider it not unread! + // Should fix: https://github.com/vector-im/element-web/issues/3263 + // https://github.com/vector-im/element-web/issues/2427 + // ...and possibly some of the others at + // https://github.com/vector-im/element-web/issues/3363 + if (room.timeline.length && room.timeline[room.timeline.length - 1].getSender() === myUserId) { + return false; + } + // get the most recent read receipt sent by our account. // N.B. this is NOT a read marker (RM, aka "read up to marker"), // despite the name of the method :(( const readUpToId = room.getEventReadUpTo(myUserId); - if (!SettingsStore.getValue("feature_thread")) { - // as we don't send RRs for our own messages, make sure we special case that - // if *we* sent the last message into the room, we consider it not unread! - // Should fix: https://github.com/vector-im/element-web/issues/3263 - // https://github.com/vector-im/element-web/issues/2427 - // ...and possibly some of the others at - // https://github.com/vector-im/element-web/issues/3363 - if (room.timeline.length && room.timeline[room.timeline.length - 1].getSender() === myUserId) { - return false; - } - } - - // if the read receipt relates to an event is that part of a thread - // we consider that there are no unread messages - // This might be a false negative, but probably the best we can do until - // the read receipts have evolved to cater for threads - const event = room.findEventById(readUpToId); - if (event?.getThread()) { - return false; - } - // this just looks at whatever history we have, which if we've only just started // up probably won't be very much, so if the last couple of events are ones that // don't count, we don't know if there are any events that do count between where From 1af3346f91f8cfe65d2596931e4099f969c55b4c Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 7 Dec 2022 14:55:55 -0500 Subject: [PATCH 02/11] Fix lint? --- src/Unread.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Unread.ts b/src/Unread.ts index 8254dd338fb..95c0865cacf 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -86,7 +86,7 @@ function doesRoomOrThreadHaveUnreadMessages(room: Room | Thread): boolean { // get the most recent read receipt sent by our account. // N.B. this is NOT a read marker (RM, aka "read up to marker"), // despite the name of the method :(( - const readUpToId = room.getEventReadUpTo(myUserId); + const readUpToId: string | null = room.getEventReadUpTo(myUserId); // this just looks at whatever history we have, which if we've only just started // up probably won't be very much, so if the last couple of events are ones that From 4f8b55a3f5528beb6d44e4fc41d999cc8b1ff51f Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 7 Dec 2022 15:16:28 -0500 Subject: [PATCH 03/11] More lint --- src/Unread.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Unread.ts b/src/Unread.ts index 95c0865cacf..feea19821c2 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -86,7 +86,7 @@ function doesRoomOrThreadHaveUnreadMessages(room: Room | Thread): boolean { // get the most recent read receipt sent by our account. // N.B. this is NOT a read marker (RM, aka "read up to marker"), // despite the name of the method :(( - const readUpToId: string | null = room.getEventReadUpTo(myUserId); + const readUpToId = room.getEventReadUpTo(myUserId!); // this just looks at whatever history we have, which if we've only just started // up probably won't be very much, so if the last couple of events are ones that From 80df691f1bef30dc4d4e8b7ba88273a22624e1b1 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 8 Dec 2022 13:31:43 -0500 Subject: [PATCH 04/11] Add tets. --- test/Unread-test.ts | 367 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 293 insertions(+), 74 deletions(-) diff --git a/test/Unread-test.ts b/test/Unread-test.ts index e96c1349312..551514c2664 100644 --- a/test/Unread-test.ts +++ b/test/Unread-test.ts @@ -19,100 +19,319 @@ import { MatrixEvent, EventType, MsgType, + Room, } from "matrix-js-sdk/src/matrix"; +import { ReceiptType } from "matrix-js-sdk/src/@types/read_receipts"; import { haveRendererForEvent } from "../src/events/EventTileFactory"; -import { getMockClientWithEventEmitter, makeBeaconEvent, mockClientMethodsUser } from "./test-utils"; -import { eventTriggersUnreadCount } from "../src/Unread"; +import { + getMockClientWithEventEmitter, + makeBeaconEvent, + mkEvent, + mockClientMethodsUser, + stubClient, +} from "./test-utils"; +import { mkThread } from "./test-utils/threads"; +import { doesRoomHaveUnreadMessages, eventTriggersUnreadCount } from "../src/Unread"; +import { MatrixClientPeg } from "../src/MatrixClientPeg"; jest.mock("../src/events/EventTileFactory", () => ({ haveRendererForEvent: jest.fn(), })); -describe('eventTriggersUnreadCount()', () => { - const aliceId = '@alice:server.org'; - const bobId = '@bob:server.org'; +describe("Unread", () => { + describe('eventTriggersUnreadCount()', () => { + const aliceId = '@alice:server.org'; + const bobId = '@bob:server.org'; - // mock user credentials - getMockClientWithEventEmitter({ - ...mockClientMethodsUser(bobId), - }); + // mock user credentials + getMockClientWithEventEmitter({ + ...mockClientMethodsUser(bobId), + }); - // setup events - const alicesMessage = new MatrixEvent({ - type: EventType.RoomMessage, - sender: aliceId, - content: { - msgtype: MsgType.Text, - body: 'Hello from Alice', - }, - }); + // setup events + const alicesMessage = new MatrixEvent({ + type: EventType.RoomMessage, + sender: aliceId, + content: { + msgtype: MsgType.Text, + body: 'Hello from Alice', + }, + }); - const bobsMessage = new MatrixEvent({ - type: EventType.RoomMessage, - sender: bobId, - content: { - msgtype: MsgType.Text, - body: 'Hello from Bob', - }, - }); + const bobsMessage = new MatrixEvent({ + type: EventType.RoomMessage, + sender: bobId, + content: { + msgtype: MsgType.Text, + body: 'Hello from Bob', + }, + }); - const redactedEvent = new MatrixEvent({ - type: EventType.RoomMessage, - sender: aliceId, - }); - redactedEvent.makeRedacted(redactedEvent); + const redactedEvent = new MatrixEvent({ + type: EventType.RoomMessage, + sender: aliceId, + }); + redactedEvent.makeRedacted(redactedEvent); - beforeEach(() => { - jest.clearAllMocks(); - mocked(haveRendererForEvent).mockClear().mockReturnValue(false); - }); + beforeEach(() => { + jest.clearAllMocks(); + mocked(haveRendererForEvent).mockClear().mockReturnValue(false); + }); - it('returns false when the event was sent by the current user', () => { - expect(eventTriggersUnreadCount(bobsMessage)).toBe(false); - // returned early before checking renderer - expect(haveRendererForEvent).not.toHaveBeenCalled(); - }); + it('returns false when the event was sent by the current user', () => { + expect(eventTriggersUnreadCount(bobsMessage)).toBe(false); + // returned early before checking renderer + expect(haveRendererForEvent).not.toHaveBeenCalled(); + }); - it('returns false for a redacted event', () => { - expect(eventTriggersUnreadCount(redactedEvent)).toBe(false); - // returned early before checking renderer - expect(haveRendererForEvent).not.toHaveBeenCalled(); - }); + it('returns false for a redacted event', () => { + expect(eventTriggersUnreadCount(redactedEvent)).toBe(false); + // returned early before checking renderer + expect(haveRendererForEvent).not.toHaveBeenCalled(); + }); - it('returns false for an event without a renderer', () => { - mocked(haveRendererForEvent).mockReturnValue(false); - expect(eventTriggersUnreadCount(alicesMessage)).toBe(false); - expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false); - }); + it('returns false for an event without a renderer', () => { + mocked(haveRendererForEvent).mockReturnValue(false); + expect(eventTriggersUnreadCount(alicesMessage)).toBe(false); + expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false); + }); - it('returns true for an event with a renderer', () => { - mocked(haveRendererForEvent).mockReturnValue(true); - expect(eventTriggersUnreadCount(alicesMessage)).toBe(true); - expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false); - }); + it('returns true for an event with a renderer', () => { + mocked(haveRendererForEvent).mockReturnValue(true); + expect(eventTriggersUnreadCount(alicesMessage)).toBe(true); + expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false); + }); + + it('returns false for beacon locations', () => { + const beaconLocationEvent = makeBeaconEvent(aliceId); + expect(eventTriggersUnreadCount(beaconLocationEvent)).toBe(false); + expect(haveRendererForEvent).not.toHaveBeenCalled(); + }); + + const noUnreadEventTypes = [ + EventType.RoomMember, + EventType.RoomThirdPartyInvite, + EventType.CallAnswer, + EventType.CallHangup, + EventType.RoomCanonicalAlias, + EventType.RoomServerAcl, + ]; - it('returns false for beacon locations', () => { - const beaconLocationEvent = makeBeaconEvent(aliceId); - expect(eventTriggersUnreadCount(beaconLocationEvent)).toBe(false); - expect(haveRendererForEvent).not.toHaveBeenCalled(); + it.each(noUnreadEventTypes)( + 'returns false without checking for renderer for events with type %s', + (eventType) => { + const event = new MatrixEvent({ + type: eventType, + sender: aliceId, + }); + expect(eventTriggersUnreadCount(event)).toBe(false); + expect(haveRendererForEvent).not.toHaveBeenCalled(); + }, + ); }); - const noUnreadEventTypes = [ - EventType.RoomMember, - EventType.RoomThirdPartyInvite, - EventType.CallAnswer, - EventType.CallHangup, - EventType.RoomCanonicalAlias, - EventType.RoomServerAcl, - ]; - - it.each(noUnreadEventTypes)('returns false without checking for renderer for events with type %s', (eventType) => { - const event = new MatrixEvent({ - type: eventType, - sender: aliceId, + describe.only("doesRoomHaveUnreadMessages()", () => { + let room; + let event; + const roomId = "!abc:server.org"; + // A different user. + const aliceId = '@alice:server.org'; + stubClient(); + const client = MatrixClientPeg.get(); + + beforeEach(() => { + // Create a room and initial event in it. + room = new Room(roomId, client, client.getUserId()); + event = mkEvent({ + event: true, + type: "m.room.message", + user: aliceId, + room: roomId, + content: {}, + }); + room.addLiveEvents([event]); + + // Don't care about the code path of hidden events. + mocked(haveRendererForEvent).mockClear().mockReturnValue(true); + }); + + it('returns true for a room with no receipts', () => { + expect(doesRoomHaveUnreadMessages(room)).toBe(true); + }); + + it('returns false for a room when the latest event was sent by the current user', () => { + event = mkEvent({ + event: true, + type: "m.room.message", + user: client.getUserId(), + room: roomId, + content: {}, + }); + // Only for timeline events. + room.addLiveEvents([event]); + + expect(doesRoomHaveUnreadMessages(room)).toBe(false); + }); + + it('returns false for a room when the read receipt is at the latest event', () => { + const receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [event.getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1 }, + }, + }, + }, + }); + room.addReceipt(receipt); + + expect(doesRoomHaveUnreadMessages(room)).toBe(false); + }); + + it('returns true for a room when the read receipt is earlier than the latest event', () => { + const receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [event.getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1 }, + }, + }, + }, + }); + room.addReceipt(receipt); + + const event2 = mkEvent({ + event: true, + type: "m.room.message", + user: aliceId, + room: roomId, + content: {}, + }); + // Only for timeline events. + room.addLiveEvents([event2]); + + expect(doesRoomHaveUnreadMessages(room)).toBe(true); + }); + + it('returns true for a room with an unread message in a thread', () => { + // Mark the main timeline as read. + const receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [event.getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1 }, + }, + }, + }, + }); + room.addReceipt(receipt); + + // Create a thread as a different user. + mkThread({ room, client, authorId: client.getUserId(), participantUserIds: [aliceId] }); + + expect(doesRoomHaveUnreadMessages(room)).toBe(true); + }); + + it('returns false for a room when the latest thread event was sent by the current user', () => { + // Mark the main timeline as read. + const receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [event.getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1 }, + }, + }, + }, + }); + room.addReceipt(receipt); + + // Create a thread as the current user.. + mkThread({ room, client, authorId: client.getUserId(), participantUserIds: [client.getUserId()] }); + + expect(doesRoomHaveUnreadMessages(room)).toBe(false); + }); + + it('returns false for a room with read thread messages', () => { + // Mark the main timeline as read. + let receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [event.getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1 }, + }, + }, + }, + }); + room.addReceipt(receipt); + + // Create threads. + const { rootEvent, events } = mkThread( + { room, client, authorId: client.getUserId(), participantUserIds: [aliceId] }, + ); + + // Mark the thread as read. + receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [events[events.length - 1].getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1, threadId: rootEvent.getId() }, + }, + }, + }, + }); + room.addReceipt(receipt); + + expect(doesRoomHaveUnreadMessages(room)).toBe(false); + }); + + it('returns true for a room when read receipt is not on the latest thread messages', () => { + // Mark the main timeline as read. + let receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [event.getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1 }, + }, + }, + }, + }); + room.addReceipt(receipt); + + // Create threads. + const { rootEvent, events } = mkThread( + { room, client, authorId: client.getUserId(), participantUserIds: [aliceId] }, + ); + + // Mark the thread as read. + receipt = new MatrixEvent({ + type: "m.receipt", + room_id: "!foo:bar", + content: { + [events[0].getId()]: { + [ReceiptType.Read]: { + [client.getUserId()]: { ts: 1, threadId: rootEvent.getId() }, + }, + }, + }, + }); + room.addReceipt(receipt); + + expect(doesRoomHaveUnreadMessages(room)).toBe(true); }); - expect(eventTriggersUnreadCount(event)).toBe(false); - expect(haveRendererForEvent).not.toHaveBeenCalled(); }); }); From 252ba69e241ada68d426f4ee1768f4f53ce8f103 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 8 Dec 2022 13:49:50 -0500 Subject: [PATCH 05/11] Remove only call. --- test/Unread-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Unread-test.ts b/test/Unread-test.ts index 551514c2664..8de7fa4f013 100644 --- a/test/Unread-test.ts +++ b/test/Unread-test.ts @@ -131,7 +131,7 @@ describe("Unread", () => { ); }); - describe.only("doesRoomHaveUnreadMessages()", () => { + describe("doesRoomHaveUnreadMessages()", () => { let room; let event; const roomId = "!abc:server.org"; From c90d481909ae1329ecfe8c1a27c1f5416ffb49ac Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Fri, 9 Dec 2022 09:23:05 -0500 Subject: [PATCH 06/11] Enable threads in tests. --- test/Unread-test.ts | 4 ++++ test/test-utils/threads.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test/Unread-test.ts b/test/Unread-test.ts index 8de7fa4f013..25e0062d428 100644 --- a/test/Unread-test.ts +++ b/test/Unread-test.ts @@ -140,6 +140,10 @@ describe("Unread", () => { stubClient(); const client = MatrixClientPeg.get(); + beforeAll(() => { + client.supportsExperimentalThreads = () => true; + }); + beforeEach(() => { // Create a room and initial event in it. room = new Room(roomId, client, client.getUserId()); diff --git a/test/test-utils/threads.ts b/test/test-utils/threads.ts index 3b07c45051b..db4a51cc718 100644 --- a/test/test-utils/threads.ts +++ b/test/test-utils/threads.ts @@ -126,7 +126,7 @@ export const mkThread = ({ const thread = room.createThread(rootEvent.getId(), rootEvent, events, true); // So that we do not have to mock the thread loading thread.initialEventsFetched = true; - thread.addEvents(events, true); + thread.addEvents(events, false); return { thread, rootEvent, events }; }; From 3eee43e3218419c5214a95532e576902c3255e28 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 9 Dec 2022 09:23:13 -0500 Subject: [PATCH 07/11] Additional fixes. --- test/Unread-test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Unread-test.ts b/test/Unread-test.ts index 25e0062d428..df71dbf9e51 100644 --- a/test/Unread-test.ts +++ b/test/Unread-test.ts @@ -258,7 +258,7 @@ describe("Unread", () => { }); room.addReceipt(receipt); - // Create a thread as the current user.. + // Create a thread as the current user. mkThread({ room, client, authorId: client.getUserId(), participantUserIds: [client.getUserId()] }); expect(doesRoomHaveUnreadMessages(room)).toBe(false); @@ -291,7 +291,7 @@ describe("Unread", () => { content: { [events[events.length - 1].getId()]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1, threadId: rootEvent.getId() }, + [client.getUserId()]: { ts: 1, thread_id: rootEvent.getId() }, }, }, }, From 860f81847905de1d851a7edcd0249eafff0de4e4 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 9 Dec 2022 09:50:44 -0500 Subject: [PATCH 08/11] Consolidate mocking in tests. --- src/Unread.ts | 2 ++ test/Unread-test.ts | 31 +++++++++---------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/Unread.ts b/src/Unread.ts index feea19821c2..50ae42e4461 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -33,6 +33,8 @@ import SettingsStore from "./settings/SettingsStore"; * @returns {boolean} True if the given event should affect the unread message count */ export function eventTriggersUnreadCount(ev: MatrixEvent): boolean { + console.log(ev.getSender()); + console.log(MatrixClientPeg.get().credentials.userId); if (ev.getSender() === MatrixClientPeg.get().credentials.userId) { return false; } diff --git a/test/Unread-test.ts b/test/Unread-test.ts index df71dbf9e51..3ba08379d6f 100644 --- a/test/Unread-test.ts +++ b/test/Unread-test.ts @@ -24,13 +24,7 @@ import { import { ReceiptType } from "matrix-js-sdk/src/@types/read_receipts"; import { haveRendererForEvent } from "../src/events/EventTileFactory"; -import { - getMockClientWithEventEmitter, - makeBeaconEvent, - mkEvent, - mockClientMethodsUser, - stubClient, -} from "./test-utils"; +import { makeBeaconEvent, mkEvent, stubClient } from "./test-utils"; import { mkThread } from "./test-utils/threads"; import { doesRoomHaveUnreadMessages, eventTriggersUnreadCount } from "../src/Unread"; import { MatrixClientPeg } from "../src/MatrixClientPeg"; @@ -40,15 +34,12 @@ jest.mock("../src/events/EventTileFactory", () => ({ })); describe("Unread", () => { - describe('eventTriggersUnreadCount()', () => { - const aliceId = '@alice:server.org'; - const bobId = '@bob:server.org'; - - // mock user credentials - getMockClientWithEventEmitter({ - ...mockClientMethodsUser(bobId), - }); + // A different user. + const aliceId = '@alice:server.org'; + stubClient(); + const client = MatrixClientPeg.get(); + describe('eventTriggersUnreadCount()', () => { // setup events const alicesMessage = new MatrixEvent({ type: EventType.RoomMessage, @@ -59,9 +50,9 @@ describe("Unread", () => { }, }); - const bobsMessage = new MatrixEvent({ + const ourMessage = new MatrixEvent({ type: EventType.RoomMessage, - sender: bobId, + sender: client.getUserId(), content: { msgtype: MsgType.Text, body: 'Hello from Bob', @@ -80,7 +71,7 @@ describe("Unread", () => { }); it('returns false when the event was sent by the current user', () => { - expect(eventTriggersUnreadCount(bobsMessage)).toBe(false); + expect(eventTriggersUnreadCount(ourMessage)).toBe(false); // returned early before checking renderer expect(haveRendererForEvent).not.toHaveBeenCalled(); }); @@ -135,10 +126,6 @@ describe("Unread", () => { let room; let event; const roomId = "!abc:server.org"; - // A different user. - const aliceId = '@alice:server.org'; - stubClient(); - const client = MatrixClientPeg.get(); beforeAll(() => { client.supportsExperimentalThreads = () => true; From 968d9e9cb6b96cdbdb9163d8455517f339edd72d Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 9 Dec 2022 10:15:47 -0500 Subject: [PATCH 09/11] Strict fixes. --- test/Unread-test.ts | 51 +++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/test/Unread-test.ts b/test/Unread-test.ts index 3ba08379d6f..b79bbe881d6 100644 --- a/test/Unread-test.ts +++ b/test/Unread-test.ts @@ -52,7 +52,7 @@ describe("Unread", () => { const ourMessage = new MatrixEvent({ type: EventType.RoomMessage, - sender: client.getUserId(), + sender: client.getUserId()!, content: { msgtype: MsgType.Text, body: 'Hello from Bob', @@ -123,9 +123,10 @@ describe("Unread", () => { }); describe("doesRoomHaveUnreadMessages()", () => { - let room; - let event; + let room: Room; + let event: MatrixEvent; const roomId = "!abc:server.org"; + const myId = client.getUserId()!; beforeAll(() => { client.supportsExperimentalThreads = () => true; @@ -133,7 +134,7 @@ describe("Unread", () => { beforeEach(() => { // Create a room and initial event in it. - room = new Room(roomId, client, client.getUserId()); + room = new Room(roomId, client, myId); event = mkEvent({ event: true, type: "m.room.message", @@ -155,7 +156,7 @@ describe("Unread", () => { event = mkEvent({ event: true, type: "m.room.message", - user: client.getUserId(), + user: myId, room: roomId, content: {}, }); @@ -170,9 +171,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [event.getId()]: { + [event.getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1 }, + [myId]: { ts: 1 }, }, }, }, @@ -187,9 +188,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [event.getId()]: { + [event.getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1 }, + [myId]: { ts: 1 }, }, }, }, @@ -215,9 +216,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [event.getId()]: { + [event.getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1 }, + [myId]: { ts: 1 }, }, }, }, @@ -225,7 +226,7 @@ describe("Unread", () => { room.addReceipt(receipt); // Create a thread as a different user. - mkThread({ room, client, authorId: client.getUserId(), participantUserIds: [aliceId] }); + mkThread({ room, client, authorId: myId, participantUserIds: [aliceId] }); expect(doesRoomHaveUnreadMessages(room)).toBe(true); }); @@ -236,9 +237,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [event.getId()]: { + [event.getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1 }, + [myId]: { ts: 1 }, }, }, }, @@ -246,7 +247,7 @@ describe("Unread", () => { room.addReceipt(receipt); // Create a thread as the current user. - mkThread({ room, client, authorId: client.getUserId(), participantUserIds: [client.getUserId()] }); + mkThread({ room, client, authorId: myId, participantUserIds: [myId] }); expect(doesRoomHaveUnreadMessages(room)).toBe(false); }); @@ -257,9 +258,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [event.getId()]: { + [event.getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1 }, + [myId]: { ts: 1 }, }, }, }, @@ -268,7 +269,7 @@ describe("Unread", () => { // Create threads. const { rootEvent, events } = mkThread( - { room, client, authorId: client.getUserId(), participantUserIds: [aliceId] }, + { room, client, authorId: myId, participantUserIds: [aliceId] }, ); // Mark the thread as read. @@ -276,9 +277,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [events[events.length - 1].getId()]: { + [events[events.length - 1].getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1, thread_id: rootEvent.getId() }, + [myId]: { ts: 1, thread_id: rootEvent.getId()! }, }, }, }, @@ -294,9 +295,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [event.getId()]: { + [event.getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1 }, + [myId]: { ts: 1 }, }, }, }, @@ -305,7 +306,7 @@ describe("Unread", () => { // Create threads. const { rootEvent, events } = mkThread( - { room, client, authorId: client.getUserId(), participantUserIds: [aliceId] }, + { room, client, authorId: myId, participantUserIds: [aliceId] }, ); // Mark the thread as read. @@ -313,9 +314,9 @@ describe("Unread", () => { type: "m.receipt", room_id: "!foo:bar", content: { - [events[0].getId()]: { + [events[0].getId()!]: { [ReceiptType.Read]: { - [client.getUserId()]: { ts: 1, threadId: rootEvent.getId() }, + [myId]: { ts: 1, threadId: rootEvent.getId()! }, }, }, }, From d6dce0176b8bbe763121d4298a19bdeee90d9c45 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Mon, 12 Dec 2022 08:24:47 -0500 Subject: [PATCH 10/11] Remove debugging code. Co-authored-by: Germain --- src/Unread.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Unread.ts b/src/Unread.ts index 50ae42e4461..feea19821c2 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -33,8 +33,6 @@ import SettingsStore from "./settings/SettingsStore"; * @returns {boolean} True if the given event should affect the unread message count */ export function eventTriggersUnreadCount(ev: MatrixEvent): boolean { - console.log(ev.getSender()); - console.log(MatrixClientPeg.get().credentials.userId); if (ev.getSender() === MatrixClientPeg.get().credentials.userId) { return false; } From 705946cc167b674799828217fbef476f359d45ba Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Mon, 12 Dec 2022 08:37:54 -0500 Subject: [PATCH 11/11] Use updated syntax. Co-authored-by: Germain --- src/Unread.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Unread.ts b/src/Unread.ts index feea19821c2..e492c7890fc 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -79,7 +79,7 @@ function doesRoomOrThreadHaveUnreadMessages(room: Room | Thread): boolean { // https://github.com/vector-im/element-web/issues/2427 // ...and possibly some of the others at // https://github.com/vector-im/element-web/issues/3363 - if (room.timeline.length && room.timeline[room.timeline.length - 1].getSender() === myUserId) { + if (room.timeline.at(-1)?.getSender() === myUserId) { return false; }