From d0f122a2bec933e2527bfade0a9180ff39777f6c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 9 Sep 2021 17:14:16 +0200 Subject: [PATCH] WIP-ish, batch visible range requests, allow setting empty ranges and... don't try to notify when the tile becomes invisible again, we don't need it currently --- .../room/timeline/TimelineViewModel.js | 59 ++++++++++++------- .../session/room/timeline/tiles/GapTile.js | 6 +- .../session/room/timeline/tiles/SimpleTile.js | 4 +- .../web/ui/session/room/TimelineView.ts | 7 ++- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/domain/session/room/timeline/TimelineViewModel.js b/src/domain/session/room/timeline/TimelineViewModel.js index 0e28cb6e..91390fd9 100644 --- a/src/domain/session/room/timeline/TimelineViewModel.js +++ b/src/domain/session/room/timeline/TimelineViewModel.js @@ -46,36 +46,51 @@ export class TimelineViewModel extends ViewModel { this._endTile = null; this._topLoadingPromise = null; this._bottomLoadingPromise = null; + this._requestedStartTile = null; + this._requestedEndTile = null; + this._requestScheduled = false; } - setVisibleTileRange(startTile, endTile, isViewportFilled) { - // we should async batch things here? + /** if this.tiles is empty, call this with undefined for both startTile and endTile */ + setVisibleTileRange(startTile, endTile) { + this._requestedStartTile = startTile; + this._requestedEndTile = endTile; + if (!this._requestScheduled) { + Promise.resolve().then(() => { + this._setVisibleTileRange(this._requestedStartTile, this._requestedEndTile); + this._requestScheduled = false; + }); + this._requestScheduled = true; + } + } - // this will prevent a (small) inserted tile from being marked visible, won't it? - if (this._startTile === startTile && this._endTile === endTile) { - return; + /** if this.tiles is empty, call this with undefined for both startTile and endTile */ + _setVisibleTileRange(startTile, endTile) { + let loadTop; + if (startTile && endTile) { + // old tiles could have been removed from tilescollection once we support unloading + this._startTile = startTile; + this._endTile = endTile; + const startIndex = this._tiles.getTileIndex(this._startTile); + const endIndex = this._tiles.getTileIndex(this._endTile); + for (const tile of this._tiles.sliceIterator(startIndex, endIndex)) { + tile.notifyVisible(); + } + loadTop = startIndex < 5; + console.log("got tiles", startIndex, endIndex, loadTop); + } else { + loadTop = true; + console.log("no tiles, load more at top"); } - // old tiles could have been removed from tilescollection once we support unloading - const oldStartIndex = this._startTile ? this._tiles.getTileIndex(this._startTile) : Number.MAX_SAFE_INTEGER; - const oldEndIndex = this._endTile ? this._tiles.getTileIndex(this._endTile) : Number.MIN_SAFE_INTEGER; - const newStartIndex = this._tiles.getTileIndex(startTile); - const newEndIndex = this._tiles.getTileIndex(endTile); - - const minIndex = Math.min(oldStartIndex, newStartIndex); - const maxIndex = Math.max(oldEndIndex, newEndIndex); - - let index = minIndex; - for (const tile of this._tiles.sliceIterator(minIndex, maxIndex)) { - const isVisible = index >= newStartIndex && index <= newEndIndex; - tile.setVisible(isVisible); - index += 1; - } - - if (!isViewportFilled || (newStartIndex < 5 && !this._topLoadingPromise)) { + if (loadTop && !this._topLoadingPromise) { this._topLoadingPromise = this._timeline.loadAtTop(10).then(() => { this._topLoadingPromise = null; + // check if more items need to be loaded by recursing + this.setVisibleTileRange(this._startTile, this._endTile); }); + } else if (loadTop) { + console.log("loadTop is true but already loading"); } } diff --git a/src/domain/session/room/timeline/tiles/GapTile.js b/src/domain/session/room/timeline/tiles/GapTile.js index c85b6a09..0863b3b6 100644 --- a/src/domain/session/room/timeline/tiles/GapTile.js +++ b/src/domain/session/room/timeline/tiles/GapTile.js @@ -44,10 +44,8 @@ export class GapTile extends SimpleTile { } } - setVisible(isVisible) { - if (isVisible) { - this.fill(); - } + notifyVisible() { + this.fill(); } updateEntry(entry, params) { diff --git a/src/domain/session/room/timeline/tiles/SimpleTile.js b/src/domain/session/room/timeline/tiles/SimpleTile.js index 96679c97..4c1c1de0 100644 --- a/src/domain/session/room/timeline/tiles/SimpleTile.js +++ b/src/domain/session/room/timeline/tiles/SimpleTile.js @@ -123,9 +123,7 @@ export class SimpleTile extends ViewModel { } - setVisible(isVisible) { - - } + notifyVisible() {} dispose() { this.setUpdateEmit(null); diff --git a/src/platform/web/ui/session/room/TimelineView.ts b/src/platform/web/ui/session/room/TimelineView.ts index 71af5f9f..8d95932f 100644 --- a/src/platform/web/ui/session/room/TimelineView.ts +++ b/src/platform/web/ui/session/room/TimelineView.ts @@ -132,11 +132,12 @@ export class TimelineView extends TemplateView { } private updateVisibleRange(startIndex: number, endIndex: number, isViewportFilled: boolean) { + // can be undefined, meaning the tiles collection is still empty const firstVisibleChild = this.tilesView!.getChildInstanceByIndex(startIndex); const lastVisibleChild = this.tilesView!.getChildInstanceByIndex(endIndex); - if (firstVisibleChild && lastVisibleChild) { - this.value.setVisibleTileRange(firstVisibleChild.value, lastVisibleChild.value, isViewportFilled); - } + //if (firstVisibleChild && lastVisibleChild) { + this.value.setVisibleTileRange(firstVisibleChild?.value, lastVisibleChild?.value, isViewportFilled); + //} } }