You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-28 05:03:59 +03:00
Fire a 'Room.timelineReset' event when we get a gappy sync
We need to reset things at the UI level when we get a gappy sync, so give the clients something to listen for. Also add a bunch of tests for that bit of code.
This commit is contained in:
@@ -143,12 +143,14 @@ function Room(roomId, opts) {
|
||||
|
||||
this._notificationCounts = {};
|
||||
|
||||
this._liveTimeline = new EventTimeline(this.roomId);
|
||||
this._fixUpLegacyTimelineFields();
|
||||
|
||||
// just a list - *not* ordered.
|
||||
this._timelines = [];
|
||||
this._timelines = [this._liveTimeline];
|
||||
this._eventIdToTimeline = {};
|
||||
this._timelineSupport = Boolean(opts.timelineSupport);
|
||||
|
||||
this.resetLiveTimeline();
|
||||
}
|
||||
utils.inherits(Room, EventEmitter);
|
||||
|
||||
@@ -165,6 +167,8 @@ Room.prototype.getLiveTimeline = function() {
|
||||
* Reset the live timeline, and start a new one.
|
||||
*
|
||||
* <p>This is used when /sync returns a 'limited' timeline.
|
||||
*
|
||||
* @fires module:client~MatrixClient#event:"Room.timelineReset"
|
||||
*/
|
||||
Room.prototype.resetLiveTimeline = function() {
|
||||
var newTimeline;
|
||||
@@ -178,10 +182,6 @@ Room.prototype.resetLiveTimeline = function() {
|
||||
newTimeline = this.addTimeline();
|
||||
}
|
||||
|
||||
if (this._liveTimeline) {
|
||||
// we have an existing timeline. This will always be true, except when
|
||||
// this method is called by our own constructor.
|
||||
|
||||
// initialise the state in the new timeline from our last known state
|
||||
var evMap = this._liveTimeline.getState(EventTimeline.FORWARDS).events;
|
||||
var events = [];
|
||||
@@ -193,9 +193,18 @@ Room.prototype.resetLiveTimeline = function() {
|
||||
}
|
||||
}
|
||||
newTimeline.initialiseState(events);
|
||||
}
|
||||
this._liveTimeline = newTimeline;
|
||||
|
||||
this._liveTimeline = newTimeline;
|
||||
this._fixUpLegacyTimelineFields();
|
||||
this.emit("Room.timelineReset", this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fix up this.timeline, this.oldState and this.currentState
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Room.prototype._fixUpLegacyTimelineFields = function() {
|
||||
// maintain this.timeline as a reference to the live timeline,
|
||||
// and this.oldState and this.currentState as references to the
|
||||
// state at the start and end of that timeline. These are more
|
||||
@@ -1218,6 +1227,18 @@ module.exports = Room;
|
||||
* });
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fires wheneer the live timeline in a room is reset.
|
||||
*
|
||||
* When we get a 'limited' sync (for example, after a network outage), we reset
|
||||
* the live timeline to be empty before adding the recent events to the new
|
||||
* timeline. This event is fired after the timeline is reset, and before the
|
||||
* new events are added.
|
||||
*
|
||||
* @event module:clinet~MatrixClient#"Room.timelineReset"
|
||||
* @param {Room} room The room whose live timeline was reset.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fires when an event we had previously received is redacted.
|
||||
*
|
||||
|
||||
@@ -84,7 +84,8 @@ SyncApi.prototype.createRoom = function(roomId) {
|
||||
timelineSupport: client.timelineSupport,
|
||||
});
|
||||
reEmit(client, room, ["Room.name", "Room.timeline", "Room.redaction",
|
||||
"Room.receipt", "Room.tags"]);
|
||||
"Room.receipt", "Room.tags",
|
||||
"Room.timelineReset"]);
|
||||
this._registerStateListeners(room);
|
||||
return room;
|
||||
};
|
||||
|
||||
@@ -512,5 +512,31 @@ describe("MatrixClient room timelines", function() {
|
||||
});
|
||||
httpBackend.flush("/sync", 1);
|
||||
});
|
||||
|
||||
it("should emit a 'Room.timelineReset' event", function(done) {
|
||||
var eventData = [
|
||||
utils.mkMessage({user: userId, room: roomId}),
|
||||
];
|
||||
setNextSyncData(eventData);
|
||||
NEXT_SYNC_DATA.rooms.join[roomId].timeline.limited = true;
|
||||
|
||||
client.on("sync", function(state) {
|
||||
if (state !== "PREPARED") { return; }
|
||||
var room = client.getRoom(roomId);
|
||||
|
||||
var emitCount = 0;
|
||||
client.on("Room.timelineReset", function(emitRoom) {
|
||||
expect(emitRoom).toEqual(room);
|
||||
emitCount++;
|
||||
});
|
||||
|
||||
httpBackend.flush("/messages", 1);
|
||||
httpBackend.flush("/sync", 1).done(function() {
|
||||
expect(emitCount).toEqual(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
httpBackend.flush("/sync", 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ var Room = sdk.Room;
|
||||
var RoomState = sdk.RoomState;
|
||||
var MatrixEvent = sdk.MatrixEvent;
|
||||
var EventStatus = sdk.EventStatus;
|
||||
var EventTimeline = sdk.EventTimeline;
|
||||
var utils = require("../test-utils");
|
||||
|
||||
describe("Room", function() {
|
||||
@@ -329,6 +330,80 @@ describe("Room", function() {
|
||||
});
|
||||
});
|
||||
|
||||
var resetTimelineTests = function(timelineSupport) {
|
||||
var events = [
|
||||
utils.mkMessage({
|
||||
room: roomId, user: userA, msg: "A message", event: true
|
||||
}),
|
||||
utils.mkEvent({
|
||||
type: "m.room.name", room: roomId, user: userA, event: true,
|
||||
content: { name: "New Room Name" }
|
||||
}),
|
||||
utils.mkEvent({
|
||||
type: "m.room.name", room: roomId, user: userA, event: true,
|
||||
content: { name: "Another New Name" }
|
||||
}),
|
||||
];
|
||||
|
||||
beforeEach(function() {
|
||||
room = new Room(roomId, {timelineSupport: timelineSupport});
|
||||
});
|
||||
|
||||
it("should copy state from previous timeline", function() {
|
||||
room.addEventsToTimeline([events[0], events[1]]);
|
||||
expect(room.getLiveTimeline().getEvents().length).toEqual(2);
|
||||
room.resetLiveTimeline();
|
||||
|
||||
room.addEventsToTimeline([events[2]]);
|
||||
var oldState = room.getLiveTimeline().getState(EventTimeline.BACKWARDS);
|
||||
var newState = room.getLiveTimeline().getState(EventTimeline.FORWARDS);
|
||||
expect(room.getLiveTimeline().getEvents().length).toEqual(1);
|
||||
expect(oldState.getStateEvents("m.room.name", "")).toEqual(events[1]);
|
||||
expect(newState.getStateEvents("m.room.name", "")).toEqual(events[2]);
|
||||
});
|
||||
|
||||
it("should reset the legacy timeline fields", function() {
|
||||
room.addEventsToTimeline([events[0], events[1]]);
|
||||
expect(room.timeline.length).toEqual(2);
|
||||
room.resetLiveTimeline();
|
||||
|
||||
room.addEventsToTimeline([events[2]]);
|
||||
var newLiveTimeline = room.getLiveTimeline();
|
||||
expect(room.timeline).toEqual(newLiveTimeline.getEvents());
|
||||
expect(room.oldState).toEqual(
|
||||
newLiveTimeline.getState(EventTimeline.BACKWARDS));
|
||||
expect(room.currentState).toEqual(
|
||||
newLiveTimeline.getState(EventTimeline.FORWARDS));
|
||||
});
|
||||
|
||||
it("should emit Room.timelineReset event", function() {
|
||||
var callCount = 0;
|
||||
room.on("Room.timelineReset", function(emitRoom) {
|
||||
callCount += 1;
|
||||
expect(emitRoom).toEqual(room);
|
||||
});
|
||||
room.resetLiveTimeline();
|
||||
expect(callCount).toEqual(1);
|
||||
});
|
||||
|
||||
it("should " + (timelineSupport ? "remember" : "forget") +
|
||||
" old timelines", function() {
|
||||
room.addEventsToTimeline([events[0]]);
|
||||
expect(room.timeline.length).toEqual(1);
|
||||
var firstLiveTimeline = room.getLiveTimeline();
|
||||
room.resetLiveTimeline();
|
||||
|
||||
var tl = room.getTimelineForEvent(events[0].getId());
|
||||
expect(tl).toBe(timelineSupport ? firstLiveTimeline : null);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
describe("resetLiveTimeline with timelinesupport enabled",
|
||||
resetTimelineTests.bind(null, true));
|
||||
describe("resetLiveTimeline with timelinesupport disabled",
|
||||
resetTimelineTests.bind(null, false));
|
||||
|
||||
describe("compareEventOrdering", function() {
|
||||
beforeEach(function() {
|
||||
room = new Room(roomId, {timelineSupport: true});
|
||||
|
||||
Reference in New Issue
Block a user