From ace4a2b0b7c207a70729e6eb6456859a4497a014 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 27 Feb 2021 22:45:11 -0700 Subject: [PATCH 1/2] Add function to determine who has read at least a given event --- src/models/room.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/models/room.js b/src/models/room.js index 9c321e1bb39..db9c934bae1 100644 --- a/src/models/room.js +++ b/src/models/room.js @@ -1584,6 +1584,44 @@ Room.prototype.recalculate = function() { } }; +/** + * Get a list of user IDs who have read up to and including the given + * event. This will look at the most recent maxEvents to identify the + * given event, and any users who have read events leading up to that + * event. If the function exceeds the given limit, an empty array will + * be returned. Otherwise, an array with at least the event sender will + * be returned. + * @param {MatrixEvent} event The event to search for. + * @param {number} maxEvents The maximum number of events to search within. + * @returns {string[]} A list of user IDs who have read the event. + */ +Room.prototype.getUsersWhoHaveRead = function(event, maxEvents) { + // First, determine if the event is a pending event. If yes, don't bother searching + if (this.getPendingEvents().some(e => e.getId() === event.getId())) { + return [event.getSender()]; + } + + // Now try to find where the event is in the timeline. We look behind for a maximum + // of 100 events just to avoid runaway loops + const events = this.getLiveTimeline().getEvents(); // timelines are most recent last + let foundEvent = false; + const receiptIds = new Set(); + for (let i = events.length - 1; i >= Math.max(0, events.length - maxEvents); i--) { + const ev = events[i]; + this.getUsersReadUpTo(ev).forEach(u => receiptIds.add(u)); + if (ev.getId() === event.getId()) { + foundEvent = true; + break; // we don't need to search any further + } + } + if (!foundEvent) { + return []; // per our contract, return nothing + } else { + receiptIds.add(event.getSender()); // also per the contract, return with the sender + } + return Array.from(receiptIds); +}; + /** * Get a list of user IDs who have read up to the given event. * @param {MatrixEvent} event the event to get read receipts for. From 382a38034af4832cb788a4ddd2d3ca7700af9964 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 2 Mar 2021 11:05:58 -0700 Subject: [PATCH 2/2] Fix comment --- src/models/room.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/models/room.js b/src/models/room.js index db9c934bae1..4955679e6f9 100644 --- a/src/models/room.js +++ b/src/models/room.js @@ -1601,8 +1601,7 @@ Room.prototype.getUsersWhoHaveRead = function(event, maxEvents) { return [event.getSender()]; } - // Now try to find where the event is in the timeline. We look behind for a maximum - // of 100 events just to avoid runaway loops + // Now try to find where the event is in the timeline const events = this.getLiveTimeline().getEvents(); // timelines are most recent last let foundEvent = false; const receiptIds = new Set();