From 58031ab21d58d84acb0aaca87b2a0a0548d2c80c Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 30 Aug 2016 00:36:52 +0100 Subject: [PATCH] fix things until they almost work again... --- lib/models/event-timeline-list.js | 37 ++++----- lib/models/room.js | 132 +++++++++++++++++++++++------- 2 files changed, 120 insertions(+), 49 deletions(-) diff --git a/lib/models/event-timeline-list.js b/lib/models/event-timeline-list.js index 44970ee42..3db20c82e 100644 --- a/lib/models/event-timeline-list.js +++ b/lib/models/event-timeline-list.js @@ -44,9 +44,10 @@ var EventTimeline = require("./event-timeline"); * map from event_id to timeline and index. */ function EventTimelineList(roomId, opts) { + this.roomId = roomId; + this._timelineSupport = Boolean(opts.timelineSupport); this._liveTimeline = new EventTimeline(this.roomId); - this._fixUpLegacyTimelineFields(); // just a list - *not* ordered. this._timelines = [this._liveTimeline]; @@ -86,8 +87,6 @@ EventTimelineList.prototype.getLiveTimeline = function(filterId) { *

This is used when /sync returns a 'limited' timeline. * * @param {string=} backPaginationToken token for back-paginating the new timeline - * - * @fires module:client~MatrixClient#event:"Room.timelineReset" */ EventTimelineList.prototype.resetLiveTimeline = function(backPaginationToken) { var newTimeline; @@ -119,23 +118,6 @@ EventTimelineList.prototype.resetLiveTimeline = function(backPaginationToken) { newTimeline.setPaginationToken(backPaginationToken, EventTimeline.BACKWARDS); this._liveTimeline = newTimeline; - this._fixUpLegacyTimelineFields(); - this.emit("Room.timelineReset", this); -}; - -/** - * Fix up this.timeline, this.oldState and this.currentState - * - * @private - */ -EventTimelineList.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 - // for backwards-compatibility than anything else. - this.timeline = this._liveTimeline.getEvents(); - this.oldState = this._liveTimeline.getState(EventTimeline.BACKWARDS); - this.currentState = this._liveTimeline.getState(EventTimeline.FORWARDS); }; /** @@ -217,6 +199,11 @@ EventTimelineList.prototype.addEventsToTimeline = function(events, toStartOfTime ); } + if (this._filter) { + var events = this._filter.filterRoomTimeline(events); + if (!events) return; + } + var direction = toStartOfTimeline ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS; var inverseDirection = toStartOfTimeline ? EventTimeline.FORWARDS : @@ -423,6 +410,16 @@ EventTimelineList.prototype.addEventToTimeline = function(event, timeline, toSta this.emit("Room.timeline", event, this, Boolean(toStartOfTimeline), false, data); }; +EventTimelineList.prototype.replaceOrAddEvent = function(localEvent, oldEventId, newEventId) { + var existingTimeline = this._eventIdToTimeline[oldEventId]; + if (existingTimeline) { + delete this._eventIdToTimeline[oldEventId]; + this._eventIdToTimeline[newEventId] = existingTimeline; + } else { + this.addEventToTimeline(localEvent, this._liveTimeline, false); + } +}; + /** * Helper method to set sender and target properties, private to Room and EventTimelineList */ diff --git a/lib/models/room.js b/lib/models/room.js index bae465f23..9edbfd317 100644 --- a/lib/models/room.js +++ b/lib/models/room.js @@ -163,6 +163,7 @@ function Room(roomId, opts) { // all our per-room timeline lists. the first one is the unfiltered ones; // the subsequent ones are the filtered ones in no particular order. this._timelineLists = [ new EventTimelineList(roomId, opts) ]; + this._fixUpLegacyTimelineFields(); // any filtered timeline lists we're maintaining for this room this._filteredTimelineLists = { @@ -196,6 +197,50 @@ Room.prototype.getPendingEvents = function() { return this._pendingEventList; }; +/** + * Get the live unfiltered timeline for this room. + * + * @return {module:models/event-timeline~EventTimeline} live timeline + */ +Room.prototype.getLiveTimeline = function(filterId) { + return this._timelineLists[0].getLiveTimeline(); +}; + + +/** + * Reset the live timeline, and start a new one. + * + *

This is used when /sync returns a 'limited' timeline. + * + * @param {string=} backPaginationToken token for back-paginating the new timeline + * + * @fires module:client~MatrixClient#event:"Room.timelineReset" + */ +Room.prototype.resetLiveTimeline = function(backPaginationToken) { + var newTimeline; + + for (var i = 0; i < this._timelineLists.length; i++) { + this._timelineLists[i].resetLiveTimeline(backPaginationToken); + } + + 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 + // for backwards-compatibility than anything else. + this.timeline = this._timelineLists[0].getLiveTimeline().getEvents(); + this.oldState = this._timelineLists[0].getLiveTimeline().getState(EventTimeline.BACKWARDS); + this.currentState = this._timelineLists[0].getLiveTimeline().getState(EventTimeline.FORWARDS); +}; /** * Get one of the notification counts for this room @@ -289,6 +334,32 @@ Room.prototype.getCanonicalAlias = function() { return null; }; +/** + * Add events to a timeline + * + *

Will fire "Room.timeline" for each event added. + * + * @param {MatrixEvent[]} events A list of events to add. + * + * @param {boolean} toStartOfTimeline True to add these events to the start + * (oldest) instead of the end (newest) of the timeline. If true, the oldest + * event will be the last element of 'events'. + * + * @param {module:models/event-timeline~EventTimeline} timeline timeline to + * add events to. + * + * @param {string=} paginationToken token for the next batch of events + * + * @fires module:client~MatrixClient#event:"Room.timeline" + * + */ +Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline, + timeline, paginationToken) { + for (var i = 0; i < this._timelineLists.length; i++) { + this._timelineLists[0] + } +}; + /** * Get a member from the current room state. * @param {string} userId The user ID of the member. @@ -368,7 +439,7 @@ Room.prototype.removeFilteredTimelineList = function(filter) { delete this._filteredTimelineLists[filter.filterId]; var i = this._timelineLists.indexOf(timelineList); if (i > -1) { - this._timelineList.splice(i, 1); + this._timelineLists.splice(i, 1); } }; @@ -385,17 +456,23 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy) { if (event.getType() === "m.room.redaction") { var redactId = event.event.redacts; - // if we know about this event, redact its contents now. - var redactedEvent = this.findEventById(redactId); - if (redactedEvent) { - redactedEvent.makeRedacted(event); - this.emit("Room.redaction", event, this); + for (var i = 0; i < this._timelineLists.length; i++) { + var timelineList = this._timelineLists[i]; + // if we know about this event, redact its contents now. + var redactedEvent = timelineList.findEventById(redactId); + if (redactedEvent) { + redactedEvent.makeRedacted(event); + // FIXME: these should be emitted from EventTimelineList probably + this.emit("Room.redaction", event, this, timelineList); - // TODO: we stash user displaynames (among other things) in - // RoomMember objects which are then attached to other events - // (in the sender and target fields). We should get those - // RoomMember objects to update themselves when the events that - // they are based on are changed. + // TODO: we stash user displaynames (among other things) in + // RoomMember objects which are then attached to other events + // (in the sender and target fields). We should get those + // RoomMember objects to update themselves when the events that + // they are based on are changed. + } + + // FIXME: apply redactions to notification list } // NB: We continue to add the redaction event to the timeline so @@ -535,13 +612,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) { var timelineList = this._timelineLists[i]; // if it's already in the timeline, update the timeline map. If it's not, add it. - var existingTimeline = timelineList._eventIdToTimeline[oldEventId]; - if (existingTimeline) { - delete timelineList._eventIdToTimeline[oldEventId]; - timelineList._eventIdToTimeline[newEventId] = existingTimeline; - } else { - timelineList._addEventToTimeline(localEvent, timelineList._liveTimeline, false); - } + timelineList.replaceOrAddEvent(localEvent, oldEventId, newEventId); } this.emit("Room.localEchoUpdated", localEvent, this, @@ -672,16 +743,19 @@ Room.prototype.addLiveEvents = function(events, duplicateStrategy) { } // sanity check that the live timeline is still live - if (this._liveTimeline.getPaginationToken(EventTimeline.FORWARDS)) { - throw new Error( - "live timeline is no longer live - it has a pagination token (" + - this._liveTimeline.getPaginationToken(EventTimeline.FORWARDS) + ")" - ); - } - if (this._liveTimeline.getNeighbouringTimeline(EventTimeline.FORWARDS)) { - throw new Error( - "live timeline is no longer live - it has a neighbouring timeline" - ); + for (var i = 0; i < this._timelineLists.length; i++) { + var liveTimeline = this._timelineLists[i].getLiveTimeline(); + if (liveTimeline.getPaginationToken(EventTimeline.FORWARDS)) { + throw new Error( + "live timeline "+i+" is no longer live - it has a pagination token (" + + timelineList.getPaginationToken(EventTimeline.FORWARDS) + ")" + ); + } + if (liveTimeline.getNeighbouringTimeline(EventTimeline.FORWARDS)) { + throw new Error( + "live timeline "+i+" is no longer live - it has a neighbouring timeline" + ); + } } for (var i = 0; i < events.length; i++) { @@ -883,7 +957,7 @@ Room.prototype._addReceiptsToStructure = function(event, receipts) { // than the one we already have. (This is managed // server-side, but because we synthesize RRs locally we // have to do it here too.) - var ordering = self.compareEventOrdering( + var ordering = self._timelineLists[0].compareEventOrdering( existingReceipt.eventId, eventId); if (ordering !== null && ordering >= 0) { return;