1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2026-01-03 23:22:30 +03:00

Add config option to sort pending events to the end of the timeline

This commit is contained in:
Kegan Dougal
2015-12-07 15:36:32 +00:00
parent c0178c3e80
commit b7ac6a2e33
3 changed files with 62 additions and 11 deletions

View File

@@ -4,6 +4,7 @@
*/
var EventEmitter = require("events").EventEmitter;
var EventStatus = require("./event").EventStatus;
var RoomState = require("./room-state");
var RoomSummary = require("./room-summary");
var MatrixEvent = require("./event").MatrixEvent;
@@ -31,9 +32,15 @@ function synthesizeReceipt(userId, event, receiptType) {
* Construct a new Room.
* @constructor
* @param {string} roomId Required. The ID of this room.
* @param {*} storageToken Optional. The token which a data store can use
* @param {Object=} opts Configuration options
* @param {*} opts.storageToken Optional. The token which a data store can use
* to remember the state of the room. What this means is dependent on the store
* implementation.
* @param {String=} opts.pendingEventOrdering Controls where pending messages appear
* in a room's timeline. If "<b>chronological</b>", messages will appear in the timeline
* when the call to <code>sendEvent</code> was made. If "<b>end</b>", pending messages
* will always appear at the end of the timeline (multiple pending messages will be sorted
* chronologically). Default: "chronological".
* @prop {string} roomId The ID of this room.
* @prop {string} name The human-readable display name for this room.
* @prop {Array<MatrixEvent>} timeline The ordered list of message events for
@@ -48,7 +55,17 @@ function synthesizeReceipt(userId, event, receiptType) {
* @prop {*} storageToken A token which a data store can use to remember
* the state of the room.
*/
function Room(roomId, storageToken) {
function Room(roomId, opts) {
opts = opts || {};
opts.pendingEventOrdering = opts.pendingEventOrdering || "chronological";
if (["chronological", "end"].indexOf(opts.pendingEventOrdering) === -1) {
throw new Error(
"opts.pendingEventOrdering MUST be either 'chronological' or " +
"'end'. Got: '" + opts.pendingEventOrdering + "'"
);
}
this.roomId = roomId;
this.name = roomId;
this.timeline = [];
@@ -59,7 +76,8 @@ function Room(roomId, storageToken) {
this.oldState = new RoomState(roomId);
this.currentState = new RoomState(roomId);
this.summary = null;
this.storageToken = storageToken;
this.storageToken = opts.storageToken;
this._opts = opts;
this._redactions = [];
// receipts should clobber based on receipt_type and user_id pairs hence
// the form of this structure. This is sub-optimal for the exposed APIs
@@ -180,10 +198,18 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline) {
};
}
var addLocalEchoToEnd = this._opts.pendingEventOrdering === "end";
for (var i = 0; i < events.length; i++) {
if (toStartOfTimeline && this._redactions.indexOf(events[i].getId()) >= 0) {
continue; // do not add the redacted event.
}
var isLocalEcho = (
!Boolean(toStartOfTimeline) && (
events[i].status === EventStatus.SENDING ||
events[i].status === EventStatus.QUEUED
)
);
setEventMetadata(events[i], stateContext, toStartOfTimeline);
// modify state
@@ -215,7 +241,22 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline) {
this.timeline.unshift(events[i]);
}
else {
this.timeline.push(events[i]);
// everything gets added to the end by default. What we actually want to
// do in this scenario is *NOT* add REAL events to the end if there are
// existing local echo events at the end.
if (addLocalEchoToEnd && !isLocalEcho) {
var insertIndex = this.timeline.length;
for (var j = this.timeline.length - 1; j >= 0; j--) {
if (!this.timeline[j].status) { // real events don't have a status
insertIndex = j + 1;
break;
}
}
this.timeline.splice(insertIndex, 0, events[i]); // insert element
}
else {
this.timeline.push(events[i]);
}
}
// synthesize and inject implicit read receipts