From 9cd5257959d984ad2a0bca98377326b50ed117f9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Sun, 16 Jun 2019 17:29:33 +0200 Subject: [PATCH] load more events when scrolled to top --- .../room/timeline/TimelineViewModel.js | 3 +- src/matrix/room/timeline/Timeline.js | 8 ++-- src/ui/web/session/room/RoomView.js | 7 +-- src/ui/web/session/room/TimelineList.js | 43 ++++++++++++++++++- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/domain/session/room/timeline/TimelineViewModel.js b/src/domain/session/room/timeline/TimelineViewModel.js index 0025c563..622ab1cb 100644 --- a/src/domain/session/room/timeline/TimelineViewModel.js +++ b/src/domain/session/room/timeline/TimelineViewModel.js @@ -28,8 +28,7 @@ export default class TimelineViewModel { // doesn't fill gaps, only loads stored entries/tiles loadAtTop() { - // load 100 entries, which may result in 0..100 tiles - return this._timeline.loadAtTop(100); + return this._timeline.loadAtTop(50); } unloadAtTop(tileAmount) { diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 52900777..05fcc3f5 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -20,7 +20,7 @@ export default class Timeline { /** @package */ async load() { - const entries = await this._timelineReader.readFromEnd(100); + const entries = await this._timelineReader.readFromEnd(50); this._entriesList.setManySorted(entries); } @@ -47,12 +47,12 @@ export default class Timeline { // tries to prepend `amount` entries to the `entries` list. async loadAtTop(amount) { - if (this._entriesList.length() === 0) { + const firstEventEntry = this._entriesList.array.find(e => !!e.event); + if (!firstEventEntry) { return; } - const firstEntry = this._entriesList.array()[0]; const entries = await this._timelineReader.readFrom( - firstEntry.asEventKey(), + firstEventEntry.asEventKey(), Direction.Backward, amount ); diff --git a/src/ui/web/session/room/RoomView.js b/src/ui/web/session/room/RoomView.js index 88b46dbc..8c370762 100644 --- a/src/ui/web/session/room/RoomView.js +++ b/src/ui/web/session/room/RoomView.js @@ -5,7 +5,6 @@ export default class RoomView extends TemplateView { constructor(viewModel) { super(viewModel, true); this._timelineList = null; - this._checkScroll = this._checkScroll.bind(this); } render(t) { @@ -37,11 +36,7 @@ export default class RoomView extends TemplateView { update(value, prop) { super.update(value, prop); if (prop === "timelineViewModel") { - this._timelineList.update({list: this.viewModel.timelineViewModel.tiles}); + this._timelineList.update({viewModel: this.viewModel.timelineViewModel}); } } - - _checkScroll() { - // const list = this._timelineList.root(); - } } diff --git a/src/ui/web/session/room/TimelineList.js b/src/ui/web/session/room/TimelineList.js index c98751ce..ab5eee0d 100644 --- a/src/ui/web/session/room/TimelineList.js +++ b/src/ui/web/session/room/TimelineList.js @@ -14,6 +14,41 @@ export default class TimelineList extends ListView { } }); this._atBottom = false; + this._onScroll = this._onScroll.bind(this); + this._topLoadingPromise = null; + this._viewModel = null; + } + + async _onScroll() { + const root = this.root(); + if (root.scrollTop === 0 && !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; + this._topLoadingPromise = null; + } + } + + update(attributes) { + if(attributes.viewModel) { + this._viewModel = attributes.viewModel; + attributes.list = attributes.viewModel.tiles; + } + super.update(attributes); + } + + mount() { + const root = super.mount(); + root.addEventListener("scroll", this._onScroll); + return root; + } + + unmount() { + this.root().removeEventListener("scroll", this._onScroll); + super.unmount(); } loadList() { @@ -23,11 +58,15 @@ export default class TimelineList extends ListView { } onBeforeListChanged() { - const root = this.root(); - const fromBottom = root.scrollHeight - root.scrollTop - root.clientHeight; + const fromBottom = this._distanceFromBottom(); this._atBottom = fromBottom < 1; } + _distanceFromBottom() { + const root = this.root(); + return root.scrollHeight - root.scrollTop - root.clientHeight; + } + onListChanged() { if (this._atBottom) { const root = this.root();