{"version":3,"file":"timeline-window.js","names":["_eventTimeline","require","_logger","DEBUG","debuglog","logger","log","bind","DEFAULT_PAGINATE_LOOP_LIMIT","TimelineWindow","constructor","client","timelineSet","opts","_defineProperty2","default","windowLimit","load","initialEventId","initialWindowSize","initFields","timeline","Error","eventIndex","events","getEvents","length","findIndex","e","getId","endIndex","Math","min","ceil","startIndex","max","start","TimelineIndex","getBaseIndex","end","eventCount","getTimelineForEvent","Promise","resolve","getEventTimeline","then","getLiveTimeline","getTimelineIndex","direction","EventTimeline","BACKWARDS","_this$start","FORWARDS","_this$end","extend","size","tl","count","retreat","advance","excess","unpaginate","canPaginate","index","minIndex","maxIndex","hasNeighbouringTimeline","getNeighbouringTimeline","paginationToken","getPaginationToken","Boolean","paginate","makeRequest","requestLimit","pendingPaginate","token","prom","paginateEventTimeline","backwards","limit","finally","undefined","r","delta","startOfTimeline","result","_this$end2","_this$end3","i","push","exports","cappedDelta","neighbour"],"sources":["../src/timeline-window.ts"],"sourcesContent":["/*\nCopyright 2016 - 2021 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { Optional } from \"matrix-events-sdk\";\n\nimport { Direction, EventTimeline } from \"./models/event-timeline\";\nimport { logger } from \"./logger\";\nimport { MatrixClient } from \"./client\";\nimport { EventTimelineSet } from \"./models/event-timeline-set\";\nimport { MatrixEvent } from \"./models/event\";\n\n/**\n * @internal\n */\nconst DEBUG = false;\n\n/**\n * @internal\n */\n/* istanbul ignore next */\nconst debuglog = DEBUG ? logger.log.bind(logger) : function (): void {};\n\n/**\n * the number of times we ask the server for more events before giving up\n *\n * @internal\n */\nconst DEFAULT_PAGINATE_LOOP_LIMIT = 5;\n\ninterface IOpts {\n /**\n * Maximum number of events to keep in the window. If more events are retrieved via pagination requests,\n * excess events will be dropped from the other end of the window.\n */\n windowLimit?: number;\n}\n\nexport class TimelineWindow {\n private readonly windowLimit: number;\n // these will be TimelineIndex objects; they delineate the 'start' and\n // 'end' of the window.\n //\n // start.index is inclusive; end.index is exclusive.\n private start?: TimelineIndex;\n private end?: TimelineIndex;\n private eventCount = 0;\n\n /**\n * Construct a TimelineWindow.\n *\n *
This abstracts the separate timelines in a Matrix {@link Room} into a single iterable thing.\n * It keeps track of the start and endpoints of the window, which can be advanced with the help\n * of pagination requests.\n *\n *
Before the window is useful, it must be initialised by calling {@link TimelineWindow#load}.\n *\n *
Note that the window will not automatically extend itself when new events\n * are received from /sync; you should arrange to call {@link TimelineWindow#paginate}\n * on {@link RoomEvent.Timeline} events.\n *\n * @param client - MatrixClient to be used for context/pagination\n * requests.\n *\n * @param timelineSet - The timelineSet to track\n *\n * @param opts - Configuration options for this window\n */\n public constructor(\n private readonly client: MatrixClient,\n private readonly timelineSet: EventTimelineSet,\n opts: IOpts = {},\n ) {\n this.windowLimit = opts.windowLimit || 1000;\n }\n\n /**\n * Initialise the window to point at a given event, or the live timeline\n *\n * @param initialEventId - If given, the window will contain the\n * given event\n * @param initialWindowSize - Size of the initial window\n */\n public load(initialEventId?: string, initialWindowSize = 20): Promise This returns true if we either have more events, or if we have a\n * pagination token which means we can paginate in that direction. It does not\n * necessarily mean that there are more events available in that direction at\n * this time.\n *\n * @param direction - EventTimeline.BACKWARDS to check if we can\n * paginate backwards; EventTimeline.FORWARDS to check if we can go forwards\n *\n * @returns true if we can paginate in the given direction\n */\n public canPaginate(direction: Direction): boolean {\n const tl = this.getTimelineIndex(direction);\n\n if (!tl) {\n debuglog(\"TimelineWindow: no timeline yet\");\n return false;\n }\n\n if (direction == EventTimeline.BACKWARDS) {\n if (tl.index > tl.minIndex()) {\n return true;\n }\n } else {\n if (tl.index < tl.maxIndex()) {\n return true;\n }\n }\n\n const hasNeighbouringTimeline = tl.timeline.getNeighbouringTimeline(direction);\n const paginationToken = tl.timeline.getPaginationToken(direction);\n return Boolean(hasNeighbouringTimeline) || Boolean(paginationToken);\n }\n\n /**\n * Attempt to extend the window\n *\n * @param direction - EventTimeline.BACKWARDS to extend the window\n * backwards (towards older events); EventTimeline.FORWARDS to go forwards.\n *\n * @param size - number of events to try to extend by. If fewer than this\n * number are immediately available, then we return immediately rather than\n * making an API call.\n *\n * @param makeRequest - whether we should make API calls to\n * fetch further events if we don't have any at all. (This has no effect if\n * the room already knows about additional events in the relevant direction,\n * even if there are fewer than 'size' of them, as we will just return those\n * we already know about.)\n *\n * @param requestLimit - limit for the number of API requests we\n * should make.\n *\n * @returns Promise which resolves to a boolean which is true if more events\n * were successfully retrieved.\n */\n public async paginate(\n direction: Direction,\n size: number,\n makeRequest = true,\n requestLimit = DEFAULT_PAGINATE_LOOP_LIMIT,\n ): Promise