diff options
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/timeline-window.js')
-rw-r--r-- | includes/external/matrix/node_modules/matrix-js-sdk/lib/timeline-window.js | 468 |
1 files changed, 0 insertions, 468 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/timeline-window.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/timeline-window.js deleted file mode 100644 index cc7f455..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/lib/timeline-window.js +++ /dev/null @@ -1,468 +0,0 @@ -"use strict"; - -var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.TimelineWindow = exports.TimelineIndex = void 0; -var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); -var _eventTimeline = require("./models/event-timeline"); -var _logger = require("./logger"); -/* -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. -*/ - -/** - * @internal - */ -const DEBUG = false; - -/** - * @internal - */ -/* istanbul ignore next */ -const debuglog = DEBUG ? _logger.logger.log.bind(_logger.logger) : function () {}; - -/** - * the number of times we ask the server for more events before giving up - * - * @internal - */ -const DEFAULT_PAGINATE_LOOP_LIMIT = 5; -class TimelineWindow { - // these will be TimelineIndex objects; they delineate the 'start' and - // 'end' of the window. - // - // start.index is inclusive; end.index is exclusive. - - /** - * Construct a TimelineWindow. - * - * <p>This abstracts the separate timelines in a Matrix {@link Room} into a single iterable thing. - * It keeps track of the start and endpoints of the window, which can be advanced with the help - * of pagination requests. - * - * <p>Before the window is useful, it must be initialised by calling {@link TimelineWindow#load}. - * - * <p>Note that the window will not automatically extend itself when new events - * are received from /sync; you should arrange to call {@link TimelineWindow#paginate} - * on {@link RoomEvent.Timeline} events. - * - * @param client - MatrixClient to be used for context/pagination - * requests. - * - * @param timelineSet - The timelineSet to track - * - * @param opts - Configuration options for this window - */ - constructor(client, timelineSet, opts = {}) { - this.client = client; - this.timelineSet = timelineSet; - (0, _defineProperty2.default)(this, "windowLimit", void 0); - (0, _defineProperty2.default)(this, "start", void 0); - (0, _defineProperty2.default)(this, "end", void 0); - (0, _defineProperty2.default)(this, "eventCount", 0); - this.windowLimit = opts.windowLimit || 1000; - } - - /** - * Initialise the window to point at a given event, or the live timeline - * - * @param initialEventId - If given, the window will contain the - * given event - * @param initialWindowSize - Size of the initial window - */ - load(initialEventId, initialWindowSize = 20) { - // given an EventTimeline, find the event we were looking for, and initialise our - // fields so that the event in question is in the middle of the window. - const initFields = timeline => { - if (!timeline) { - throw new Error("No timeline given to initFields"); - } - let eventIndex; - const events = timeline.getEvents(); - if (!initialEventId) { - // we were looking for the live timeline: initialise to the end - eventIndex = events.length; - } else { - eventIndex = events.findIndex(e => e.getId() === initialEventId); - if (eventIndex < 0) { - throw new Error("getEventTimeline result didn't include requested event"); - } - } - const endIndex = Math.min(events.length, eventIndex + Math.ceil(initialWindowSize / 2)); - const startIndex = Math.max(0, endIndex - initialWindowSize); - this.start = new TimelineIndex(timeline, startIndex - timeline.getBaseIndex()); - this.end = new TimelineIndex(timeline, endIndex - timeline.getBaseIndex()); - this.eventCount = endIndex - startIndex; - }; - - // We avoid delaying the resolution of the promise by a reactor tick if we already have the data we need, - // which is important to keep room-switching feeling snappy. - if (this.timelineSet.getTimelineForEvent(initialEventId)) { - initFields(this.timelineSet.getTimelineForEvent(initialEventId)); - return Promise.resolve(); - } else if (initialEventId) { - return this.client.getEventTimeline(this.timelineSet, initialEventId).then(initFields); - } else { - initFields(this.timelineSet.getLiveTimeline()); - return Promise.resolve(); - } - } - - /** - * Get the TimelineIndex of the window in the given direction. - * - * @param direction - EventTimeline.BACKWARDS to get the TimelineIndex - * at the start of the window; EventTimeline.FORWARDS to get the TimelineIndex at - * the end. - * - * @returns The requested timeline index if one exists, null - * otherwise. - */ - getTimelineIndex(direction) { - if (direction == _eventTimeline.EventTimeline.BACKWARDS) { - var _this$start; - return (_this$start = this.start) !== null && _this$start !== void 0 ? _this$start : null; - } else if (direction == _eventTimeline.EventTimeline.FORWARDS) { - var _this$end; - return (_this$end = this.end) !== null && _this$end !== void 0 ? _this$end : null; - } else { - throw new Error("Invalid direction '" + direction + "'"); - } - } - - /** - * Try to extend the window using events that are already in the underlying - * TimelineIndex. - * - * @param direction - EventTimeline.BACKWARDS to try extending it - * backwards; EventTimeline.FORWARDS to try extending it forwards. - * @param size - number of events to try to extend by. - * - * @returns true if the window was extended, false otherwise. - */ - extend(direction, size) { - const tl = this.getTimelineIndex(direction); - if (!tl) { - debuglog("TimelineWindow: no timeline yet"); - return false; - } - const count = direction == _eventTimeline.EventTimeline.BACKWARDS ? tl.retreat(size) : tl.advance(size); - if (count) { - this.eventCount += count; - debuglog("TimelineWindow: increased cap by " + count + " (now " + this.eventCount + ")"); - // remove some events from the other end, if necessary - const excess = this.eventCount - this.windowLimit; - if (excess > 0) { - this.unpaginate(excess, direction != _eventTimeline.EventTimeline.BACKWARDS); - } - return true; - } - return false; - } - - /** - * Check if this window can be extended - * - * <p>This returns true if we either have more events, or if we have a - * pagination token which means we can paginate in that direction. It does not - * necessarily mean that there are more events available in that direction at - * this time. - * - * @param direction - EventTimeline.BACKWARDS to check if we can - * paginate backwards; EventTimeline.FORWARDS to check if we can go forwards - * - * @returns true if we can paginate in the given direction - */ - canPaginate(direction) { - const tl = this.getTimelineIndex(direction); - if (!tl) { - debuglog("TimelineWindow: no timeline yet"); - return false; - } - if (direction == _eventTimeline.EventTimeline.BACKWARDS) { - if (tl.index > tl.minIndex()) { - return true; - } - } else { - if (tl.index < tl.maxIndex()) { - return true; - } - } - const hasNeighbouringTimeline = tl.timeline.getNeighbouringTimeline(direction); - const paginationToken = tl.timeline.getPaginationToken(direction); - return Boolean(hasNeighbouringTimeline) || Boolean(paginationToken); - } - - /** - * Attempt to extend the window - * - * @param direction - EventTimeline.BACKWARDS to extend the window - * backwards (towards older events); EventTimeline.FORWARDS to go forwards. - * - * @param size - number of events to try to extend by. If fewer than this - * number are immediately available, then we return immediately rather than - * making an API call. - * - * @param makeRequest - whether we should make API calls to - * fetch further events if we don't have any at all. (This has no effect if - * the room already knows about additional events in the relevant direction, - * even if there are fewer than 'size' of them, as we will just return those - * we already know about.) - * - * @param requestLimit - limit for the number of API requests we - * should make. - * - * @returns Promise which resolves to a boolean which is true if more events - * were successfully retrieved. - */ - async paginate(direction, size, makeRequest = true, requestLimit = DEFAULT_PAGINATE_LOOP_LIMIT) { - // Either wind back the message cap (if there are enough events in the - // timeline to do so), or fire off a pagination request. - const tl = this.getTimelineIndex(direction); - if (!tl) { - debuglog("TimelineWindow: no timeline yet"); - return false; - } - if (tl.pendingPaginate) { - return tl.pendingPaginate; - } - - // try moving the cap - if (this.extend(direction, size)) { - return true; - } - if (!makeRequest || requestLimit === 0) { - // todo: should we return something different to indicate that there - // might be more events out there, but we haven't found them yet? - return false; - } - - // try making a pagination request - const token = tl.timeline.getPaginationToken(direction); - if (!token) { - debuglog("TimelineWindow: no token"); - return false; - } - debuglog("TimelineWindow: starting request"); - const prom = this.client.paginateEventTimeline(tl.timeline, { - backwards: direction == _eventTimeline.EventTimeline.BACKWARDS, - limit: size - }).finally(function () { - tl.pendingPaginate = undefined; - }).then(r => { - debuglog("TimelineWindow: request completed with result " + r); - if (!r) { - return this.paginate(direction, size, false, 0); - } - - // recurse to advance the index into the results. - // - // If we don't get any new events, we want to make sure we keep asking - // the server for events for as long as we have a valid pagination - // token. In particular, we want to know if we've actually hit the - // start of the timeline, or if we just happened to know about all of - // the events thanks to https://matrix.org/jira/browse/SYN-645. - // - // On the other hand, we necessarily want to wait forever for the - // server to make its mind up about whether there are other events, - // because it gives a bad user experience - // (https://github.com/vector-im/vector-web/issues/1204). - return this.paginate(direction, size, true, requestLimit - 1); - }); - tl.pendingPaginate = prom; - return prom; - } - - /** - * Remove `delta` events from the start or end of the timeline. - * - * @param delta - number of events to remove from the timeline - * @param startOfTimeline - if events should be removed from the start - * of the timeline. - */ - unpaginate(delta, startOfTimeline) { - const tl = startOfTimeline ? this.start : this.end; - if (!tl) { - throw new Error(`Attempting to unpaginate startOfTimeline=${startOfTimeline} but don't have this direction`); - } - - // sanity-check the delta - if (delta > this.eventCount || delta < 0) { - throw new Error(`Attemting to unpaginate ${delta} events, but only have ${this.eventCount} in the timeline`); - } - while (delta > 0) { - const count = startOfTimeline ? tl.advance(delta) : tl.retreat(delta); - if (count <= 0) { - // sadness. This shouldn't be possible. - throw new Error("Unable to unpaginate any further, but still have " + this.eventCount + " events"); - } - delta -= count; - this.eventCount -= count; - debuglog("TimelineWindow.unpaginate: dropped " + count + " (now " + this.eventCount + ")"); - } - } - - /** - * Get a list of the events currently in the window - * - * @returns the events in the window - */ - getEvents() { - if (!this.start) { - // not yet loaded - return []; - } - const result = []; - - // iterate through each timeline between this.start and this.end - // (inclusive). - let timeline = this.start.timeline; - // eslint-disable-next-line no-constant-condition - while (true) { - var _this$end2, _this$end3; - const events = timeline.getEvents(); - - // For the first timeline in the chain, we want to start at - // this.start.index. For the last timeline in the chain, we want to - // stop before this.end.index. Otherwise, we want to copy all of the - // events in the timeline. - // - // (Note that both this.start.index and this.end.index are relative - // to their respective timelines' BaseIndex). - // - let startIndex = 0; - let endIndex = events.length; - if (timeline === this.start.timeline) { - startIndex = this.start.index + timeline.getBaseIndex(); - } - if (timeline === ((_this$end2 = this.end) === null || _this$end2 === void 0 ? void 0 : _this$end2.timeline)) { - endIndex = this.end.index + timeline.getBaseIndex(); - } - for (let i = startIndex; i < endIndex; i++) { - result.push(events[i]); - } - - // if we're not done, iterate to the next timeline. - if (timeline === ((_this$end3 = this.end) === null || _this$end3 === void 0 ? void 0 : _this$end3.timeline)) { - break; - } else { - timeline = timeline.getNeighbouringTimeline(_eventTimeline.EventTimeline.FORWARDS); - } - } - return result; - } -} - -/** - * A thing which contains a timeline reference, and an index into it. - * @internal - */ -exports.TimelineWindow = TimelineWindow; -class TimelineIndex { - // index: the indexes are relative to BaseIndex, so could well be negative. - constructor(timeline, index) { - this.timeline = timeline; - this.index = index; - (0, _defineProperty2.default)(this, "pendingPaginate", void 0); - } - - /** - * @returns the minimum possible value for the index in the current - * timeline - */ - minIndex() { - return this.timeline.getBaseIndex() * -1; - } - - /** - * @returns the maximum possible value for the index in the current - * timeline (exclusive - ie, it actually returns one more than the index - * of the last element). - */ - maxIndex() { - return this.timeline.getEvents().length - this.timeline.getBaseIndex(); - } - - /** - * Try move the index forward, or into the neighbouring timeline - * - * @param delta - number of events to advance by - * @returns number of events successfully advanced by - */ - advance(delta) { - if (!delta) { - return 0; - } - - // first try moving the index in the current timeline. See if there is room - // to do so. - let cappedDelta; - if (delta < 0) { - // we want to wind the index backwards. - // - // (this.minIndex() - this.index) is a negative number whose magnitude - // is the amount of room we have to wind back the index in the current - // timeline. We cap delta to this quantity. - cappedDelta = Math.max(delta, this.minIndex() - this.index); - if (cappedDelta < 0) { - this.index += cappedDelta; - return cappedDelta; - } - } else { - // we want to wind the index forwards. - // - // (this.maxIndex() - this.index) is a (positive) number whose magnitude - // is the amount of room we have to wind forward the index in the current - // timeline. We cap delta to this quantity. - cappedDelta = Math.min(delta, this.maxIndex() - this.index); - if (cappedDelta > 0) { - this.index += cappedDelta; - return cappedDelta; - } - } - - // the index is already at the start/end of the current timeline. - // - // next see if there is a neighbouring timeline to switch to. - const neighbour = this.timeline.getNeighbouringTimeline(delta < 0 ? _eventTimeline.EventTimeline.BACKWARDS : _eventTimeline.EventTimeline.FORWARDS); - if (neighbour) { - this.timeline = neighbour; - if (delta < 0) { - this.index = this.maxIndex(); - } else { - this.index = this.minIndex(); - } - debuglog("paginate: switched to new neighbour"); - - // recurse, using the next timeline - return this.advance(delta); - } - return 0; - } - - /** - * Try move the index backwards, or into the neighbouring timeline - * - * @param delta - number of events to retreat by - * @returns number of events successfully retreated by - */ - retreat(delta) { - return this.advance(delta * -1) * -1; - } -} -exports.TimelineIndex = TimelineIndex; -//# sourceMappingURL=timeline-window.js.map
\ No newline at end of file |