matrix-js-sdk 42.1.0 → 42.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/lib/@types/beacon.d.ts +1 -1
- package/lib/@types/beacon.js +1 -1
- package/lib/@types/beacon.js.map +1 -1
- package/lib/@types/extensible_events.d.ts.map +1 -1
- package/lib/@types/extensible_events.js.map +1 -1
- package/lib/autodiscovery.js.map +1 -1
- package/lib/browser-index.js.map +1 -1
- package/lib/client.d.ts +12 -5
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +23 -26
- package/lib/client.js.map +1 -1
- package/lib/common-crypto/key-passphrase.js +1 -1
- package/lib/common-crypto/key-passphrase.js.map +1 -1
- package/lib/crypto/store/indexeddb-crypto-store-backend.js +2 -1
- package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
- package/lib/crypto/store/indexeddb-crypto-store.d.ts.map +1 -1
- package/lib/crypto/store/indexeddb-crypto-store.js +1 -1
- package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
- package/lib/crypto/store/memory-crypto-store.js.map +1 -1
- package/lib/embedded.d.ts +16 -0
- package/lib/embedded.d.ts.map +1 -1
- package/lib/embedded.js +19 -6
- package/lib/embedded.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
- package/lib/matrixrtc/MembershipManager.js.map +1 -1
- package/lib/matrixrtc/MembershipManagerActionScheduler.js.map +1 -1
- package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
- package/lib/matrixrtc/ToDeviceKeyTransport.js.map +1 -1
- package/lib/matrixrtc/membershipData/rtc.js.map +1 -1
- package/lib/matrixrtc/utils.d.ts +0 -1
- package/lib/matrixrtc/utils.d.ts.map +1 -1
- package/lib/matrixrtc/utils.js +0 -1
- package/lib/matrixrtc/utils.js.map +1 -1
- package/lib/models/event-timeline-set.js +3 -3
- package/lib/models/event-timeline-set.js.map +1 -1
- package/lib/models/event.d.ts.map +1 -1
- package/lib/models/event.js.map +1 -1
- package/lib/models/invites-ignorer.js.map +1 -1
- package/lib/models/poll.js.map +1 -1
- package/lib/models/read-receipt.js.map +1 -1
- package/lib/models/relations-container.d.ts +10 -0
- package/lib/models/relations-container.d.ts.map +1 -1
- package/lib/models/relations-container.js +39 -17
- package/lib/models/relations-container.js.map +1 -1
- package/lib/models/relations.js +1 -1
- package/lib/models/relations.js.map +1 -1
- package/lib/models/room.js +3 -3
- package/lib/models/room.js.map +1 -1
- package/lib/models/thread.d.ts +3 -0
- package/lib/models/thread.d.ts.map +1 -1
- package/lib/models/thread.js +36 -3
- package/lib/models/thread.js.map +1 -1
- package/lib/oauth/authorize.js +1 -1
- package/lib/oauth/authorize.js.map +1 -1
- package/lib/oauth/index.js +4 -2
- package/lib/oauth/index.js.map +1 -1
- package/lib/pollingCachedValue.d.ts +77 -0
- package/lib/pollingCachedValue.d.ts.map +1 -0
- package/lib/pollingCachedValue.js +160 -0
- package/lib/pollingCachedValue.js.map +1 -0
- package/lib/pushprocessor.js.map +1 -1
- package/lib/receipt-accumulator.d.ts.map +1 -1
- package/lib/receipt-accumulator.js.map +1 -1
- package/lib/rendezvous/MSC4108SignInWithQR.d.ts.map +1 -1
- package/lib/rendezvous/MSC4108SignInWithQR.js +2 -3
- package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
- package/lib/rtcTransportsCachedValue.d.ts +9 -0
- package/lib/rtcTransportsCachedValue.d.ts.map +1 -0
- package/lib/rtcTransportsCachedValue.js +38 -0
- package/lib/rtcTransportsCachedValue.js.map +1 -0
- package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +1 -1
- package/lib/rust-crypto/backup.d.ts +2 -3
- package/lib/rust-crypto/backup.d.ts.map +1 -1
- package/lib/rust-crypto/backup.js.map +1 -1
- package/lib/rust-crypto/index.d.ts +10 -4
- package/lib/rust-crypto/index.d.ts.map +1 -1
- package/lib/rust-crypto/index.js +20 -3
- package/lib/rust-crypto/index.js.map +1 -1
- package/lib/rust-crypto/libolm_migration.js.map +1 -1
- package/lib/rust-crypto/rust-crypto.js.map +1 -1
- package/lib/sliding-sync-sdk.js.map +1 -1
- package/lib/sliding-sync.js.map +1 -1
- package/lib/store/indexeddb-local-backend.js +1 -1
- package/lib/store/indexeddb-local-backend.js.map +1 -1
- package/lib/store/indexeddb-store-worker.d.ts.map +1 -1
- package/lib/store/indexeddb-store-worker.js +1 -0
- package/lib/store/indexeddb-store-worker.js.map +1 -1
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js.map +1 -1
- package/lib/utils.d.ts +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +1 -0
- package/lib/utils.js.map +1 -1
- package/lib/webrtc/call.js.map +1 -1
- package/lib/webrtc/groupCall.js.map +1 -1
- package/lib/webrtc/mediaHandler.js.map +1 -1
- package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
- package/lib/webrtc/stats/transportStatsBuilder.js.map +1 -1
- package/lib/wellKnownCachedValue.d.ts +8 -0
- package/lib/wellKnownCachedValue.d.ts.map +1 -0
- package/lib/wellKnownCachedValue.js +34 -0
- package/lib/wellKnownCachedValue.js.map +1 -0
- package/package.json +4 -4
- package/src/@types/beacon.ts +1 -1
- package/src/@types/extensible_events.ts +3 -4
- package/src/autodiscovery.ts +2 -2
- package/src/browser-index.ts +1 -1
- package/src/client.ts +48 -40
- package/src/common-crypto/key-passphrase.ts +1 -1
- package/src/crypto/store/indexeddb-crypto-store-backend.ts +2 -1
- package/src/crypto/store/indexeddb-crypto-store.ts +1 -3
- package/src/crypto/store/memory-crypto-store.ts +1 -1
- package/src/embedded.ts +34 -11
- package/src/matrixrtc/MatrixRTCSession.ts +3 -3
- package/src/matrixrtc/MembershipManager.ts +1 -1
- package/src/matrixrtc/MembershipManagerActionScheduler.ts +1 -1
- package/src/matrixrtc/RTCEncryptionManager.ts +2 -2
- package/src/matrixrtc/ToDeviceKeyTransport.ts +3 -3
- package/src/matrixrtc/membershipData/rtc.ts +1 -1
- package/src/matrixrtc/utils.ts +0 -2
- package/src/models/event-timeline-set.ts +3 -3
- package/src/models/event.ts +7 -10
- package/src/models/invites-ignorer.ts +1 -1
- package/src/models/poll.ts +1 -1
- package/src/models/read-receipt.ts +1 -1
- package/src/models/relations-container.ts +55 -19
- package/src/models/relations.ts +1 -1
- package/src/models/room.ts +9 -9
- package/src/models/thread.ts +49 -4
- package/src/oauth/authorize.ts +1 -1
- package/src/oauth/index.ts +2 -2
- package/src/pollingCachedValue.ts +184 -0
- package/src/pushprocessor.ts +3 -3
- package/src/receipt-accumulator.ts +1 -2
- package/src/rendezvous/MSC4108SignInWithQR.ts +3 -4
- package/src/rtcTransportsCachedValue.ts +40 -0
- package/src/rust-crypto/PerSessionKeyBackupDownloader.ts +1 -1
- package/src/rust-crypto/backup.ts +1 -5
- package/src/rust-crypto/index.ts +23 -25
- package/src/rust-crypto/libolm_migration.ts +1 -1
- package/src/rust-crypto/rust-crypto.ts +3 -3
- package/src/sliding-sync-sdk.ts +1 -1
- package/src/sliding-sync.ts +1 -1
- package/src/store/indexeddb-local-backend.ts +1 -1
- package/src/store/indexeddb-store-worker.ts +1 -0
- package/src/sync.ts +4 -3
- package/src/utils.ts +3 -2
- package/src/webrtc/call.ts +6 -6
- package/src/webrtc/groupCall.ts +7 -7
- package/src/webrtc/mediaHandler.ts +1 -1
- package/src/webrtc/stats/callStatsReportGatherer.ts +2 -2
- package/src/webrtc/stats/transportStatsBuilder.ts +1 -1
- package/src/wellKnownCachedValue.ts +34 -0
|
@@ -20,6 +20,7 @@ import { EventStatus, type MatrixEvent, MatrixEventEvent } from "./event.ts";
|
|
|
20
20
|
import { type EventTimelineSet } from "./event-timeline-set.ts";
|
|
21
21
|
import { type MatrixClient } from "../client.ts";
|
|
22
22
|
import { type Room } from "./room.ts";
|
|
23
|
+
import { logger } from "../logger.ts";
|
|
23
24
|
|
|
24
25
|
export class RelationsContainer {
|
|
25
26
|
// A tree of objects to access a set of related children for an event, as in:
|
|
@@ -89,29 +90,58 @@ export class RelationsContainer {
|
|
|
89
90
|
* @param event - The new child event to be aggregated.
|
|
90
91
|
* @param timelineSet - The event timeline set within which to search for the related event if any.
|
|
91
92
|
*/
|
|
92
|
-
public aggregateChildEvent(event: MatrixEvent, timelineSet?: EventTimelineSet): void
|
|
93
|
+
public aggregateChildEvent(event: MatrixEvent, timelineSet?: EventTimelineSet): void;
|
|
94
|
+
/**
|
|
95
|
+
* Add a relation event using a known target that is not in the timeline yet.
|
|
96
|
+
*
|
|
97
|
+
* @param event - The new child event to be aggregated.
|
|
98
|
+
* @param timelineSet - The event timeline set within which to search for the related event.
|
|
99
|
+
* @param targetEvent - The known relation target.
|
|
100
|
+
* @returns A promise which resolves after aggregation.
|
|
101
|
+
*/
|
|
102
|
+
public aggregateChildEvent(
|
|
103
|
+
event: MatrixEvent,
|
|
104
|
+
timelineSet: EventTimelineSet,
|
|
105
|
+
targetEvent: MatrixEvent,
|
|
106
|
+
): Promise<void>;
|
|
107
|
+
public aggregateChildEvent(
|
|
108
|
+
event: MatrixEvent,
|
|
109
|
+
timelineSet?: EventTimelineSet,
|
|
110
|
+
targetEvent?: MatrixEvent,
|
|
111
|
+
): void | Promise<void> {
|
|
112
|
+
const aggregation = this.aggregateChildEventInternal(event, timelineSet, targetEvent);
|
|
113
|
+
if (targetEvent) return aggregation;
|
|
114
|
+
|
|
115
|
+
void aggregation.catch((error) => logger.error("Failed to aggregate child event: ", error));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private aggregateChildEventInternal(
|
|
119
|
+
event: MatrixEvent,
|
|
120
|
+
timelineSet?: EventTimelineSet,
|
|
121
|
+
targetEvent?: MatrixEvent,
|
|
122
|
+
): Promise<void> {
|
|
93
123
|
if (event.isRedacted() || event.status === EventStatus.CANCELLED) {
|
|
94
|
-
return;
|
|
124
|
+
return Promise.resolve();
|
|
95
125
|
}
|
|
96
126
|
|
|
97
127
|
const relation = event.getRelation();
|
|
98
|
-
if (!relation) return;
|
|
99
|
-
|
|
100
|
-
const onEventDecrypted = (): void => {
|
|
101
|
-
if (event.isDecryptionFailure()) {
|
|
102
|
-
// This could for example happen if the encryption keys are not yet available.
|
|
103
|
-
// The event may still be decrypted later. Register the listener again.
|
|
104
|
-
event.once(MatrixEventEvent.Decrypted, onEventDecrypted);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.aggregateChildEvent(event, timelineSet);
|
|
109
|
-
};
|
|
128
|
+
if (!relation) return Promise.resolve();
|
|
110
129
|
|
|
111
130
|
// If the event is currently encrypted, wait until it has been decrypted.
|
|
112
131
|
if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {
|
|
113
|
-
|
|
114
|
-
|
|
132
|
+
return new Promise<void>((resolve, reject) => {
|
|
133
|
+
const onEventDecrypted = (): void => {
|
|
134
|
+
if (event.isDecryptionFailure()) {
|
|
135
|
+
// This could for example happen if the encryption keys are not yet available.
|
|
136
|
+
// The event may still be decrypted later. Register the listener again.
|
|
137
|
+
event.once(MatrixEventEvent.Decrypted, onEventDecrypted);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
void this.aggregateChildEventInternal(event, timelineSet, targetEvent).then(resolve, reject);
|
|
142
|
+
};
|
|
143
|
+
event.once(MatrixEventEvent.Decrypted, onEventDecrypted);
|
|
144
|
+
});
|
|
115
145
|
}
|
|
116
146
|
|
|
117
147
|
const { event_id: relatesToEventId, rel_type: relationType } = relation;
|
|
@@ -130,20 +160,26 @@ export class RelationsContainer {
|
|
|
130
160
|
}
|
|
131
161
|
|
|
132
162
|
let relationsWithEventType = relationsWithRelType.get(eventType);
|
|
163
|
+
const isNewRelationCollection = !relationsWithEventType;
|
|
164
|
+
let targetEventUpdate = Promise.resolve();
|
|
133
165
|
if (!relationsWithEventType) {
|
|
134
166
|
relationsWithEventType = new Relations(relationType!, eventType, this.client);
|
|
135
167
|
relationsWithRelType.set(eventType, relationsWithEventType);
|
|
168
|
+
}
|
|
136
169
|
|
|
170
|
+
if (isNewRelationCollection || targetEvent) {
|
|
137
171
|
const room = this.room ?? timelineSet?.room;
|
|
138
172
|
const relatesToEvent =
|
|
139
173
|
timelineSet?.findEventById(relatesToEventId!) ??
|
|
140
174
|
room?.findEventById(relatesToEventId!) ??
|
|
141
|
-
room?.getPendingEvent(relatesToEventId!)
|
|
175
|
+
room?.getPendingEvent(relatesToEventId!) ??
|
|
176
|
+
targetEvent;
|
|
142
177
|
if (relatesToEvent) {
|
|
143
|
-
relationsWithEventType.setTargetEvent(relatesToEvent);
|
|
178
|
+
targetEventUpdate = relationsWithEventType.setTargetEvent(relatesToEvent);
|
|
144
179
|
}
|
|
145
180
|
}
|
|
146
181
|
|
|
147
|
-
relationsWithEventType.addEvent(event);
|
|
182
|
+
const addEventUpdate = relationsWithEventType.addEvent(event);
|
|
183
|
+
return Promise.all([targetEventUpdate, addEventUpdate]).then(() => undefined);
|
|
148
184
|
}
|
|
149
185
|
}
|
package/src/models/relations.ts
CHANGED
|
@@ -336,7 +336,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|
|
336
336
|
* @param targetEvent - the event the relations are related to.
|
|
337
337
|
*/
|
|
338
338
|
public async setTargetEvent(event: MatrixEvent): Promise<void> {
|
|
339
|
-
if (this.targetEvent) {
|
|
339
|
+
if (this.targetEvent === event) {
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
342
|
this.targetEvent = event;
|
package/src/models/room.ts
CHANGED
|
@@ -939,7 +939,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
939
939
|
private getFunctionalMembers(): string[] {
|
|
940
940
|
const mFunctionalMembers = this.currentState.getStateEvents(UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, "");
|
|
941
941
|
if (Array.isArray(mFunctionalMembers?.getContent().service_members)) {
|
|
942
|
-
return mFunctionalMembers
|
|
942
|
+
return mFunctionalMembers.getContent().service_members;
|
|
943
943
|
}
|
|
944
944
|
return [];
|
|
945
945
|
}
|
|
@@ -949,7 +949,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
949
949
|
|
|
950
950
|
// Only generate a fallback avatar if the conversation is with a single specific other user (a "DM").
|
|
951
951
|
let nonFunctionalMemberCount = 0;
|
|
952
|
-
this.getMembers()
|
|
952
|
+
this.getMembers().forEach((m) => {
|
|
953
953
|
if (m.membership !== "join" && m.membership !== "invite") return;
|
|
954
954
|
if (functionalMembers.includes(m.userId)) return;
|
|
955
955
|
nonFunctionalMemberCount++;
|
|
@@ -1070,7 +1070,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
1070
1070
|
if (rawMembersEvents === null || this.hasEncryptionStateEvent()) {
|
|
1071
1071
|
fromServer = true;
|
|
1072
1072
|
rawMembersEvents = await this.loadMembersFromServer();
|
|
1073
|
-
logger.log(`LL: got ${rawMembersEvents.length}
|
|
1073
|
+
logger.log(`LL: got ${rawMembersEvents.length} members from server for room ${this.roomId}`);
|
|
1074
1074
|
}
|
|
1075
1075
|
const memberEvents = rawMembersEvents.filter(noUnsafeEventProps).map(this.client.getEventMapper());
|
|
1076
1076
|
return { memberEvents, fromServer };
|
|
@@ -1129,7 +1129,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
1129
1129
|
.getMembers()
|
|
1130
1130
|
.filter((m) => m.isOutOfBand())
|
|
1131
1131
|
.map((m) => m.events.member?.event as IStateEventWithRoomId);
|
|
1132
|
-
logger.log(`LL: telling store to write ${oobMembers.length}
|
|
1132
|
+
logger.log(`LL: telling store to write ${oobMembers.length} members for room ${this.roomId}`);
|
|
1133
1133
|
const store = this.client.store;
|
|
1134
1134
|
return (
|
|
1135
1135
|
store
|
|
@@ -1171,7 +1171,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
1171
1171
|
*/
|
|
1172
1172
|
private cleanupAfterLeaving(): void {
|
|
1173
1173
|
this.clearLoadedMembersIfNeeded().catch((err) => {
|
|
1174
|
-
logger.error(`error after clearing loaded members from
|
|
1174
|
+
logger.error(`error after clearing loaded members from room ${this.roomId} after leaving`);
|
|
1175
1175
|
logger.log(err);
|
|
1176
1176
|
});
|
|
1177
1177
|
}
|
|
@@ -2078,7 +2078,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
2078
2078
|
};
|
|
2079
2079
|
|
|
2080
2080
|
if (filterType === ThreadFilterType.My) {
|
|
2081
|
-
definition
|
|
2081
|
+
definition.room!.timeline![FILTER_RELATED_BY_SENDERS.name] = [myUserId];
|
|
2082
2082
|
}
|
|
2083
2083
|
|
|
2084
2084
|
filter.setDefinition(definition);
|
|
@@ -2410,7 +2410,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
2410
2410
|
const threadRootId = event.threadRootId;
|
|
2411
2411
|
|
|
2412
2412
|
// Where the parent is the thread root and this is a non-thread relation this should live only in the main timeline
|
|
2413
|
-
if (!!parentEventId && !isThreadRelation && (threadRootId === parentEventId || roots?.has(parentEventId
|
|
2413
|
+
if (!!parentEventId && !isThreadRelation && (threadRootId === parentEventId || roots?.has(parentEventId))) {
|
|
2414
2414
|
return {
|
|
2415
2415
|
shouldLiveInRoom: true,
|
|
2416
2416
|
shouldLiveInThread: false,
|
|
@@ -3208,7 +3208,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
3208
3208
|
);
|
|
3209
3209
|
} else {
|
|
3210
3210
|
// When `threadSupport` is disabled treat all events as timelineEvents
|
|
3211
|
-
return [events
|
|
3211
|
+
return [events, [] as MatrixEvent[], [] as MatrixEvent[]];
|
|
3212
3212
|
}
|
|
3213
3213
|
}
|
|
3214
3214
|
|
|
@@ -3240,7 +3240,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|
|
3240
3240
|
Object.keys(content).forEach((eventId: string) => {
|
|
3241
3241
|
Object.keys(content[eventId]).forEach((receiptType: ReceiptType | string) => {
|
|
3242
3242
|
Object.keys(content[eventId][receiptType]).forEach((userId: string) => {
|
|
3243
|
-
const receipt = content[eventId][receiptType][userId]
|
|
3243
|
+
const receipt = content[eventId][receiptType][userId];
|
|
3244
3244
|
const receiptForMainTimeline = !receipt.thread_id || receipt.thread_id === MAIN_ROOM_TIMELINE;
|
|
3245
3245
|
const receiptDestination: Thread | this | undefined = receiptForMainTimeline
|
|
3246
3246
|
? this
|
package/src/models/thread.ts
CHANGED
|
@@ -132,6 +132,8 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
|
|
|
132
132
|
*/
|
|
133
133
|
public initialEventsFetched = !Thread.hasServerSideSupport;
|
|
134
134
|
private initalEventFetchProm: Promise<boolean> | undefined;
|
|
135
|
+
private preInitEventTargets = new Map<string, MatrixEvent>();
|
|
136
|
+
private preInitObserverState = { active: true };
|
|
135
137
|
|
|
136
138
|
/**
|
|
137
139
|
* An array of events to add to the timeline once the thread has been initialised
|
|
@@ -170,6 +172,9 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
|
|
|
170
172
|
this.reEmitter = new TypedReEmitter(this);
|
|
171
173
|
|
|
172
174
|
this.reEmitter.reEmit(this.timelineSet, [RoomEvent.Timeline, RoomEvent.TimelineReset]);
|
|
175
|
+
this.once(ThreadEvent.Delete, () => {
|
|
176
|
+
this.preInitObserverState.active = false;
|
|
177
|
+
});
|
|
173
178
|
|
|
174
179
|
this.room.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
|
|
175
180
|
this.room.on(RoomEvent.Redaction, this.onRedaction);
|
|
@@ -364,10 +369,19 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
|
|
|
364
369
|
// Modify this event to point at our room's state, and mark its thread
|
|
365
370
|
// as this.
|
|
366
371
|
this.setEventMetadata(event);
|
|
372
|
+
const eventId = event.getId();
|
|
373
|
+
if (
|
|
374
|
+
!this.initialEventsFetched &&
|
|
375
|
+
eventId &&
|
|
376
|
+
!event.isRelation(RelationType.Annotation) &&
|
|
377
|
+
!event.isRelation(RelationType.Replace)
|
|
378
|
+
) {
|
|
379
|
+
this.preInitEventTargets.set(eventId, event);
|
|
380
|
+
}
|
|
367
381
|
|
|
368
382
|
// Decide whether this event is going to be added at the end of the timeline.
|
|
369
383
|
const lastReply = this.lastReply();
|
|
370
|
-
const isNewestReply = !lastReply || event.localTimestamp >= lastReply
|
|
384
|
+
const isNewestReply = !lastReply || event.localTimestamp >= lastReply.localTimestamp;
|
|
371
385
|
|
|
372
386
|
if (!Thread.hasServerSideSupport) {
|
|
373
387
|
// When there's no server-side support, just add it to the end of the timeline.
|
|
@@ -438,12 +452,33 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
|
|
|
438
452
|
*/
|
|
439
453
|
this.replayEvents?.push(event);
|
|
440
454
|
|
|
441
|
-
//
|
|
442
|
-
// reaction counts/summary visible while the thread is still initialising.
|
|
443
|
-
// Only aggregate as child: parent aggregation is unnecessary here.
|
|
455
|
+
// Aggregate annotations immediately to keep reaction counts visible.
|
|
444
456
|
if (event.isRelation(RelationType.Annotation)) {
|
|
445
457
|
this.timelineSet.relations?.aggregateChildEvent(event, this.timelineSet);
|
|
446
458
|
}
|
|
459
|
+
|
|
460
|
+
// Edits can also be aggregated immediately when their target is already
|
|
461
|
+
// known. If it is not known yet, replay still handles them after pagination.
|
|
462
|
+
if (event.isRelation(RelationType.Replace)) {
|
|
463
|
+
const targetEventId = event.getRelation()?.event_id;
|
|
464
|
+
const targetEvent = targetEventId ? this.findPreInitTargetEvent(targetEventId) : undefined;
|
|
465
|
+
if (targetEvent && targetEventId) {
|
|
466
|
+
const weakThread = new WeakRef(this);
|
|
467
|
+
const observerState = this.preInitObserverState;
|
|
468
|
+
const eventId = event.getId();
|
|
469
|
+
void this.timelineSet.relations
|
|
470
|
+
.aggregateChildEvent(event, this.timelineSet, targetEvent)
|
|
471
|
+
.then(() => {
|
|
472
|
+
const thread = weakThread.deref();
|
|
473
|
+
if (!thread || !observerState.active) return;
|
|
474
|
+
const effectiveTarget = thread.findPreInitTargetEvent(targetEventId);
|
|
475
|
+
if (effectiveTarget?.replacingEvent()?.getId() === eventId) {
|
|
476
|
+
thread.emit(ThreadEvent.Update, thread);
|
|
477
|
+
}
|
|
478
|
+
})
|
|
479
|
+
.catch((error) => logger.error("Failed to aggregate pre-initialization thread edit: ", error));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
447
482
|
} else {
|
|
448
483
|
// Case 2: this is happening later, and we have a timeline. In
|
|
449
484
|
// this case, these events might be out-of order.
|
|
@@ -474,6 +509,15 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
|
|
|
474
509
|
}
|
|
475
510
|
}
|
|
476
511
|
|
|
512
|
+
private findPreInitTargetEvent(eventId: string): MatrixEvent | undefined {
|
|
513
|
+
return (
|
|
514
|
+
this.timelineSet.findEventById(eventId) ??
|
|
515
|
+
this.room.findEventById(eventId) ??
|
|
516
|
+
this.preInitEventTargets.get(eventId) ??
|
|
517
|
+
(this.lastEvent?.getId() === eventId ? this.lastEvent : undefined)
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
|
|
477
521
|
public async processEvent(event: MatrixEvent | null | undefined): Promise<void> {
|
|
478
522
|
if (event) {
|
|
479
523
|
this.setEventMetadata(event);
|
|
@@ -642,6 +686,7 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
|
|
|
642
686
|
this.addEvent(event, false);
|
|
643
687
|
}
|
|
644
688
|
this.replayEvents = null;
|
|
689
|
+
this.preInitEventTargets.clear();
|
|
645
690
|
// just to make sure that, if we've created a timeline window for this thread before the thread itself
|
|
646
691
|
// existed (e.g. when creating a new thread), we'll make sure the panel is force refreshed correctly.
|
|
647
692
|
this.emit(RoomEvent.TimelineReset, this.room, this.timelineSet, true);
|
package/src/oauth/authorize.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
hasRequiredStringProperty,
|
|
25
25
|
isRecord,
|
|
26
26
|
} from "../@types/type-guards.ts";
|
|
27
|
-
import { Method } from "../http-api";
|
|
27
|
+
import { Method } from "../http-api/index.ts";
|
|
28
28
|
import { OAuthGrantType } from "./register.ts";
|
|
29
29
|
import { sleep } from "../utils.ts";
|
|
30
30
|
|
package/src/oauth/index.ts
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
} from "./register.ts";
|
|
35
35
|
import { encodeUnpaddedBase64Url } from "../base64.ts";
|
|
36
36
|
import { sha256 } from "../digest.ts";
|
|
37
|
-
import { HTTPError, Method } from "../http-api";
|
|
37
|
+
import { HTTPError, Method } from "../http-api/index.ts";
|
|
38
38
|
import { logger } from "../logger.ts";
|
|
39
39
|
import { OAuth2Error } from "./error.ts";
|
|
40
40
|
import { secureRandomString } from "../randomstring.ts";
|
|
@@ -126,7 +126,7 @@ export class OAuth2 {
|
|
|
126
126
|
throw error;
|
|
127
127
|
} else {
|
|
128
128
|
logger.error("Dynamic registration request failed", error);
|
|
129
|
-
throw new Error(OAuth2Error.DynamicRegistrationFailed);
|
|
129
|
+
throw new Error(OAuth2Error.DynamicRegistrationFailed, { cause: error });
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2026 The Matrix.org Foundation C.I.C.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { calculateRetryBackoff } from "./http-api/index.ts";
|
|
18
|
+
import { type Logger } from "./logger.ts";
|
|
19
|
+
import { sleep } from "./utils.ts";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* How to fetch and cache a given value, as passed to {@link PollingCachedValue}.
|
|
23
|
+
*/
|
|
24
|
+
export interface PollingCachedValueOptions<ValueType> {
|
|
25
|
+
/** The name of the cached value (for tracing/logs). */
|
|
26
|
+
name: string;
|
|
27
|
+
/** The logger to derive this value's child logger from. */
|
|
28
|
+
logger: Logger;
|
|
29
|
+
/** Fetches a fresh value. Rejections are retried according to the retry policy. */
|
|
30
|
+
fetch: () => Promise<ValueType>;
|
|
31
|
+
/**
|
|
32
|
+
* The default time-to-live before the value gets refreshed, overridable per run
|
|
33
|
+
* via {@link PollingCachedValue.start}.
|
|
34
|
+
* If undefined the value never expires; use {@link PollingCachedValue.refresh} to clear the cache.
|
|
35
|
+
*/
|
|
36
|
+
ttlMillis?: number;
|
|
37
|
+
/** Called when a new value is cached. Use to emit changes if needed. */
|
|
38
|
+
onValueCached?: (value: ValueType) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Determines whether a non-transient error should be cached.
|
|
41
|
+
* By default errors are not cached, i.e. the next attempt retries the fetch.
|
|
42
|
+
*/
|
|
43
|
+
shouldCacheError?: (error: unknown) => boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Defines a generic mechanism to fetch and cache a value, refreshing it periodically.
|
|
48
|
+
*/
|
|
49
|
+
export class PollingCachedValue<ValueType> {
|
|
50
|
+
private cached?: ValueType;
|
|
51
|
+
private fetchPromise?: Promise<ValueType>;
|
|
52
|
+
private ttlTimeoutHandle?: ReturnType<typeof setTimeout>;
|
|
53
|
+
|
|
54
|
+
private isStopped = false;
|
|
55
|
+
private ttlMillis?: number;
|
|
56
|
+
|
|
57
|
+
private readonly logger: Logger;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Build a generic mechanism allowing to fetch and cache a given value.
|
|
61
|
+
* @param opts - Describes what to fetch and how to cache it, see {@link PollingCachedValueOptions}.
|
|
62
|
+
*/
|
|
63
|
+
public constructor(private readonly opts: PollingCachedValueOptions<ValueType>) {
|
|
64
|
+
this.ttlMillis = opts.ttlMillis;
|
|
65
|
+
this.logger = opts.logger.getChild(`PollingCachedValue<${opts.name}>`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Gets the cached value if any.
|
|
70
|
+
*/
|
|
71
|
+
public get(): ValueType | undefined {
|
|
72
|
+
return this.cached;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Ensures that the value was fetched once before getting the actual cached value.
|
|
77
|
+
*/
|
|
78
|
+
public async wait(): Promise<ValueType | undefined> {
|
|
79
|
+
await this.doFetch();
|
|
80
|
+
return this.cached;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Call this as early as possible and when the value can already be fetched.
|
|
85
|
+
* @param ttlMillis - The time-to-live before the value gets refreshed, overriding the one
|
|
86
|
+
* given at construction. If omitted the configured default is kept.
|
|
87
|
+
*/
|
|
88
|
+
public start(ttlMillis?: number): void {
|
|
89
|
+
if (ttlMillis !== undefined) {
|
|
90
|
+
this.ttlMillis = ttlMillis;
|
|
91
|
+
}
|
|
92
|
+
this.isStopped = false;
|
|
93
|
+
// Request a fetch as soon as possible
|
|
94
|
+
this.doFetch().catch((err) => {
|
|
95
|
+
this.logger.debug("Cached value fetch on start did fail", err);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Call when the client is stopped, or when the cached value is no longer needed.
|
|
100
|
+
*/
|
|
101
|
+
public stop(): void {
|
|
102
|
+
if (this.ttlTimeoutHandle) {
|
|
103
|
+
clearTimeout(this.ttlTimeoutHandle);
|
|
104
|
+
}
|
|
105
|
+
this.isStopped = true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Force to refresh.
|
|
110
|
+
* @throws
|
|
111
|
+
*/
|
|
112
|
+
public async refresh(): Promise<ValueType | undefined> {
|
|
113
|
+
await this.doFetch(true);
|
|
114
|
+
return this.cached;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Internal fetch method
|
|
119
|
+
* @param force - if set to true will force a fetch of the value even if a fetch is already in progress.
|
|
120
|
+
* @private
|
|
121
|
+
*/
|
|
122
|
+
private async doFetch(force: boolean = false): Promise<void> {
|
|
123
|
+
if (this.fetchPromise && !force) {
|
|
124
|
+
await this.fetchPromise;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.fetchPromise = this.fetchWithRetryPolicy();
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
this.cached = await this.fetchPromise;
|
|
132
|
+
if (this.isStopped) {
|
|
133
|
+
this.fetchPromise = undefined;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.logger.trace(`New cachedValue: ${this.cached}`);
|
|
137
|
+
this.opts.onValueCached?.(this.cached);
|
|
138
|
+
// The value is cached only for a given time.
|
|
139
|
+
if (this.ttlMillis) {
|
|
140
|
+
this.ttlTimeoutHandle = setTimeout(() => {
|
|
141
|
+
this.fetchPromise = undefined;
|
|
142
|
+
void this.doFetch();
|
|
143
|
+
}, this.ttlMillis);
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
this.logger.debug(`Error fetching server value for ${error}`);
|
|
147
|
+
if (this.isStopped) {
|
|
148
|
+
this.fetchPromise = undefined;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (!this.opts.shouldCacheError?.(error)) {
|
|
152
|
+
// clear the promise, i.e next tentative will retry to fetch
|
|
153
|
+
this.fetchPromise = undefined;
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Gracefully handle transient error retries, respect retry_after_millis for rate limits.
|
|
161
|
+
* @private
|
|
162
|
+
*/
|
|
163
|
+
private async fetchWithRetryPolicy(): Promise<ValueType> {
|
|
164
|
+
let currentRetryCount = 0;
|
|
165
|
+
while (true) {
|
|
166
|
+
try {
|
|
167
|
+
return await this.opts.fetch();
|
|
168
|
+
} catch (e) {
|
|
169
|
+
this.logger.trace(`Failed to fetch retry: ${e}`);
|
|
170
|
+
if (this.isStopped) {
|
|
171
|
+
throw e;
|
|
172
|
+
}
|
|
173
|
+
currentRetryCount++;
|
|
174
|
+
const backoff = calculateRetryBackoff(e, currentRetryCount, true);
|
|
175
|
+
if (backoff < 0) {
|
|
176
|
+
// Max number of retries reached, or error is not retryable. rethrow the error
|
|
177
|
+
throw e;
|
|
178
|
+
}
|
|
179
|
+
// wait for the specified time and then retry the request
|
|
180
|
+
await sleep(backoff);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
package/src/pushprocessor.ts
CHANGED
|
@@ -294,7 +294,7 @@ export class PushProcessor {
|
|
|
294
294
|
// These lines are mostly to make the tests happy. We shouldn't run into these
|
|
295
295
|
// properties missing in practice.
|
|
296
296
|
if (!newRules) newRules = {} as IPushRules;
|
|
297
|
-
if (!newRules.global) newRules.global = {}
|
|
297
|
+
if (!newRules.global) newRules.global = {};
|
|
298
298
|
if (!newRules.global.override) newRules.global.override = [];
|
|
299
299
|
if (!newRules.global.underride) newRules.global.underride = [];
|
|
300
300
|
|
|
@@ -349,7 +349,7 @@ export class PushProcessor {
|
|
|
349
349
|
// These lines are mostly to make the tests happy. We shouldn't run into these
|
|
350
350
|
// properties missing in practice.
|
|
351
351
|
if (!newRules) newRules = {} as IPushRules;
|
|
352
|
-
if (!newRules.global) newRules.global = {}
|
|
352
|
+
if (!newRules.global) newRules.global = {};
|
|
353
353
|
if (!newRules.global.override) newRules.global.override = [];
|
|
354
354
|
if (!newRules.global.room) newRules.global.room = [];
|
|
355
355
|
if (!newRules.global.sender) newRules.global.sender = [];
|
|
@@ -846,7 +846,7 @@ export class PushProcessor {
|
|
|
846
846
|
for (const kind of RULEKINDS_IN_ORDER) {
|
|
847
847
|
if (this.client.pushRules[scope][kind] === undefined) continue;
|
|
848
848
|
|
|
849
|
-
for (const rule of this.client.pushRules[scope][kind]
|
|
849
|
+
for (const rule of this.client.pushRules[scope][kind]) {
|
|
850
850
|
if (rule.rule_id === ruleId) return { rule, kind };
|
|
851
851
|
}
|
|
852
852
|
}
|
|
@@ -17,7 +17,6 @@ limitations under the License.
|
|
|
17
17
|
import { type IMinimalEvent } from "./sync-accumulator.ts";
|
|
18
18
|
import { EventType } from "./@types/event.ts";
|
|
19
19
|
import { isSupportedReceiptType, MapWithDefault, recursiveMapToObject } from "./utils.ts";
|
|
20
|
-
import { type IContent } from "./models/event.ts";
|
|
21
20
|
import { type ReceiptContent, type ReceiptType } from "./@types/read_receipts.ts";
|
|
22
21
|
|
|
23
22
|
interface AccumulatedReceipt {
|
|
@@ -162,7 +161,7 @@ export class ReceiptAccumulator {
|
|
|
162
161
|
room_id: roomId,
|
|
163
162
|
content: {
|
|
164
163
|
// $event_id: { "m.read": { $user_id: $json } }
|
|
165
|
-
}
|
|
164
|
+
},
|
|
166
165
|
};
|
|
167
166
|
|
|
168
167
|
const receiptEventContent: MapWithDefault<
|
|
@@ -385,7 +385,7 @@ export class MSC4108SignInWithQR {
|
|
|
385
385
|
);
|
|
386
386
|
}
|
|
387
387
|
if (payload.type === PayloadType.Failure) {
|
|
388
|
-
throw new RendezvousError("Failed",
|
|
388
|
+
throw new RendezvousError("Failed", payload.reason);
|
|
389
389
|
}
|
|
390
390
|
if (payload.type !== PayloadType.ProtocolAccepted) {
|
|
391
391
|
throw new RendezvousError("Unexpected message received", MSC4108FailureReason.UnexpectedMessageReceived);
|
|
@@ -412,11 +412,10 @@ export class MSC4108SignInWithQR {
|
|
|
412
412
|
} else if (res.error === "access_denied") {
|
|
413
413
|
reason = MSC4108FailureReason.UserCancelled;
|
|
414
414
|
}
|
|
415
|
-
|
|
415
|
+
await this.send({
|
|
416
416
|
type: PayloadType.Failure,
|
|
417
417
|
reason,
|
|
418
|
-
};
|
|
419
|
-
await this.send(payload);
|
|
418
|
+
} satisfies FailurePayload);
|
|
420
419
|
|
|
421
420
|
throw new RendezvousError("Rejection from device authorization endpoint", reason);
|
|
422
421
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2026 The Matrix.org Foundation C.I.C.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { PollingCachedValue } from "./pollingCachedValue.ts";
|
|
18
|
+
import { type Transport } from "./matrixrtc/index.ts";
|
|
19
|
+
import { ClientEvent, type MatrixClient } from "./client.ts";
|
|
20
|
+
import { type Logger } from "./logger.ts";
|
|
21
|
+
import { MatrixError } from "./http-api/index.ts";
|
|
22
|
+
|
|
23
|
+
const TRANSPORT_CACHE_TTL_MILLISECONDS = 1000 * 60 * 60 * 24; // 1 day
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Builds a cache for the rtc/transport discovery end-point of the given client.
|
|
27
|
+
*/
|
|
28
|
+
export function createRtcTransportsCachedValue(client: MatrixClient, logger: Logger): PollingCachedValue<Transport[]> {
|
|
29
|
+
return new PollingCachedValue({
|
|
30
|
+
name: "RTCTransports",
|
|
31
|
+
logger,
|
|
32
|
+
ttlMillis: TRANSPORT_CACHE_TTL_MILLISECONDS,
|
|
33
|
+
fetch: () => client._unstable_getRTCTransports(),
|
|
34
|
+
onValueCached: (transports) => client.emit(ClientEvent.RtcTransportsUpdated, transports),
|
|
35
|
+
// If the end point is not supported by the homeserver it will be a 404 error.
|
|
36
|
+
// This is a final error, it can be cached, no need to retry everytime.
|
|
37
|
+
// It will retry when ttl has expired.
|
|
38
|
+
shouldCacheError: (error) => error instanceof MatrixError && error.httpStatus === 404,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -394,7 +394,7 @@ export class PerSessionKeyBackupDownloader {
|
|
|
394
394
|
): Promise<void> {
|
|
395
395
|
const sessionsToImport: Record<string, KeyBackupSession> = { [sessionInfo.megolmSessionId]: data };
|
|
396
396
|
|
|
397
|
-
const keys = await configuration
|
|
397
|
+
const keys = await configuration.decryptor.decryptSessions(sessionsToImport);
|
|
398
398
|
for (const k of keys) {
|
|
399
399
|
k.room_id = sessionInfo.roomId;
|
|
400
400
|
}
|
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
type KeyBackupCheck,
|
|
24
24
|
type KeyBackupInfo,
|
|
25
25
|
type KeyBackupSession,
|
|
26
|
-
type Curve25519SessionData,
|
|
27
26
|
type KeyBackupRestoreOpts,
|
|
28
27
|
type KeyBackupRestoreResult,
|
|
29
28
|
type KeyBackupRoomSessions,
|
|
@@ -42,7 +41,6 @@ import {
|
|
|
42
41
|
CryptoEvent,
|
|
43
42
|
ImportRoomKeyStage,
|
|
44
43
|
} from "../crypto-api/index.ts";
|
|
45
|
-
import { type AESEncryptedSecretStoragePayload } from "../@types/AESEncryptedSecretStoragePayload.ts";
|
|
46
44
|
import { type IMegolmSessionData } from "../@types/crypto.ts";
|
|
47
45
|
|
|
48
46
|
/** Authentification of the backup info, depends on algorithm */
|
|
@@ -901,9 +899,7 @@ export class RustBackupDecryptor implements BackupDecryptor {
|
|
|
901
899
|
/**
|
|
902
900
|
* Implements {@link BackupDecryptor#decryptSessions}
|
|
903
901
|
*/
|
|
904
|
-
public async decryptSessions(
|
|
905
|
-
ciphertexts: Record<string, KeyBackupSession<Curve25519SessionData | AESEncryptedSecretStoragePayload>>,
|
|
906
|
-
): Promise<IMegolmSessionData[]> {
|
|
902
|
+
public async decryptSessions(ciphertexts: Record<string, KeyBackupSession>): Promise<IMegolmSessionData[]> {
|
|
907
903
|
const keys: IMegolmSessionData[] = [];
|
|
908
904
|
for (const [sessionId, sessionData] of Object.entries(ciphertexts)) {
|
|
909
905
|
try {
|