diff --git a/src/matrix/room/BaseRoom.js b/src/matrix/room/BaseRoom.js index 7ee04761..1bee3823 100644 --- a/src/matrix/room/BaseRoom.js +++ b/src/matrix/room/BaseRoom.js @@ -21,7 +21,7 @@ import {RelationWriter} from "./timeline/persistence/RelationWriter.js"; import {Timeline} from "./timeline/Timeline.js"; import {FragmentIdComparer} from "./timeline/FragmentIdComparer.js"; import {WrappedError} from "../error.js" -import {fetchOrLoadMembers} from "./members/load.js"; +import {fetchOrLoadMembers, loadMember} from "./members/load.js"; import {MemberList} from "./members/MemberList.js"; import {Heroes} from "./members/Heroes.js"; import {EventEntry} from "./timeline/entries/EventEntry.js"; @@ -54,6 +54,7 @@ export class BaseRoom extends EventEmitter { this._observedEvents = null; this._powerLevels = null; this._powerLevelLoading = null; + this._observedMembers = null; } async _eventIdsToEntries(eventIds, txn) { @@ -214,6 +215,23 @@ export class BaseRoom extends EventEmitter { } } + async observeMember(userId) { + if (!this._observedMembers) { + this._observedMembers = new Map(); + } + const mapMember = this._observedMembers.get(userId); + if (mapMember) { + // Hit, we're already observing this member + return mapMember; + } + // Miss, load from storage and set in map + const member = await loadMember({roomId: this._roomId, userId, storage: this._storage}); + const observableMember = new RetainedObservableValue(member, () => this._observedMembers.delete(userId)); + this._observedMembers.set(userId, observableMember); + return observableMember; + } + + /** @public */ async loadMemberList(log = null) { if (this._memberList) { diff --git a/src/matrix/room/Room.js b/src/matrix/room/Room.js index a8e94326..c49d6a4e 100644 --- a/src/matrix/room/Room.js +++ b/src/matrix/room/Room.js @@ -209,6 +209,9 @@ export class Room extends BaseRoom { if (this._memberList) { this._memberList.afterSync(memberChanges); } + if (this._observedMembers) { + this._updateObservedMembers(memberChanges); + } if (this._timeline) { for (const [userId, memberChange] of memberChanges.entries()) { if (userId === this._user.id) { @@ -250,6 +253,15 @@ export class Room extends BaseRoom { } } + _updateObservedMembers(memberChanges) { + for (const [userId, memberChange] of memberChanges) { + const observableMember = this._observedMembers.get(userId); + if (observableMember) { + observableMember.set(memberChange.member); + } + } + } + needsAfterSyncCompleted({shouldFlushKeyShares}) { return shouldFlushKeyShares; } diff --git a/src/matrix/room/members/load.js b/src/matrix/room/members/load.js index 52ae58c4..eb4ca247 100644 --- a/src/matrix/room/members/load.js +++ b/src/matrix/room/members/load.js @@ -90,3 +90,9 @@ export async function fetchOrLoadMembers(options, logger) { return loadMembers(options); } } + +export async function loadMember({roomId, userId, storage}) { + const txn = await storage.readTxn([storage.storeNames.roomMembers,]); + const member = await txn.roomMembers.get(roomId, userId); + return new RoomMember(member); +}