diff --git a/src/domain/session/room/RoomViewModel.js b/src/domain/session/room/RoomViewModel.js index 09de2b8b..cb6e6119 100644 --- a/src/domain/session/room/RoomViewModel.js +++ b/src/domain/session/room/RoomViewModel.js @@ -18,7 +18,7 @@ export default class RoomViewModel extends EventEmitter { this._room.on("change", this._onRoomChange); try { this._timeline = await this._room.openTimeline(); - this._timelineVM = new TimelineViewModel(this._timeline, this._ownUserId); + this._timelineVM = new TimelineViewModel(this._room, this._timeline, this._ownUserId); this.emit("change", "timelineViewModel"); } catch (err) { console.error(`room.openTimeline(): ${err.message}:\n${err.stack}`); diff --git a/src/domain/session/room/timeline/TimelineViewModel.js b/src/domain/session/room/timeline/TimelineViewModel.js index 622ab1cb..2e952a76 100644 --- a/src/domain/session/room/timeline/TimelineViewModel.js +++ b/src/domain/session/room/timeline/TimelineViewModel.js @@ -18,12 +18,12 @@ import TilesCollection from "./TilesCollection.js"; import tilesCreator from "./tilesCreator.js"; export default class TimelineViewModel { - constructor(timeline, ownUserId) { + constructor(room, timeline, ownUserId) { this._timeline = timeline; // once we support sending messages we could do // timeline.entries.concat(timeline.pendingEvents) // for an ObservableList that also contains local echos - this._tiles = new TilesCollection(timeline.entries, tilesCreator({timeline, ownUserId})); + this._tiles = new TilesCollection(timeline.entries, tilesCreator({room, ownUserId})); } // doesn't fill gaps, only loads stored entries/tiles diff --git a/src/domain/session/room/timeline/tilesCreator.js b/src/domain/session/room/timeline/tilesCreator.js index 9f583650..87d70238 100644 --- a/src/domain/session/room/timeline/tilesCreator.js +++ b/src/domain/session/room/timeline/tilesCreator.js @@ -4,11 +4,11 @@ import LocationTile from "./tiles/LocationTile.js"; import RoomNameTile from "./tiles/RoomNameTile.js"; import RoomMemberTile from "./tiles/RoomMemberTile.js"; -export default function ({timeline, ownUserId}) { +export default function ({room, ownUserId}) { return function tilesCreator(entry, emitUpdate) { const options = {entry, emitUpdate, ownUserId}; if (entry.isGap) { - return new GapTile(options, timeline); + return new GapTile(options, room); } else if (entry.eventType) { switch (entry.eventType) { case "m.room.message": { diff --git a/src/matrix/room/room.js b/src/matrix/room/room.js index d493bc00..530e42fd 100644 --- a/src/matrix/room/room.js +++ b/src/matrix/room/room.js @@ -1,6 +1,7 @@ import EventEmitter from "../../EventEmitter.js"; import RoomSummary from "./summary.js"; import SyncWriter from "./timeline/persistence/SyncWriter.js"; +import GapWriter from "./timeline/persistence/GapWriter.js"; import Timeline from "./timeline/Timeline.js"; import FragmentIdComparer from "./timeline/FragmentIdComparer.js"; import SendQueue from "./sending/SendQueue.js"; @@ -58,6 +59,26 @@ export default class Room extends EventEmitter { this._sendQueue.enqueueEvent(eventType, content); } + + /** @public */ + async fillGap(fragmentEntry, amount) { + const response = await this._hsApi.messages(this._roomId, { + from: fragmentEntry.token, + dir: fragmentEntry.direction.asApiString(), + limit: amount, + filter: {lazy_load_members: true} + }).response(); + const gapWriter = new GapWriter({ + roomId: this._roomId, + storage: this._storage, + fragmentIdComparer: this._fragmentIdComparer + }); + const newEntries = await gapWriter.writeFragmentFill(fragmentEntry, response); + if (this._timeline) { + this._timeline.addGapEntries(newEntries) + } + } + get name() { return this._summary.name; } @@ -73,7 +94,6 @@ export default class Room extends EventEmitter { this._timeline = new Timeline({ roomId: this.id, storage: this._storage, - hsApi: this._hsApi, fragmentIdComparer: this._fragmentIdComparer, pendingEvents: this._sendQueue.pendingEvents, closeCallback: () => this._timeline = null, diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 99828479..a13fa304 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -1,16 +1,14 @@ import { SortedArray, MappedList, ConcatList } from "../../../observable/index.js"; import Direction from "./Direction.js"; -import GapWriter from "./persistence/GapWriter.js"; import TimelineReader from "./persistence/TimelineReader.js"; import PendingEventEntry from "./entries/PendingEventEntry.js"; export default class Timeline { - constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, user, hsApi}) { + constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, user}) { this._roomId = roomId; this._storage = storage; this._closeCallback = closeCallback; this._fragmentIdComparer = fragmentIdComparer; - this._hsApi = hsApi; this._remoteEntries = new SortedArray((a, b) => a.compare(b)); this._timelineReader = new TimelineReader({ roomId: this._roomId, @@ -36,23 +34,11 @@ export default class Timeline { this._remoteEntries.setManySorted(newEntries); } - /** @public */ - async fillGap(fragmentEntry, amount) { - const response = await this._hsApi.messages(this._roomId, { - from: fragmentEntry.token, - dir: fragmentEntry.direction.asApiString(), - limit: amount, - filter: {lazy_load_members: true} - }).response(); - const gapWriter = new GapWriter({ - roomId: this._roomId, - storage: this._storage, - fragmentIdComparer: this._fragmentIdComparer - }); - const newEntries = await gapWriter.writeFragmentFill(fragmentEntry, response); + /** @package */ + addGapEntries(newEntries) { this._remoteEntries.setManySorted(newEntries); } - + // tries to prepend `amount` entries to the `entries` list. async loadAtTop(amount) { const firstEventEntry = this._remoteEntries.array.find(e => !!e.eventType);