adjust Timeline to changes, gap persister
This commit is contained in:
parent
a6b17cf25a
commit
75100c1c60
2 changed files with 21 additions and 24 deletions
|
@ -1,7 +1,7 @@
|
||||||
import EventEmitter from "../../EventEmitter.js";
|
import EventEmitter from "../../EventEmitter.js";
|
||||||
import RoomSummary from "./summary.js";
|
import RoomSummary from "./summary.js";
|
||||||
import Timeline from "./timeline.js";
|
|
||||||
import SyncPersister from "./timeline/persistence/SyncPersister.js";
|
import SyncPersister from "./timeline/persistence/SyncPersister.js";
|
||||||
|
import Timeline from "./timeline/Timeline.js";
|
||||||
import FragmentIdComparer from "./timeline/FragmentIdComparer.js";
|
import FragmentIdComparer from "./timeline/FragmentIdComparer.js";
|
||||||
|
|
||||||
export default class Room extends EventEmitter {
|
export default class Room extends EventEmitter {
|
||||||
|
@ -54,6 +54,7 @@ export default class Room extends EventEmitter {
|
||||||
roomId: this.id,
|
roomId: this.id,
|
||||||
storage: this._storage,
|
storage: this._storage,
|
||||||
hsApi: this._hsApi,
|
hsApi: this._hsApi,
|
||||||
|
fragmentIdComparer: this._fragmentIdComparer,
|
||||||
closeCallback: () => this._timeline = null,
|
closeCallback: () => this._timeline = null,
|
||||||
});
|
});
|
||||||
await this._timeline.load();
|
await this._timeline.load();
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
import { ObservableArray } from "../../observable/index.js";
|
import { ObservableArray } from "../../../observable/index.js";
|
||||||
import sortedIndex from "../../utils/sortedIndex.js";
|
import sortedIndex from "../../../utils/sortedIndex.js";
|
||||||
|
import GapPersister from "./persistence/GapPersister.js";
|
||||||
|
|
||||||
export default class Timeline {
|
export default class Timeline {
|
||||||
constructor({roomId, storage, closeCallback}) {
|
constructor({roomId, storage, closeCallback, fragmentIdComparer}) {
|
||||||
this._roomId = roomId;
|
this._roomId = roomId;
|
||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
this._closeCallback = closeCallback;
|
this._closeCallback = closeCallback;
|
||||||
this._entriesList = new ObservableArray();
|
this._entriesList = new ObservableArray();
|
||||||
|
this._fragmentIdComparer = fragmentIdComparer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @package */
|
/** @package */
|
||||||
async load() {
|
async load() {
|
||||||
const txn = await this._storage.readTxn([this._storage.storeNames.roomTimeline]);
|
const txn = await this._storage.readTxn([this._storage.storeNames.timelineEvents]);
|
||||||
const entries = await txn.roomTimeline.lastEvents(this._roomId, 100);
|
const entries = await txn.roomTimeline.lastEvents(this._roomId, 100);
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
this._entriesList.append(entry);
|
this._entriesList.append(entry);
|
||||||
|
@ -26,31 +28,25 @@ export default class Timeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
async fillGap(gapEntry, amount) {
|
async fillGap(fragmentEntry, amount) {
|
||||||
const gap = gapEntry.gap;
|
|
||||||
let direction;
|
|
||||||
if (gap.prev_batch) {
|
|
||||||
direction = "b";
|
|
||||||
} else if (gap.next_batch) {
|
|
||||||
direction = "f";
|
|
||||||
} else {
|
|
||||||
throw new Error("Invalid gap, no prev_batch or next_batch field: " + JSON.stringify(gapEntry.gap));
|
|
||||||
}
|
|
||||||
const token = gap.prev_batch || gap.next_batch;
|
|
||||||
|
|
||||||
const response = await this._hsApi.messages(this._roomId, {
|
const response = await this._hsApi.messages(this._roomId, {
|
||||||
from: token,
|
from: fragmentEntry.token,
|
||||||
dir: direction,
|
dir: fragmentEntry.direction.asApiString(),
|
||||||
limit: amount
|
limit: amount
|
||||||
});
|
});
|
||||||
|
|
||||||
const newEntries = await this._persister.persistGapFill(gapEntry, response);
|
const gapPersister = new GapPersister({
|
||||||
|
roomId: this._roomId,
|
||||||
|
storage: this._storage,
|
||||||
|
fragmentIdComparer: this._fragmentIdComparer
|
||||||
|
});
|
||||||
|
const newEntries = await gapPersister.persistFragmentFill(fragmentEntry, response);
|
||||||
// find where to replace existing gap with newEntries by doing binary search
|
// find where to replace existing gap with newEntries by doing binary search
|
||||||
const gapIdx = sortedIndex(this._entriesList.array, gapEntry.sortKey, (key, entry) => {
|
const gapIdx = sortedIndex(this._entriesList.array, fragmentEntry, (fragmentEntry, entry) => {
|
||||||
return key.compare(entry.sortKey);
|
return fragmentEntry.compare(entry);
|
||||||
});
|
});
|
||||||
// only replace the gap if it's currently in the timeline
|
// only replace the gap if it's currently in the timeline
|
||||||
if (this._entriesList.at(gapIdx) === gapEntry) {
|
if (this._entriesList.at(gapIdx) === fragmentEntry) {
|
||||||
this._entriesList.removeAt(gapIdx);
|
this._entriesList.removeAt(gapIdx);
|
||||||
this._entriesList.insertMany(gapIdx, newEntries);
|
this._entriesList.insertMany(gapIdx, newEntries);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +55,7 @@ export default class Timeline {
|
||||||
async loadAtTop(amount) {
|
async loadAtTop(amount) {
|
||||||
const firstEntry = this._entriesList.at(0);
|
const firstEntry = this._entriesList.at(0);
|
||||||
if (firstEntry) {
|
if (firstEntry) {
|
||||||
const txn = await this._storage.readTxn([this._storage.storeNames.roomTimeline]);
|
const txn = await this._storage.readTxn([this._storage.storeNames.timelineEvents]);
|
||||||
const topEntries = await txn.roomTimeline.eventsBefore(this._roomId, firstEntry.sortKey, amount);
|
const topEntries = await txn.roomTimeline.eventsBefore(this._roomId, firstEntry.sortKey, amount);
|
||||||
this._entriesList.insertMany(0, topEntries);
|
this._entriesList.insertMany(0, topEntries);
|
||||||
return topEntries.length;
|
return topEntries.length;
|
Reference in a new issue