Skip to content

Commit 3b485c3

Browse files
committed
Don't reset unread count when adding a synthetic receipt
Fixes #3684 and there are lots more details about why we chose this solution in that issue.
1 parent 88ec0e3 commit 3b485c3

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

spec/unit/room.spec.ts

+81
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,87 @@ describe("Room", function () {
14531453
}
14541454

14551455
describe("addReceipt", function () {
1456+
describe("resets the unread count", () => {
1457+
const event1 = utils.mkMessage({ room: roomId, user: userA, msg: "1", event: true });
1458+
const event2 = utils.mkMessage({ room: roomId, user: userA, msg: "2", event: true });
1459+
1460+
it("should reset the unread count when our non-synthetic receipt points to the latest event", () => {
1461+
// Given a room with 2 events, and an unread count set.
1462+
room.client.isInitialSyncComplete = jest.fn().mockReturnValue(true);
1463+
room.timeline = [event1, event2];
1464+
room.setUnread(NotificationCountType.Total, 45);
1465+
room.setUnread(NotificationCountType.Highlight, 57);
1466+
// Sanity check:
1467+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(45);
1468+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(57);
1469+
1470+
// When I receive a receipt for me for the last event
1471+
const receipt = mkReceipt(roomId, [mkRecord(event2.getId()!, "m.read", userA, 123)]);
1472+
room.addReceipt(receipt);
1473+
1474+
// Then the count is set to 0
1475+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(0);
1476+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(0);
1477+
});
1478+
1479+
it("should not reset the unread count when someone else's receipt points to the latest event", () => {
1480+
// Given a room with 2 events, and an unread count set.
1481+
room.client.isInitialSyncComplete = jest.fn().mockReturnValue(true);
1482+
room.timeline = [event1, event2];
1483+
room.setUnread(NotificationCountType.Total, 45);
1484+
room.setUnread(NotificationCountType.Highlight, 57);
1485+
// Sanity check:
1486+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(45);
1487+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(57);
1488+
1489+
// When I receive a receipt for someone else for the last event
1490+
const receipt = mkReceipt(roomId, [mkRecord(event2.getId()!, "m.read", userB, 123)]);
1491+
room.addReceipt(receipt);
1492+
1493+
// Then the count is unchanged because it's not my receipt
1494+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(45);
1495+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(57);
1496+
});
1497+
1498+
it("should not reset the unread count when our non-synthetic receipt points to an earlier event", () => {
1499+
// Given a room with 2 events, and an unread count set.
1500+
room.client.isInitialSyncComplete = jest.fn().mockReturnValue(true);
1501+
room.timeline = [event1, event2];
1502+
room.setUnread(NotificationCountType.Total, 45);
1503+
room.setUnread(NotificationCountType.Highlight, 57);
1504+
// Sanity check:
1505+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(45);
1506+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(57);
1507+
1508+
// When I receive a receipt for me for an earlier event
1509+
const receipt = mkReceipt(roomId, [mkRecord(event1.getId()!, "m.read", userA, 123)]);
1510+
room.addReceipt(receipt);
1511+
1512+
// Then the count is unchanged because it wasn't the latest event
1513+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(45);
1514+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(57);
1515+
});
1516+
1517+
it("should not reset the unread count when our a synthetic receipt points to the latest event", () => {
1518+
// Given a room with 2 events, and an unread count set.
1519+
room.client.isInitialSyncComplete = jest.fn().mockReturnValue(true);
1520+
room.timeline = [event1, event2];
1521+
room.setUnread(NotificationCountType.Total, 45);
1522+
room.setUnread(NotificationCountType.Highlight, 57);
1523+
// Sanity check:
1524+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(45);
1525+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(57);
1526+
1527+
// When I receive a synthetic receipt for me for the last event
1528+
const receipt = mkReceipt(roomId, [mkRecord(event2.getId()!, "m.read", userA, 123)]);
1529+
room.addReceipt(receipt, true);
1530+
1531+
// Then the count is unchanged because the receipt was synthetic
1532+
expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toEqual(45);
1533+
expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toEqual(57);
1534+
});
1535+
});
1536+
14561537
it("should store the receipt so it can be obtained via getReceiptsForEvent", function () {
14571538
const ts = 13787898424;
14581539
room.addReceipt(mkReceipt(roomId, [mkRecord(eventToAck.getId()!, "m.read", userB, ts)]));

src/models/room.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2952,7 +2952,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
29522952
// from synapse
29532953
// This needs to be done after the initial sync as we do not want this
29542954
// logic to run whilst the room is being initialised
2955-
if (this.client.isInitialSyncComplete() && userId === this.client.getUserId()) {
2955+
if (!synthetic && this.client.isInitialSyncComplete() && userId === this.client.getUserId()) {
29562956
const lastEvent = receiptDestination.timeline[receiptDestination.timeline.length - 1];
29572957
if (lastEvent && eventId === lastEvent.getId() && userId === lastEvent.getSender()) {
29582958
receiptDestination.setUnread(NotificationCountType.Total, 0);

0 commit comments

Comments
 (0)