From b012b1dc993f9df27c709658033569c9632f94d7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 3 Mar 2021 14:53:22 +0100 Subject: [PATCH] Show correct profile for pending messages --- src/matrix/room/Room.js | 11 ++++++++-- src/matrix/room/timeline/Timeline.js | 21 +++++++++++++++---- .../timeline/entries/PendingEventEntry.js | 15 ++++++++++--- .../timeline/persistence/TimelineReader.js | 10 ++++----- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/matrix/room/Room.js b/src/matrix/room/Room.js index 89653b62..2497f0b9 100644 --- a/src/matrix/room/Room.js +++ b/src/matrix/room/Room.js @@ -313,6 +313,14 @@ export class Room extends EventEmitter { if (this._memberList) { this._memberList.afterSync(memberChanges); } + if (this._timeline) { + for (const [userId, memberChange] of memberChanges.entries()) { + if (userId === this._user.id) { + this._timeline.updateOwnMember(memberChange.member); + break; + } + } + } } let emitChange = false; if (summaryChanges) { @@ -646,14 +654,13 @@ export class Room extends EventEmitter { this._roomEncryption.notifyTimelineClosed(); } }, - user: this._user, clock: this._platform.clock, logger: this._platform.logger, }); if (this._roomEncryption) { this._timeline.enableEncryption(this._decryptEntries.bind(this, DecryptionSource.Timeline)); } - await this._timeline.load(); + await this._timeline.load(this._user); return this._timeline; }); } diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 7e2d2110..6389461a 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -19,15 +19,17 @@ import {Disposables} from "../../../utils/Disposables.js"; import {Direction} from "./Direction.js"; import {TimelineReader} from "./persistence/TimelineReader.js"; import {PendingEventEntry} from "./entries/PendingEventEntry.js"; +import {RoomMember} from "../members/RoomMember.js"; export class Timeline { - constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, user, clock}) { + constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, clock}) { this._roomId = roomId; this._storage = storage; this._closeCallback = closeCallback; this._fragmentIdComparer = fragmentIdComparer; this._disposables = new Disposables(); this._remoteEntries = new SortedArray((a, b) => a.compare(b)); + this._ownMember = null; this._timelineReader = new TimelineReader({ roomId: this._roomId, storage: this._storage, @@ -35,7 +37,7 @@ export class Timeline { }); this._readerRequest = null; const localEntries = new MappedList(pendingEvents, pe => { - return new PendingEventEntry({pendingEvent: pe, user, clock}); + return new PendingEventEntry({pendingEvent: pe, member: this._ownMember, clock}); }, (pee, params) => { pee.notifyUpdate(params); }); @@ -43,9 +45,16 @@ export class Timeline { } /** @package */ - async load() { + async load(user) { + const txn = this._storage.readTxn(this._timelineReader.readTxnStores.concat(this._storage.storeNames.roomMembers)); + const memberData = await txn.roomMembers.get(this._roomId, user.id); + this._ownMember = new RoomMember(memberData); + // it should be fine to not update the local entries, + // as they should only populate once the view subscribes to it + // if they are populated already, the sender profile would be empty + // 30 seems to be a good amount to fill the entire screen - const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30)); + const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30, txn)); try { const entries = await readerRequest.complete(); this._remoteEntries.setManySorted(entries); @@ -54,6 +63,10 @@ export class Timeline { } } + updateOwnMember(member) { + this._ownMember = member; + } + replaceEntries(entries) { for (const entry of entries) { this._remoteEntries.replace(entry); diff --git a/src/matrix/room/timeline/entries/PendingEventEntry.js b/src/matrix/room/timeline/entries/PendingEventEntry.js index eff14cb5..7a22d426 100644 --- a/src/matrix/room/timeline/entries/PendingEventEntry.js +++ b/src/matrix/room/timeline/entries/PendingEventEntry.js @@ -17,10 +17,11 @@ limitations under the License. import {BaseEntry, PENDING_FRAGMENT_ID} from "./BaseEntry.js"; export class PendingEventEntry extends BaseEntry { - constructor({pendingEvent, user, clock}) { + constructor({pendingEvent, member, clock}) { super(null); this._pendingEvent = pendingEvent; - this._user = user; + /** @type {RoomMember} */ + this._member = member; this._clock = clock; } @@ -49,7 +50,15 @@ export class PendingEventEntry extends BaseEntry { } get sender() { - return this._user.id; + return this._member?.userId; + } + + get displayName() { + return this._member?.name; + } + + get avatarUrl() { + return this._member?.avatarUrl; } get timestamp() { diff --git a/src/matrix/room/timeline/persistence/TimelineReader.js b/src/matrix/room/timeline/persistence/TimelineReader.js index 7493727c..b4e18cf4 100644 --- a/src/matrix/room/timeline/persistence/TimelineReader.js +++ b/src/matrix/room/timeline/persistence/TimelineReader.js @@ -95,7 +95,7 @@ export class TimelineReader { this._decryptEntries = decryptEntries; } - _openTxn() { + get readTxnStores() { const stores = [ this._storage.storeNames.timelineEvents, this._storage.storeNames.timelineFragments, @@ -103,19 +103,19 @@ export class TimelineReader { if (this._decryptEntries) { stores.push(this._storage.storeNames.inboundGroupSessions); } - return this._storage.readTxn(stores); + return stores; } readFrom(eventKey, direction, amount) { return new ReaderRequest(async r => { - const txn = this._openTxn(); + const txn = this._storage.readTxn(this.readTxnStores); return await this._readFrom(eventKey, direction, amount, r, txn); }); } - readFromEnd(amount) { + readFromEnd(amount, existingTxn = null) { return new ReaderRequest(async r => { - const txn = this._openTxn(); + const txn = existingTxn || this._storage.readTxn(this.readTxnStores); const liveFragment = await txn.timelineFragments.liveFragment(this._roomId); let entries; // room hasn't been synced yet