if we don't have our own member yet, fetch it from the server and store
This commit is contained in:
parent
d94aeff98c
commit
be3d734319
4 changed files with 62 additions and 10 deletions
|
@ -189,6 +189,10 @@ export class HomeServerApi {
|
|||
return this._get(`/rooms/${encodeURIComponent(roomId)}/messages`, params, null, options);
|
||||
}
|
||||
|
||||
roomState(roomId, eventType, stateKey, options = null) {
|
||||
return this._get(`/rooms/${encodeURIComponent(roomId)}/state/${encodeURIComponent(eventType)}/${encodeURIComponent(stateKey)}`, null, null, options);
|
||||
}
|
||||
|
||||
// params is at, membership and not_membership
|
||||
members(roomId, params, options = null) {
|
||||
return this._get(`/rooms/${encodeURIComponent(roomId)}/members`, params, null, options);
|
||||
|
|
|
@ -425,8 +425,13 @@ export class Room extends EventEmitter {
|
|||
|
||||
/** @public */
|
||||
sendEvent(eventType, content, attachments, log = null) {
|
||||
this._platform.logger.wrapOrRun(log, "send", log => {
|
||||
this._platform.logger.wrapOrRun(log, "send", async log => {
|
||||
log.set("id", this.id);
|
||||
if (this._timeline) {
|
||||
// ensure we have our own member loaded for the local echo
|
||||
await this._timeline.ensureOwnMember(
|
||||
this._user, this._summary.data.membership, this._hsApi, log);
|
||||
}
|
||||
return this._sendQueue.enqueueEvent(eventType, content, attachments, log);
|
||||
});
|
||||
}
|
||||
|
@ -678,7 +683,12 @@ export class Room extends EventEmitter {
|
|||
if (this._roomEncryption) {
|
||||
this._timeline.enableEncryption(this._decryptEntries.bind(this, DecryptionSource.Timeline));
|
||||
}
|
||||
await this._timeline.load(this._user, log);
|
||||
if (this._sendQueue.pendingEvents.length !== 0) {
|
||||
// ensure we have our own member loaded for the local echo
|
||||
await this._timeline.ensureOwnMember(
|
||||
this._user, this._summary.data.membership, this._hsApi, log);
|
||||
}
|
||||
await this._timeline.load(log);
|
||||
return this._timeline;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,6 +23,15 @@ export class RoomMember {
|
|||
this._data = data;
|
||||
}
|
||||
|
||||
static async fromFetch(roomId, userId, hsApi, log) {
|
||||
const memberEvent = await hsApi.roomState(this._roomId, EVENT_TYPE, userId, {log}).response();
|
||||
return RoomMember.fromMemberEvent(memberEvent);
|
||||
}
|
||||
|
||||
static fromUserId(roomId, userId, membership) {
|
||||
return new RoomMember({roomId, userId, membership});
|
||||
}
|
||||
|
||||
static fromMemberEvent(roomId, memberEvent) {
|
||||
const userId = memberEvent?.state_key;
|
||||
if (typeof userId !== "string") {
|
||||
|
|
|
@ -45,14 +45,8 @@ export class Timeline {
|
|||
}
|
||||
|
||||
/** @package */
|
||||
async load(user, log) {
|
||||
const txn = await 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
|
||||
|
||||
async load(log) {
|
||||
const txn = await this._storage.readTxn(this._timelineReader.readTxnStores);
|
||||
// 30 seems to be a good amount to fill the entire screen
|
||||
const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30, txn, log));
|
||||
try {
|
||||
|
@ -63,6 +57,41 @@ export class Timeline {
|
|||
}
|
||||
}
|
||||
|
||||
async ensureOwnMember(user, myMembership, hsApi, log) {
|
||||
if (this._ownMember) {
|
||||
return;
|
||||
}
|
||||
const txn = await this._storage.readTxn(this._storage.storeNames.roomMembers);
|
||||
const memberData = await txn.roomMembers.get(this._roomId, user.id);
|
||||
if (memberData) {
|
||||
this._ownMember = new RoomMember(memberData);
|
||||
} else {
|
||||
await log.wrap("own member missing", async log => {
|
||||
// important this *never* throws, not even when offline,
|
||||
// as it would prevent enqueueing a message, or opening the timeline
|
||||
try {
|
||||
this._ownMember = await RoomMember.fromFetch(this._roomId, user.id, hsApi, log);
|
||||
const writeTxn = await this._storage.readWriteTxn(this._storage.storeNames.roomMembers);
|
||||
// check we still don't have the member after the fetch (e.g. from sync)
|
||||
// just to make sure we don't overwrite it
|
||||
const memberData = await writeTxn.roomMembers.get(this._roomId, user.id);
|
||||
if(!memberData) {
|
||||
writeTxn.roomMembers.set(this._roomId, this._ownMember.serialize());
|
||||
await writeTxn.complete();
|
||||
} else {
|
||||
this._ownMember = new RoomMember(memberData);
|
||||
}
|
||||
} catch (err) {
|
||||
log.error = err;
|
||||
if (!this._ownMember) {
|
||||
log.set("fallback", true);
|
||||
this._ownMember = RoomMember.fromUserId(this._roomId, user.id, myMembership);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateOwnMember(member) {
|
||||
this._ownMember = member;
|
||||
}
|
||||
|
|
Reference in a new issue