This commit is contained in:
Bruno Windels 2020-09-22 18:22:37 +02:00
parent fe8c63b5f2
commit 241176d6fb
4 changed files with 74 additions and 37 deletions

View file

@ -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);

View file

@ -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,

View file

@ -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;
} }

View file

@ -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 {