Consider the unthreaded read receipt for Unread dot state (#11117)

* Consider the unthreaded read receipt for Unread dot state also

* Add tests

* Fix strict types
This commit is contained in:
Michael Telatynski 2023-06-21 16:07:16 +01:00 committed by GitHub
parent 9b5b053148
commit 767cd628f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 12 deletions

View file

@ -159,15 +159,13 @@ function makeHasReceipt(
// If we found an event matching our receipt, then it's easy: this event // If we found an event matching our receipt, then it's easy: this event
// has a receipt if its ID is the same as the one in the receipt. // has a receipt if its ID is the same as the one in the receipt.
return (ev) => ev.getId() == readUpToId; return (ev) => ev.getId() == readUpToId;
} else {
// If we didn't, we have to guess by saying if this event is before the
// receipt's ts, then it we pretend it has a receipt.
const receipt = roomOrThread.getReadReceiptForUserId(myUserId);
if (receipt) {
const receiptTimestamp = receipt.data.ts;
return (ev) => ev.getTs() < receiptTimestamp;
} else {
return (_ev) => false;
}
} }
// If we didn't, we have to guess by saying if this event is before the
// receipt's ts, then it we pretend it has a receipt.
const receiptTs = roomOrThread.getReadReceiptForUserId(myUserId)?.data.ts ?? 0;
const unthreadedReceiptTs = roomOrThread.getLastUnthreadedReceiptFor(myUserId)?.ts ?? 0;
// We pick the more recent of the two receipts as the latest
const receiptTimestamp = Math.max(receiptTs, unthreadedReceiptTs);
return (ev) => ev.getTs() < receiptTimestamp;
} }

View file

@ -22,7 +22,11 @@ import { logger } from "matrix-js-sdk/src/logger";
import { haveRendererForEvent } from "../src/events/EventTileFactory"; import { haveRendererForEvent } from "../src/events/EventTileFactory";
import { makeBeaconEvent, mkEvent, stubClient } from "./test-utils"; import { makeBeaconEvent, mkEvent, stubClient } from "./test-utils";
import { mkThread } from "./test-utils/threads"; import { mkThread } from "./test-utils/threads";
import { doesRoomHaveUnreadMessages, eventTriggersUnreadCount } from "../src/Unread"; import {
doesRoomHaveUnreadMessages,
doesRoomOrThreadHaveUnreadMessages,
eventTriggersUnreadCount,
} from "../src/Unread";
import { MatrixClientPeg } from "../src/MatrixClientPeg"; import { MatrixClientPeg } from "../src/MatrixClientPeg";
jest.mock("../src/events/EventTileFactory", () => ({ jest.mock("../src/events/EventTileFactory", () => ({
@ -122,7 +126,7 @@ describe("Unread", () => {
let room: Room; let room: Room;
let event: MatrixEvent; let event: MatrixEvent;
const roomId = "!abc:server.org"; const roomId = "!abc:server.org";
const myId = client.getUserId()!; const myId = client.getSafeUserId();
beforeAll(() => { beforeAll(() => {
client.supportsThreads = () => true; client.supportsThreads = () => true;
@ -429,4 +433,73 @@ describe("Unread", () => {
); );
}); });
}); });
describe("doesRoomOrThreadHaveUnreadMessages()", () => {
let room: Room;
let event: MatrixEvent;
const roomId = "!abc:server.org";
const myId = client.getSafeUserId();
beforeAll(() => {
client.supportsThreads = () => true;
});
beforeEach(() => {
room = new Room(roomId, client, myId);
jest.spyOn(logger, "warn");
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("should consider unthreaded read receipts for main timeline", () => {
// Send unthreaded receipt into room pointing at the latest event
room.addReceipt(
new MatrixEvent({
type: "m.receipt",
room_id: "!foo:bar",
content: {
[event.getId()!]: {
[ReceiptType.Read]: {
[myId]: { ts: 1 },
},
},
},
}),
);
expect(doesRoomOrThreadHaveUnreadMessages(room)).toBe(false);
});
it("should consider unthreaded read receipts for thread timelines", () => {
// Provide an unthreaded read receipt with ts greater than the latest thread event
const receipt = new MatrixEvent({
type: "m.receipt",
room_id: "!foo:bar",
content: {
[event.getId()!]: {
[ReceiptType.Read]: {
[myId]: { ts: 10000000000 },
},
},
},
});
room.addReceipt(receipt);
const { thread } = mkThread({ room, client, authorId: myId, participantUserIds: [aliceId] });
expect(thread.replyToEvent!.getTs()).toBeLessThan(
receipt.getContent()[event.getId()!][ReceiptType.Read][myId].ts,
);
expect(doesRoomOrThreadHaveUnreadMessages(thread)).toBe(false);
});
});
}); });