1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-09 10:22:46 +03:00

Synthesize implicit read receipts in recalculateRoom to make them correct when the room is first loaded.

This commit is contained in:
David Baker
2015-11-06 15:13:30 +00:00
parent 5f6e52f367
commit 14a48c1182

View File

@@ -201,16 +201,10 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline) {
// This is really ugly because JS has no way to express an object literal
// where the name of a key comes from an expression
if (events[i].sender) {
var fakeReceipt = {content: {}};
fakeReceipt.content[events[i].getId()] = {
'm.read': {
}
};
fakeReceipt.content[events[i].getId()]['m.read'][events[i].sender.userId] = {
ts: events[i].getTs()
};
this.addReceipt(new MatrixEvent(fakeReceipt));
if (!toStartOfTimeline && events[i].sender) {
this.addReceipt(new MatrixEvent(this._synthesizeReceipt(
events[i].sender.userId, events[i], "m.read"
)));
}
this.emit("Room.timeline", events[i], this, Boolean(toStartOfTimeline), false);
@@ -347,8 +341,60 @@ Room.prototype.recalculate = function(userId) {
if (oldName !== this.name) {
this.emit("Room.name", this);
}
// recalculate read receipts, adding implicit ones where necessary
// NB. This is a duplication of logic for injecting implicit receipts,
// it would be technically possible to only ever generate these
// receipts in addEventsToTimeline but doing so means correctly
// choosing whether to keep or replace the existing receipt which
// is complex and slow. This is faster and more understandable.
var usersFound = {};
for (var i = this.timeline.length - 1; i >= 0; --i) {
// loop through the timeline backwards looking for either an
// event sent by each user or a real receipt from them.
// Replace the read receipt for that user with whichever
// occurs later in the timeline (ie. first because we're going
// backwards).
var e = this.timeline[i];
var readReceiptsForEvent = this.getReceiptsForEvent(e);
for (var receiptIt = 0; receiptIt < readReceiptsForEvent.length; ++receiptIt) {
var receipt = readReceiptsForEvent[receiptIt];
if (receipt.type !== "m.read") { continue; }
var userId = receipt.userId;
if (usersFound[userId]) { continue; }
// Then this is the receipt we keep for this user
usersFound[userId] = 1;
}
if (e.sender && usersFound[e.sender.userId] === undefined) {
// no receipt yet for this sender, so we synthesize one.
this.addReceipt(this._synthesizeReceipt(e.sender.userId, e, "m.read"));
usersFound[e.sender.userId] = 1;
}
}
};
Room.prototype._synthesizeReceipt = function(userId, event, receiptType) {
// This is really ugly because JS has no way to express an object literal
// where the name of a key comes from an expression
var fakeReceipt = {content: {}};
fakeReceipt.content[event.getId()] = {};
fakeReceipt.content[event.getId()][receiptType] = {};
fakeReceipt.content[event.getId()][receiptType][userId] = {
ts: event
};
return new MatrixEvent(fakeReceipt);
}
/**
* Get a list of user IDs who have <b>read up to</b> the given event.