diff --git a/src/domain/session/room/timeline/TimelineViewModel.js b/src/domain/session/room/timeline/TimelineViewModel.js index 222a05b7..eafc092c 100644 --- a/src/domain/session/room/timeline/TimelineViewModel.js +++ b/src/domain/session/room/timeline/TimelineViewModel.js @@ -34,8 +34,6 @@ when loading, it just reads events from a sortkey backwards or forwards... import {TilesCollection} from "./TilesCollection.js"; import {ViewModel} from "../../../ViewModel.js"; - - export class TimelineViewModel extends ViewModel { constructor(options) { super(options); @@ -45,7 +43,6 @@ export class TimelineViewModel extends ViewModel { this._startTile = null; this._endTile = null; this._topLoadingPromise = null; - this._bottomLoadingPromise = null; this._requestedStartTile = null; this._requestedEndTile = null; this._requestScheduled = false; @@ -56,7 +53,7 @@ export class TimelineViewModel extends ViewModel { this._requestedStartTile = startTile; this._requestedEndTile = endTile; if (!this._requestScheduled) { - Promise.resolve().then(() => { + requestIdleCallback(() => { this._setVisibleTileRange(this._requestedStartTile, this._requestedEndTile); this._requestScheduled = false; }); @@ -72,14 +69,15 @@ export class TimelineViewModel extends ViewModel { 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)) { + for (const tile of this._tiles.sliceIterator(startIndex, endIndex + 1)) { tile.notifyVisible(); } - loadTop = startIndex < 5; - console.log("got tiles", startIndex, endIndex, loadTop); + loadTop = startIndex < 10; + // console.log("got tiles", startIndex, endIndex, loadTop); } else { + // tiles collection is empty, load more at top loadTop = true; - console.log("no tiles, load more at top"); + // console.log("no tiles, load more at top"); } if (loadTop && !this._topLoadingPromise) { @@ -91,7 +89,7 @@ export class TimelineViewModel extends ViewModel { } }); } else if (loadTop) { - console.log("loadTop is true but already loading"); + // console.log("loadTop is true but already loading"); } } diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index fdfaee48..2a9cfec7 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -72,8 +72,10 @@ export class Timeline { // as they should only populate once the view subscribes to it // if they are populated already, the sender profile would be empty - // 30 seems to be a good amount to fill the entire screen - const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30, txn, log)); + // choose good amount here between showing messages initially and + // not spending too much time decrypting messages before showing the timeline. + // more messages should be loaded automatically until the viewport is full by the view if needed. + const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(5, txn, log)); try { const entries = await readerRequest.complete(); this._setupEntries(entries); diff --git a/src/platform/web/ui/css/timeline.css b/src/platform/web/ui/css/timeline.css index 25ba5a10..97582990 100644 --- a/src/platform/web/ui/css/timeline.css +++ b/src/platform/web/ui/css/timeline.css @@ -20,6 +20,8 @@ limitations under the License. overscroll-behavior: contain; padding: 0; margin: 0; + /* need to read the offsetTop of tiles relative to this element in TimelineView */ + position: relative; } .RoomView_body > .Timeline > ul { diff --git a/src/platform/web/ui/session/room/TimelineView.ts b/src/platform/web/ui/session/room/TimelineView.ts index 8d95932f..06a2788e 100644 --- a/src/platform/web/ui/session/room/TimelineView.ts +++ b/src/platform/web/ui/session/room/TimelineView.ts @@ -91,7 +91,7 @@ export class TimelineView extends TemplateView { tiles.style.setProperty("margin-top", `${missingTilesHeight}px`); // we don't have enough tiles to fill the viewport, so set all as visible const len = this.value.tiles.length; - this.updateVisibleRange(0, len - 1, false); + this.updateVisibleRange(0, len - 1); } else { tiles.style.removeProperty("margin-top"); if (this.stickToBottom) { @@ -104,7 +104,7 @@ export class TimelineView extends TemplateView { timeline.scrollBy(0, bottomDiff); this.anchoredBottom = newAnchoredBottom; } else { - console.log("restore: bottom didn't change, must be below viewport"); + // console.log("restore: bottom didn't change, must be below viewport"); } } } @@ -122,22 +122,21 @@ export class TimelineView extends TemplateView { bottomNodeIndex = len - 1; } else { const viewportBottom = scrollTop + clientHeight; + // console.log(`viewportBottom: ${viewportBottom} (${scrollTop} + ${clientHeight})`); const anchoredNodeIndex = findFirstNodeIndexAtOrBelow(tiles, viewportBottom); this.anchoredNode = tiles.childNodes[anchoredNodeIndex] as HTMLElement; this.anchoredBottom = bottom(this.anchoredNode!); bottomNodeIndex = anchoredNodeIndex; } let topNodeIndex = findFirstNodeIndexAtOrBelow(tiles, scrollTop, bottomNodeIndex); - this.updateVisibleRange(topNodeIndex, bottomNodeIndex, true); + this.updateVisibleRange(topNodeIndex, bottomNodeIndex); } - private updateVisibleRange(startIndex: number, endIndex: number, isViewportFilled: boolean) { + private updateVisibleRange(startIndex: number, endIndex: number) { // 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); - //} + this.value.setVisibleTileRange(firstVisibleChild?.value, lastVisibleChild?.value); } }