diff --git a/src/ui/web/session/room/TimelineList.js b/src/ui/web/session/room/TimelineList.js index 9697bce6..49e254cf 100644 --- a/src/ui/web/session/room/TimelineList.js +++ b/src/ui/web/session/room/TimelineList.js @@ -40,19 +40,38 @@ export class TimelineList extends ListView { this._viewModel = viewModel; } - async _onScroll() { - const root = this.root(); - if (root.scrollTop < 100 && !this._topLoadingPromise && this._viewModel) { - const beforeFromBottom = this._distanceFromBottom(); - this._topLoadingPromise = this._viewModel.loadAtTop(); - await this._topLoadingPromise; - const fromBottom = this._distanceFromBottom(); - const amountGrown = fromBottom - beforeFromBottom; - root.scrollTop = root.scrollTop + amountGrown; + async _loadAtTopWhile(predicate) { + try { + while (predicate()) { + // fill, not enough content to fill timeline + this._topLoadingPromise = this._viewModel.loadAtTop(); + await this._topLoadingPromise; + } + } + catch (err) { + //ignore error, as it is handled in the VM + } + finally { this._topLoadingPromise = null; } } + async _onScroll() { + const PAGINATE_OFFSET = 100; + const root = this.root(); + if (root.scrollTop < PAGINATE_OFFSET && !this._topLoadingPromise && this._viewModel) { + // to calculate total amountGrown to check when we stop loading + let beforeContentHeight = root.scrollHeight; + // to adjust scrollTop every time + let lastContentHeight = beforeContentHeight; + // load until pagination offset is reached again + this._loadAtTopWhile(() => { + const contentHeight = root.scrollHeight; + const amountGrown = contentHeight - beforeContentHeight; + root.scrollTop = root.scrollTop + (contentHeight - lastContentHeight); + lastContentHeight = contentHeight; + return amountGrown < PAGINATE_OFFSET; + }); } } @@ -70,7 +89,15 @@ export class TimelineList extends ListView { loadList() { super.loadList(); const root = this.root(); - root.scrollTop = root.scrollHeight; + const {scrollHeight, clientHeight} = root; + if (scrollHeight > clientHeight) { + root.scrollTop = root.scrollHeight; + } + // load while viewport is not filled + this._loadAtTopWhile(() => { + const {scrollHeight, clientHeight} = root; + return scrollHeight <= clientHeight; + }); } onBeforeListChanged() { @@ -84,8 +111,8 @@ export class TimelineList extends ListView { } onListChanged() { + const root = this.root(); if (this._atBottom) { - const root = this.root(); root.scrollTop = root.scrollHeight; } }