Skip to content
Snippets Groups Projects
Commit 601c250f authored by David Baker's avatar David Baker
Browse files

Fix member events breaking on timeline reset

We were re-adding the listeners too late as state is inserted into
the timeline as part of resetting it causing, among other things,
newMember events to fire. These would be missed, causing those new
RoomMember objects to not get their reEmit set up.

Fixes https://github.com/vector-im/riot-web/issues/4624
parent e2599071
Branches
No related tags found
No related merge requests found
......@@ -150,10 +150,12 @@ EventTimelineSet.prototype.replaceEventId = function(oldEventId, newEventId) {
*
* @param {string=} backPaginationToken token for back-paginating the new timeline
* @param {?bool} flush Whether to flush the non-live timelines too.
* @param {?function} onNewLiveTimeline Called with the new unfiltered, live timeline
* as soon as it's available. This can be used to set event listeners.
*
* @fires module:client~MatrixClient#event:"Room.timelineReset"
*/
EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flush) {
EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flush, onNewLiveTimeline) {
// if timeline support is disabled, forget about the old timelines
const resetAllTimelines = !this._timelineSupport || flush;
......@@ -166,6 +168,12 @@ EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flu
newTimeline = this.addTimeline();
}
// Allow event listeners to be set up before we start injecting events
// as otherwise events will be missed: most importantly the RoomState.newMember
// events which are used to set up reEmit on Member events and only fired when
// room members are first created.
if (onNewLiveTimeline) onNewLiveTimeline(newTimeline);
// initialise the state in the new timeline from our last known state
const evMap = this._liveTimeline.getState(EventTimeline.FORWARDS).events;
const events = [];
......
......@@ -207,9 +207,16 @@ Room.prototype.getLiveTimeline = function() {
* @param {string=} backPaginationToken token for back-paginating the new timeline
* @param {boolean=} flush True to remove all events in all timelines. If false, only
* the live timeline is reset.
* @param {Object=} onNewLiveTimeline Function called with the new live timeline object
* once it has been created, but before it has had any event inserted into it. This can be
* used to add any event listeners.
*/
Room.prototype.resetLiveTimeline = function(backPaginationToken, flush) {
for (let i = 0; i < this._timelineSets.length; i++) {
Room.prototype.resetLiveTimeline = function(backPaginationToken, flush, onNewLiveTimeline) {
// The unfiltered timeline set (we pass the onNewLiveTimeline callback here)
this._timelineSets[0].resetLiveTimeline(backPaginationToken, flush, onNewLiveTimeline);
// any other timeline sets
for (let i = 1; i < this._timelineSets.length; i++) {
this._timelineSets[i].resetLiveTimeline(backPaginationToken, flush);
}
......
......@@ -120,7 +120,7 @@ SyncApi.prototype.createRoom = function(roomId) {
"Room.localEchoUpdated",
"Room.accountData",
]);
this._registerStateListeners(room);
this._registerStateListeners(room, room.currentState);
return room;
};
......@@ -128,15 +128,15 @@ SyncApi.prototype.createRoom = function(roomId) {
* @param {Room} room
* @private
*/
SyncApi.prototype._registerStateListeners = function(room) {
SyncApi.prototype._registerStateListeners = function(room, currentState) {
const client = this.client;
// we need to also re-emit room state and room member events, so hook it up
// to the client now. We need to add a listener for RoomState.members in
// order to hook them correctly. (TODO: find a better way?)
reEmit(client, room.currentState, [
reEmit(client, currentState, [
"RoomState.events", "RoomState.members", "RoomState.newMember",
]);
room.currentState.on("RoomState.newMember", function(event, state, member) {
currentState.on("RoomState.newMember", function(event, state, member) {
member.user = client.getUser(member.userId);
reEmit(
client, member,
......@@ -892,14 +892,15 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
room.resetLiveTimeline(
joinObj.timeline.prev_batch,
self.opts.canResetEntireTimeline(room.roomId),
(newLiveTimeline) => {
self._registerStateListeners(room, newLiveTimeline.getState(EventTimeline.FORWARDS));
}
);
// We have to assume any gap in any timeline is
// reason to stop incrementally tracking notifications and
// reset the timeline.
client.resetNotifTimelineSet();
self._registerStateListeners(room);
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment