forked from mystiq/hydrogen-web
mark fragment in storage when start of timeline is reached
so we don't keep looping to fetch more messages when scrolled all the way up
This commit is contained in:
parent
1261ac05d1
commit
37597e2acb
6 changed files with 44 additions and 5 deletions
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -42,13 +43,16 @@ export class TimelineViewModel {
|
||||||
this._tiles = new TilesCollection(timeline.entries, tilesCreator({room, ownUserId}));
|
this._tiles = new TilesCollection(timeline.entries, tilesCreator({room, ownUserId}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// doesn't fill gaps, only loads stored entries/tiles
|
/**
|
||||||
loadAtTop() {
|
* @return {bool} startReached if the start of the timeline was reached
|
||||||
|
*/
|
||||||
|
async loadAtTop() {
|
||||||
const firstTile = this._tiles.getFirst();
|
const firstTile = this._tiles.getFirst();
|
||||||
if (firstTile.shape === "gap") {
|
if (firstTile.shape === "gap") {
|
||||||
return firstTile.fill();
|
return firstTile.fill();
|
||||||
} else {
|
} else {
|
||||||
return this._timeline.loadAtTop(50);
|
await this._timeline.loadAtTop(50);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ export class GapTile extends SimpleTile {
|
||||||
this.emitChange("isLoading");
|
this.emitChange("isLoading");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// edgeReached will have been updated by fillGap
|
||||||
|
return this._entry.edgeReached;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateEntry(entry, params) {
|
updateEntry(entry, params) {
|
||||||
|
|
|
@ -83,6 +83,9 @@ export class Room extends EventEmitter {
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
async fillGap(fragmentEntry, amount) {
|
async fillGap(fragmentEntry, amount) {
|
||||||
|
if (fragmentEntry.edgeReached) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const response = await this._hsApi.messages(this._roomId, {
|
const response = await this._hsApi.messages(this._roomId, {
|
||||||
from: fragmentEntry.token,
|
from: fragmentEntry.token,
|
||||||
dir: fragmentEntry.direction.asApiString(),
|
dir: fragmentEntry.direction.asApiString(),
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class FragmentBoundaryEntry extends BaseEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
get isGap() {
|
get isGap() {
|
||||||
return !!this.token;
|
return !!this.token && !this.edgeReached;
|
||||||
}
|
}
|
||||||
|
|
||||||
get token() {
|
get token() {
|
||||||
|
@ -79,6 +79,25 @@ export class FragmentBoundaryEntry extends BaseEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get edgeReached() {
|
||||||
|
if (this.started) {
|
||||||
|
return this.fragment.startReached;
|
||||||
|
} else {
|
||||||
|
return this.fragment.endReached;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set edgeReached(reached) {
|
||||||
|
|
||||||
|
if (this.started) {
|
||||||
|
this.fragment.startReached = reached;
|
||||||
|
} else {
|
||||||
|
this.fragment.endReached = reached;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
get linkedFragmentId() {
|
get linkedFragmentId() {
|
||||||
if (this.started) {
|
if (this.started) {
|
||||||
return this.fragment.previousId;
|
return this.fragment.previousId;
|
||||||
|
|
|
@ -178,6 +178,14 @@ export class GapWriter {
|
||||||
if (fragmentEntry.token !== start) {
|
if (fragmentEntry.token !== start) {
|
||||||
throw new Error("start is not equal to prev_batch or next_batch");
|
throw new Error("start is not equal to prev_batch or next_batch");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// begin (or end) of timeline reached
|
||||||
|
if (chunk.length === 0) {
|
||||||
|
fragmentEntry.edgeReached = true;
|
||||||
|
await txn.timelineFragments.update(fragmentEntry.fragment);
|
||||||
|
return {entries: [fragmentEntry], fragments: []};
|
||||||
|
}
|
||||||
|
|
||||||
// find last event in fragment so we get the eventIndex to begin creating keys at
|
// find last event in fragment so we get the eventIndex to begin creating keys at
|
||||||
let lastKey = await this._findFragmentEdgeEventKey(fragmentEntry, txn);
|
let lastKey = await this._findFragmentEdgeEventKey(fragmentEntry, txn);
|
||||||
// find out if any event in chunk is already present using findFirstOrLastOccurringEventId
|
// find out if any event in chunk is already present using findFirstOrLastOccurringEventId
|
||||||
|
|
|
@ -45,7 +45,10 @@ export class TimelineList extends ListView {
|
||||||
while (predicate()) {
|
while (predicate()) {
|
||||||
// fill, not enough content to fill timeline
|
// fill, not enough content to fill timeline
|
||||||
this._topLoadingPromise = this._viewModel.loadAtTop();
|
this._topLoadingPromise = this._viewModel.loadAtTop();
|
||||||
await this._topLoadingPromise;
|
const startReached = await this._topLoadingPromise;
|
||||||
|
if (startReached) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
|
|
Loading…
Reference in a new issue