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:
parent
9b5b053148
commit
767cd628f9
2 changed files with 83 additions and 12 deletions
|
@ -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
|
// 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.
|
// receipt's ts, then it we pretend it has a receipt.
|
||||||
const receipt = roomOrThread.getReadReceiptForUserId(myUserId);
|
const receiptTs = roomOrThread.getReadReceiptForUserId(myUserId)?.data.ts ?? 0;
|
||||||
if (receipt) {
|
const unthreadedReceiptTs = roomOrThread.getLastUnthreadedReceiptFor(myUserId)?.ts ?? 0;
|
||||||
const receiptTimestamp = receipt.data.ts;
|
// We pick the more recent of the two receipts as the latest
|
||||||
|
const receiptTimestamp = Math.max(receiptTs, unthreadedReceiptTs);
|
||||||
return (ev) => ev.getTs() < receiptTimestamp;
|
return (ev) => ev.getTs() < receiptTimestamp;
|
||||||
} else {
|
|
||||||
return (_ev) => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue