WIP
This commit is contained in:
parent
fe8c63b5f2
commit
241176d6fb
4 changed files with 74 additions and 37 deletions
|
@ -52,6 +52,15 @@ export class Room extends EventEmitter {
|
||||||
this._clock = clock;
|
this._clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_readEntriesToRetryDecryption(retryEventIds) {
|
||||||
|
const readFromEventKey = retryEventIds.length !== 0;
|
||||||
|
const stores =
|
||||||
|
const txn = await this._storage.readTxn([
|
||||||
|
this._storage.storeNames.timelineEvents,
|
||||||
|
this._storage.storeNames.inboundGroupSessions,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
async notifyRoomKeys(roomKeys) {
|
async notifyRoomKeys(roomKeys) {
|
||||||
if (this._roomEncryption) {
|
if (this._roomEncryption) {
|
||||||
let retryEventIds = this._roomEncryption.applyRoomKeys(roomKeys);
|
let retryEventIds = this._roomEncryption.applyRoomKeys(roomKeys);
|
||||||
|
|
|
@ -122,6 +122,23 @@ function processTimelineEvent(data, eventEntry, isInitialSync, isTimelineOpen, o
|
||||||
data.lastMessageBody = body;
|
data.lastMessageBody = body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// store the event key of the last decrypted event so when decryption does succeed,
|
||||||
|
// we can attempt to re-decrypt from this point to update the room summary
|
||||||
|
if (!!data.encryption && eventEntry.isEncrypted && eventEntry.isDecrypted) {
|
||||||
|
let hasLargerEventKey = true;
|
||||||
|
if (data.lastDecryptedEventKey) {
|
||||||
|
try {
|
||||||
|
hasLargerEventKey = eventEntry.compare(data.lastDecryptedEventKey) > 0;
|
||||||
|
} catch (err) {
|
||||||
|
hasLargerEventKey = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasLargerEventKey) {
|
||||||
|
data = data.cloneIfNeeded();
|
||||||
|
const {fragmentId, entryIndex} = eventEntry;
|
||||||
|
data.lastDecryptedEventKey = {fragmentId, entryIndex};
|
||||||
|
}
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +172,7 @@ class SummaryData {
|
||||||
this.lastMessageTimestamp = copy ? copy.lastMessageTimestamp : null;
|
this.lastMessageTimestamp = copy ? copy.lastMessageTimestamp : null;
|
||||||
this.isUnread = copy ? copy.isUnread : false;
|
this.isUnread = copy ? copy.isUnread : false;
|
||||||
this.encryption = copy ? copy.encryption : null;
|
this.encryption = copy ? copy.encryption : null;
|
||||||
|
this.lastDecryptedEventKey = copy ? copy.lastDecryptedEventKey : null;
|
||||||
this.isDirectMessage = copy ? copy.isDirectMessage : false;
|
this.isDirectMessage = copy ? copy.isDirectMessage : false;
|
||||||
this.membership = copy ? copy.membership : null;
|
this.membership = copy ? copy.membership : null;
|
||||||
this.inviteCount = copy ? copy.inviteCount : 0;
|
this.inviteCount = copy ? copy.inviteCount : 0;
|
||||||
|
@ -261,6 +279,10 @@ export class RoomSummary {
|
||||||
return this._data.tags;
|
return this._data.tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get lastDecryptedEventKey() {
|
||||||
|
return this._data.lastDecryptedEventKey;
|
||||||
|
}
|
||||||
|
|
||||||
writeClearUnread(txn) {
|
writeClearUnread(txn) {
|
||||||
const data = new SummaryData(this._data);
|
const data = new SummaryData(this._data);
|
||||||
data.isUnread = false;
|
data.isUnread = false;
|
||||||
|
@ -290,9 +312,6 @@ export class RoomSummary {
|
||||||
processTimelineEntries(timelineEntries, isInitialSync, isTimelineOpen) {
|
processTimelineEntries(timelineEntries, isInitialSync, isTimelineOpen) {
|
||||||
// clear cloned flag, so cloneIfNeeded makes a copy and
|
// clear cloned flag, so cloneIfNeeded makes a copy and
|
||||||
// this._data is not modified if any field is changed.
|
// this._data is not modified if any field is changed.
|
||||||
|
|
||||||
processTimelineEvent
|
|
||||||
|
|
||||||
this._data.cloned = false;
|
this._data.cloned = false;
|
||||||
const data = applyTimelineEntries(
|
const data = applyTimelineEntries(
|
||||||
this._data,
|
this._data,
|
||||||
|
|
|
@ -82,6 +82,10 @@ export class EventEntry extends BaseEntry {
|
||||||
return this._eventEntry.event.type === "m.room.encrypted";
|
return this._eventEntry.event.type === "m.room.encrypted";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isDecrypted() {
|
||||||
|
return !!this._decryptionResult?.event;
|
||||||
|
}
|
||||||
|
|
||||||
get isVerified() {
|
get isVerified() {
|
||||||
return this.isEncrypted && this._decryptionResult?.isVerified;
|
return this.isEncrypted && this._decryptionResult?.isVerified;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,44 @@ class ReaderRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function readFromWithTxn(eventKey, direction, amount, r, txn) {
|
||||||
|
let entries = [];
|
||||||
|
const timelineStore = txn.timelineEvents;
|
||||||
|
const fragmentStore = txn.timelineFragments;
|
||||||
|
|
||||||
|
while (entries.length < amount && eventKey) {
|
||||||
|
let eventsWithinFragment;
|
||||||
|
if (direction.isForward) {
|
||||||
|
eventsWithinFragment = await timelineStore.eventsAfter(this._roomId, eventKey, amount);
|
||||||
|
} else {
|
||||||
|
eventsWithinFragment = await timelineStore.eventsBefore(this._roomId, eventKey, amount);
|
||||||
|
}
|
||||||
|
let eventEntries = eventsWithinFragment.map(e => new EventEntry(e, this._fragmentIdComparer));
|
||||||
|
entries = directionalConcat(entries, eventEntries, direction);
|
||||||
|
// prepend or append eventsWithinFragment to entries, and wrap them in EventEntry
|
||||||
|
|
||||||
|
if (entries.length < amount) {
|
||||||
|
const fragment = await fragmentStore.get(this._roomId, eventKey.fragmentId);
|
||||||
|
// this._fragmentIdComparer.addFragment(fragment);
|
||||||
|
let fragmentEntry = new FragmentBoundaryEntry(fragment, direction.isBackward, this._fragmentIdComparer);
|
||||||
|
// append or prepend fragmentEntry, reuse func from GapWriter?
|
||||||
|
directionalAppend(entries, fragmentEntry, direction);
|
||||||
|
// only continue loading if the fragment boundary can't be backfilled
|
||||||
|
if (!fragmentEntry.token && fragmentEntry.hasLinkedFragment) {
|
||||||
|
const nextFragment = await fragmentStore.get(this._roomId, fragmentEntry.linkedFragmentId);
|
||||||
|
this._fragmentIdComparer.add(nextFragment);
|
||||||
|
const nextFragmentEntry = new FragmentBoundaryEntry(nextFragment, direction.isForward, this._fragmentIdComparer);
|
||||||
|
directionalAppend(entries, nextFragmentEntry, direction);
|
||||||
|
eventKey = nextFragmentEntry.asEventKey();
|
||||||
|
} else {
|
||||||
|
eventKey = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
export class TimelineReader {
|
export class TimelineReader {
|
||||||
constructor({roomId, storage, fragmentIdComparer}) {
|
constructor({roomId, storage, fragmentIdComparer}) {
|
||||||
this._roomId = roomId;
|
this._roomId = roomId;
|
||||||
|
@ -87,40 +125,7 @@ export class TimelineReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
async _readFrom(eventKey, direction, amount, r, txn) {
|
async _readFrom(eventKey, direction, amount, r, txn) {
|
||||||
let entries = [];
|
const entries = readFromWithTxn(eventKey, direction, amount, r, txn);
|
||||||
const timelineStore = txn.timelineEvents;
|
|
||||||
const fragmentStore = txn.timelineFragments;
|
|
||||||
|
|
||||||
while (entries.length < amount && eventKey) {
|
|
||||||
let eventsWithinFragment;
|
|
||||||
if (direction.isForward) {
|
|
||||||
eventsWithinFragment = await timelineStore.eventsAfter(this._roomId, eventKey, amount);
|
|
||||||
} else {
|
|
||||||
eventsWithinFragment = await timelineStore.eventsBefore(this._roomId, eventKey, amount);
|
|
||||||
}
|
|
||||||
let eventEntries = eventsWithinFragment.map(e => new EventEntry(e, this._fragmentIdComparer));
|
|
||||||
entries = directionalConcat(entries, eventEntries, direction);
|
|
||||||
// prepend or append eventsWithinFragment to entries, and wrap them in EventEntry
|
|
||||||
|
|
||||||
if (entries.length < amount) {
|
|
||||||
const fragment = await fragmentStore.get(this._roomId, eventKey.fragmentId);
|
|
||||||
// this._fragmentIdComparer.addFragment(fragment);
|
|
||||||
let fragmentEntry = new FragmentBoundaryEntry(fragment, direction.isBackward, this._fragmentIdComparer);
|
|
||||||
// append or prepend fragmentEntry, reuse func from GapWriter?
|
|
||||||
directionalAppend(entries, fragmentEntry, direction);
|
|
||||||
// only continue loading if the fragment boundary can't be backfilled
|
|
||||||
if (!fragmentEntry.token && fragmentEntry.hasLinkedFragment) {
|
|
||||||
const nextFragment = await fragmentStore.get(this._roomId, fragmentEntry.linkedFragmentId);
|
|
||||||
this._fragmentIdComparer.add(nextFragment);
|
|
||||||
const nextFragmentEntry = new FragmentBoundaryEntry(nextFragment, direction.isForward, this._fragmentIdComparer);
|
|
||||||
directionalAppend(entries, nextFragmentEntry, direction);
|
|
||||||
eventKey = nextFragmentEntry.asEventKey();
|
|
||||||
} else {
|
|
||||||
eventKey = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._decryptEntries) {
|
if (this._decryptEntries) {
|
||||||
r.decryptRequest = this._decryptEntries(entries, txn);
|
r.decryptRequest = this._decryptEntries(entries, txn);
|
||||||
try {
|
try {
|
||||||
|
|
Reference in a new issue