diff options
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/models/event-timeline.js')
-rw-r--r-- | includes/external/matrix/node_modules/matrix-js-sdk/lib/models/event-timeline.js | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/models/event-timeline.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/models/event-timeline.js new file mode 100644 index 0000000..9857888 --- /dev/null +++ b/includes/external/matrix/node_modules/matrix-js-sdk/lib/models/event-timeline.js @@ -0,0 +1,433 @@ +"use strict"; + +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.EventTimeline = exports.Direction = void 0; +var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); +var _logger = require("../logger"); +var _roomState2 = require("./room-state"); +var _event = require("../@types/event"); +/* +Copyright 2016 - 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +let Direction; +exports.Direction = Direction; +(function (Direction) { + Direction["Backward"] = "b"; + Direction["Forward"] = "f"; +})(Direction || (exports.Direction = Direction = {})); +class EventTimeline { + /** + * Symbolic constant for methods which take a 'direction' argument: + * refers to the start of the timeline, or backwards in time. + */ + + /** + * Symbolic constant for methods which take a 'direction' argument: + * refers to the end of the timeline, or forwards in time. + */ + + /** + * Static helper method to set sender and target properties + * + * @param event - the event whose metadata is to be set + * @param stateContext - the room state to be queried + * @param toStartOfTimeline - if true the event's forwardLooking flag is set false + */ + static setEventMetadata(event, stateContext, toStartOfTimeline) { + var _event$sender, _event$sender$events, _event$target, _event$target$events; + // When we try to generate a sentinel member before we have that member + // in the members object, we still generate a sentinel but it doesn't + // have a membership event, so test to see if events.member is set. We + // check this to avoid overriding non-sentinel members by sentinel ones + // when adding the event to a filtered timeline + if (!((_event$sender = event.sender) !== null && _event$sender !== void 0 && (_event$sender$events = _event$sender.events) !== null && _event$sender$events !== void 0 && _event$sender$events.member)) { + event.sender = stateContext.getSentinelMember(event.getSender()); + } + if (!((_event$target = event.target) !== null && _event$target !== void 0 && (_event$target$events = _event$target.events) !== null && _event$target$events !== void 0 && _event$target$events.member) && event.getType() === _event.EventType.RoomMember) { + 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; + } + } + } + /** + * Construct a new EventTimeline + * + * <p>An EventTimeline represents a contiguous sequence of events in a room. + * + * <p>As well as keeping track of the events themselves, it stores the state of + * the room at the beginning and end of the timeline, and pagination tokens for + * going backwards and forwards in the timeline. + * + * <p>In order that clients can meaningfully maintain an index into a timeline, + * the EventTimeline object tracks a 'baseIndex'. This starts at zero, but is + * incremented when events are prepended to the timeline. The index of an event + * relative to baseIndex therefore remains constant. + * + * <p>Once a timeline joins up with its neighbour, they are linked together into a + * doubly-linked list. + * + * @param eventTimelineSet - the set of timelines this is part of + */ + constructor(eventTimelineSet) { + var _eventTimelineSet$roo, _eventTimelineSet$roo2; + this.eventTimelineSet = eventTimelineSet; + (0, _defineProperty2.default)(this, "roomId", void 0); + (0, _defineProperty2.default)(this, "name", void 0); + (0, _defineProperty2.default)(this, "events", []); + (0, _defineProperty2.default)(this, "baseIndex", 0); + (0, _defineProperty2.default)(this, "startState", void 0); + (0, _defineProperty2.default)(this, "endState", void 0); + (0, _defineProperty2.default)(this, "startToken", null); + (0, _defineProperty2.default)(this, "endToken", null); + (0, _defineProperty2.default)(this, "prevTimeline", null); + (0, _defineProperty2.default)(this, "nextTimeline", null); + (0, _defineProperty2.default)(this, "paginationRequests", { + [Direction.Backward]: null, + [Direction.Forward]: null + }); + this.roomId = (_eventTimelineSet$roo = (_eventTimelineSet$roo2 = eventTimelineSet.room) === null || _eventTimelineSet$roo2 === void 0 ? void 0 : _eventTimelineSet$roo2.roomId) !== null && _eventTimelineSet$roo !== void 0 ? _eventTimelineSet$roo : null; + if (this.roomId) { + this.startState = new _roomState2.RoomState(this.roomId); + this.endState = new _roomState2.RoomState(this.roomId); + } + + // this is used by client.js + this.paginationRequests = { + b: null, + f: null + }; + this.name = this.roomId + ":" + new Date().toISOString(); + } + + /** + * Initialise the start and end state with the given events + * + * <p>This can only be called before any events are added. + * + * @param stateEvents - list of state events to initialise the + * state with. + * @throws Error if an attempt is made to call this after addEvent is called. + */ + initialiseState(stateEvents, { + timelineWasEmpty + } = {}) { + var _this$startState, _this$endState; + if (this.events.length > 0) { + throw new Error("Cannot initialise state after events are added"); + } + (_this$startState = this.startState) === null || _this$startState === void 0 ? void 0 : _this$startState.setStateEvents(stateEvents, { + timelineWasEmpty + }); + (_this$endState = this.endState) === null || _this$endState === void 0 ? void 0 : _this$endState.setStateEvents(stateEvents, { + timelineWasEmpty + }); + } + + /** + * Forks the (live) timeline, taking ownership of the existing directional state of this timeline. + * All attached listeners will keep receiving state updates from the new live timeline state. + * The end state of this timeline gets replaced with an independent copy of the current RoomState, + * and will need a new pagination token if it ever needs to paginate forwards. + * @param direction - EventTimeline.BACKWARDS to get the state at the + * start of the timeline; EventTimeline.FORWARDS to get the state at the end + * of the timeline. + * + * @returns the new timeline + */ + forkLive(direction) { + const forkState = this.getState(direction); + const timeline = new EventTimeline(this.eventTimelineSet); + timeline.startState = forkState === null || forkState === void 0 ? void 0 : forkState.clone(); + // Now clobber the end state of the new live timeline with that from the + // previous live timeline. It will be identical except that we'll keep + // using the same RoomMember objects for the 'live' set of members with any + // listeners still attached + timeline.endState = forkState; + // Firstly, we just stole the current timeline's end state, so it needs a new one. + // Make an immutable copy of the state so back pagination will get the correct sentinels. + this.endState = forkState === null || forkState === void 0 ? void 0 : forkState.clone(); + return timeline; + } + + /** + * Creates an independent timeline, inheriting the directional state from this timeline. + * + * @param direction - EventTimeline.BACKWARDS to get the state at the + * start of the timeline; EventTimeline.FORWARDS to get the state at the end + * of the timeline. + * + * @returns the new timeline + */ + fork(direction) { + const forkState = this.getState(direction); + const timeline = new EventTimeline(this.eventTimelineSet); + timeline.startState = forkState === null || forkState === void 0 ? void 0 : forkState.clone(); + timeline.endState = forkState === null || forkState === void 0 ? void 0 : forkState.clone(); + return timeline; + } + + /** + * Get the ID of the room for this timeline + * @returns room ID + */ + getRoomId() { + return this.roomId; + } + + /** + * Get the filter for this timeline's timelineSet (if any) + * @returns filter + */ + getFilter() { + return this.eventTimelineSet.getFilter(); + } + + /** + * Get the timelineSet for this timeline + * @returns timelineSet + */ + getTimelineSet() { + return this.eventTimelineSet; + } + + /** + * Get the base index. + * + * <p>This is an index which is incremented when events are prepended to the + * timeline. An individual event therefore stays at the same index in the array + * relative to the base index (although note that a given event's index may + * well be less than the base index, thus giving that event a negative relative + * index). + */ + getBaseIndex() { + return this.baseIndex; + } + + /** + * Get the list of events in this context + * + * @returns An array of MatrixEvents + */ + getEvents() { + return this.events; + } + + /** + * Get the room state at the start/end of the timeline + * + * @param direction - EventTimeline.BACKWARDS to get the state at the + * start of the timeline; EventTimeline.FORWARDS to get the state at the end + * of the timeline. + * + * @returns state at the start/end of the timeline + */ + getState(direction) { + if (direction == EventTimeline.BACKWARDS) { + return this.startState; + } else if (direction == EventTimeline.FORWARDS) { + return this.endState; + } else { + throw new Error("Invalid direction '" + direction + "'"); + } + } + + /** + * Get a pagination token + * + * @param direction - EventTimeline.BACKWARDS to get the pagination + * token for going backwards in time; EventTimeline.FORWARDS to get the + * pagination token for going forwards in time. + * + * @returns pagination token + */ + getPaginationToken(direction) { + if (this.roomId) { + return this.getState(direction).paginationToken; + } else if (direction === Direction.Backward) { + return this.startToken; + } else { + return this.endToken; + } + } + + /** + * Set a pagination token + * + * @param token - pagination token + * + * @param direction - EventTimeline.BACKWARDS to set the pagination + * token for going backwards in time; EventTimeline.FORWARDS to set the + * pagination token for going forwards in time. + */ + setPaginationToken(token, direction) { + if (this.roomId) { + this.getState(direction).paginationToken = token; + } else if (direction === Direction.Backward) { + this.startToken = token; + } else { + this.endToken = token; + } + } + + /** + * Get the next timeline in the series + * + * @param direction - EventTimeline.BACKWARDS to get the previous + * timeline; EventTimeline.FORWARDS to get the next timeline. + * + * @returns previous or following timeline, if they have been + * joined up. + */ + getNeighbouringTimeline(direction) { + if (direction == EventTimeline.BACKWARDS) { + return this.prevTimeline; + } else if (direction == EventTimeline.FORWARDS) { + return this.nextTimeline; + } else { + throw new Error("Invalid direction '" + direction + "'"); + } + } + + /** + * Set the next timeline in the series + * + * @param neighbour - previous/following timeline + * + * @param direction - EventTimeline.BACKWARDS to set the previous + * timeline; EventTimeline.FORWARDS to set the next timeline. + * + * @throws Error if an attempt is made to set the neighbouring timeline when + * it is already set. + */ + setNeighbouringTimeline(neighbour, direction) { + if (this.getNeighbouringTimeline(direction)) { + throw new Error("timeline already has a neighbouring timeline - " + "cannot reset neighbour (direction: " + direction + ")"); + } + if (direction == EventTimeline.BACKWARDS) { + this.prevTimeline = neighbour; + } else if (direction == EventTimeline.FORWARDS) { + this.nextTimeline = neighbour; + } else { + throw new Error("Invalid direction '" + direction + "'"); + } + + // make sure we don't try to paginate this timeline + this.setPaginationToken(null, direction); + } + + /** + * Add a new event to the timeline, and update the state + * + * @param event - new event + * @param options - addEvent options + */ + + addEvent(event, toStartOfTimelineOrOpts, roomState) { + let toStartOfTimeline = !!toStartOfTimelineOrOpts; + let timelineWasEmpty; + if (typeof toStartOfTimelineOrOpts === "object") { + ({ + toStartOfTimeline, + roomState, + timelineWasEmpty + } = toStartOfTimelineOrOpts); + } else if (toStartOfTimelineOrOpts !== undefined) { + // Deprecation warning + // FIXME: Remove after 2023-06-01 (technical debt) + _logger.logger.warn("Overload deprecated: " + "`EventTimeline.addEvent(event, toStartOfTimeline, roomState?)` " + "is deprecated in favor of the overload with `EventTimeline.addEvent(event, IAddEventOptions)`"); + } + if (!roomState) { + roomState = toStartOfTimeline ? this.startState : this.endState; + } + const timelineSet = this.getTimelineSet(); + if (timelineSet.room) { + EventTimeline.setEventMetadata(event, roomState, toStartOfTimeline); + + // modify state but only on unfiltered timelineSets + if (event.isState() && timelineSet.room.getUnfilteredTimelineSet() === timelineSet) { + var _roomState; + (_roomState = roomState) === null || _roomState === void 0 ? void 0 : _roomState.setStateEvents([event], { + timelineWasEmpty + }); + // it is possible that the act of setting the state event means we + // can set more metadata (specifically sender/target props), so try + // it again if the prop wasn't previously set. It may also mean that + // the sender/target is updated (if the event set was a room member event) + // so we want to use the *updated* member (new avatar/name) instead. + // + // However, we do NOT want to do this on member events if we're going + // back in time, else we'll set the .sender value for BEFORE the given + // member event, whereas we want to set the .sender value for the ACTUAL + // member event itself. + if (!event.sender || event.getType() === _event.EventType.RoomMember && !toStartOfTimeline) { + EventTimeline.setEventMetadata(event, roomState, toStartOfTimeline); + } + } + } + let insertIndex; + if (toStartOfTimeline) { + insertIndex = 0; + } else { + insertIndex = this.events.length; + } + this.events.splice(insertIndex, 0, event); // insert element + if (toStartOfTimeline) { + this.baseIndex++; + } + } + + /** + * Remove an event from the timeline + * + * @param eventId - ID of event to be removed + * @returns removed event, or null if not found + */ + removeEvent(eventId) { + for (let i = this.events.length - 1; i >= 0; i--) { + const ev = this.events[i]; + if (ev.getId() == eventId) { + this.events.splice(i, 1); + if (i < this.baseIndex) { + this.baseIndex--; + } + return ev; + } + } + return null; + } + + /** + * Return a string to identify this timeline, for debugging + * + * @returns name for this timeline + */ + toString() { + return this.name; + } +} +exports.EventTimeline = EventTimeline; +(0, _defineProperty2.default)(EventTimeline, "BACKWARDS", Direction.Backward); +(0, _defineProperty2.default)(EventTimeline, "FORWARDS", Direction.Forward); +//# sourceMappingURL=event-timeline.js.map
\ No newline at end of file |