Make powerLevels observable

Signed-off-by: RMidhunSuresh <rmidhunsuresh@gmail.com>
This commit is contained in:
RMidhunSuresh 2021-07-14 12:59:44 +05:30
parent d1f465e6cc
commit 8a976ef24b
4 changed files with 50 additions and 30 deletions

View file

@ -6,8 +6,10 @@ import {Disambiguator} from "./disambiguator.js";
export class MemberListViewModel extends ViewModel { export class MemberListViewModel extends ViewModel {
constructor(options) { constructor(options) {
super(options); super(options);
const powerLevels = options.powerLevelsObservable.get();
// We should subscribe to the observable here so that we can resort when pl changes
this.memberTileViewModels = this._mapTileViewModels(this._filterJoinedMembers(options.members)) this.memberTileViewModels = this._mapTileViewModels(this._filterJoinedMembers(options.members))
.sortValues(createMemberComparator(options.powerLevels)); .sortValues(createMemberComparator(powerLevels));
this.nameDisambiguator = new Disambiguator(); this.nameDisambiguator = new Disambiguator();
this.mediaRepository = options.mediaRepository; this.mediaRepository = options.mediaRepository;
} }

View file

@ -14,7 +14,8 @@ export class RightPanelViewModel extends ViewModel {
async _getMemberArguments() { async _getMemberArguments() {
const list = await this._room.loadMemberList(); const list = await this._room.loadMemberList();
const room = this._room; const room = this._room;
return {members: list.members, powerLevels: room.powerLevels, mediaRepository: room.mediaRepository}; const powerLevelsObservable = await this._room.observePowerLevels();
return {members: list.members, powerLevelsObservable, mediaRepository: room.mediaRepository};
} }
_setupNavigation() { _setupNavigation() {

View file

@ -28,6 +28,9 @@ import {EventEntry} from "./timeline/entries/EventEntry.js";
import {ObservedEventMap} from "./ObservedEventMap.js"; import {ObservedEventMap} from "./ObservedEventMap.js";
import {DecryptionSource} from "../e2ee/common.js"; import {DecryptionSource} from "../e2ee/common.js";
import {ensureLogItem} from "../../logging/utils.js"; import {ensureLogItem} from "../../logging/utils.js";
import {TimelineReader} from "./timeline/persistence/TimelineReader.js";
import {PowerLevels} from "./timeline/PowerLevels.js";
import {RetainedObservableValue} from "../../observable/ObservableValue.js";
const EVENT_ENCRYPTED_TYPE = "m.room.encrypted"; const EVENT_ENCRYPTED_TYPE = "m.room.encrypted";
@ -388,8 +391,44 @@ export class BaseRoom extends EventEmitter {
return this._summary.data.membership; return this._summary.data.membership;
} }
get powerLevels() { async loadPowerLevels() {
return this._timeline.powerLevels; const timelineReader = new TimelineReader({
roomId: this._roomId,
storage: this._storage,
fragmentIdComparer: this._fragmentIdComparer
});
const txn = await this._storage.readTxn(
timelineReader.readTxnStores.concat(this._storage.storeNames.roomMembers, this._storage.storeNames.roomState)
);
const powerLevelsState = await txn.roomState.get(this._roomId, "m.room.power_levels", "");
if (powerLevelsState) {
return new PowerLevels({
powerLevelEvent: powerLevelsState.event,
ownUserId: this._user.id,
membership: this.membership
});
}
const createState = await txn.roomState.get(this._roomId, "m.room.create", "");
if (createState) {
return new PowerLevels({
createEvent: createState.event,
ownUserId: this._user.id,
membership: this.membership
});
} else {
const membership = this.membership;
return new PowerLevels({ownUserId: this._user.id, membership});
}
}
async observePowerLevels() {
let observable = this._powerLevels;
if (!observable) {
const powerLevels = await this.loadPowerLevels();
observable = new RetainedObservableValue(powerLevels, () => { this._powerLevels = null; });
this._powerLevels = observable;
}
return observable;
} }
enableSessionBackup(sessionBackup) { enableSessionBackup(sessionBackup) {
@ -433,6 +472,7 @@ export class BaseRoom extends EventEmitter {
}, },
clock: this._platform.clock, clock: this._platform.clock,
logger: this._platform.logger, logger: this._platform.logger,
powerLevelsObservable: await this.observePowerLevels()
}); });
try { try {
if (this._roomEncryption) { if (this._roomEncryption) {

View file

@ -21,12 +21,11 @@ import {Direction} from "./Direction.js";
import {TimelineReader} from "./persistence/TimelineReader.js"; import {TimelineReader} from "./persistence/TimelineReader.js";
import {PendingEventEntry} from "./entries/PendingEventEntry.js"; import {PendingEventEntry} from "./entries/PendingEventEntry.js";
import {RoomMember} from "../members/RoomMember.js"; import {RoomMember} from "../members/RoomMember.js";
import {PowerLevels} from "./PowerLevels.js";
import {getRelation, ANNOTATION_RELATION_TYPE} from "./relations.js"; import {getRelation, ANNOTATION_RELATION_TYPE} from "./relations.js";
import {REDACTION_TYPE} from "../common.js"; import {REDACTION_TYPE} from "../common.js";
export class Timeline { export class Timeline {
constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, clock}) { constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, clock, powerLevelsObservable}) {
this._roomId = roomId; this._roomId = roomId;
this._storage = storage; this._storage = storage;
this._closeCallback = closeCallback; this._closeCallback = closeCallback;
@ -44,7 +43,8 @@ export class Timeline {
}); });
this._readerRequest = null; this._readerRequest = null;
this._allEntries = null; this._allEntries = null;
this._powerLevels = null; this._powerLevels = powerLevelsObservable.get();
this._disposables.track(powerLevelsObservable.subscribe(powerLevels => this._powerLevels = powerLevels));
} }
/** @package */ /** @package */
@ -66,7 +66,6 @@ export class Timeline {
// as they should only populate once the view subscribes to it // as they should only populate once the view subscribes to it
// if they are populated already, the sender profile would be empty // if they are populated already, the sender profile would be empty
this._powerLevels = await this._loadPowerLevels(membership, txn);
// 30 seems to be a good amount to fill the entire screen // 30 seems to be a good amount to fill the entire screen
const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30, txn, log)); const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30, txn, log));
try { try {
@ -78,28 +77,6 @@ export class Timeline {
// txn should be assumed to have finished here, as decryption will close it. // txn should be assumed to have finished here, as decryption will close it.
} }
async _loadPowerLevels(membership, txn) {
// TODO: update power levels as state is updated
const powerLevelsState = await txn.roomState.get(this._roomId, "m.room.power_levels", "");
if (powerLevelsState) {
return new PowerLevels({
powerLevelEvent: powerLevelsState.event,
ownUserId: this._ownMember.userId,
membership
});
}
const createState = await txn.roomState.get(this._roomId, "m.room.create", "");
if (createState) {
return new PowerLevels({
createEvent: createState.event,
ownUserId: this._ownMember.userId,
membership
});
} else {
return new PowerLevels({ownUserId: this._ownMember.userId, membership});
}
}
_setupEntries(timelineEntries) { _setupEntries(timelineEntries) {
this._remoteEntries.setManySorted(timelineEntries); this._remoteEntries.setManySorted(timelineEntries);
if (this._pendingEvents) { if (this._pendingEvents) {