From 05f05bb577a66b91c2fefe4b0049fccd64fea99e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 19 Jul 2021 19:36:09 +0530 Subject: [PATCH 1/7] Add method to get member from storage Signed-off-by: RMidhunSuresh --- src/matrix/room/BaseRoom.js | 20 +++++++++++++++++++- src/matrix/room/Room.js | 12 ++++++++++++ src/matrix/room/members/load.js | 6 ++++++ 3 files changed, 37 insertions(+), 1 deletion(-) 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); +} From 3aeb0c4d9899146376088f19705629c6fb37f130 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 21 Jul 2021 18:34:55 +0530 Subject: [PATCH 2/7] Indicate if no member found Signed-off-by: RMidhunSuresh --- src/matrix/room/BaseRoom.js | 3 +++ src/matrix/room/members/load.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/matrix/room/BaseRoom.js b/src/matrix/room/BaseRoom.js index 1bee3823..3314e9b1 100644 --- a/src/matrix/room/BaseRoom.js +++ b/src/matrix/room/BaseRoom.js @@ -226,6 +226,9 @@ export class BaseRoom extends EventEmitter { } // Miss, load from storage and set in map const member = await loadMember({roomId: this._roomId, userId, storage: this._storage}); + if (!member) { + return false; + } const observableMember = new RetainedObservableValue(member, () => this._observedMembers.delete(userId)); this._observedMembers.set(userId, observableMember); return observableMember; diff --git a/src/matrix/room/members/load.js b/src/matrix/room/members/load.js index eb4ca247..a7b2e641 100644 --- a/src/matrix/room/members/load.js +++ b/src/matrix/room/members/load.js @@ -94,5 +94,5 @@ export async function fetchOrLoadMembers(options, logger) { 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); + return member? new RoomMember(member) : undefined; } From 6cfb4cfbe02a87852497ac2f214c625a7b33b5eb Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 2 Aug 2021 17:50:09 +0530 Subject: [PATCH 3/7] Support state events Signed-off-by: RMidhunSuresh --- src/matrix/net/HomeServerApi.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index 02d4dc2d..a9b63f8e 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -130,6 +130,10 @@ export class HomeServerApi { {}, {}, options); } + state(roomId, eventType, stateKey, options = null) { + return this._get(`/rooms/${encodeURIComponent(roomId)}/state/${encodeURIComponent(eventType)}/${encodeURIComponent(stateKey)}`, {}, null, options); + } + passwordLogin(username, password, initialDeviceDisplayName, options = null) { return this._unauthedRequest("POST", this._url("/login"), null, { "type": "m.login.password", From bb68b4d3677658bbcd841ded2ebba1227852996e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 2 Aug 2021 22:50:02 +0530 Subject: [PATCH 4/7] Fetch member data from from state event if needed Signed-off-by: RMidhunSuresh --- src/matrix/room/BaseRoom.js | 12 +++++++++--- src/matrix/room/members/load.js | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/matrix/room/BaseRoom.js b/src/matrix/room/BaseRoom.js index 3314e9b1..47e4b390 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, loadMember} from "./members/load.js"; +import {fetchOrLoadMembers, fetchOrLoadMember} from "./members/load.js"; import {MemberList} from "./members/MemberList.js"; import {Heroes} from "./members/Heroes.js"; import {EventEntry} from "./timeline/entries/EventEntry.js"; @@ -224,8 +224,14 @@ export class BaseRoom extends EventEmitter { // 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}); + // Miss, load from storage/hs and set in map + const member = await fetchOrLoadMember({ + summary: this._summary, + roomId: this._roomId, + userId, + storage: this._storage, + hsApi: this._hsApi + }, this._platform.logger); if (!member) { return false; } diff --git a/src/matrix/room/members/load.js b/src/matrix/room/members/load.js index a7b2e641..8bd6c761 100644 --- a/src/matrix/room/members/load.js +++ b/src/matrix/room/members/load.js @@ -91,8 +91,39 @@ export async function fetchOrLoadMembers(options, logger) { } } -export async function loadMember({roomId, userId, storage}) { +export async function fetchOrLoadMember(options, logger) { + const member = await loadMember(options); + const {summary} = options; + if (!summary.data.hasFetchedMembers && !member) { + // We haven't fetched the memberlist yet; so ping the hs to see if this member does exist + return logger.wrapOrRun(options.log, "fetchMember", log => fetchMember(options, log)); + } + return member; +} + +async function loadMember({roomId, userId, storage}) { const txn = await storage.readTxn([storage.storeNames.roomMembers,]); const member = await txn.roomMembers.get(roomId, userId); return member? new RoomMember(member) : undefined; } + +async function fetchMember({roomId, userId, hsApi, storage}, log) { + const memberData = await hsApi.state(roomId, "m.room.member", userId, {log}).response(); + const member = new RoomMember({ + roomId, + userId, + membership: memberData.membership, + avatarUrl: memberData.avatar_url, + displayName: memberData.displayname, + }); + const txn = await storage.readWriteTxn([storage.storeNames.roomMembers]); + try { + txn.roomMembers.set(member.serialize()); + } + catch(e) { + txn.abort(); + throw e; + } + await txn.complete(); + return member; +} From e363d329217dff583ca8bf5a64743cbae4809759 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 2 Aug 2021 23:42:55 +0530 Subject: [PATCH 5/7] Return null on error Signed-off-by: RMidhunSuresh --- src/matrix/room/members/load.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/matrix/room/members/load.js b/src/matrix/room/members/load.js index 8bd6c761..fe1b1c59 100644 --- a/src/matrix/room/members/load.js +++ b/src/matrix/room/members/load.js @@ -108,7 +108,16 @@ async function loadMember({roomId, userId, storage}) { } async function fetchMember({roomId, userId, hsApi, storage}, log) { - const memberData = await hsApi.state(roomId, "m.room.member", userId, {log}).response(); + let memberData; + try { + memberData = await hsApi.state(roomId, "m.room.member", userId, { log }).response(); + } + catch (error) { + if (error.name === "HomeServerError" && error.errcode === "M_NOT_FOUND") { + return null; + } + throw error; + } const member = new RoomMember({ roomId, userId, From c9a4c393edf2f7a9fca65681f06f88db4abdbeb0 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 2 Aug 2021 23:51:19 +0530 Subject: [PATCH 6/7] Return null Signed-off-by: RMidhunSuresh --- src/matrix/room/BaseRoom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/room/BaseRoom.js b/src/matrix/room/BaseRoom.js index 47e4b390..b24ef706 100644 --- a/src/matrix/room/BaseRoom.js +++ b/src/matrix/room/BaseRoom.js @@ -233,7 +233,7 @@ export class BaseRoom extends EventEmitter { hsApi: this._hsApi }, this._platform.logger); if (!member) { - return false; + return null; } const observableMember = new RetainedObservableValue(member, () => this._observedMembers.delete(userId)); this._observedMembers.set(userId, observableMember); From 7e481080b539c664a43223f142dbaa65addefdc2 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 5 Aug 2021 16:32:06 +0530 Subject: [PATCH 7/7] Return null Signed-off-by: RMidhunSuresh --- src/matrix/room/members/load.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/room/members/load.js b/src/matrix/room/members/load.js index fe1b1c59..5077d793 100644 --- a/src/matrix/room/members/load.js +++ b/src/matrix/room/members/load.js @@ -104,7 +104,7 @@ export async function fetchOrLoadMember(options, logger) { async function loadMember({roomId, userId, storage}) { const txn = await storage.readTxn([storage.storeNames.roomMembers,]); const member = await txn.roomMembers.get(roomId, userId); - return member? new RoomMember(member) : undefined; + return member? new RoomMember(member) : null; } async function fetchMember({roomId, userId, hsApi, storage}, log) {