diff --git a/lib/models/event-timeline-list.js b/lib/models/event-timeline-list.js index 8e59114cb..41fde4fc6 100644 --- a/lib/models/event-timeline-list.js +++ b/lib/models/event-timeline-list.js @@ -21,6 +21,16 @@ var EventEmitter = require("events").EventEmitter; var utils = require("../utils"); var EventTimeline = require("./event-timeline"); +// var DEBUG = false; +var DEBUG = true; + +if (DEBUG) { + // using bind means that we get to keep useful line numbers in the console + var debuglog = console.log.bind(console); +} else { + var debuglog = function() {}; +} + /** * Construct a set of EventTimeline objects, typically on behalf of a given * room. A room may have multiple EventTimelineSets for different levels @@ -82,6 +92,18 @@ EventTimelineList.prototype.getLiveTimeline = function(filterId) { return this._liveTimeline; }; +EventTimelineList.prototype.eventIdToTimeline = function(eventId) { + return this._eventIdToTimeline[eventId]; +}; + +EventTimelineList.prototype.replaceEventId = function(oldEventId, newEventId) { + var existingTimeline = this._eventIdToTimeline[oldEventId]; + if (existingTimeline) { + delete this._eventIdToTimeline[oldEventId]; + this._eventIdToTimeline[newEventId] = existingTimeline; + } +}; + /** * Reset the live timeline, and start a new one. * @@ -149,7 +171,7 @@ EventTimelineList.prototype.findEventById = function(eventId) { }; /** - * Add a new timeline to this room + * Add a new timeline to this timeline list * * @return {module:models/event-timeline~EventTimeline} newly-created timeline */ @@ -360,7 +382,7 @@ EventTimelineList.prototype.addLiveEvent = function(event, duplicateStrategy) { for (var j = 0; j < tlEvents.length; j++) { if (tlEvents[j].getId() === event.getId()) { // still need to set the right metadata on this event - this.setEventMetadata( + EventTimeline.setEventMetadata( event, timeline.getState(EventTimeline.FORWARDS), false @@ -421,29 +443,6 @@ EventTimelineList.prototype.replaceOrAddEvent = function(localEvent, oldEventId, } }; -/** - * Helper method to set sender and target properties, private to Room and EventTimelineList - */ -EventTimelineList.prototype.setEventMetadata = function(event, stateContext, toStartOfTimeline) { - event.sender = stateContext.getSentinelMember( - event.getSender() - ); - if (event.getType() === "m.room.member") { - event.target = stateContext.getSentinelMember( - event.getStateKey() - ); - } - if (event.isState()) { - // room state has no concept of 'old' or 'current', but we want the - // room state to regress back to previous values if toStartOfTimeline - // is set, which means inspecting prev_content if it exists. This - // is done by toggling the forwardLooking flag. - if (toStartOfTimeline) { - event.forwardLooking = false; - } - } -} - /** * Removes a single event from this room. * diff --git a/lib/models/event-timeline.js b/lib/models/event-timeline.js index 4123849ac..6c083b7c8 100644 --- a/lib/models/event-timeline.js +++ b/lib/models/event-timeline.js @@ -217,7 +217,7 @@ EventTimeline.prototype.setNeighbouringTimeline = function(neighbour, direction) EventTimeline.prototype.addEvent = function(event, atStart) { var stateContext = atStart ? this._startState : this._endState; - setEventMetadata(event, stateContext, atStart); + EventTimeline.setEventMetadata(event, stateContext, atStart); // modify state if (event.isState()) { @@ -233,7 +233,7 @@ EventTimeline.prototype.addEvent = function(event, atStart) { // member event, whereas we want to set the .sender value for the ACTUAL // member event itself. if (!event.sender || (event.getType() === "m.room.member" && !atStart)) { - setEventMetadata(event, stateContext, atStart); + EventTimeline.setEventMetadata(event, stateContext, atStart); } } @@ -251,7 +251,10 @@ EventTimeline.prototype.addEvent = function(event, atStart) { } }; -function setEventMetadata(event, stateContext, toStartOfTimeline) { +/** + * Static helper method to set sender and target properties + */ +EventTimeline.setEventMetadata = function(event, stateContext, toStartOfTimeline) { // set sender and target properties event.sender = stateContext.getSentinelMember( event.getSender() diff --git a/lib/models/room.js b/lib/models/room.js index 80ca543c3..501de8174 100644 --- a/lib/models/room.js +++ b/lib/models/room.js @@ -256,6 +256,15 @@ Room.prototype.getTimelineForEvent = function(eventId) { return this._timelineLists[0].getTimelineForEvent(eventId); }; +/** + * Add a new timeline to this room's unfiltered timeline list + * + * @return {module:models/event-timeline~EventTimeline} newly-created timeline + */ +Room.prototype.addTimeline = function() { + return this._timelineLists[0].addTimeline(); +}; + /** * Get an event which is stored in our unfiltered timeline set * @@ -264,7 +273,7 @@ Room.prototype.getTimelineForEvent = function(eventId) { */ Room.prototype.findEventById = function(eventId) { return this._timelineLists[0].findEventById(eventId); -} +}; /** * Get one of the notification counts for this room @@ -578,7 +587,7 @@ Room.prototype.addPendingEvent = function(event, txnId) { // call setEventMetadata to set up event.sender etc // as event is shared over all timelinelists, we set up its metadata based // on the unfiltered timelineList. - this._timelineLists[0].setEventMetadata( + EventTimeline.setEventMetadata( event, this._timelineLists[0].getLiveTimeline().getState(EventTimeline.FORWARDS), false @@ -696,7 +705,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) { // SENT races against /sync, so we have to special-case it. if (newStatus == EventStatus.SENT) { - var timeline = this._eventIdToTimeline[newEventId]; + var timeline = this._timelineLists[0].eventIdToTimeline(newEventId); if (timeline) { // we've already received the event via the event stream. // nothing more to do here. @@ -727,10 +736,8 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) { // if the event was already in the timeline (which will be the case if // opts.pendingEventOrdering==chronological), we need to update the // timeline map. - var existingTimeline = this._eventIdToTimeline[oldEventId]; - if (existingTimeline) { - delete this._eventIdToTimeline[oldEventId]; - this._eventIdToTimeline[newEventId] = existingTimeline; + for (var i = 0; i < this._timelineLists.length; i++) { + this._timelineLists[i].replaceEventId(oldEventId, newEventId); } } else if (newStatus == EventStatus.CANCELLED) { diff --git a/spec/unit/room.spec.js b/spec/unit/room.spec.js index 83d170109..176e9f45b 100644 --- a/spec/unit/room.spec.js +++ b/spec/unit/room.spec.js @@ -479,14 +479,14 @@ describe("Room", function() { it("should handle events in the same timeline", function() { room.addLiveEvents(events); - expect(room.compareEventOrdering(events[0].getId(), - events[1].getId())) + expect(room._timelineLists[0].compareEventOrdering(events[0].getId(), + events[1].getId())) .toBeLessThan(0); - expect(room.compareEventOrdering(events[2].getId(), - events[1].getId())) + expect(room._timelineLists[0].compareEventOrdering(events[2].getId(), + events[1].getId())) .toBeGreaterThan(0); - expect(room.compareEventOrdering(events[1].getId(), - events[1].getId())) + expect(room._timelineLists[0].compareEventOrdering(events[1].getId(), + events[1].getId())) .toEqual(0); }); @@ -498,11 +498,11 @@ describe("Room", function() { room.addEventsToTimeline([events[0]], false, oldTimeline); room.addLiveEvents([events[1]]); - expect(room.compareEventOrdering(events[0].getId(), - events[1].getId())) + expect(room._timelineLists[0].compareEventOrdering(events[0].getId(), + events[1].getId())) .toBeLessThan(0); - expect(room.compareEventOrdering(events[1].getId(), - events[0].getId())) + expect(room._timelineLists[0].compareEventOrdering(events[1].getId(), + events[0].getId())) .toBeGreaterThan(0); }); @@ -512,22 +512,22 @@ describe("Room", function() { room.addEventsToTimeline([events[0]], false, oldTimeline); room.addLiveEvents([events[1]]); - expect(room.compareEventOrdering(events[0].getId(), - events[1].getId())) + expect(room._timelineLists[0].compareEventOrdering(events[0].getId(), + events[1].getId())) .toBe(null); - expect(room.compareEventOrdering(events[1].getId(), - events[0].getId())) + expect(room._timelineLists[0].compareEventOrdering(events[1].getId(), + events[0].getId())) .toBe(null); }); it("should return null for unknown events", function() { room.addLiveEvents(events); - expect(room.compareEventOrdering(events[0].getId(), "xxx")) + expect(room._timelineLists[0].compareEventOrdering(events[0].getId(), "xxx")) .toBe(null); - expect(room.compareEventOrdering("xxx", events[0].getId())) + expect(room._timelineLists[0].compareEventOrdering("xxx", events[0].getId())) .toBe(null); - expect(room.compareEventOrdering(events[0].getId(), + expect(room._timelineLists[0].compareEventOrdering(events[0].getId(), events[0].getId())) .toBe(0); });