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 {
constructor(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))
.sortValues(createMemberComparator(options.powerLevels));
.sortValues(createMemberComparator(powerLevels));
this.nameDisambiguator = new Disambiguator();
this.mediaRepository = options.mediaRepository;
}

View file

@ -14,7 +14,8 @@ export class RightPanelViewModel extends ViewModel {
async _getMemberArguments() {
const list = await this._room.loadMemberList();
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() {

View file

@ -28,6 +28,9 @@ import {EventEntry} from "./timeline/entries/EventEntry.js";
import {ObservedEventMap} from "./ObservedEventMap.js";
import {DecryptionSource} from "../e2ee/common.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";
@ -388,8 +391,44 @@ export class BaseRoom extends EventEmitter {
return this._summary.data.membership;
}
get powerLevels() {
return this._timeline.powerLevels;
async loadPowerLevels() {
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) {
@ -433,6 +472,7 @@ export class BaseRoom extends EventEmitter {
},
clock: this._platform.clock,
logger: this._platform.logger,
powerLevelsObservable: await this.observePowerLevels()
});
try {
if (this._roomEncryption) {

View file

@ -21,12 +21,11 @@ import {Direction} from "./Direction.js";
import {TimelineReader} from "./persistence/TimelineReader.js";
import {PendingEventEntry} from "./entries/PendingEventEntry.js";
import {RoomMember} from "../members/RoomMember.js";
import {PowerLevels} from "./PowerLevels.js";
import {getRelation, ANNOTATION_RELATION_TYPE} from "./relations.js";
import {REDACTION_TYPE} from "../common.js";
export class Timeline {
constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, clock}) {
constructor({roomId, storage, closeCallback, fragmentIdComparer, pendingEvents, clock, powerLevelsObservable}) {
this._roomId = roomId;
this._storage = storage;
this._closeCallback = closeCallback;
@ -44,7 +43,8 @@ export class Timeline {
});
this._readerRequest = null;
this._allEntries = null;
this._powerLevels = null;
this._powerLevels = powerLevelsObservable.get();
this._disposables.track(powerLevelsObservable.subscribe(powerLevels => this._powerLevels = powerLevels));
}
/** @package */
@ -66,7 +66,6 @@ export class Timeline {
// as they should only populate once the view subscribes to it
// 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
const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(30, txn, log));
try {
@ -78,28 +77,6 @@ export class Timeline {
// 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) {
this._remoteEntries.setManySorted(timelineEntries);
if (this._pendingEvents) {