2019-02-27 22:50:08 +01:00
|
|
|
import { ObservableArray } from "../../observable/index.js";
|
|
|
|
|
|
|
|
export default class Timeline {
|
|
|
|
constructor({roomId, storage, closeCallback}) {
|
|
|
|
this._roomId = roomId;
|
|
|
|
this._storage = storage;
|
|
|
|
this._closeCallback = closeCallback;
|
|
|
|
this._entriesList = new ObservableArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @package */
|
|
|
|
async load() {
|
|
|
|
const txn = await this._storage.readTxn([this._storage.storeNames.roomTimeline]);
|
|
|
|
const entries = await txn.roomTimeline.lastEvents(this._roomId, 100);
|
|
|
|
for (const entry of entries) {
|
|
|
|
this._entriesList.append(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @package */
|
|
|
|
appendLiveEntries(newEntries) {
|
|
|
|
for (const entry of newEntries) {
|
|
|
|
this._entriesList.append(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-08 20:03:18 +01:00
|
|
|
/** @public */
|
|
|
|
async fillGap(gapEntry, 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({
|
|
|
|
roomId: this._roomId,
|
|
|
|
from: token,
|
|
|
|
dir: direction,
|
|
|
|
limit: amount
|
|
|
|
});
|
|
|
|
const newEntries = await this._persister.persistGapFill(gapEntry, response);
|
|
|
|
// find where to replace existing gap with newEntries by doing binary search
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-27 22:50:08 +01:00
|
|
|
/** @public */
|
|
|
|
get entries() {
|
|
|
|
return this._entriesList;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @public */
|
|
|
|
close() {
|
|
|
|
this._closeCallback();
|
|
|
|
}
|
|
|
|
}
|