diff --git a/src/matrix/room/timeline/FragmentIdComparer.js b/src/matrix/room/timeline/FragmentIdComparer.js index d88b257b..d1a11564 100644 --- a/src/matrix/room/timeline/FragmentIdComparer.js +++ b/src/matrix/room/timeline/FragmentIdComparer.js @@ -78,6 +78,14 @@ function createIslands(fragments) { return islands.map(a => new Island(a)); } +class Fragment { + constructor(id, previousId, nextId) { + this.id = id; + this.previousId = previousId; + this.nextId = nextId; + } +} + class Island { constructor(sortedFragments) { this._idToSortIndex = new Map(); @@ -134,13 +142,6 @@ export default class FragmentIdComparer { rebuild(fragments) { const islands = createIslands(fragments); - const fragmentJson = JSON.stringify(islands.map(i => { - return Array.from(i._idToSortIndex.entries()) - .map(([id, idx]) => {return {id, idx};}) - .sort((a, b) => a.idx - b.idx); - })); - const firstFragment = this._fragmentsById.values().next().value; - console.log("rebuilt fragment index", firstFragment && firstFragment.roomId, fragmentJson); this._idToIsland = new Map(); for(let island of islands) { for(let id of island.fragmentIds) { @@ -149,8 +150,32 @@ export default class FragmentIdComparer { } } + /** use for fragments coming out of persistence, not newly created ones, or also fragments for a new island (like for a permalink) */ add(fragment) { - this._fragmentsById.set(fragment.id, fragment); + const copy = new Fragment(fragment.id, fragment.previousId, fragment.nextId); + this._fragmentsById.set(fragment.id, copy); + this.rebuild(this._fragmentsById.values()); + } + + /** use for appending newly created fragments */ + append(id, previousId) { + const fragment = new Fragment(id, previousId, null); + const prevFragment = this._fragmentsById.get(previousId); + if (prevFragment) { + prevFragment.nextId = id; + } + this._fragmentsById.set(id, fragment); + this.rebuild(this._fragmentsById.values()); + } + + /** use for prepending newly created fragments */ + prepend(id, nextId) { + const fragment = new Fragment(id, null, nextId); + const nextFragment = this._fragmentsById.get(nextId); + if (nextFragment) { + nextFragment.previousId = id; + } + this._fragmentsById.set(id, fragment); this.rebuild(this._fragmentsById.values()); } } @@ -254,6 +279,22 @@ export function tests() { assert.throws(() => index.compare(1, 2)); assert(index.compare(11, 12) < 0); }, + test_append(assert) { + const index = new FragmentIdComparer([]); + // add livefragment when opening timeline, + // note that there is no nextId as the sync + // hasn't come in yet + index.add({id: 1}); + // now sync comes in and replaces the live fragment + index.append(2, 1); + assert(index.compare(1, 2) < 0); + }, + test_prepend(assert) { + const index = new FragmentIdComparer([]); + index.add({id: 2}); + index.prepend(1, 2); + assert(index.compare(1, 2) < 0); + } } } //#endif diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 353b8634..99828479 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -33,13 +33,7 @@ export default class Timeline { /** @package */ appendLiveEntries(newEntries) { - try { - this._remoteEntries.setManySorted(newEntries); - } catch (err) { - console.error("error while appending live entries in roomId", this._roomId); - console.error(err.stack); - throw err; - } + this._remoteEntries.setManySorted(newEntries); } /** @public */ diff --git a/src/matrix/room/timeline/persistence/SyncWriter.js b/src/matrix/room/timeline/persistence/SyncWriter.js index be7d8f9b..8143ced0 100644 --- a/src/matrix/room/timeline/persistence/SyncWriter.js +++ b/src/matrix/room/timeline/persistence/SyncWriter.js @@ -77,7 +77,7 @@ export default class SyncWriter { nextToken: null }; txn.timelineFragments.add(newFragment); - this._fragmentIdComparer.add(newFragment); + this._fragmentIdComparer.append(newFragmentId, oldFragmentId); return {oldFragment, newFragment}; }