This commit is contained in:
Bruno Windels 2021-09-10 14:47:05 +02:00
parent 98cc1e2715
commit 9411e6f065
4 changed files with 19 additions and 18 deletions

View file

@ -34,8 +34,6 @@ when loading, it just reads events from a sortkey backwards or forwards...
import {TilesCollection} from "./TilesCollection.js"; import {TilesCollection} from "./TilesCollection.js";
import {ViewModel} from "../../../ViewModel.js"; import {ViewModel} from "../../../ViewModel.js";
export class TimelineViewModel extends ViewModel { export class TimelineViewModel extends ViewModel {
constructor(options) { constructor(options) {
super(options); super(options);
@ -45,7 +43,6 @@ export class TimelineViewModel extends ViewModel {
this._startTile = null; this._startTile = null;
this._endTile = null; this._endTile = null;
this._topLoadingPromise = null; this._topLoadingPromise = null;
this._bottomLoadingPromise = null;
this._requestedStartTile = null; this._requestedStartTile = null;
this._requestedEndTile = null; this._requestedEndTile = null;
this._requestScheduled = false; this._requestScheduled = false;
@ -56,7 +53,7 @@ export class TimelineViewModel extends ViewModel {
this._requestedStartTile = startTile; this._requestedStartTile = startTile;
this._requestedEndTile = endTile; this._requestedEndTile = endTile;
if (!this._requestScheduled) { if (!this._requestScheduled) {
Promise.resolve().then(() => { requestIdleCallback(() => {
this._setVisibleTileRange(this._requestedStartTile, this._requestedEndTile); this._setVisibleTileRange(this._requestedStartTile, this._requestedEndTile);
this._requestScheduled = false; this._requestScheduled = false;
}); });
@ -72,14 +69,15 @@ export class TimelineViewModel extends ViewModel {
this._endTile = endTile; this._endTile = endTile;
const startIndex = this._tiles.getTileIndex(this._startTile); const startIndex = this._tiles.getTileIndex(this._startTile);
const endIndex = this._tiles.getTileIndex(this._endTile); 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(); tile.notifyVisible();
} }
loadTop = startIndex < 5; loadTop = startIndex < 10;
console.log("got tiles", startIndex, endIndex, loadTop); // console.log("got tiles", startIndex, endIndex, loadTop);
} else { } else {
// tiles collection is empty, load more at top
loadTop = true; loadTop = true;
console.log("no tiles, load more at top"); // console.log("no tiles, load more at top");
} }
if (loadTop && !this._topLoadingPromise) { if (loadTop && !this._topLoadingPromise) {
@ -91,7 +89,7 @@ export class TimelineViewModel extends ViewModel {
} }
}); });
} else if (loadTop) { } else if (loadTop) {
console.log("loadTop is true but already loading"); // console.log("loadTop is true but already loading");
} }
} }

View file

@ -72,8 +72,10 @@ export class Timeline {
// as they should only populate once the view subscribes to it // as they should only populate once the view subscribes to it
// if they are populated already, the sender profile would be empty // if they are populated already, the sender profile would be empty
// 30 seems to be a good amount to fill the entire screen // choose good amount here between showing messages initially and
const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30, txn, log)); // 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 { try {
const entries = await readerRequest.complete(); const entries = await readerRequest.complete();
this._setupEntries(entries); this._setupEntries(entries);

View file

@ -20,6 +20,8 @@ limitations under the License.
overscroll-behavior: contain; overscroll-behavior: contain;
padding: 0; padding: 0;
margin: 0; margin: 0;
/* need to read the offsetTop of tiles relative to this element in TimelineView */
position: relative;
} }
.RoomView_body > .Timeline > ul { .RoomView_body > .Timeline > ul {

View file

@ -91,7 +91,7 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
tiles.style.setProperty("margin-top", `${missingTilesHeight}px`); tiles.style.setProperty("margin-top", `${missingTilesHeight}px`);
// we don't have enough tiles to fill the viewport, so set all as visible // we don't have enough tiles to fill the viewport, so set all as visible
const len = this.value.tiles.length; const len = this.value.tiles.length;
this.updateVisibleRange(0, len - 1, false); this.updateVisibleRange(0, len - 1);
} else { } else {
tiles.style.removeProperty("margin-top"); tiles.style.removeProperty("margin-top");
if (this.stickToBottom) { if (this.stickToBottom) {
@ -104,7 +104,7 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
timeline.scrollBy(0, bottomDiff); timeline.scrollBy(0, bottomDiff);
this.anchoredBottom = newAnchoredBottom; this.anchoredBottom = newAnchoredBottom;
} else { } 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<TimelineViewModel> {
bottomNodeIndex = len - 1; bottomNodeIndex = len - 1;
} else { } else {
const viewportBottom = scrollTop + clientHeight; const viewportBottom = scrollTop + clientHeight;
// console.log(`viewportBottom: ${viewportBottom} (${scrollTop} + ${clientHeight})`);
const anchoredNodeIndex = findFirstNodeIndexAtOrBelow(tiles, viewportBottom); const anchoredNodeIndex = findFirstNodeIndexAtOrBelow(tiles, viewportBottom);
this.anchoredNode = tiles.childNodes[anchoredNodeIndex] as HTMLElement; this.anchoredNode = tiles.childNodes[anchoredNodeIndex] as HTMLElement;
this.anchoredBottom = bottom(this.anchoredNode!); this.anchoredBottom = bottom(this.anchoredNode!);
bottomNodeIndex = anchoredNodeIndex; bottomNodeIndex = anchoredNodeIndex;
} }
let topNodeIndex = findFirstNodeIndexAtOrBelow(tiles, scrollTop, bottomNodeIndex); 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 // can be undefined, meaning the tiles collection is still empty
const firstVisibleChild = this.tilesView!.getChildInstanceByIndex(startIndex); const firstVisibleChild = this.tilesView!.getChildInstanceByIndex(startIndex);
const lastVisibleChild = this.tilesView!.getChildInstanceByIndex(endIndex); const lastVisibleChild = this.tilesView!.getChildInstanceByIndex(endIndex);
//if (firstVisibleChild && lastVisibleChild) { this.value.setVisibleTileRange(firstVisibleChild?.value, lastVisibleChild?.value);
this.value.setVisibleTileRange(firstVisibleChild?.value, lastVisibleChild?.value, isViewportFilled);
//}
} }
} }