From bd32ed5598bc0e183bbf2065be0a162766ba233b Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 9 Sep 2016 16:49:39 +0100 Subject: [PATCH] refactr paginateNotifTimeline out of existence --- lib/client.js | 201 +++++++++++++++++------------------------ lib/timeline-window.js | 6 +- 2 files changed, 85 insertions(+), 122 deletions(-) diff --git a/lib/client.js b/lib/client.js index 7baf529e1..a34a6f861 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1683,7 +1683,7 @@ MatrixClient.prototype.getEventTimeline = function(timelineSet, eventId) { * @param {module:models/event-timeline~EventTimeline} eventTimeline timeline * object to be updated * @param {Object} [opts] - * @param {boolean} [opts.backwards = false] true to fill backwards, + * @param {bool} [opts.backwards = false] true to fill backwards, * false to go forwards * @param {number} [opts.limit = 30] number of events to request * @@ -1691,11 +1691,19 @@ MatrixClient.prototype.getEventTimeline = function(timelineSet, eventId) { * events and we reached either end of the timeline; else true. */ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { + var isNotifTimeline = (eventTimeline.getTimelineSet() === this._notifTimelineSet); + // TODO: we should implement a backoff (as per scrollback()) to deal more // nicely with HTTP errors. opts = opts || {}; var backwards = opts.backwards || false; + if (isNotifTimeline) { + if (!backwards) { + throw new Error("paginateNotifTimeline can only paginate backwards"); + } + } + var room = this.getRoom(eventTimeline.getRoomId()); if (!room) { throw new Error("Unknown room " + eventTimeline.getRoomId()); @@ -1716,42 +1724,85 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { return pendingRequest; } - var path = utils.encodeUri( - "/rooms/$roomId/messages", {$roomId: eventTimeline.getRoomId()} - ); - var params = { - from: token, - limit: ('limit' in opts) ? opts.limit : 30, - dir: dir - }; + if (isNotifTimeline) { + var path = "/notifications"; + var params = { + from: token, + limit: ('limit' in opts) ? opts.limit : 30, + only: 'highlight', + }; - var filter = eventTimeline.getFilter(); - if (filter) { - // XXX: it's horrific that /messages' filter parameter doesn't match - // /sync's one - see https://matrix.org/jira/browse/SPEC-451 - params.filter = JSON.stringify(filter.getRoomTimelineFilterComponent()); + var self = this; + var promise = + this._http.authedRequestWithPrefix(undefined, "GET", path, params, + undefined, httpApi.PREFIX_UNSTABLE + ).then(function(res) { + var token = res.next_token; + var matrixEvents = []; + + for (var i = 0; i < res.notifications.length; i++) { + var notification = res.notifications[i]; + var event = self.getEventMapper()(notification.event); + event.setPushActions( + PushProcessor.actionListToActionsObject(notification.actions) + ); + event.event.room_id = notification.room_id; // XXX: gutwrenching + matrixEvents[i] = event; + } + + eventTimeline.getTimelineSet() + .addEventsToTimeline(matrixEvents, backwards, eventTimeline, token); + + // if we've hit the end of the timeline, we need to stop trying to + // paginate. We need to keep the 'forwards' token though, to make sure + // we can recover from gappy syncs. + if (backwards && !res.next_token) { + eventTimeline.setPaginationToken(null, dir); + } + return res.next_token ? true : false; + }).finally(function() { + eventTimeline._paginationRequests[dir] = null; + }); + eventTimeline._paginationRequests[dir] = promise; } + else { + var path = utils.encodeUri( + "/rooms/$roomId/messages", {$roomId: eventTimeline.getRoomId()} + ); + var params = { + from: token, + limit: ('limit' in opts) ? opts.limit : 30, + dir: dir + }; - var self = this; - - var promise = - this._http.authedRequest(undefined, "GET", path, params - ).then(function(res) { - var token = res.end; - var matrixEvents = utils.map(res.chunk, self.getEventMapper()); - room.addEventsToTimeline(matrixEvents, backwards, eventTimeline, token); - - // if we've hit the end of the timeline, we need to stop trying to - // paginate. We need to keep the 'forwards' token though, to make sure - // we can recover from gappy syncs. - if (backwards && res.end == res.start) { - eventTimeline.setPaginationToken(null, dir); + var filter = eventTimeline.getFilter(); + if (filter) { + // XXX: it's horrific that /messages' filter parameter doesn't match + // /sync's one - see https://matrix.org/jira/browse/SPEC-451 + params.filter = JSON.stringify(filter.getRoomTimelineFilterComponent()); } - return res.end != res.start; - }).finally(function() { - eventTimeline._paginationRequests[dir] = null; - }); - eventTimeline._paginationRequests[dir] = promise; + + var self = this; + + var promise = + this._http.authedRequest(undefined, "GET", path, params + ).then(function(res) { + var token = res.end; + var matrixEvents = utils.map(res.chunk, self.getEventMapper()); + room.addEventsToTimeline(matrixEvents, backwards, eventTimeline, token); + + // if we've hit the end of the timeline, we need to stop trying to + // paginate. We need to keep the 'forwards' token though, to make sure + // we can recover from gappy syncs. + if (backwards && res.end == res.start) { + eventTimeline.setPaginationToken(null, dir); + } + return res.end != res.start; + }).finally(function() { + eventTimeline._paginationRequests[dir] = null; + }); + eventTimeline._paginationRequests[dir] = promise; + } return promise; }; @@ -1789,90 +1840,6 @@ MatrixClient.prototype.resetNotifTimelineSet = function() { */ }; -/** - * Take an EventTimeline, and backfill results from the notifications API. - * In future, the notifications API should probably be replaced by /messages - * with a custom filter or something - so we don't feel too bad about this being - * cargoculted from paginateEventTimeLine. - * - * @param {module:models/event-timeline~EventTimeline} eventTimeline timeline - * object to be updated - * @param {Object} [opts] - * @param {boolean} [opts.backwards = false] true to fill backwards, - * false to go forwards. Forwards is not implemented yet! - * @param {number} [opts.limit = 30] number of events to request - * - * @return {module:client.Promise} Resolves to a boolean: false if there are no - * events and we reached either end of the timeline; else true. - */ -MatrixClient.prototype.paginateNotifTimeline = function(eventTimeline, opts) { - // TODO: we should implement a backoff (as per scrollback()) to deal more - // nicely with HTTP errors. - opts = opts || {}; - var backwards = opts.backwards || false; - - if (!backwards) { - throw new Error("paginateNotifTimeline can only paginate backwards"); - } - - if (eventTimeline.getRoomId()) { - throw new Error("paginateNotifTimeline should never be called on a " + - "timeline associated with a room"); - } - - var dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS; - - var token = eventTimeline.getPaginationToken(dir); - - var pendingRequest = eventTimeline._paginationRequests[dir]; - if (pendingRequest) { - // already a request in progress - return the existing promise - return pendingRequest; - } - - var path = "/notifications"; - var params = { - from: token, - limit: ('limit' in opts) ? opts.limit : 30, - only: 'highlight', - }; - - var self = this; - var promise = - this._http.authedRequestWithPrefix(undefined, "GET", path, params, - undefined, httpApi.PREFIX_UNSTABLE - ).then(function(res) { - var token = res.next_token; - var matrixEvents = []; - - for (var i = 0; i < res.notifications.length; i++) { - var notification = res.notifications[i]; - var event = self.getEventMapper()(notification.event); - event.setPushActions( - PushProcessor.actionListToActionsObject(notification.actions) - ); - event.event.room_id = notification.room_id; // XXX: gutwrenching - matrixEvents[i] = event; - } - - eventTimeline.getTimelineSet() - .addEventsToTimeline(matrixEvents, backwards, eventTimeline, token); - - // if we've hit the end of the timeline, we need to stop trying to - // paginate. We need to keep the 'forwards' token though, to make sure - // we can recover from gappy syncs. - if (backwards && !res.next_token) { - eventTimeline.setPaginationToken(null, dir); - } - return res.next_token ? true : false; - }).finally(function() { - eventTimeline._paginationRequests[dir] = null; - }); - eventTimeline._paginationRequests[dir] = promise; - - return promise; -}; - /** * Peek into a room and receive updates about the room. This only works if the * history visibility for the room is world_readable. diff --git a/lib/timeline-window.js b/lib/timeline-window.js index 9c6b28345..1889631ae 100644 --- a/lib/timeline-window.js +++ b/lib/timeline-window.js @@ -255,11 +255,7 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest, debuglog("TimelineWindow: starting request"); var self = this; - var paginateTimeline = tl.timeline.getRoomId() ? - this._client.paginateEventTimeline : - this._client.paginateNotifTimeline; - - var prom = paginateTimeline.call(this._client, tl.timeline, { + var prom = this._client.paginateEventTimeline(tl.timeline, { backwards: direction == EventTimeline.BACKWARDS, limit: size }).finally(function() {