1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-09-01 21:21:58 +03:00

Merge pull request #44 from matrix-org/implicit_read_receipts_2

Synthesize implicit read receipts in recalculateRoom
This commit is contained in:
David Baker
2015-11-09 15:08:04 +00:00

View File

@@ -10,6 +10,23 @@ var MatrixEvent = require("./event").MatrixEvent;
var utils = require("../utils");
var ContentRepo = require("../content-repo");
function synthesizeReceipt(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: {},
type: "m.receipt",
room_id: event.getRoomId()
};
fakeReceipt.content[event.getId()] = {};
fakeReceipt.content[event.getId()][receiptType] = {};
fakeReceipt.content[event.getId()][receiptType][userId] = {
ts: event
};
return new MatrixEvent(fakeReceipt);
}
/**
* Construct a new Room.
* @constructor
@@ -207,16 +224,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(synthesizeReceipt(
events[i].sender.userId, events[i], "m.read"
)));
}
this.emit("Room.timeline", events[i], this, Boolean(toStartOfTimeline), false);
@@ -356,6 +367,45 @@ 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; }
if (usersFound[receipt.userId]) { continue; }
// Then this is the receipt we keep for this user
usersFound[receipt.userId] = 1;
}
if (e.sender && usersFound[e.sender.userId] === undefined) {
// no receipt yet for this sender, so we synthesize one.
this.addReceipt(synthesizeReceipt(e.sender.userId, e, "m.read"));
usersFound[e.sender.userId] = 1;
}
}
};