You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-29 16:43:09 +03:00
make /notification pagination actually work
This commit is contained in:
@@ -1793,6 +1793,38 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) {
|
|||||||
return promise;
|
return promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the notifTimelineSet entirely, paginating in some historical notifs as
|
||||||
|
* a starting point for subsequent pagination.
|
||||||
|
*/
|
||||||
|
MatrixClient.prototype.resetNotifTimelineSet = function() {
|
||||||
|
if (!this._notifTimelineSet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This thing is a total hack, and results in duplicate events being
|
||||||
|
// added to the timeline both from /sync and /notifications, and lots of
|
||||||
|
// slow and wasteful processing and pagination. The correct solution is to
|
||||||
|
// extend /messages or /search or something to filter on notifications.
|
||||||
|
|
||||||
|
// use the fictitious token 'end'. in practice we would ideally give it
|
||||||
|
// the oldest backwards pagination token from /sync, but /sync doesn't
|
||||||
|
// know about /notifications, so we have no choice but to start paginating
|
||||||
|
// from the current point in time. This may well overlap with historical
|
||||||
|
// notifs which are then inserted into the timeline by /sync responses.
|
||||||
|
this._notifTimelineSet.resetLiveTimeline('end', true);
|
||||||
|
|
||||||
|
// we could try to paginate a single event at this point in order to get
|
||||||
|
// a more valid pagination token, but it just ends up with an out of order
|
||||||
|
// timeline. given what a mess this is and given we're going to have duplicate
|
||||||
|
// events anyway, just leave it with the dummy token for now.
|
||||||
|
/*
|
||||||
|
this.paginateNotifTimeline(this._notifTimelineSet.getLiveTimeline(), {
|
||||||
|
backwards: true,
|
||||||
|
limit: 1
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take an EventTimeline, and backfill results from the notifications API.
|
* Take an EventTimeline, and backfill results from the notifications API.
|
||||||
@@ -1853,11 +1885,14 @@ MatrixClient.prototype.paginateNotifTimeline = function(eventTimeline, opts) {
|
|||||||
for (var i = 0; i < res.notifications.length; i++) {
|
for (var i = 0; i < res.notifications.length; i++) {
|
||||||
var notification = res.notifications[i];
|
var notification = res.notifications[i];
|
||||||
var event = self.getEventMapper()(notification.event);
|
var event = self.getEventMapper()(notification.event);
|
||||||
event.setPushActions(notification.actions);
|
event.setPushActions(
|
||||||
|
PushProcessor.actionListToActionsObject(notification.actions)
|
||||||
|
);
|
||||||
|
event.event.room_id = notification.room_id; // XXX: gutwrenching
|
||||||
matrixEvents[i] = event;
|
matrixEvents[i] = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventTimeline.getEventTimelineSet()
|
eventTimeline.getTimelineSet()
|
||||||
.addEventsToTimeline(matrixEvents, backwards, eventTimeline, token);
|
.addEventsToTimeline(matrixEvents, backwards, eventTimeline, token);
|
||||||
|
|
||||||
// if we've hit the end of the timeline, we need to stop trying to
|
// if we've hit the end of the timeline, we need to stop trying to
|
||||||
|
|||||||
@@ -149,11 +149,12 @@ EventTimelineSet.prototype.replaceEventId = function(oldEventId, newEventId) {
|
|||||||
* <p>This is used when /sync returns a 'limited' timeline.
|
* <p>This is used when /sync returns a 'limited' timeline.
|
||||||
*
|
*
|
||||||
* @param {string=} backPaginationToken token for back-paginating the new timeline
|
* @param {string=} backPaginationToken token for back-paginating the new timeline
|
||||||
|
* @param {?bool} flush Whether to flush the non-live timelines too.
|
||||||
*/
|
*/
|
||||||
EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken) {
|
EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flush) {
|
||||||
var newTimeline;
|
var newTimeline;
|
||||||
|
|
||||||
if (!this._timelineSupport) {
|
if (!this._timelineSupport || flush) {
|
||||||
// if timeline support is disabled, forget about the old timelines
|
// if timeline support is disabled, forget about the old timelines
|
||||||
newTimeline = new EventTimeline(this);
|
newTimeline = new EventTimeline(this);
|
||||||
this._timelines = [newTimeline];
|
this._timelines = [newTimeline];
|
||||||
|
|||||||
33
lib/sync.js
33
lib/sync.js
@@ -72,6 +72,7 @@ function SyncApi(client, opts) {
|
|||||||
this._running = false;
|
this._running = false;
|
||||||
this._keepAliveTimer = null;
|
this._keepAliveTimer = null;
|
||||||
this._connectionReturnedDefer = null;
|
this._connectionReturnedDefer = null;
|
||||||
|
this._notifEvents = []; // accumulator of sync events in the current sync response
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -392,6 +393,16 @@ SyncApi.prototype.sync = function() {
|
|||||||
client.getOrCreateFilter(
|
client.getOrCreateFilter(
|
||||||
getFilterName(client.credentials.userId), filter
|
getFilterName(client.credentials.userId), filter
|
||||||
).done(function(filterId) {
|
).done(function(filterId) {
|
||||||
|
// prepare the notif timeline for pagination before we receive
|
||||||
|
// sync responses. Technically there are two small races here:
|
||||||
|
// 1: the reset will execute async and may race with the /sync.
|
||||||
|
// 2: the reset may return before the sync, and the room may go
|
||||||
|
// so fast that in the gap before the sync returns we may miss some
|
||||||
|
// notifs. This is incredibly unlikely however.
|
||||||
|
// The right solution would be to tie /sync pagination tokens into
|
||||||
|
// notifications.
|
||||||
|
client.resetNotifTimelineSet();
|
||||||
|
|
||||||
self._sync({ filterId: filterId });
|
self._sync({ filterId: filterId });
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
self._startKeepAlives().done(function() {
|
self._startKeepAlives().done(function() {
|
||||||
@@ -655,7 +666,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.notifEvents = [];
|
this._notifEvents = [];
|
||||||
|
|
||||||
// Handle invites
|
// Handle invites
|
||||||
inviteRooms.forEach(function(inviteObj) {
|
inviteRooms.forEach(function(inviteObj) {
|
||||||
@@ -742,6 +753,12 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
|
|||||||
room.currentState.paginationToken = syncToken;
|
room.currentState.paginationToken = syncToken;
|
||||||
self._deregisterStateListeners(room);
|
self._deregisterStateListeners(room);
|
||||||
room.resetLiveTimeline(joinObj.timeline.prev_batch);
|
room.resetLiveTimeline(joinObj.timeline.prev_batch);
|
||||||
|
|
||||||
|
// XXX: for now 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);
|
self._registerStateListeners(room);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -792,11 +809,11 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// update the notification timeline, if appropriate
|
// update the notification timeline, if appropriate
|
||||||
if (this.notifEvents.length) {
|
if (this._notifEvents.length) {
|
||||||
this.notifEvents.sort(function(a, b) {
|
this._notifEvents.sort(function(a, b) {
|
||||||
return a.getTs() - b.getTs();
|
return a.getTs() - b.getTs();
|
||||||
});
|
});
|
||||||
this.notifEvents.forEach(function(event) {
|
this._notifEvents.forEach(function(event) {
|
||||||
client.getNotifTimelineSet().addLiveEvent(event);
|
client.getNotifTimelineSet().addLiveEvent(event);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -988,12 +1005,14 @@ SyncApi.prototype._processRoomEvents = function(room, stateEventList,
|
|||||||
// may make notifications appear which should have the right name.
|
// may make notifications appear which should have the right name.
|
||||||
room.recalculate(this.client.credentials.userId);
|
room.recalculate(this.client.credentials.userId);
|
||||||
|
|
||||||
// gather our notifications into this.notifEvents
|
// gather our notifications into this._notifEvents
|
||||||
if (client.getNotifTimelineSet()) {
|
if (client.getNotifTimelineSet()) {
|
||||||
for (var i = 0; i < timelineEventList.length; i++) {
|
for (var i = 0; i < timelineEventList.length; i++) {
|
||||||
var pushActions = client.getPushActionsForEvent(timelineEventList[i]);
|
var pushActions = client.getPushActionsForEvent(timelineEventList[i]);
|
||||||
if (pushActions && pushActions.notify) {
|
if (pushActions && pushActions.notify &&
|
||||||
this.notifEvents.push(timelineEventList[i]);
|
pushActions.tweaks && pushActions.tweaks.highlight)
|
||||||
|
{
|
||||||
|
this._notifEvents.push(timelineEventList[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user