diff --git a/src/domain/session/room/timeline/tiles/SimpleTile.js b/src/domain/session/room/timeline/tiles/SimpleTile.js index ddfa0e4e..48935948 100644 --- a/src/domain/session/room/timeline/tiles/SimpleTile.js +++ b/src/domain/session/room/timeline/tiles/SimpleTile.js @@ -69,4 +69,8 @@ export default class SimpleTile { get internalId() { return this._entry.asEventKey().toString(); } + + get isPending() { + return this._entry.isPending; + } } diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 05fcc3f5..5ca48561 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -1,32 +1,39 @@ -import { SortedArray } from "../../../observable/index.js"; +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, hsApi}) { + constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, user, hsApi}) { this._roomId = roomId; this._storage = storage; this._closeCallback = closeCallback; this._fragmentIdComparer = fragmentIdComparer; this._hsApi = hsApi; - this._entriesList = new SortedArray((a, b) => a.compare(b)); + this._remoteEntries = new SortedArray((a, b) => a.compare(b)); this._timelineReader = new TimelineReader({ roomId: this._roomId, storage: this._storage, fragmentIdComparer: this._fragmentIdComparer }); + const localEntries = new MappedList(pendingEvents, pe => { + return new PendingEventEntry({pendingEvent: pe, user}); + }, (pee, params) => { + pee.notifyUpdate(params); + }); + this._allEntries = new ConcatList(this._remoteEntries, localEntries); } /** @package */ async load() { const entries = await this._timelineReader.readFromEnd(50); - this._entriesList.setManySorted(entries); + this._remoteEntries.setManySorted(entries); } /** @package */ appendLiveEntries(newEntries) { - this._entriesList.setManySorted(newEntries); + this._remoteEntries.setManySorted(newEntries); } /** @public */ @@ -42,12 +49,12 @@ export default class Timeline { fragmentIdComparer: this._fragmentIdComparer }); const newEntries = await gapWriter.writeFragmentFill(fragmentEntry, response); - this._entriesList.setManySorted(newEntries); + this._remoteEntries.setManySorted(newEntries); } // tries to prepend `amount` entries to the `entries` list. async loadAtTop(amount) { - const firstEventEntry = this._entriesList.array.find(e => !!e.event); + const firstEventEntry = this._remoteEntries.array.find(e => !!e.event); if (!firstEventEntry) { return; } @@ -56,12 +63,12 @@ export default class Timeline { Direction.Backward, amount ); - this._entriesList.setManySorted(entries); + this._remoteEntries.setManySorted(entries); } /** @public */ get entries() { - return this._entriesList; + return this._allEntries; } /** @public */ diff --git a/src/matrix/room/timeline/entries/PendingEventEntry.js b/src/matrix/room/timeline/entries/PendingEventEntry.js index 4aa143d2..63e8ba84 100644 --- a/src/matrix/room/timeline/entries/PendingEventEntry.js +++ b/src/matrix/room/timeline/entries/PendingEventEntry.js @@ -39,7 +39,15 @@ export default class PendingEventEntry extends BaseEntry { return null; } + get isPending() { + return true; + } + get id() { return this._pendingEvent.txnId; } + + notifyUpdate() { + + } } diff --git a/src/ui/web/css/timeline.css b/src/ui/web/css/timeline.css index aea0be49..0b38857c 100644 --- a/src/ui/web/css/timeline.css +++ b/src/ui/web/css/timeline.css @@ -53,6 +53,10 @@ background-color: darkgreen; } +.TextMessageView.pending .message-container { + background-color: #333; +} + .message-container p { margin: 5px 0; } diff --git a/src/ui/web/session/room/timeline/TextMessageView.js b/src/ui/web/session/room/timeline/TextMessageView.js index 3d489c5c..a4d698eb 100644 --- a/src/ui/web/session/room/timeline/TextMessageView.js +++ b/src/ui/web/session/room/timeline/TextMessageView.js @@ -4,7 +4,7 @@ export default class TextMessageView extends TemplateView { render(t, vm) { // no bindings ... should this be a template view? return t.li( - {className: {"TextMessageView": true, own: vm.isOwn}}, + {className: {"TextMessageView": true, own: vm.isOwn, pending: vm.isPending}}, t.div({className: "message-container"}, [ t.div({className: "sender"}, vm => vm.isContinuation ? "" : vm.sender), t.p([vm.text, t.time(vm.date + " " + vm.time)]),