You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-06 12:02:40 +03:00
Update eslint-plugin-matrix-org and improve visibilities & types (#2887)
This commit is contained in:
committed by
GitHub
parent
e085609572
commit
c0f7df8c3b
@@ -85,5 +85,14 @@ module.exports = {
|
|||||||
// We use a `logger` intermediary module
|
// We use a `logger` intermediary module
|
||||||
"no-console": "error",
|
"no-console": "error",
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
files: [
|
||||||
|
"spec/**/*.ts",
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
// We don't need super strict typing in test utilities
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": "off",
|
||||||
|
},
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
@@ -99,7 +99,7 @@
|
|||||||
"eslint-config-google": "^0.14.0",
|
"eslint-config-google": "^0.14.0",
|
||||||
"eslint-import-resolver-typescript": "^3.5.1",
|
"eslint-import-resolver-typescript": "^3.5.1",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-plugin-matrix-org": "^0.7.0",
|
"eslint-plugin-matrix-org": "^0.8.0",
|
||||||
"eslint-plugin-unicorn": "^44.0.2",
|
"eslint-plugin-unicorn": "^44.0.2",
|
||||||
"exorcist": "^2.0.0",
|
"exorcist": "^2.0.0",
|
||||||
"fake-indexeddb": "^4.0.0",
|
"fake-indexeddb": "^4.0.0",
|
||||||
|
@@ -709,11 +709,11 @@ describe("MatrixClient syncing", () => {
|
|||||||
const room = client!.getRoom(roomOne)!;
|
const room = client!.getRoom(roomOne)!;
|
||||||
const stateAtStart = room.getLiveTimeline().getState(EventTimeline.BACKWARDS)!;
|
const stateAtStart = room.getLiveTimeline().getState(EventTimeline.BACKWARDS)!;
|
||||||
const startRoomNameEvent = stateAtStart.getStateEvents('m.room.name', '');
|
const startRoomNameEvent = stateAtStart.getStateEvents('m.room.name', '');
|
||||||
expect(startRoomNameEvent.getContent().name).toEqual('Old room name');
|
expect(startRoomNameEvent!.getContent().name).toEqual('Old room name');
|
||||||
|
|
||||||
const stateAtEnd = room.getLiveTimeline().getState(EventTimeline.FORWARDS)!;
|
const stateAtEnd = room.getLiveTimeline().getState(EventTimeline.FORWARDS)!;
|
||||||
const endRoomNameEvent = stateAtEnd.getStateEvents('m.room.name', '');
|
const endRoomNameEvent = stateAtEnd.getStateEvents('m.room.name', '');
|
||||||
expect(endRoomNameEvent.getContent().name).toEqual('A new room name');
|
expect(endRoomNameEvent!.getContent().name).toEqual('A new room name');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1599,7 +1599,7 @@ describe("MatrixClient syncing", () => {
|
|||||||
expect(room.roomId).toBe(roomOne);
|
expect(room.roomId).toBe(roomOne);
|
||||||
expect(room.getMyMembership()).toBe("leave");
|
expect(room.getMyMembership()).toBe("leave");
|
||||||
expect(room.name).toBe("Room Name");
|
expect(room.name).toBe("Room Name");
|
||||||
expect(room.currentState.getStateEvents("m.room.name", "").getId()).toBe("$eventId");
|
expect(room.currentState.getStateEvents("m.room.name", "")?.getId()).toBe("$eventId");
|
||||||
expect(room.timeline[0].getContent().body).toBe("Message 1");
|
expect(room.timeline[0].getContent().body).toBe("Message 1");
|
||||||
expect(room.timeline[1].getContent().body).toBe("Message 2");
|
expect(room.timeline[1].getContent().body).toBe("Message 2");
|
||||||
client?.stopPeeking();
|
client?.stopPeeking();
|
||||||
|
@@ -179,7 +179,7 @@ describe("RoomWidgetClient", () => {
|
|||||||
// It should've also inserted the event into the room object
|
// It should've also inserted the event into the room object
|
||||||
const room = client.getRoom("!1:example.org");
|
const room = client.getRoom("!1:example.org");
|
||||||
expect(room).not.toBeNull();
|
expect(room).not.toBeNull();
|
||||||
expect(room!.currentState.getStateEvents("org.example.foo", "bar").getEffectiveEvent()).toEqual(event);
|
expect(room!.currentState.getStateEvents("org.example.foo", "bar")?.getEffectiveEvent()).toEqual(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("backfills", async () => {
|
it("backfills", async () => {
|
||||||
@@ -195,7 +195,7 @@ describe("RoomWidgetClient", () => {
|
|||||||
|
|
||||||
const room = client.getRoom("!1:example.org");
|
const room = client.getRoom("!1:example.org");
|
||||||
expect(room).not.toBeNull();
|
expect(room).not.toBeNull();
|
||||||
expect(room!.currentState.getStateEvents("org.example.foo", "bar").getEffectiveEvent()).toEqual(event);
|
expect(room!.currentState.getStateEvents("org.example.foo", "bar")?.getEffectiveEvent()).toEqual(event);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -152,7 +152,7 @@ describe("RoomState", function() {
|
|||||||
it("should return a single MatrixEvent if a state_key was specified",
|
it("should return a single MatrixEvent if a state_key was specified",
|
||||||
function() {
|
function() {
|
||||||
const event = state.getStateEvents("m.room.member", userA);
|
const event = state.getStateEvents("m.room.member", userA);
|
||||||
expect(event.getContent()).toMatchObject({
|
expect(event?.getContent()).toMatchObject({
|
||||||
membership: "join",
|
membership: "join",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -22,7 +22,7 @@ import { EventEmitter } from "events";
|
|||||||
import { ListenerMap, TypedEventEmitter } from "./models/typed-event-emitter";
|
import { ListenerMap, TypedEventEmitter } from "./models/typed-event-emitter";
|
||||||
|
|
||||||
export class ReEmitter {
|
export class ReEmitter {
|
||||||
constructor(private readonly target: EventEmitter) {}
|
public constructor(private readonly target: EventEmitter) {}
|
||||||
|
|
||||||
// Map from emitter to event name to re-emitter
|
// Map from emitter to event name to re-emitter
|
||||||
private reEmitters = new Map<EventEmitter, Map<string, (...args: any[]) => void>>();
|
private reEmitters = new Map<EventEmitter, Map<string, (...args: any[]) => void>>();
|
||||||
@@ -38,7 +38,7 @@ export class ReEmitter {
|
|||||||
// We include the source as the last argument for event handlers which may need it,
|
// We include the source as the last argument for event handlers which may need it,
|
||||||
// such as read receipt listeners on the client class which won't have the context
|
// such as read receipt listeners on the client class which won't have the context
|
||||||
// of the room.
|
// of the room.
|
||||||
const forSource = (...args: any[]) => {
|
const forSource = (...args: any[]): void => {
|
||||||
// EventEmitter special cases 'error' to make the emit function throw if no
|
// EventEmitter special cases 'error' to make the emit function throw if no
|
||||||
// handler is attached, which sort of makes sense for making sure that something
|
// handler is attached, which sort of makes sense for making sure that something
|
||||||
// handles an error, but for re-emitting, there could be a listener on the original
|
// handles an error, but for re-emitting, there could be a listener on the original
|
||||||
@@ -74,7 +74,7 @@ export class TypedReEmitter<
|
|||||||
Events extends string,
|
Events extends string,
|
||||||
Arguments extends ListenerMap<Events>,
|
Arguments extends ListenerMap<Events>,
|
||||||
> extends ReEmitter {
|
> extends ReEmitter {
|
||||||
constructor(target: TypedEventEmitter<Events, Arguments>) {
|
public constructor(target: TypedEventEmitter<Events, Arguments>) {
|
||||||
super(target);
|
super(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ export class ToDeviceMessageQueue {
|
|||||||
private retryTimeout: ReturnType<typeof setTimeout> | null = null;
|
private retryTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||||
private retryAttempts = 0;
|
private retryAttempts = 0;
|
||||||
|
|
||||||
constructor(private client: MatrixClient) {
|
public constructor(private client: MatrixClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(): void {
|
public start(): void {
|
||||||
|
@@ -1010,7 +1010,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
// A manager for determining which invites should be ignored.
|
// A manager for determining which invites should be ignored.
|
||||||
public readonly ignoredInvites: IgnoredInvites;
|
public readonly ignoredInvites: IgnoredInvites;
|
||||||
|
|
||||||
constructor(opts: IMatrixClientCreateOpts) {
|
public constructor(opts: IMatrixClientCreateOpts) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
opts.baseUrl = utils.ensureNoTrailingSlash(opts.baseUrl);
|
opts.baseUrl = utils.ensureNoTrailingSlash(opts.baseUrl);
|
||||||
@@ -1232,7 +1232,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
// shallow-copy the opts dict before modifying and storing it
|
// shallow-copy the opts dict before modifying and storing it
|
||||||
this.clientOpts = Object.assign({}, opts) as IStoredClientOpts;
|
this.clientOpts = Object.assign({}, opts) as IStoredClientOpts;
|
||||||
this.clientOpts.crypto = this.crypto;
|
this.clientOpts.crypto = this.crypto;
|
||||||
this.clientOpts.canResetEntireTimeline = (roomId) => {
|
this.clientOpts.canResetEntireTimeline = (roomId): boolean => {
|
||||||
if (!this.canResetTimelineCallback) {
|
if (!this.canResetTimelineCallback) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1259,7 +1259,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* High level helper method to stop the client from polling and allow a
|
* High level helper method to stop the client from polling and allow a
|
||||||
* clean shutdown.
|
* clean shutdown.
|
||||||
*/
|
*/
|
||||||
public stopClient() {
|
public stopClient(): void {
|
||||||
this.crypto?.stop(); // crypto might have been initialised even if the client wasn't fully started
|
this.crypto?.stop(); // crypto might have been initialised even if the client wasn't fully started
|
||||||
|
|
||||||
if (!this.clientRunning) return; // already stopped
|
if (!this.clientRunning) return; // already stopped
|
||||||
@@ -1536,7 +1536,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* when creating the client.
|
* when creating the client.
|
||||||
* @param {boolean} force True to force use of TURN servers
|
* @param {boolean} force True to force use of TURN servers
|
||||||
*/
|
*/
|
||||||
public setForceTURN(force: boolean) {
|
public setForceTURN(force: boolean): void {
|
||||||
this.forceTURN = force;
|
this.forceTURN = force;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1544,7 +1544,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* Set whether to advertise transfer support to other parties on Matrix calls.
|
* Set whether to advertise transfer support to other parties on Matrix calls.
|
||||||
* @param {boolean} support True to advertise the 'm.call.transferee' capability
|
* @param {boolean} support True to advertise the 'm.call.transferee' capability
|
||||||
*/
|
*/
|
||||||
public setSupportsCallTransfer(support: boolean) {
|
public setSupportsCallTransfer(support: boolean): void {
|
||||||
this.supportsCallTransfer = support;
|
this.supportsCallTransfer = support;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1678,7 +1678,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* and may change without warning.</b>
|
* and may change without warning.</b>
|
||||||
* @param {boolean} guest True if this is a guest account.
|
* @param {boolean} guest True if this is a guest account.
|
||||||
*/
|
*/
|
||||||
public setGuest(guest: boolean) {
|
public setGuest(guest: boolean): void {
|
||||||
// EXPERIMENTAL:
|
// EXPERIMENTAL:
|
||||||
// If the token is a macaroon, it should be encoded in it that it is a 'guest'
|
// If the token is a macaroon, it should be encoded in it that it is a 'guest'
|
||||||
// access token, which means that the SDK can determine this entirely without
|
// access token, which means that the SDK can determine this entirely without
|
||||||
@@ -1721,7 +1721,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
*
|
*
|
||||||
* @param {EventTimelineSet} set
|
* @param {EventTimelineSet} set
|
||||||
*/
|
*/
|
||||||
public setNotifTimelineSet(set: EventTimelineSet) {
|
public setNotifTimelineSet(set: EventTimelineSet): void {
|
||||||
this.notifTimelineSet = set;
|
this.notifTimelineSet = set;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2279,11 +2279,11 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* send, in order to speed up sending of the message.
|
* send, in order to speed up sending of the message.
|
||||||
* @param {module:models/room} room the room the event is in
|
* @param {module:models/room} room the room the event is in
|
||||||
*/
|
*/
|
||||||
public prepareToEncrypt(room: Room) {
|
public prepareToEncrypt(room: Room): void {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
return this.crypto.prepareToEncrypt(room);
|
this.crypto.prepareToEncrypt(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2324,7 +2324,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* auth data as an object. Can be called multiple times, first with an empty
|
* auth data as an object. Can be called multiple times, first with an empty
|
||||||
* authDict, to obtain the flows.
|
* authDict, to obtain the flows.
|
||||||
*/
|
*/
|
||||||
public bootstrapCrossSigning(opts: IBootstrapCrossSigningOpts) {
|
public bootstrapCrossSigning(opts: IBootstrapCrossSigningOpts): Promise<void> {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -2352,11 +2352,11 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
*
|
*
|
||||||
* @param {boolean} val True to trust cross-signed devices
|
* @param {boolean} val True to trust cross-signed devices
|
||||||
*/
|
*/
|
||||||
public setCryptoTrustCrossSignedDevices(val: boolean) {
|
public setCryptoTrustCrossSignedDevices(val: boolean): void {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
return this.crypto.setCryptoTrustCrossSignedDevices(val);
|
this.crypto.setCryptoTrustCrossSignedDevices(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2497,7 +2497,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* @param {Array} keys The IDs of the keys to use to encrypt the secret or null/undefined
|
* @param {Array} keys The IDs of the keys to use to encrypt the secret or null/undefined
|
||||||
* to use the default (will throw if no default key is set).
|
* to use the default (will throw if no default key is set).
|
||||||
*/
|
*/
|
||||||
public storeSecret(name: string, secret: string, keys?: string[]) {
|
public storeSecret(name: string, secret: string, keys?: string[]): Promise<void> {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -2575,7 +2575,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
*
|
*
|
||||||
* @param {string} keyId The new default key ID
|
* @param {string} keyId The new default key ID
|
||||||
*/
|
*/
|
||||||
public setDefaultSecretStorageKeyId(keyId: string) {
|
public setDefaultSecretStorageKeyId(keyId: string): Promise<void> {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -2716,7 +2716,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
*
|
*
|
||||||
* This should not normally be necessary.
|
* This should not normally be necessary.
|
||||||
*/
|
*/
|
||||||
public forceDiscardSession(roomId: string) {
|
public forceDiscardSession(roomId: string): void {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-End encryption disabled");
|
throw new Error("End-to-End encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -2840,7 +2840,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
/**
|
/**
|
||||||
* Disable backing up of keys.
|
* Disable backing up of keys.
|
||||||
*/
|
*/
|
||||||
public disableKeyBackup() {
|
public disableKeyBackup(): void {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -3044,7 +3044,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* Marks all group sessions as needing to be backed up and schedules them to
|
* Marks all group sessions as needing to be backed up and schedules them to
|
||||||
* upload in the background as soon as possible.
|
* upload in the background as soon as possible.
|
||||||
*/
|
*/
|
||||||
public async scheduleAllGroupSessionsForBackup() {
|
public async scheduleAllGroupSessionsForBackup(): Promise<void> {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -3401,7 +3401,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* @param {array} userIds a list of users to share with. The keys will be sent to
|
* @param {array} userIds a list of users to share with. The keys will be sent to
|
||||||
* all of the user's current devices.
|
* all of the user's current devices.
|
||||||
*/
|
*/
|
||||||
public async sendSharedHistoryKeys(roomId: string, userIds: string[]) {
|
public async sendSharedHistoryKeys(roomId: string, userIds: string[]): Promise<void> {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -3685,7 +3685,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* @param {MatrixEvent} event Event to cancel
|
* @param {MatrixEvent} event Event to cancel
|
||||||
* @throws Error if the event is not in QUEUED, NOT_SENT or ENCRYPTING state
|
* @throws Error if the event is not in QUEUED, NOT_SENT or ENCRYPTING state
|
||||||
*/
|
*/
|
||||||
public cancelPendingEvent(event: MatrixEvent) {
|
public cancelPendingEvent(event: MatrixEvent): void {
|
||||||
if (![EventStatus.QUEUED, EventStatus.NOT_SENT, EventStatus.ENCRYPTING].includes(event.status!)) {
|
if (![EventStatus.QUEUED, EventStatus.NOT_SENT, EventStatus.ENCRYPTING].includes(event.status!)) {
|
||||||
throw new Error("cannot cancel an event with status " + event.status);
|
throw new Error("cannot cancel an event with status " + event.status);
|
||||||
}
|
}
|
||||||
@@ -3834,7 +3834,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
public async unstable_createLiveBeacon(
|
public async unstable_createLiveBeacon(
|
||||||
roomId: Room["roomId"],
|
roomId: Room["roomId"],
|
||||||
beaconInfoContent: MBeaconInfoEventContent,
|
beaconInfoContent: MBeaconInfoEventContent,
|
||||||
) {
|
): Promise<ISendEventResponse> {
|
||||||
return this.unstable_setLiveBeacon(roomId, beaconInfoContent);
|
return this.unstable_setLiveBeacon(roomId, beaconInfoContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3849,7 +3849,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
public async unstable_setLiveBeacon(
|
public async unstable_setLiveBeacon(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
beaconInfoContent: MBeaconInfoEventContent,
|
beaconInfoContent: MBeaconInfoEventContent,
|
||||||
) {
|
): Promise<ISendEventResponse> {
|
||||||
return this.sendStateEvent(roomId, M_BEACON_INFO.name, beaconInfoContent, this.getUserId()!);
|
return this.sendStateEvent(roomId, M_BEACON_INFO.name, beaconInfoContent, this.getUserId()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4121,7 +4121,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
return this.isRoomEncrypted(roomId) ? EventType.RoomMessageEncrypted : eventType;
|
return this.isRoomEncrypted(roomId) ? EventType.RoomMessageEncrypted : eventType;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updatePendingEventStatus(room: Room | null, event: MatrixEvent, newStatus: EventStatus) {
|
protected updatePendingEventStatus(room: Room | null, event: MatrixEvent, newStatus: EventStatus): void {
|
||||||
if (room) {
|
if (room) {
|
||||||
room.updatePendingEvent(event, newStatus);
|
room.updatePendingEvent(event, newStatus);
|
||||||
} else {
|
} else {
|
||||||
@@ -4944,12 +4944,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
const populationResults: { [roomId: string]: Error } = {};
|
const populationResults: { [roomId: string]: Error } = {};
|
||||||
const promises: Promise<any>[] = [];
|
const promises: Promise<any>[] = [];
|
||||||
|
|
||||||
const doLeave = (roomId: string) => {
|
const doLeave = (roomId: string): Promise<void> => {
|
||||||
return this.leave(roomId).then(() => {
|
return this.leave(roomId).then(() => {
|
||||||
delete populationResults[roomId];
|
delete populationResults[roomId];
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
// suppress error
|
||||||
populationResults[roomId] = err;
|
populationResults[roomId] = err;
|
||||||
return null; // suppress error
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5904,7 +5904,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* Reset the notifTimelineSet entirely, paginating in some historical notifs as
|
* Reset the notifTimelineSet entirely, paginating in some historical notifs as
|
||||||
* a starting point for subsequent pagination.
|
* a starting point for subsequent pagination.
|
||||||
*/
|
*/
|
||||||
public resetNotifTimelineSet() {
|
public resetNotifTimelineSet(): void {
|
||||||
if (!this.notifTimelineSet) {
|
if (!this.notifTimelineSet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5949,7 +5949,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
/**
|
/**
|
||||||
* Stop any ongoing room peeking.
|
* Stop any ongoing room peeking.
|
||||||
*/
|
*/
|
||||||
public stopPeeking() {
|
public stopPeeking(): void {
|
||||||
if (this.peekSync) {
|
if (this.peekSync) {
|
||||||
this.peekSync.stopPeeking();
|
this.peekSync.stopPeeking();
|
||||||
this.peekSync = null;
|
this.peekSync = null;
|
||||||
@@ -6683,7 +6683,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
*
|
*
|
||||||
* @param {boolean} allow
|
* @param {boolean} allow
|
||||||
*/
|
*/
|
||||||
public setFallbackICEServerAllowed(allow: boolean) {
|
public setFallbackICEServerAllowed(allow: boolean): void {
|
||||||
this.fallbackICEServerAllowed = allow;
|
this.fallbackICEServerAllowed = allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7024,7 +7024,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* Default: returns false.
|
* Default: returns false.
|
||||||
* @param {Function} cb The callback which will be invoked.
|
* @param {Function} cb The callback which will be invoked.
|
||||||
*/
|
*/
|
||||||
public setCanResetTimelineCallback(cb: ResetTimelineCallback) {
|
public setCanResetTimelineCallback(cb: ResetTimelineCallback): void {
|
||||||
this.canResetTimelineCallback = cb;
|
this.canResetTimelineCallback = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7164,7 +7164,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* Set the identity server URL of this client
|
* Set the identity server URL of this client
|
||||||
* @param {string} url New identity server URL
|
* @param {string} url New identity server URL
|
||||||
*/
|
*/
|
||||||
public setIdentityServerUrl(url: string) {
|
public setIdentityServerUrl(url: string): void {
|
||||||
this.idBaseUrl = utils.ensureNoTrailingSlash(url);
|
this.idBaseUrl = utils.ensureNoTrailingSlash(url);
|
||||||
this.http.setIdBaseUrl(this.idBaseUrl);
|
this.http.setIdBaseUrl(this.idBaseUrl);
|
||||||
}
|
}
|
||||||
@@ -7181,7 +7181,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* Set the access token associated with this account.
|
* Set the access token associated with this account.
|
||||||
* @param {string} token The new access token.
|
* @param {string} token The new access token.
|
||||||
*/
|
*/
|
||||||
public setAccessToken(token: string) {
|
public setAccessToken(token: string): void {
|
||||||
this.http.opts.accessToken = token;
|
this.http.opts.accessToken = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,6 +33,7 @@ import {
|
|||||||
LegacyLocationEventContent,
|
LegacyLocationEventContent,
|
||||||
} from "./@types/location";
|
} from "./@types/location";
|
||||||
import { MRoomTopicEventContent, MTopicContent, M_TOPIC } from "./@types/topic";
|
import { MRoomTopicEventContent, MTopicContent, M_TOPIC } from "./@types/topic";
|
||||||
|
import { IContent } from "./models/event";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the content for a HTML Message event
|
* Generates the content for a HTML Message event
|
||||||
@@ -40,7 +41,7 @@ import { MRoomTopicEventContent, MTopicContent, M_TOPIC } from "./@types/topic";
|
|||||||
* @param {string} htmlBody the HTML representation of the message
|
* @param {string} htmlBody the HTML representation of the message
|
||||||
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
|
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
|
||||||
*/
|
*/
|
||||||
export function makeHtmlMessage(body: string, htmlBody: string) {
|
export function makeHtmlMessage(body: string, htmlBody: string): IContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Text,
|
msgtype: MsgType.Text,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@@ -55,7 +56,7 @@ export function makeHtmlMessage(body: string, htmlBody: string) {
|
|||||||
* @param {string} htmlBody the HTML representation of the notice
|
* @param {string} htmlBody the HTML representation of the notice
|
||||||
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
|
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
|
||||||
*/
|
*/
|
||||||
export function makeHtmlNotice(body: string, htmlBody: string) {
|
export function makeHtmlNotice(body: string, htmlBody: string): IContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Notice,
|
msgtype: MsgType.Notice,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@@ -70,7 +71,7 @@ export function makeHtmlNotice(body: string, htmlBody: string) {
|
|||||||
* @param {string} htmlBody the HTML representation of the emote
|
* @param {string} htmlBody the HTML representation of the emote
|
||||||
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
|
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
|
||||||
*/
|
*/
|
||||||
export function makeHtmlEmote(body: string, htmlBody: string) {
|
export function makeHtmlEmote(body: string, htmlBody: string): IContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Emote,
|
msgtype: MsgType.Emote,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
@@ -84,7 +85,7 @@ export function makeHtmlEmote(body: string, htmlBody: string) {
|
|||||||
* @param {string} body the plaintext body of the emote
|
* @param {string} body the plaintext body of the emote
|
||||||
* @returns {{msgtype: string, body: string}}
|
* @returns {{msgtype: string, body: string}}
|
||||||
*/
|
*/
|
||||||
export function makeTextMessage(body: string) {
|
export function makeTextMessage(body: string): IContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Text,
|
msgtype: MsgType.Text,
|
||||||
body: body,
|
body: body,
|
||||||
@@ -96,7 +97,7 @@ export function makeTextMessage(body: string) {
|
|||||||
* @param {string} body the plaintext body of the notice
|
* @param {string} body the plaintext body of the notice
|
||||||
* @returns {{msgtype: string, body: string}}
|
* @returns {{msgtype: string, body: string}}
|
||||||
*/
|
*/
|
||||||
export function makeNotice(body: string) {
|
export function makeNotice(body: string): IContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Notice,
|
msgtype: MsgType.Notice,
|
||||||
body: body,
|
body: body,
|
||||||
@@ -108,7 +109,7 @@ export function makeNotice(body: string) {
|
|||||||
* @param {string} body the plaintext body of the emote
|
* @param {string} body the plaintext body of the emote
|
||||||
* @returns {{msgtype: string, body: string}}
|
* @returns {{msgtype: string, body: string}}
|
||||||
*/
|
*/
|
||||||
export function makeEmoteMessage(body: string) {
|
export function makeEmoteMessage(body: string): IContent {
|
||||||
return {
|
return {
|
||||||
msgtype: MsgType.Emote,
|
msgtype: MsgType.Emote,
|
||||||
body: body,
|
body: body,
|
||||||
|
@@ -21,7 +21,7 @@ limitations under the License.
|
|||||||
|
|
||||||
import { PkSigning } from "@matrix-org/olm";
|
import { PkSigning } from "@matrix-org/olm";
|
||||||
|
|
||||||
import { decodeBase64, encodeBase64, pkSign, pkVerify } from './olmlib';
|
import { decodeBase64, encodeBase64, IObject, pkSign, pkVerify } from './olmlib';
|
||||||
import { logger } from '../logger';
|
import { logger } from '../logger';
|
||||||
import { IndexedDBCryptoStore } from '../crypto/store/indexeddb-crypto-store';
|
import { IndexedDBCryptoStore } from '../crypto/store/indexeddb-crypto-store';
|
||||||
import { decryptAES, encryptAES } from './aes';
|
import { decryptAES, encryptAES } from './aes';
|
||||||
@@ -74,7 +74,7 @@ export class CrossSigningInfo {
|
|||||||
* Requires getCrossSigningKey and saveCrossSigningKeys
|
* Requires getCrossSigningKey and saveCrossSigningKeys
|
||||||
* @param {object} cacheCallbacks Callbacks used to interact with the cache
|
* @param {object} cacheCallbacks Callbacks used to interact with the cache
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly userId: string,
|
public readonly userId: string,
|
||||||
private callbacks: ICryptoCallbacks = {},
|
private callbacks: ICryptoCallbacks = {},
|
||||||
private cacheCallbacks: ICacheCallbacks = {},
|
private cacheCallbacks: ICacheCallbacks = {},
|
||||||
@@ -175,7 +175,7 @@ export class CrossSigningInfo {
|
|||||||
// check what SSSS keys have encrypted the master key (if any)
|
// check what SSSS keys have encrypted the master key (if any)
|
||||||
const stored = await secretStorage.isStored("m.cross_signing.master") || {};
|
const stored = await secretStorage.isStored("m.cross_signing.master") || {};
|
||||||
// then check which of those SSSS keys have also encrypted the SSK and USK
|
// then check which of those SSSS keys have also encrypted the SSK and USK
|
||||||
function intersect(s: Record<string, ISecretStorageKeyInfo>) {
|
function intersect(s: Record<string, ISecretStorageKeyInfo>): void {
|
||||||
for (const k of Object.keys(stored)) {
|
for (const k of Object.keys(stored)) {
|
||||||
if (!s[k]) {
|
if (!s[k]) {
|
||||||
delete stored[k];
|
delete stored[k];
|
||||||
@@ -586,7 +586,14 @@ export class CrossSigningInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deviceToObject(device: DeviceInfo, userId: string) {
|
interface DeviceObject extends IObject {
|
||||||
|
algorithms: string[];
|
||||||
|
keys: Record<string, string>;
|
||||||
|
device_id: string;
|
||||||
|
user_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deviceToObject(device: DeviceInfo, userId: string): DeviceObject {
|
||||||
return {
|
return {
|
||||||
algorithms: device.algorithms,
|
algorithms: device.algorithms,
|
||||||
keys: device.keys,
|
keys: device.keys,
|
||||||
@@ -606,7 +613,7 @@ export enum CrossSigningLevel {
|
|||||||
* Represents the ways in which we trust a user
|
* Represents the ways in which we trust a user
|
||||||
*/
|
*/
|
||||||
export class UserTrustLevel {
|
export class UserTrustLevel {
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly crossSigningVerified: boolean,
|
private readonly crossSigningVerified: boolean,
|
||||||
private readonly crossSigningVerifiedBefore: boolean,
|
private readonly crossSigningVerifiedBefore: boolean,
|
||||||
private readonly tofu: boolean,
|
private readonly tofu: boolean,
|
||||||
@@ -646,7 +653,7 @@ export class UserTrustLevel {
|
|||||||
* Represents the ways in which we trust a device
|
* Represents the ways in which we trust a device
|
||||||
*/
|
*/
|
||||||
export class DeviceTrustLevel {
|
export class DeviceTrustLevel {
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly crossSigningVerified: boolean,
|
public readonly crossSigningVerified: boolean,
|
||||||
public readonly tofu: boolean,
|
public readonly tofu: boolean,
|
||||||
private readonly localVerified: boolean,
|
private readonly localVerified: boolean,
|
||||||
@@ -775,7 +782,7 @@ export async function requestKeysDuringVerification(
|
|||||||
// CrossSigningInfo.getCrossSigningKey() to validate/cache
|
// CrossSigningInfo.getCrossSigningKey() to validate/cache
|
||||||
const crossSigning = new CrossSigningInfo(
|
const crossSigning = new CrossSigningInfo(
|
||||||
original.userId,
|
original.userId,
|
||||||
{ getCrossSigningKey: async (type) => {
|
{ getCrossSigningKey: async (type): Promise<Uint8Array> => {
|
||||||
logger.debug("Cross-signing: requesting secret", type, deviceId);
|
logger.debug("Cross-signing: requesting secret", type, deviceId);
|
||||||
const { promise } = client.requestSecret(
|
const { promise } = client.requestSecret(
|
||||||
`m.cross_signing.${type}`, [deviceId],
|
`m.cross_signing.${type}`, [deviceId],
|
||||||
@@ -801,7 +808,7 @@ export async function requestKeysDuringVerification(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// also request and cache the key backup key
|
// also request and cache the key backup key
|
||||||
const backupKeyPromise = (async () => {
|
const backupKeyPromise = (async (): Promise<void> => {
|
||||||
const cachedKey = await client.crypto!.getSessionBackupPrivateKey();
|
const cachedKey = await client.crypto!.getSessionBackupPrivateKey();
|
||||||
if (!cachedKey) {
|
if (!cachedKey) {
|
||||||
logger.info("No cached backup key found. Requesting...");
|
logger.info("No cached backup key found. Requesting...");
|
||||||
|
@@ -102,7 +102,7 @@ export class DeviceList extends TypedEventEmitter<EmittedEvents, CryptoEventHand
|
|||||||
|
|
||||||
private readonly serialiser: DeviceListUpdateSerialiser;
|
private readonly serialiser: DeviceListUpdateSerialiser;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
baseApis: MatrixClient,
|
baseApis: MatrixClient,
|
||||||
private readonly cryptoStore: CryptoStore,
|
private readonly cryptoStore: CryptoStore,
|
||||||
olmDevice: OlmDevice,
|
olmDevice: OlmDevice,
|
||||||
@@ -117,7 +117,7 @@ export class DeviceList extends TypedEventEmitter<EmittedEvents, CryptoEventHand
|
|||||||
/**
|
/**
|
||||||
* Load the device tracking state from storage
|
* Load the device tracking state from storage
|
||||||
*/
|
*/
|
||||||
public async load() {
|
public async load(): Promise<void> {
|
||||||
await this.cryptoStore.doTxn(
|
await this.cryptoStore.doTxn(
|
||||||
'readonly', [IndexedDBCryptoStore.STORE_DEVICE_DATA], (txn) => {
|
'readonly', [IndexedDBCryptoStore.STORE_DEVICE_DATA], (txn) => {
|
||||||
this.cryptoStore.getEndToEndDeviceData(txn, (deviceData) => {
|
this.cryptoStore.getEndToEndDeviceData(txn, (deviceData) => {
|
||||||
@@ -150,7 +150,7 @@ export class DeviceList extends TypedEventEmitter<EmittedEvents, CryptoEventHand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop() {
|
public stop(): void {
|
||||||
if (this.saveTimer !== null) {
|
if (this.saveTimer !== null) {
|
||||||
clearTimeout(this.saveTimer);
|
clearTimeout(this.saveTimer);
|
||||||
}
|
}
|
||||||
@@ -693,7 +693,7 @@ class DeviceListUpdateSerialiser {
|
|||||||
* @param {object} olmDevice The Olm Device
|
* @param {object} olmDevice The Olm Device
|
||||||
* @param {object} deviceList The device list object, the device list to be updated
|
* @param {object} deviceList The device list object, the device list to be updated
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly baseApis: MatrixClient,
|
private readonly baseApis: MatrixClient,
|
||||||
private readonly olmDevice: OlmDevice,
|
private readonly olmDevice: OlmDevice,
|
||||||
private readonly deviceList: DeviceList,
|
private readonly deviceList: DeviceList,
|
||||||
|
@@ -61,7 +61,7 @@ export class EncryptionSetupBuilder {
|
|||||||
* @param {Object.<String, MatrixEvent>} accountData pre-existing account data, will only be read, not written.
|
* @param {Object.<String, MatrixEvent>} accountData pre-existing account data, will only be read, not written.
|
||||||
* @param {CryptoCallbacks} delegateCryptoCallbacks crypto callbacks to delegate to if the key isn't in cache yet
|
* @param {CryptoCallbacks} delegateCryptoCallbacks crypto callbacks to delegate to if the key isn't in cache yet
|
||||||
*/
|
*/
|
||||||
constructor(accountData: Record<string, MatrixEvent>, delegateCryptoCallbacks?: ICryptoCallbacks) {
|
public constructor(accountData: Record<string, MatrixEvent>, delegateCryptoCallbacks?: ICryptoCallbacks) {
|
||||||
this.accountDataClientAdapter = new AccountDataClientAdapter(accountData);
|
this.accountDataClientAdapter = new AccountDataClientAdapter(accountData);
|
||||||
this.crossSigningCallbacks = new CrossSigningCallbacks();
|
this.crossSigningCallbacks = new CrossSigningCallbacks();
|
||||||
this.ssssCryptoCallbacks = new SSSSCryptoCallbacks(delegateCryptoCallbacks);
|
this.ssssCryptoCallbacks = new SSSSCryptoCallbacks(delegateCryptoCallbacks);
|
||||||
@@ -192,7 +192,7 @@ export class EncryptionSetupOperation {
|
|||||||
* @param {Object} keyBackupInfo
|
* @param {Object} keyBackupInfo
|
||||||
* @param {Object} keySignatures
|
* @param {Object} keySignatures
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly accountData: Map<string, object>,
|
private readonly accountData: Map<string, object>,
|
||||||
private readonly crossSigningKeys?: ICrossSigningKeys,
|
private readonly crossSigningKeys?: ICrossSigningKeys,
|
||||||
private readonly keyBackupInfo?: IKeyBackupInfo,
|
private readonly keyBackupInfo?: IKeyBackupInfo,
|
||||||
@@ -272,7 +272,7 @@ class AccountDataClientAdapter
|
|||||||
/**
|
/**
|
||||||
* @param {Object.<String, MatrixEvent>} existingValues existing account data
|
* @param {Object.<String, MatrixEvent>} existingValues existing account data
|
||||||
*/
|
*/
|
||||||
constructor(private readonly existingValues: Record<string, MatrixEvent>) {
|
public constructor(private readonly existingValues: Record<string, MatrixEvent>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ class CrossSigningCallbacks implements ICryptoCallbacks, ICacheCallbacks {
|
|||||||
return Promise.resolve(this.privateKeys.get(type) ?? null);
|
return Promise.resolve(this.privateKeys.get(type) ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public saveCrossSigningKeys(privateKeys: Record<string, Uint8Array>) {
|
public saveCrossSigningKeys(privateKeys: Record<string, Uint8Array>): void {
|
||||||
for (const [type, privateKey] of Object.entries(privateKeys)) {
|
for (const [type, privateKey] of Object.entries(privateKeys)) {
|
||||||
this.privateKeys.set(type, privateKey);
|
this.privateKeys.set(type, privateKey);
|
||||||
}
|
}
|
||||||
@@ -356,7 +356,7 @@ class CrossSigningCallbacks implements ICryptoCallbacks, ICacheCallbacks {
|
|||||||
class SSSSCryptoCallbacks {
|
class SSSSCryptoCallbacks {
|
||||||
private readonly privateKeys = new Map<string, Uint8Array>();
|
private readonly privateKeys = new Map<string, Uint8Array>();
|
||||||
|
|
||||||
constructor(private readonly delegateCryptoCallbacks?: ICryptoCallbacks) {}
|
public constructor(private readonly delegateCryptoCallbacks?: ICryptoCallbacks) {}
|
||||||
|
|
||||||
public async getSecretStorageKey(
|
public async getSecretStorageKey(
|
||||||
{ keys }: { keys: Record<string, ISecretStorageKeyInfo> },
|
{ keys }: { keys: Record<string, ISecretStorageKeyInfo> },
|
||||||
|
@@ -177,13 +177,13 @@ export class OlmDevice {
|
|||||||
// Used by olm to serialise prekey message decryptions
|
// Used by olm to serialise prekey message decryptions
|
||||||
public olmPrekeyPromise: Promise<any> = Promise.resolve(); // set by consumers
|
public olmPrekeyPromise: Promise<any> = Promise.resolve(); // set by consumers
|
||||||
|
|
||||||
constructor(private readonly cryptoStore: CryptoStore) {
|
public constructor(private readonly cryptoStore: CryptoStore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {array} The version of Olm.
|
* @return {array} The version of Olm.
|
||||||
*/
|
*/
|
||||||
static getOlmVersion(): [number, number, number] {
|
public static getOlmVersion(): [number, number, number] {
|
||||||
return global.Olm.get_library_version();
|
return global.Olm.get_library_version();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1515,7 +1515,9 @@ export class OlmDevice {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSharedHistoryInboundGroupSessions(roomId: string): Promise<[senderKey: string, sessionId: string][]> {
|
public async getSharedHistoryInboundGroupSessions(
|
||||||
|
roomId: string,
|
||||||
|
): Promise<[senderKey: string, sessionId: string][]> {
|
||||||
let result: Promise<[senderKey: string, sessionId: string][]>;
|
let result: Promise<[senderKey: string, sessionId: string][]>;
|
||||||
await this.cryptoStore.doTxn(
|
await this.cryptoStore.doTxn(
|
||||||
'readonly', [
|
'readonly', [
|
||||||
|
@@ -102,7 +102,7 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
|
|
||||||
private clientRunning = true;
|
private clientRunning = true;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly baseApis: MatrixClient,
|
private readonly baseApis: MatrixClient,
|
||||||
private readonly deviceId: string,
|
private readonly deviceId: string,
|
||||||
private readonly cryptoStore: CryptoStore,
|
private readonly cryptoStore: CryptoStore,
|
||||||
@@ -352,7 +352,7 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const startSendingOutgoingRoomKeyRequests = () => {
|
const startSendingOutgoingRoomKeyRequests = (): void => {
|
||||||
if (this.sendOutgoingRoomKeyRequestsRunning) {
|
if (this.sendOutgoingRoomKeyRequestsRunning) {
|
||||||
throw new Error("RoomKeyRequestSend already in progress!");
|
throw new Error("RoomKeyRequestSend already in progress!");
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,7 @@ export class RoomList {
|
|||||||
// Object of roomId -> room e2e info object (body of the m.room.encryption event)
|
// Object of roomId -> room e2e info object (body of the m.room.encryption event)
|
||||||
private roomEncryption: Record<string, IRoomEncryption> = {};
|
private roomEncryption: Record<string, IRoomEncryption> = {};
|
||||||
|
|
||||||
constructor(private readonly cryptoStore?: CryptoStore) {}
|
public constructor(private readonly cryptoStore?: CryptoStore) {}
|
||||||
|
|
||||||
public async init(): Promise<void> {
|
public async init(): Promise<void> {
|
||||||
await this.cryptoStore!.doTxn(
|
await this.cryptoStore!.doTxn(
|
||||||
|
@@ -78,7 +78,7 @@ export class SecretStorage<B extends MatrixClient | undefined = MatrixClient> {
|
|||||||
// as you don't request any secrets.
|
// as you don't request any secrets.
|
||||||
// A better solution would probably be to split this class up into secret storage and
|
// A better solution would probably be to split this class up into secret storage and
|
||||||
// secret sharing which are really two separate things, even though they share an MSC.
|
// secret sharing which are really two separate things, even though they share an MSC.
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly accountDataAdapter: IAccountDataClient,
|
private readonly accountDataAdapter: IAccountDataClient,
|
||||||
private readonly cryptoCallbacks: ICryptoCallbacks,
|
private readonly cryptoCallbacks: ICryptoCallbacks,
|
||||||
private readonly baseApis: B,
|
private readonly baseApis: B,
|
||||||
@@ -381,7 +381,7 @@ export class SecretStorage<B extends MatrixClient | undefined = MatrixClient> {
|
|||||||
const deferred = defer<string>();
|
const deferred = defer<string>();
|
||||||
this.requests.set(requestId, { name, devices, deferred });
|
this.requests.set(requestId, { name, devices, deferred });
|
||||||
|
|
||||||
const cancel = (reason: string) => {
|
const cancel = (reason: string): void => {
|
||||||
// send cancellation event
|
// send cancellation event
|
||||||
const cancelData = {
|
const cancelData = {
|
||||||
action: "request_cancellation",
|
action: "request_cancellation",
|
||||||
|
@@ -78,7 +78,7 @@ export abstract class EncryptionAlgorithm {
|
|||||||
protected readonly baseApis: MatrixClient;
|
protected readonly baseApis: MatrixClient;
|
||||||
protected readonly roomId?: string;
|
protected readonly roomId?: string;
|
||||||
|
|
||||||
constructor(params: IParams) {
|
public constructor(params: IParams) {
|
||||||
this.userId = params.userId;
|
this.userId = params.userId;
|
||||||
this.deviceId = params.deviceId;
|
this.deviceId = params.deviceId;
|
||||||
this.crypto = params.crypto;
|
this.crypto = params.crypto;
|
||||||
@@ -150,7 +150,7 @@ export abstract class DecryptionAlgorithm {
|
|||||||
protected readonly baseApis: MatrixClient;
|
protected readonly baseApis: MatrixClient;
|
||||||
protected readonly roomId?: string;
|
protected readonly roomId?: string;
|
||||||
|
|
||||||
constructor(params: DecryptionClassParams) {
|
public constructor(params: DecryptionClassParams) {
|
||||||
this.userId = params.userId;
|
this.userId = params.userId;
|
||||||
this.crypto = params.crypto;
|
this.crypto = params.crypto;
|
||||||
this.olmDevice = params.olmDevice;
|
this.olmDevice = params.olmDevice;
|
||||||
@@ -242,7 +242,7 @@ export abstract class DecryptionAlgorithm {
|
|||||||
export class DecryptionError extends Error {
|
export class DecryptionError extends Error {
|
||||||
public readonly detailedString: string;
|
public readonly detailedString: string;
|
||||||
|
|
||||||
constructor(public readonly code: string, msg: string, details?: Record<string, string | Error>) {
|
public constructor(public readonly code: string, msg: string, details?: Record<string, string | Error>) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.name = 'DecryptionError';
|
this.name = 'DecryptionError';
|
||||||
@@ -272,7 +272,7 @@ function detailedStringForDecryptionError(err: DecryptionError, details?: Record
|
|||||||
* @extends Error
|
* @extends Error
|
||||||
*/
|
*/
|
||||||
export class UnknownDeviceError extends Error {
|
export class UnknownDeviceError extends Error {
|
||||||
constructor(
|
public constructor(
|
||||||
msg: string,
|
msg: string,
|
||||||
public readonly devices: Record<string, Record<string, object>>,
|
public readonly devices: Record<string, Record<string, object>>,
|
||||||
public event?: MatrixEvent,
|
public event?: MatrixEvent,
|
||||||
|
@@ -136,7 +136,7 @@ class OutboundSessionInfo {
|
|||||||
public sharedWithDevices: Record<string, Record<string, SharedWithData>> = {};
|
public sharedWithDevices: Record<string, Record<string, SharedWithData>> = {};
|
||||||
public blockedDevicesNotified: Record<string, Record<string, boolean>> = {};
|
public blockedDevicesNotified: Record<string, Record<string, boolean>> = {};
|
||||||
|
|
||||||
constructor(public readonly sessionId: string, public readonly sharedHistory = false) {
|
public constructor(public readonly sessionId: string, public readonly sharedHistory = false) {
|
||||||
this.creationTime = new Date().getTime();
|
this.creationTime = new Date().getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
|
|||||||
|
|
||||||
protected readonly roomId: string;
|
protected readonly roomId: string;
|
||||||
|
|
||||||
constructor(params: IParams & Required<Pick<IParams, "roomId">>) {
|
public constructor(params: IParams & Required<Pick<IParams, "roomId">>) {
|
||||||
super(params);
|
super(params);
|
||||||
this.roomId = params.roomId;
|
this.roomId = params.roomId;
|
||||||
|
|
||||||
@@ -347,7 +347,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
|
|||||||
singleOlmCreationPhase: boolean,
|
singleOlmCreationPhase: boolean,
|
||||||
blocked: IBlockedMap,
|
blocked: IBlockedMap,
|
||||||
session: OutboundSessionInfo,
|
session: OutboundSessionInfo,
|
||||||
) {
|
): Promise<void> {
|
||||||
// now check if we need to share with any devices
|
// now check if we need to share with any devices
|
||||||
const shareMap: Record<string, DeviceInfo[]> = {};
|
const shareMap: Record<string, DeviceInfo[]> = {};
|
||||||
|
|
||||||
@@ -386,13 +386,13 @@ class MegolmEncryption extends EncryptionAlgorithm {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
(async () => {
|
(async (): Promise<void> => {
|
||||||
// share keys with devices that we already have a session for
|
// share keys with devices that we already have a session for
|
||||||
logger.debug(`Sharing keys with existing Olm sessions in ${this.roomId}`, olmSessions);
|
logger.debug(`Sharing keys with existing Olm sessions in ${this.roomId}`, olmSessions);
|
||||||
await this.shareKeyWithOlmSessions(session, key, payload, olmSessions);
|
await this.shareKeyWithOlmSessions(session, key, payload, olmSessions);
|
||||||
logger.debug(`Shared keys with existing Olm sessions in ${this.roomId}`);
|
logger.debug(`Shared keys with existing Olm sessions in ${this.roomId}`);
|
||||||
})(),
|
})(),
|
||||||
(async () => {
|
(async (): Promise<void> => {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Sharing keys (start phase 1) with new Olm sessions in ${this.roomId}`,
|
`Sharing keys (start phase 1) with new Olm sessions in ${this.roomId}`,
|
||||||
devicesWithoutSession,
|
devicesWithoutSession,
|
||||||
@@ -415,7 +415,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
|
|||||||
if (!singleOlmCreationPhase && (Date.now() - start < 10000)) {
|
if (!singleOlmCreationPhase && (Date.now() - start < 10000)) {
|
||||||
// perform the second phase of olm session creation if requested,
|
// perform the second phase of olm session creation if requested,
|
||||||
// and if the first phase didn't take too long
|
// and if the first phase didn't take too long
|
||||||
(async () => {
|
(async (): Promise<void> => {
|
||||||
// Retry sending keys to devices that we were unable to establish
|
// Retry sending keys to devices that we were unable to establish
|
||||||
// an olm session for. This time, we use a longer timeout, but we
|
// an olm session for. This time, we use a longer timeout, but we
|
||||||
// do this in the background and don't block anything else while we
|
// do this in the background and don't block anything else while we
|
||||||
@@ -452,7 +452,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
|
|||||||
}
|
}
|
||||||
logger.debug(`Shared keys (all phases done) with new Olm sessions in ${this.roomId}`);
|
logger.debug(`Shared keys (all phases done) with new Olm sessions in ${this.roomId}`);
|
||||||
})(),
|
})(),
|
||||||
(async () => {
|
(async (): Promise<void> => {
|
||||||
logger.debug(`There are ${Object.entries(blocked).length} blocked devices in ${this.roomId}`,
|
logger.debug(`There are ${Object.entries(blocked).length} blocked devices in ${this.roomId}`,
|
||||||
Object.entries(blocked));
|
Object.entries(blocked));
|
||||||
|
|
||||||
@@ -809,7 +809,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
|
|||||||
errorDevices: IOlmDevice[],
|
errorDevices: IOlmDevice[],
|
||||||
otkTimeout: number,
|
otkTimeout: number,
|
||||||
failedServers?: string[],
|
failedServers?: string[],
|
||||||
) {
|
): Promise<void> {
|
||||||
logger.debug(`Ensuring Olm sessions for devices in ${this.roomId}`);
|
logger.debug(`Ensuring Olm sessions for devices in ${this.roomId}`);
|
||||||
const devicemap = await olmlib.ensureOlmSessionsForDevices(
|
const devicemap = await olmlib.ensureOlmSessionsForDevices(
|
||||||
this.olmDevice, this.baseApis, devicesByUser, false, otkTimeout, failedServers,
|
this.olmDevice, this.baseApis, devicesByUser, false, otkTimeout, failedServers,
|
||||||
@@ -969,7 +969,7 @@ class MegolmEncryption extends EncryptionAlgorithm {
|
|||||||
|
|
||||||
this.encryptionPreparation = {
|
this.encryptionPreparation = {
|
||||||
startTime: Date.now(),
|
startTime: Date.now(),
|
||||||
promise: (async () => {
|
promise: (async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
logger.debug(`Getting devices in ${this.roomId}`);
|
logger.debug(`Getting devices in ${this.roomId}`);
|
||||||
const [devicesInRoom, blocked] = await this.getDevicesInRoom(room);
|
const [devicesInRoom, blocked] = await this.getDevicesInRoom(room);
|
||||||
@@ -1231,7 +1231,7 @@ class MegolmDecryption extends DecryptionAlgorithm {
|
|||||||
|
|
||||||
protected readonly roomId: string;
|
protected readonly roomId: string;
|
||||||
|
|
||||||
constructor(params: DecryptionClassParams<IParams & Required<Pick<IParams, "roomId">>>) {
|
public constructor(params: DecryptionClassParams<IParams & Required<Pick<IParams, "roomId">>>) {
|
||||||
super(params);
|
super(params);
|
||||||
this.roomId = params.roomId;
|
this.roomId = params.roomId;
|
||||||
}
|
}
|
||||||
|
@@ -120,7 +120,7 @@ export class BackupManager {
|
|||||||
private sendingBackups: boolean; // Are we currently sending backups?
|
private sendingBackups: boolean; // Are we currently sending backups?
|
||||||
private sessionLastCheckAttemptedTime: Record<string, number> = {}; // When did we last try to check the server for a given session id?
|
private sessionLastCheckAttemptedTime: Record<string, number> = {}; // When did we last try to check the server for a given session id?
|
||||||
|
|
||||||
constructor(private readonly baseApis: MatrixClient, public readonly getKey: GetKey) {
|
public constructor(private readonly baseApis: MatrixClient, public readonly getKey: GetKey) {
|
||||||
this.checkedForBackup = false;
|
this.checkedForBackup = false;
|
||||||
this.sendingBackups = false;
|
this.sendingBackups = false;
|
||||||
}
|
}
|
||||||
@@ -609,7 +609,7 @@ export class BackupManager {
|
|||||||
export class Curve25519 implements BackupAlgorithm {
|
export class Curve25519 implements BackupAlgorithm {
|
||||||
public static algorithmName = "m.megolm_backup.v1.curve25519-aes-sha2";
|
public static algorithmName = "m.megolm_backup.v1.curve25519-aes-sha2";
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
public authData: ICurve25519AuthData,
|
public authData: ICurve25519AuthData,
|
||||||
private publicKey: any, // FIXME: PkEncryption
|
private publicKey: any, // FIXME: PkEncryption
|
||||||
private getKey: () => Promise<Uint8Array>,
|
private getKey: () => Promise<Uint8Array>,
|
||||||
@@ -661,7 +661,7 @@ export class Curve25519 implements BackupAlgorithm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get untrusted() { return true; }
|
public get untrusted(): boolean { return true; }
|
||||||
|
|
||||||
public async encryptSession(data: Record<string, any>): Promise<any> {
|
public async encryptSession(data: Record<string, any>): Promise<any> {
|
||||||
const plainText: Record<string, any> = Object.assign({}, data);
|
const plainText: Record<string, any> = Object.assign({}, data);
|
||||||
@@ -735,7 +735,7 @@ const UNSTABLE_MSC3270_NAME = new UnstableValue(
|
|||||||
export class Aes256 implements BackupAlgorithm {
|
export class Aes256 implements BackupAlgorithm {
|
||||||
public static algorithmName = UNSTABLE_MSC3270_NAME.name;
|
public static algorithmName = UNSTABLE_MSC3270_NAME.name;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly authData: IAes256AuthData,
|
public readonly authData: IAes256AuthData,
|
||||||
private readonly key: Uint8Array,
|
private readonly key: Uint8Array,
|
||||||
) {}
|
) {}
|
||||||
@@ -786,7 +786,7 @@ export class Aes256 implements BackupAlgorithm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get untrusted() { return false; }
|
public get untrusted(): boolean { return false; }
|
||||||
|
|
||||||
public encryptSession(data: Record<string, any>): Promise<any> {
|
public encryptSession(data: Record<string, any>): Promise<any> {
|
||||||
const plainText: Record<string, any> = Object.assign({}, data);
|
const plainText: Record<string, any> = Object.assign({}, data);
|
||||||
|
@@ -62,7 +62,7 @@ export class DehydrationManager {
|
|||||||
private keyInfo?: {[props: string]: any};
|
private keyInfo?: {[props: string]: any};
|
||||||
private deviceDisplayName?: string;
|
private deviceDisplayName?: string;
|
||||||
|
|
||||||
constructor(private readonly crypto: Crypto) {
|
public constructor(private readonly crypto: Crypto) {
|
||||||
this.getDehydrationKeyFromCache();
|
this.getDehydrationKeyFromCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ export class DehydrationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop() {
|
public stop(): void {
|
||||||
if (this.timeoutId) {
|
if (this.timeoutId) {
|
||||||
global.clearTimeout(this.timeoutId);
|
global.clearTimeout(this.timeoutId);
|
||||||
this.timeoutId = undefined;
|
this.timeoutId = undefined;
|
||||||
|
@@ -94,7 +94,7 @@ export class DeviceInfo {
|
|||||||
public unsigned: Record<string, any> = {};
|
public unsigned: Record<string, any> = {};
|
||||||
public signatures: ISignatures = {};
|
public signatures: ISignatures = {};
|
||||||
|
|
||||||
constructor(public readonly deviceId: string) {}
|
public constructor(public readonly deviceId: string) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a DeviceInfo for JSON serialisation in the session store
|
* Prepare a DeviceInfo for JSON serialisation in the session store
|
||||||
|
@@ -278,7 +278,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
/**
|
/**
|
||||||
* @return {string} The version of Olm.
|
* @return {string} The version of Olm.
|
||||||
*/
|
*/
|
||||||
static getOlmVersion(): [number, number, number] {
|
public static getOlmVersion(): [number, number, number] {
|
||||||
return OlmDevice.getOlmVersion();
|
return OlmDevice.getOlmVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
* Each element can either be a string from MatrixClient.verificationMethods
|
* Each element can either be a string from MatrixClient.verificationMethods
|
||||||
* or a class that implements a verification method.
|
* or a class that implements a verification method.
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly baseApis: MatrixClient,
|
public readonly baseApis: MatrixClient,
|
||||||
public readonly userId: string,
|
public readonly userId: string,
|
||||||
private readonly deviceId: string,
|
private readonly deviceId: string,
|
||||||
@@ -465,7 +465,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
|
|
||||||
// Assuming no app-supplied callback, default to getting from SSSS.
|
// Assuming no app-supplied callback, default to getting from SSSS.
|
||||||
if (!cryptoCallbacks.getCrossSigningKey && cryptoCallbacks.getSecretStorageKey) {
|
if (!cryptoCallbacks.getCrossSigningKey && cryptoCallbacks.getSecretStorageKey) {
|
||||||
cryptoCallbacks.getCrossSigningKey = async (type) => {
|
cryptoCallbacks.getCrossSigningKey = async (type): Promise<Uint8Array | null> => {
|
||||||
return CrossSigningInfo.getFromSecretStorage(type, this.secretStorage);
|
return CrossSigningInfo.getFromSecretStorage(type, this.secretStorage);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -709,7 +709,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Reset the cross-signing keys
|
// Reset the cross-signing keys
|
||||||
const resetCrossSigning = async () => {
|
const resetCrossSigning = async (): Promise<void> => {
|
||||||
crossSigningInfo.resetKeys();
|
crossSigningInfo.resetKeys();
|
||||||
// Sign master key with device key
|
// Sign master key with device key
|
||||||
await this.signObject(crossSigningInfo.keys.master);
|
await this.signObject(crossSigningInfo.keys.master);
|
||||||
@@ -846,12 +846,12 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
*/
|
*/
|
||||||
// TODO this does not resolve with what it says it does
|
// TODO this does not resolve with what it says it does
|
||||||
public async bootstrapSecretStorage({
|
public async bootstrapSecretStorage({
|
||||||
createSecretStorageKey = async () => ({} as IRecoveryKey),
|
createSecretStorageKey = async (): Promise<IRecoveryKey> => ({} as IRecoveryKey),
|
||||||
keyBackupInfo,
|
keyBackupInfo,
|
||||||
setupNewKeyBackup,
|
setupNewKeyBackup,
|
||||||
setupNewSecretStorage,
|
setupNewSecretStorage,
|
||||||
getKeyBackupPassphrase,
|
getKeyBackupPassphrase,
|
||||||
}: ICreateSecretStorageOpts = {}) {
|
}: ICreateSecretStorageOpts = {}): Promise<void> {
|
||||||
logger.log("Bootstrapping Secure Secret Storage");
|
logger.log("Bootstrapping Secure Secret Storage");
|
||||||
const delegateCryptoCallbacks = this.baseApis.cryptoCallbacks;
|
const delegateCryptoCallbacks = this.baseApis.cryptoCallbacks;
|
||||||
const builder = new EncryptionSetupBuilder(
|
const builder = new EncryptionSetupBuilder(
|
||||||
@@ -868,7 +868,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
let newKeyId: string | null = null;
|
let newKeyId: string | null = null;
|
||||||
|
|
||||||
// create a new SSSS key and set it as default
|
// create a new SSSS key and set it as default
|
||||||
const createSSSS = async (opts: IAddSecretStorageKeyOpts, privateKey?: Uint8Array) => {
|
const createSSSS = async (opts: IAddSecretStorageKeyOpts, privateKey?: Uint8Array): Promise<string> => {
|
||||||
if (privateKey) {
|
if (privateKey) {
|
||||||
opts.key = privateKey;
|
opts.key = privateKey;
|
||||||
}
|
}
|
||||||
@@ -884,7 +884,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
return keyId;
|
return keyId;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ensureCanCheckPassphrase = async (keyId: string, keyInfo: ISecretStorageKeyInfo) => {
|
const ensureCanCheckPassphrase = async (keyId: string, keyInfo: ISecretStorageKeyInfo): Promise<void> => {
|
||||||
if (!keyInfo.mac) {
|
if (!keyInfo.mac) {
|
||||||
const key = await this.baseApis.cryptoCallbacks.getSecretStorageKey?.(
|
const key = await this.baseApis.cryptoCallbacks.getSecretStorageKey?.(
|
||||||
{ keys: { [keyId]: keyInfo } }, "",
|
{ keys: { [keyId]: keyInfo } }, "",
|
||||||
@@ -903,7 +903,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const signKeyBackupWithCrossSigning = async (keyBackupAuthData: IKeyBackupInfo["auth_data"]) => {
|
const signKeyBackupWithCrossSigning = async (keyBackupAuthData: IKeyBackupInfo["auth_data"]): Promise<void> => {
|
||||||
if (
|
if (
|
||||||
this.crossSigningInfo.getId() &&
|
this.crossSigningInfo.getId() &&
|
||||||
await this.crossSigningInfo.isStoredInKeyCache("master")
|
await this.crossSigningInfo.isStoredInKeyCache("master")
|
||||||
@@ -1241,7 +1241,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
const signedDevice = await this.crossSigningInfo.signDevice(this.userId, device);
|
const signedDevice = await this.crossSigningInfo.signDevice(this.userId, device);
|
||||||
logger.info(`Starting background key sig upload for ${this.deviceId}`);
|
logger.info(`Starting background key sig upload for ${this.deviceId}`);
|
||||||
|
|
||||||
const upload = ({ shouldEmit = false }) => {
|
const upload = ({ shouldEmit = false }): Promise<void> => {
|
||||||
return this.baseApis.uploadKeySignatures({
|
return this.baseApis.uploadKeySignatures({
|
||||||
[this.userId]: {
|
[this.userId]: {
|
||||||
[this.deviceId]: signedDevice!,
|
[this.deviceId]: signedDevice!,
|
||||||
@@ -1475,7 +1475,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
/*
|
/*
|
||||||
* Event handler for DeviceList's userNewDevices event
|
* Event handler for DeviceList's userNewDevices event
|
||||||
*/
|
*/
|
||||||
private onDeviceListUserCrossSigningUpdated = async (userId: string) => {
|
private onDeviceListUserCrossSigningUpdated = async (userId: string): Promise<void> => {
|
||||||
if (userId === this.userId) {
|
if (userId === this.userId) {
|
||||||
// An update to our own cross-signing key.
|
// An update to our own cross-signing key.
|
||||||
// Get the new key first:
|
// Get the new key first:
|
||||||
@@ -1657,7 +1657,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
|
|
||||||
const keysToUpload = Object.keys(keySignatures);
|
const keysToUpload = Object.keys(keySignatures);
|
||||||
if (keysToUpload.length) {
|
if (keysToUpload.length) {
|
||||||
const upload = ({ shouldEmit = false }) => {
|
const upload = ({ shouldEmit = false }): Promise<void> => {
|
||||||
logger.info(`Starting background key sig upload for ${keysToUpload}`);
|
logger.info(`Starting background key sig upload for ${keysToUpload}`);
|
||||||
return this.baseApis.uploadKeySignatures({ [this.userId]: keySignatures })
|
return this.baseApis.uploadKeySignatures({ [this.userId]: keySignatures })
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -1864,7 +1864,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setNeedsNewFallback(needsNewFallback: boolean) {
|
public setNeedsNewFallback(needsNewFallback: boolean): void {
|
||||||
this.needsNewFallback = needsNewFallback;
|
this.needsNewFallback = needsNewFallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1873,7 +1873,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if it's time to upload one-time keys, and do so if so.
|
// check if it's time to upload one-time keys, and do so if so.
|
||||||
private maybeUploadOneTimeKeys() {
|
private maybeUploadOneTimeKeys(): void {
|
||||||
// frequency with which to check & upload one-time keys
|
// frequency with which to check & upload one-time keys
|
||||||
const uploadPeriod = 1000 * 60; // one minute
|
const uploadPeriod = 1000 * 60; // one minute
|
||||||
|
|
||||||
@@ -1919,7 +1919,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
// out stale private keys that won't receive a message.
|
// out stale private keys that won't receive a message.
|
||||||
const keyLimit = Math.floor(maxOneTimeKeys / 2);
|
const keyLimit = Math.floor(maxOneTimeKeys / 2);
|
||||||
|
|
||||||
const uploadLoop = async (keyCount: number) => {
|
const uploadLoop = async (keyCount: number): Promise<void> => {
|
||||||
while (keyLimit > keyCount || this.getNeedsNewFallback()) {
|
while (keyLimit > keyCount || this.getNeedsNewFallback()) {
|
||||||
// Ask olm to generate new one time keys, then upload them to synapse.
|
// Ask olm to generate new one time keys, then upload them to synapse.
|
||||||
if (keyLimit > keyCount) {
|
if (keyLimit > keyCount) {
|
||||||
@@ -2155,7 +2155,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
);
|
);
|
||||||
const device = await this.crossSigningInfo.signUser(xsk);
|
const device = await this.crossSigningInfo.signUser(xsk);
|
||||||
if (device) {
|
if (device) {
|
||||||
const upload = async ({ shouldEmit = false }) => {
|
const upload = async ({ shouldEmit = false }): Promise<void> => {
|
||||||
logger.info("Uploading signature for " + userId + "...");
|
logger.info("Uploading signature for " + userId + "...");
|
||||||
const response = await this.baseApis.uploadKeySignatures({
|
const response = await this.baseApis.uploadKeySignatures({
|
||||||
[userId]: {
|
[userId]: {
|
||||||
@@ -2246,7 +2246,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (device) {
|
if (device) {
|
||||||
const upload = async ({ shouldEmit = false }) => {
|
const upload = async ({ shouldEmit = false }): Promise<void> => {
|
||||||
logger.info("Uploading signature for " + deviceId);
|
logger.info("Uploading signature for " + deviceId);
|
||||||
const response = await this.baseApis.uploadKeySignatures({
|
const response = await this.baseApis.uploadKeySignatures({
|
||||||
[userId]: {
|
[userId]: {
|
||||||
@@ -2645,7 +2645,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
* @returns {Promise} when all devices for the room have been fetched and marked to track
|
* @returns {Promise} when all devices for the room have been fetched and marked to track
|
||||||
*/
|
*/
|
||||||
public trackRoomDevices(roomId: string): Promise<void> {
|
public trackRoomDevices(roomId: string): Promise<void> {
|
||||||
const trackMembers = async () => {
|
const trackMembers = async (): Promise<void> => {
|
||||||
// not an encrypted room
|
// not an encrypted room
|
||||||
if (!this.roomEncryptors.has(roomId)) {
|
if (!this.roomEncryptors.has(roomId)) {
|
||||||
return;
|
return;
|
||||||
@@ -2747,7 +2747,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
let failures = 0;
|
let failures = 0;
|
||||||
const total = keys.length;
|
const total = keys.length;
|
||||||
|
|
||||||
function updateProgress() {
|
function updateProgress(): void {
|
||||||
opts.progressCallback?.({
|
opts.progressCallback?.({
|
||||||
stage: "load_keys",
|
stage: "load_keys",
|
||||||
successes,
|
successes,
|
||||||
@@ -3187,7 +3187,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMembership = (event: MatrixEvent, member: RoomMember, oldMembership?: string) => {
|
private onMembership = (event: MatrixEvent, member: RoomMember, oldMembership?: string): void => {
|
||||||
try {
|
try {
|
||||||
this.onRoomMembership(event, member, oldMembership);
|
this.onRoomMembership(event, member, oldMembership);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -3340,7 +3340,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
if (!InRoomChannel.validateEvent(event, this.baseApis)) {
|
if (!InRoomChannel.validateEvent(event, this.baseApis)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const createRequest = (event: MatrixEvent) => {
|
const createRequest = (event: MatrixEvent): VerificationRequest => {
|
||||||
const channel = new InRoomChannel(this.baseApis, event.getRoomId()!);
|
const channel = new InRoomChannel(this.baseApis, event.getRoomId()!);
|
||||||
return new VerificationRequest(
|
return new VerificationRequest(
|
||||||
channel, this.verificationMethods, this.baseApis);
|
channel, this.verificationMethods, this.baseApis);
|
||||||
@@ -3361,7 +3361,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
try {
|
try {
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
eventIdListener = resolve;
|
eventIdListener = resolve;
|
||||||
statusListener = () => {
|
statusListener = (): void => {
|
||||||
if (event.status == EventStatus.CANCELLED) {
|
if (event.status == EventStatus.CANCELLED) {
|
||||||
reject(new Error("Event status set to CANCELLED."));
|
reject(new Error("Event status set to CANCELLED."));
|
||||||
}
|
}
|
||||||
@@ -3420,7 +3420,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
// retry decryption for all events sent by the sender_key. This will
|
// retry decryption for all events sent by the sender_key. This will
|
||||||
// update the events to show a message indicating that the olm session was
|
// update the events to show a message indicating that the olm session was
|
||||||
// wedged.
|
// wedged.
|
||||||
const retryDecryption = () => {
|
const retryDecryption = (): void => {
|
||||||
const roomDecryptors = this.getRoomDecryptors(olmlib.MEGOLM_ALGORITHM);
|
const roomDecryptors = this.getRoomDecryptors(olmlib.MEGOLM_ALGORITHM);
|
||||||
for (const decryptor of roomDecryptors) {
|
for (const decryptor of roomDecryptors) {
|
||||||
decryptor.retryDecryptionFromSender(deviceKey);
|
decryptor.retryDecryptionFromSender(deviceKey);
|
||||||
@@ -3692,7 +3692,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.share = () => {
|
req.share = (): void => {
|
||||||
decryptor.shareKeysWithDevice(req);
|
decryptor.shareKeysWithDevice(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3863,14 +3863,14 @@ export class IncomingRoomKeyRequest {
|
|||||||
public readonly requestBody: IRoomKeyRequestBody;
|
public readonly requestBody: IRoomKeyRequestBody;
|
||||||
public share: () => void;
|
public share: () => void;
|
||||||
|
|
||||||
constructor(event: MatrixEvent) {
|
public constructor(event: MatrixEvent) {
|
||||||
const content = event.getContent();
|
const content = event.getContent();
|
||||||
|
|
||||||
this.userId = event.getSender()!;
|
this.userId = event.getSender()!;
|
||||||
this.deviceId = content.requesting_device_id;
|
this.deviceId = content.requesting_device_id;
|
||||||
this.requestId = content.request_id;
|
this.requestId = content.request_id;
|
||||||
this.requestBody = content.body || {};
|
this.requestBody = content.body || {};
|
||||||
this.share = () => {
|
this.share = (): void => {
|
||||||
throw new Error("don't know how to share keys for this request yet");
|
throw new Error("don't know how to share keys for this request yet");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -3888,7 +3888,7 @@ class IncomingRoomKeyRequestCancellation {
|
|||||||
public readonly deviceId: string;
|
public readonly deviceId: string;
|
||||||
public readonly requestId: string;
|
public readonly requestId: string;
|
||||||
|
|
||||||
constructor(event: MatrixEvent) {
|
public constructor(event: MatrixEvent) {
|
||||||
const content = event.getContent();
|
const content = event.getContent();
|
||||||
|
|
||||||
this.userId = event.getSender()!;
|
this.userId = event.getSender()!;
|
||||||
|
@@ -82,7 +82,7 @@ export async function encryptMessageForDevice(
|
|||||||
recipientUserId: string,
|
recipientUserId: string,
|
||||||
recipientDevice: DeviceInfo,
|
recipientDevice: DeviceInfo,
|
||||||
payloadFields: Record<string, any>,
|
payloadFields: Record<string, any>,
|
||||||
) {
|
): Promise<void> {
|
||||||
const deviceKey = recipientDevice.getIdentityKey();
|
const deviceKey = recipientDevice.getIdentityKey();
|
||||||
const sessionId = await olmDevice.getSessionIdForDevice(deviceKey);
|
const sessionId = await olmDevice.getSessionIdForDevice(deviceKey);
|
||||||
if (sessionId === null) {
|
if (sessionId === null) {
|
||||||
@@ -173,7 +173,7 @@ export async function getExistingOlmSessions(
|
|||||||
for (const deviceInfo of devices) {
|
for (const deviceInfo of devices) {
|
||||||
const deviceId = deviceInfo.deviceId;
|
const deviceId = deviceInfo.deviceId;
|
||||||
const key = deviceInfo.getIdentityKey();
|
const key = deviceInfo.getIdentityKey();
|
||||||
promises.push((async () => {
|
promises.push((async (): Promise<void> => {
|
||||||
const sessionId = await olmDevice.getSessionIdForDevice(
|
const sessionId = await olmDevice.getSessionIdForDevice(
|
||||||
key, true,
|
key, true,
|
||||||
);
|
);
|
||||||
@@ -256,7 +256,7 @@ export async function ensureOlmSessionsForDevices(
|
|||||||
// conditions. If we find that we already have a session, then
|
// conditions. If we find that we already have a session, then
|
||||||
// we'll resolve
|
// we'll resolve
|
||||||
olmDevice.sessionsInProgress[key] = new Promise(resolve => {
|
olmDevice.sessionsInProgress[key] = new Promise(resolve => {
|
||||||
resolveSession[key] = (v: any) => {
|
resolveSession[key] = (v: any): void => {
|
||||||
delete olmDevice.sessionsInProgress[key];
|
delete olmDevice.sessionsInProgress[key];
|
||||||
resolve(v);
|
resolve(v);
|
||||||
};
|
};
|
||||||
@@ -463,7 +463,7 @@ export async function verifySignature(
|
|||||||
signingUserId: string,
|
signingUserId: string,
|
||||||
signingDeviceId: string,
|
signingDeviceId: string,
|
||||||
signingKey: string,
|
signingKey: string,
|
||||||
) {
|
): Promise<void> {
|
||||||
const signKeyId = "ed25519:" + signingDeviceId;
|
const signKeyId = "ed25519:" + signingDeviceId;
|
||||||
const signatures = obj.signatures || {};
|
const signatures = obj.signatures || {};
|
||||||
const userSigs = signatures[signingUserId] || {};
|
const userSigs = signatures[signingUserId] || {};
|
||||||
@@ -527,7 +527,7 @@ export function pkSign(obj: IObject, key: PkSigning, userId: string, pubKey: str
|
|||||||
* @param {string} pubKey The public key to use to verify
|
* @param {string} pubKey The public key to use to verify
|
||||||
* @param {string} userId The user ID who signed the object
|
* @param {string} userId The user ID who signed the object
|
||||||
*/
|
*/
|
||||||
export function pkVerify(obj: IObject, pubKey: string, userId: string) {
|
export function pkVerify(obj: IObject, pubKey: string, userId: string): void {
|
||||||
const keyId = "ed25519:" + pubKey;
|
const keyId = "ed25519:" + pubKey;
|
||||||
if (!(obj.signatures && obj.signatures[userId] && obj.signatures[userId][keyId])) {
|
if (!(obj.signatures && obj.signatures[userId] && obj.signatures[userId][keyId])) {
|
||||||
throw new Error("No signature");
|
throw new Error("No signature");
|
||||||
|
@@ -48,11 +48,11 @@ export class Backend implements CryptoStore {
|
|||||||
/**
|
/**
|
||||||
* @param {IDBDatabase} db
|
* @param {IDBDatabase} db
|
||||||
*/
|
*/
|
||||||
constructor(private db: IDBDatabase) {
|
public constructor(private db: IDBDatabase) {
|
||||||
// make sure we close the db on `onversionchange` - otherwise
|
// make sure we close the db on `onversionchange` - otherwise
|
||||||
// attempts to delete the database will block (and subsequent
|
// attempts to delete the database will block (and subsequent
|
||||||
// attempts to re-create it will also block).
|
// attempts to re-create it will also block).
|
||||||
db.onversionchange = () => {
|
db.onversionchange = (): void => {
|
||||||
logger.log(`versionchange for indexeddb ${this.db.name}: closing`);
|
logger.log(`versionchange for indexeddb ${this.db.name}: closing`);
|
||||||
db.close();
|
db.close();
|
||||||
};
|
};
|
||||||
@@ -103,7 +103,7 @@ export class Backend implements CryptoStore {
|
|||||||
`enqueueing key request for ${requestBody.room_id} / ` +
|
`enqueueing key request for ${requestBody.room_id} / ` +
|
||||||
requestBody.session_id,
|
requestBody.session_id,
|
||||||
);
|
);
|
||||||
txn.oncomplete = () => {resolve(request);};
|
txn.oncomplete = (): void => {resolve(request);};
|
||||||
const store = txn.objectStore("outgoingRoomKeyRequests");
|
const store = txn.objectStore("outgoingRoomKeyRequests");
|
||||||
store.add(request);
|
store.add(request);
|
||||||
});
|
});
|
||||||
@@ -157,7 +157,7 @@ export class Backend implements CryptoStore {
|
|||||||
requestBody.session_id,
|
requestBody.session_id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
cursorReq.onsuccess = () => {
|
cursorReq.onsuccess = (): void => {
|
||||||
const cursor = cursorReq.result;
|
const cursor = cursorReq.result;
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
// no match found
|
// no match found
|
||||||
@@ -201,7 +201,7 @@ export class Backend implements CryptoStore {
|
|||||||
let stateIndex = 0;
|
let stateIndex = 0;
|
||||||
let result: OutgoingRoomKeyRequest;
|
let result: OutgoingRoomKeyRequest;
|
||||||
|
|
||||||
function onsuccess(this: IDBRequest<IDBCursorWithValue | null>) {
|
function onsuccess(this: IDBRequest<IDBCursorWithValue | null>): void {
|
||||||
const cursor = this.result;
|
const cursor = this.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
// got a match
|
// got a match
|
||||||
@@ -243,8 +243,8 @@ export class Backend implements CryptoStore {
|
|||||||
const index = store.index("state");
|
const index = store.index("state");
|
||||||
const request = index.getAll(wantedState);
|
const request = index.getAll(wantedState);
|
||||||
|
|
||||||
request.onsuccess = () => resolve(request.result);
|
request.onsuccess = (): void => resolve(request.result);
|
||||||
request.onerror = () => reject(request.error);
|
request.onerror = (): void => reject(request.error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ export class Backend implements CryptoStore {
|
|||||||
let stateIndex = 0;
|
let stateIndex = 0;
|
||||||
const results: OutgoingRoomKeyRequest[] = [];
|
const results: OutgoingRoomKeyRequest[] = [];
|
||||||
|
|
||||||
function onsuccess(this: IDBRequest<IDBCursorWithValue | null>) {
|
function onsuccess(this: IDBRequest<IDBCursorWithValue | null>): void {
|
||||||
const cursor = this.result;
|
const cursor = this.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
const keyReq = cursor.value;
|
const keyReq = cursor.value;
|
||||||
@@ -309,7 +309,7 @@ export class Backend implements CryptoStore {
|
|||||||
): Promise<OutgoingRoomKeyRequest | null> {
|
): Promise<OutgoingRoomKeyRequest | null> {
|
||||||
let result: OutgoingRoomKeyRequest | null = null;
|
let result: OutgoingRoomKeyRequest | null = null;
|
||||||
|
|
||||||
function onsuccess(this: IDBRequest<IDBCursorWithValue | null>) {
|
function onsuccess(this: IDBRequest<IDBCursorWithValue | null>): void {
|
||||||
const cursor = this.result;
|
const cursor = this.result;
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
return;
|
return;
|
||||||
@@ -348,7 +348,7 @@ export class Backend implements CryptoStore {
|
|||||||
): Promise<OutgoingRoomKeyRequest | null> {
|
): Promise<OutgoingRoomKeyRequest | null> {
|
||||||
const txn = this.db.transaction("outgoingRoomKeyRequests", "readwrite");
|
const txn = this.db.transaction("outgoingRoomKeyRequests", "readwrite");
|
||||||
const cursorReq = txn.objectStore("outgoingRoomKeyRequests").openCursor(requestId);
|
const cursorReq = txn.objectStore("outgoingRoomKeyRequests").openCursor(requestId);
|
||||||
cursorReq.onsuccess = () => {
|
cursorReq.onsuccess = (): void => {
|
||||||
const cursor = cursorReq.result;
|
const cursor = cursorReq.result;
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
return;
|
return;
|
||||||
@@ -371,7 +371,7 @@ export class Backend implements CryptoStore {
|
|||||||
public getAccount(txn: IDBTransaction, func: (accountPickle: string | null) => void): void {
|
public getAccount(txn: IDBTransaction, func: (accountPickle: string | null) => void): void {
|
||||||
const objectStore = txn.objectStore("account");
|
const objectStore = txn.objectStore("account");
|
||||||
const getReq = objectStore.get("-");
|
const getReq = objectStore.get("-");
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
func(getReq.result || null);
|
func(getReq.result || null);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -391,7 +391,7 @@ export class Backend implements CryptoStore {
|
|||||||
): void {
|
): void {
|
||||||
const objectStore = txn.objectStore("account");
|
const objectStore = txn.objectStore("account");
|
||||||
const getReq = objectStore.get("crossSigningKeys");
|
const getReq = objectStore.get("crossSigningKeys");
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
func(getReq.result || null);
|
func(getReq.result || null);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -407,7 +407,7 @@ export class Backend implements CryptoStore {
|
|||||||
): void {
|
): void {
|
||||||
const objectStore = txn.objectStore("account");
|
const objectStore = txn.objectStore("account");
|
||||||
const getReq = objectStore.get(`ssss_cache:${type}`);
|
const getReq = objectStore.get(`ssss_cache:${type}`);
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
func(getReq.result || null);
|
func(getReq.result || null);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -435,7 +435,7 @@ export class Backend implements CryptoStore {
|
|||||||
public countEndToEndSessions(txn: IDBTransaction, func: (count: number) => void): void {
|
public countEndToEndSessions(txn: IDBTransaction, func: (count: number) => void): void {
|
||||||
const objectStore = txn.objectStore("sessions");
|
const objectStore = txn.objectStore("sessions");
|
||||||
const countReq = objectStore.count();
|
const countReq = objectStore.count();
|
||||||
countReq.onsuccess = function() {
|
countReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
func(countReq.result);
|
func(countReq.result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -453,7 +453,7 @@ export class Backend implements CryptoStore {
|
|||||||
const idx = objectStore.index("deviceKey");
|
const idx = objectStore.index("deviceKey");
|
||||||
const getReq = idx.openCursor(deviceKey);
|
const getReq = idx.openCursor(deviceKey);
|
||||||
const results: Parameters<Parameters<Backend["getEndToEndSessions"]>[2]>[0] = {};
|
const results: Parameters<Parameters<Backend["getEndToEndSessions"]>[2]>[0] = {};
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
const cursor = getReq.result;
|
const cursor = getReq.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
results[cursor.value.sessionId] = {
|
results[cursor.value.sessionId] = {
|
||||||
@@ -479,7 +479,7 @@ export class Backend implements CryptoStore {
|
|||||||
): void {
|
): void {
|
||||||
const objectStore = txn.objectStore("sessions");
|
const objectStore = txn.objectStore("sessions");
|
||||||
const getReq = objectStore.get([deviceKey, sessionId]);
|
const getReq = objectStore.get([deviceKey, sessionId]);
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
if (getReq.result) {
|
if (getReq.result) {
|
||||||
func({
|
func({
|
||||||
@@ -498,7 +498,7 @@ export class Backend implements CryptoStore {
|
|||||||
public getAllEndToEndSessions(txn: IDBTransaction, func: (session: ISessionInfo | null) => void): void {
|
public getAllEndToEndSessions(txn: IDBTransaction, func: (session: ISessionInfo | null) => void): void {
|
||||||
const objectStore = txn.objectStore("sessions");
|
const objectStore = txn.objectStore("sessions");
|
||||||
const getReq = objectStore.openCursor();
|
const getReq = objectStore.openCursor();
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
const cursor = getReq.result;
|
const cursor = getReq.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
@@ -546,7 +546,7 @@ export class Backend implements CryptoStore {
|
|||||||
const objectStore = txn.objectStore("session_problems");
|
const objectStore = txn.objectStore("session_problems");
|
||||||
const index = objectStore.index("deviceKey");
|
const index = objectStore.index("deviceKey");
|
||||||
const req = index.getAll(deviceKey);
|
const req = index.getAll(deviceKey);
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
const problems = req.result;
|
const problems = req.result;
|
||||||
if (!problems.length) {
|
if (!problems.length) {
|
||||||
result = null;
|
result = null;
|
||||||
@@ -583,7 +583,7 @@ export class Backend implements CryptoStore {
|
|||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
const { userId, deviceInfo } = device;
|
const { userId, deviceInfo } = device;
|
||||||
const getReq = objectStore.get([userId, deviceInfo.deviceId]);
|
const getReq = objectStore.get([userId, deviceInfo.deviceId]);
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
if (!getReq.result) {
|
if (!getReq.result) {
|
||||||
objectStore.put({ userId, deviceId: deviceInfo.deviceId });
|
objectStore.put({ userId, deviceId: deviceInfo.deviceId });
|
||||||
ret.push(device);
|
ret.push(device);
|
||||||
@@ -608,7 +608,7 @@ export class Backend implements CryptoStore {
|
|||||||
let withheld: IWithheld | null | boolean = false;
|
let withheld: IWithheld | null | boolean = false;
|
||||||
const objectStore = txn.objectStore("inbound_group_sessions");
|
const objectStore = txn.objectStore("inbound_group_sessions");
|
||||||
const getReq = objectStore.get([senderCurve25519Key, sessionId]);
|
const getReq = objectStore.get([senderCurve25519Key, sessionId]);
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
if (getReq.result) {
|
if (getReq.result) {
|
||||||
session = getReq.result.session;
|
session = getReq.result.session;
|
||||||
@@ -625,7 +625,7 @@ export class Backend implements CryptoStore {
|
|||||||
|
|
||||||
const withheldObjectStore = txn.objectStore("inbound_group_sessions_withheld");
|
const withheldObjectStore = txn.objectStore("inbound_group_sessions_withheld");
|
||||||
const withheldGetReq = withheldObjectStore.get([senderCurve25519Key, sessionId]);
|
const withheldGetReq = withheldObjectStore.get([senderCurve25519Key, sessionId]);
|
||||||
withheldGetReq.onsuccess = function() {
|
withheldGetReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
if (withheldGetReq.result) {
|
if (withheldGetReq.result) {
|
||||||
withheld = withheldGetReq.result.session;
|
withheld = withheldGetReq.result.session;
|
||||||
@@ -644,7 +644,7 @@ export class Backend implements CryptoStore {
|
|||||||
public getAllEndToEndInboundGroupSessions(txn: IDBTransaction, func: (session: ISession | null) => void): void {
|
public getAllEndToEndInboundGroupSessions(txn: IDBTransaction, func: (session: ISession | null) => void): void {
|
||||||
const objectStore = txn.objectStore("inbound_group_sessions");
|
const objectStore = txn.objectStore("inbound_group_sessions");
|
||||||
const getReq = objectStore.openCursor();
|
const getReq = objectStore.openCursor();
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
const cursor = getReq.result;
|
const cursor = getReq.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
try {
|
try {
|
||||||
@@ -677,7 +677,7 @@ export class Backend implements CryptoStore {
|
|||||||
const addReq = objectStore.add({
|
const addReq = objectStore.add({
|
||||||
senderCurve25519Key, sessionId, session: sessionData,
|
senderCurve25519Key, sessionId, session: sessionData,
|
||||||
});
|
});
|
||||||
addReq.onerror = (ev) => {
|
addReq.onerror = (ev): void => {
|
||||||
if (addReq.error?.name === 'ConstraintError') {
|
if (addReq.error?.name === 'ConstraintError') {
|
||||||
// This stops the error from triggering the txn's onerror
|
// This stops the error from triggering the txn's onerror
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
@@ -722,7 +722,7 @@ export class Backend implements CryptoStore {
|
|||||||
public getEndToEndDeviceData(txn: IDBTransaction, func: (deviceData: IDeviceData | null) => void): void {
|
public getEndToEndDeviceData(txn: IDBTransaction, func: (deviceData: IDeviceData | null) => void): void {
|
||||||
const objectStore = txn.objectStore("device_data");
|
const objectStore = txn.objectStore("device_data");
|
||||||
const getReq = objectStore.get("-");
|
const getReq = objectStore.get("-");
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
try {
|
try {
|
||||||
func(getReq.result || null);
|
func(getReq.result || null);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -745,7 +745,7 @@ export class Backend implements CryptoStore {
|
|||||||
const rooms: Parameters<Parameters<Backend["getEndToEndRooms"]>[1]>[0] = {};
|
const rooms: Parameters<Parameters<Backend["getEndToEndRooms"]>[1]>[0] = {};
|
||||||
const objectStore = txn.objectStore("rooms");
|
const objectStore = txn.objectStore("rooms");
|
||||||
const getReq = objectStore.openCursor();
|
const getReq = objectStore.openCursor();
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
const cursor = getReq.result;
|
const cursor = getReq.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
rooms[cursor.key as string] = cursor.value;
|
rooms[cursor.key as string] = cursor.value;
|
||||||
@@ -771,17 +771,17 @@ export class Backend implements CryptoStore {
|
|||||||
"readonly",
|
"readonly",
|
||||||
);
|
);
|
||||||
txn.onerror = reject;
|
txn.onerror = reject;
|
||||||
txn.oncomplete = function() {
|
txn.oncomplete = function(): void {
|
||||||
resolve(sessions);
|
resolve(sessions);
|
||||||
};
|
};
|
||||||
const objectStore = txn.objectStore("sessions_needing_backup");
|
const objectStore = txn.objectStore("sessions_needing_backup");
|
||||||
const sessionStore = txn.objectStore("inbound_group_sessions");
|
const sessionStore = txn.objectStore("inbound_group_sessions");
|
||||||
const getReq = objectStore.openCursor();
|
const getReq = objectStore.openCursor();
|
||||||
getReq.onsuccess = function() {
|
getReq.onsuccess = function(): void {
|
||||||
const cursor = getReq.result;
|
const cursor = getReq.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
const sessionGetReq = sessionStore.get(cursor.key);
|
const sessionGetReq = sessionStore.get(cursor.key);
|
||||||
sessionGetReq.onsuccess = function() {
|
sessionGetReq.onsuccess = function(): void {
|
||||||
sessions.push({
|
sessions.push({
|
||||||
senderKey: sessionGetReq.result.senderCurve25519Key,
|
senderKey: sessionGetReq.result.senderCurve25519Key,
|
||||||
sessionId: sessionGetReq.result.sessionId,
|
sessionId: sessionGetReq.result.sessionId,
|
||||||
@@ -804,7 +804,7 @@ export class Backend implements CryptoStore {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const req = objectStore.count();
|
const req = objectStore.count();
|
||||||
req.onerror = reject;
|
req.onerror = reject;
|
||||||
req.onsuccess = () => resolve(req.result);
|
req.onsuccess = (): void => resolve(req.result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,7 +852,7 @@ export class Backend implements CryptoStore {
|
|||||||
}
|
}
|
||||||
const objectStore = txn.objectStore("shared_history_inbound_group_sessions");
|
const objectStore = txn.objectStore("shared_history_inbound_group_sessions");
|
||||||
const req = objectStore.get([roomId]);
|
const req = objectStore.get([roomId]);
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
const { sessions } = req.result || { sessions: [] };
|
const { sessions } = req.result || { sessions: [] };
|
||||||
sessions.push([senderKey, sessionId]);
|
sessions.push([senderKey, sessionId]);
|
||||||
objectStore.put({ roomId, sessions });
|
objectStore.put({ roomId, sessions });
|
||||||
@@ -871,7 +871,7 @@ export class Backend implements CryptoStore {
|
|||||||
const objectStore = txn.objectStore("shared_history_inbound_group_sessions");
|
const objectStore = txn.objectStore("shared_history_inbound_group_sessions");
|
||||||
const req = objectStore.get([roomId]);
|
const req = objectStore.get([roomId]);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
const { sessions } = req.result || { sessions: [] };
|
const { sessions } = req.result || { sessions: [] };
|
||||||
resolve(sessions);
|
resolve(sessions);
|
||||||
};
|
};
|
||||||
@@ -891,7 +891,7 @@ export class Backend implements CryptoStore {
|
|||||||
}
|
}
|
||||||
const objectStore = txn.objectStore("parked_shared_history");
|
const objectStore = txn.objectStore("parked_shared_history");
|
||||||
const req = objectStore.get([roomId]);
|
const req = objectStore.get([roomId]);
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
const { parked } = req.result || { parked: [] };
|
const { parked } = req.result || { parked: [] };
|
||||||
parked.push(parkedData);
|
parked.push(parkedData);
|
||||||
objectStore.put({ roomId, parked });
|
objectStore.put({ roomId, parked });
|
||||||
@@ -909,7 +909,7 @@ export class Backend implements CryptoStore {
|
|||||||
}
|
}
|
||||||
const cursorReq = txn.objectStore("parked_shared_history").openCursor(roomId);
|
const cursorReq = txn.objectStore("parked_shared_history").openCursor(roomId);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
cursorReq.onsuccess = () => {
|
cursorReq.onsuccess = (): void => {
|
||||||
const cursor = cursorReq.result;
|
const cursor = cursorReq.result;
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
resolve([]);
|
resolve([]);
|
||||||
@@ -957,32 +957,32 @@ export class Backend implements CryptoStore {
|
|||||||
|
|
||||||
type DbMigration = (db: IDBDatabase) => void;
|
type DbMigration = (db: IDBDatabase) => void;
|
||||||
const DB_MIGRATIONS: DbMigration[] = [
|
const DB_MIGRATIONS: DbMigration[] = [
|
||||||
(db) => { createDatabase(db); },
|
(db): void => { createDatabase(db); },
|
||||||
(db) => { db.createObjectStore("account"); },
|
(db): void => { db.createObjectStore("account"); },
|
||||||
(db) => {
|
(db): void => {
|
||||||
const sessionsStore = db.createObjectStore("sessions", {
|
const sessionsStore = db.createObjectStore("sessions", {
|
||||||
keyPath: ["deviceKey", "sessionId"],
|
keyPath: ["deviceKey", "sessionId"],
|
||||||
});
|
});
|
||||||
sessionsStore.createIndex("deviceKey", "deviceKey");
|
sessionsStore.createIndex("deviceKey", "deviceKey");
|
||||||
},
|
},
|
||||||
(db) => {
|
(db): void => {
|
||||||
db.createObjectStore("inbound_group_sessions", {
|
db.createObjectStore("inbound_group_sessions", {
|
||||||
keyPath: ["senderCurve25519Key", "sessionId"],
|
keyPath: ["senderCurve25519Key", "sessionId"],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(db) => { db.createObjectStore("device_data"); },
|
(db): void => { db.createObjectStore("device_data"); },
|
||||||
(db) => { db.createObjectStore("rooms"); },
|
(db): void => { db.createObjectStore("rooms"); },
|
||||||
(db) => {
|
(db): void => {
|
||||||
db.createObjectStore("sessions_needing_backup", {
|
db.createObjectStore("sessions_needing_backup", {
|
||||||
keyPath: ["senderCurve25519Key", "sessionId"],
|
keyPath: ["senderCurve25519Key", "sessionId"],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(db) => {
|
(db): void => {
|
||||||
db.createObjectStore("inbound_group_sessions_withheld", {
|
db.createObjectStore("inbound_group_sessions_withheld", {
|
||||||
keyPath: ["senderCurve25519Key", "sessionId"],
|
keyPath: ["senderCurve25519Key", "sessionId"],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(db) => {
|
(db): void => {
|
||||||
const problemsStore = db.createObjectStore("session_problems", {
|
const problemsStore = db.createObjectStore("session_problems", {
|
||||||
keyPath: ["deviceKey", "time"],
|
keyPath: ["deviceKey", "time"],
|
||||||
});
|
});
|
||||||
@@ -992,12 +992,12 @@ const DB_MIGRATIONS: DbMigration[] = [
|
|||||||
keyPath: ["userId", "deviceId"],
|
keyPath: ["userId", "deviceId"],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(db) => {
|
(db): void => {
|
||||||
db.createObjectStore("shared_history_inbound_group_sessions", {
|
db.createObjectStore("shared_history_inbound_group_sessions", {
|
||||||
keyPath: ["roomId"],
|
keyPath: ["roomId"],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(db) => {
|
(db): void => {
|
||||||
db.createObjectStore("parked_shared_history", {
|
db.createObjectStore("parked_shared_history", {
|
||||||
keyPath: ["roomId"],
|
keyPath: ["roomId"],
|
||||||
});
|
});
|
||||||
@@ -1037,7 +1037,7 @@ interface IWrappedIDBTransaction extends IDBTransaction {
|
|||||||
* Aborts a transaction with a given exception
|
* Aborts a transaction with a given exception
|
||||||
* The transaction promise will be rejected with this exception.
|
* The transaction promise will be rejected with this exception.
|
||||||
*/
|
*/
|
||||||
function abortWithException(txn: IDBTransaction, e: Error) {
|
function abortWithException(txn: IDBTransaction, e: Error): void {
|
||||||
// We cheekily stick our exception onto the transaction object here
|
// We cheekily stick our exception onto the transaction object here
|
||||||
// We could alternatively make the thing we pass back to the app
|
// We could alternatively make the thing we pass back to the app
|
||||||
// an object containing the transaction and exception.
|
// an object containing the transaction and exception.
|
||||||
@@ -1052,13 +1052,13 @@ function abortWithException(txn: IDBTransaction, e: Error) {
|
|||||||
|
|
||||||
function promiseifyTxn<T>(txn: IDBTransaction): Promise<T | null> {
|
function promiseifyTxn<T>(txn: IDBTransaction): Promise<T | null> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
txn.oncomplete = () => {
|
txn.oncomplete = (): void => {
|
||||||
if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) {
|
if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) {
|
||||||
reject((txn as IWrappedIDBTransaction)._mx_abortexception);
|
reject((txn as IWrappedIDBTransaction)._mx_abortexception);
|
||||||
}
|
}
|
||||||
resolve(null);
|
resolve(null);
|
||||||
};
|
};
|
||||||
txn.onerror = (event) => {
|
txn.onerror = (event): void => {
|
||||||
if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) {
|
if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) {
|
||||||
reject((txn as IWrappedIDBTransaction)._mx_abortexception);
|
reject((txn as IWrappedIDBTransaction)._mx_abortexception);
|
||||||
} else {
|
} else {
|
||||||
@@ -1066,7 +1066,7 @@ function promiseifyTxn<T>(txn: IDBTransaction): Promise<T | null> {
|
|||||||
reject(txn.error);
|
reject(txn.error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
txn.onabort = (event) => {
|
txn.onabort = (event): void => {
|
||||||
if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) {
|
if ((txn as IWrappedIDBTransaction)._mx_abortexception !== undefined) {
|
||||||
reject((txn as IWrappedIDBTransaction)._mx_abortexception);
|
reject((txn as IWrappedIDBTransaction)._mx_abortexception);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -73,7 +73,7 @@ export class IndexedDBCryptoStore implements CryptoStore {
|
|||||||
* @param {IDBFactory} indexedDB global indexedDB instance
|
* @param {IDBFactory} indexedDB global indexedDB instance
|
||||||
* @param {string} dbName name of db to connect to
|
* @param {string} dbName name of db to connect to
|
||||||
*/
|
*/
|
||||||
constructor(private readonly indexedDB: IDBFactory, private readonly dbName: string) {}
|
public constructor(private readonly indexedDB: IDBFactory, private readonly dbName: string) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure the database exists and is up-to-date, or fall back to
|
* Ensure the database exists and is up-to-date, or fall back to
|
||||||
@@ -99,24 +99,24 @@ export class IndexedDBCryptoStore implements CryptoStore {
|
|||||||
|
|
||||||
const req = this.indexedDB.open(this.dbName, IndexedDBCryptoStoreBackend.VERSION);
|
const req = this.indexedDB.open(this.dbName, IndexedDBCryptoStoreBackend.VERSION);
|
||||||
|
|
||||||
req.onupgradeneeded = (ev) => {
|
req.onupgradeneeded = (ev): void => {
|
||||||
const db = req.result;
|
const db = req.result;
|
||||||
const oldVersion = ev.oldVersion;
|
const oldVersion = ev.oldVersion;
|
||||||
IndexedDBCryptoStoreBackend.upgradeDatabase(db, oldVersion);
|
IndexedDBCryptoStoreBackend.upgradeDatabase(db, oldVersion);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onblocked = () => {
|
req.onblocked = (): void => {
|
||||||
logger.log(
|
logger.log(
|
||||||
`can't yet open IndexedDBCryptoStore because it is open elsewhere`,
|
`can't yet open IndexedDBCryptoStore because it is open elsewhere`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onerror = (ev) => {
|
req.onerror = (ev): void => {
|
||||||
logger.log("Error connecting to indexeddb", ev);
|
logger.log("Error connecting to indexeddb", ev);
|
||||||
reject(req.error);
|
reject(req.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
const db = req.result;
|
const db = req.result;
|
||||||
|
|
||||||
logger.log(`connected to indexeddb ${this.dbName}`);
|
logger.log(`connected to indexeddb ${this.dbName}`);
|
||||||
@@ -179,18 +179,18 @@ export class IndexedDBCryptoStore implements CryptoStore {
|
|||||||
logger.log(`Removing indexeddb instance: ${this.dbName}`);
|
logger.log(`Removing indexeddb instance: ${this.dbName}`);
|
||||||
const req = this.indexedDB.deleteDatabase(this.dbName);
|
const req = this.indexedDB.deleteDatabase(this.dbName);
|
||||||
|
|
||||||
req.onblocked = () => {
|
req.onblocked = (): void => {
|
||||||
logger.log(
|
logger.log(
|
||||||
`can't yet delete IndexedDBCryptoStore because it is open elsewhere`,
|
`can't yet delete IndexedDBCryptoStore because it is open elsewhere`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onerror = (ev) => {
|
req.onerror = (ev): void => {
|
||||||
logger.log("Error deleting data from indexeddb", ev);
|
logger.log("Error deleting data from indexeddb", ev);
|
||||||
reject(req.error);
|
reject(req.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
logger.log(`Removed indexeddb instance: ${this.dbName}`);
|
logger.log(`Removed indexeddb instance: ${this.dbName}`);
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
@@ -322,7 +322,7 @@ export class IndexedDBCryptoStore implements CryptoStore {
|
|||||||
* @param {*} txn An active transaction. See doTxn().
|
* @param {*} txn An active transaction. See doTxn().
|
||||||
* @param {function(string)} func Called with the account pickle
|
* @param {function(string)} func Called with the account pickle
|
||||||
*/
|
*/
|
||||||
public getAccount(txn: IDBTransaction, func: (accountPickle: string | null) => void) {
|
public getAccount(txn: IDBTransaction, func: (accountPickle: string | null) => void): void {
|
||||||
this.backend!.getAccount(txn, func);
|
this.backend!.getAccount(txn, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,7 +76,7 @@ export class LocalStorageCryptoStore extends MemoryCryptoStore {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private readonly store: Storage) {
|
public constructor(private readonly store: Storage) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ export class LocalStorageCryptoStore extends MemoryCryptoStore {
|
|||||||
setJsonItem(this.store, key, problems);
|
setJsonItem(this.store, key, problems);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEndToEndSessionProblem(deviceKey: string, timestamp: number): Promise<IProblem | null> {
|
public async getEndToEndSessionProblem(deviceKey: string, timestamp: number): Promise<IProblem | null> {
|
||||||
const key = keyEndToEndSessionProblems(deviceKey);
|
const key = keyEndToEndSessionProblems(deviceKey);
|
||||||
const problems = getJsonItem<IProblem[]>(this.store, key) || [];
|
const problems = getJsonItem<IProblem[]>(this.store, key) || [];
|
||||||
if (!problems.length) {
|
if (!problems.length) {
|
||||||
@@ -408,7 +408,7 @@ export class LocalStorageCryptoStore extends MemoryCryptoStore {
|
|||||||
setJsonItem(this.store, E2E_PREFIX + `ssss_cache.${type}`, key);
|
setJsonItem(this.store, E2E_PREFIX + `ssss_cache.${type}`, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
doTxn<T>(mode: Mode, stores: Iterable<string>, func: (txn: unknown) => T): Promise<T> {
|
public doTxn<T>(mode: Mode, stores: Iterable<string>, func: (txn: unknown) => T): Promise<T> {
|
||||||
return Promise.resolve(func(null));
|
return Promise.resolve(func(null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -279,7 +279,7 @@ export class MemoryCryptoStore implements CryptoStore {
|
|||||||
|
|
||||||
// Olm Account
|
// Olm Account
|
||||||
|
|
||||||
public getAccount(txn: unknown, func: (accountPickle: string | null) => void) {
|
public getAccount(txn: unknown, func: (accountPickle: string | null) => void): void {
|
||||||
func(this.account);
|
func(this.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ import { ListenerMap, TypedEventEmitter } from "../../models/typed-event-emitter
|
|||||||
const timeoutException = new Error("Verification timed out");
|
const timeoutException = new Error("Verification timed out");
|
||||||
|
|
||||||
export class SwitchStartEventError extends Error {
|
export class SwitchStartEventError extends Error {
|
||||||
constructor(public readonly startEvent: MatrixEvent | null) {
|
public constructor(public readonly startEvent: MatrixEvent | null) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ export class VerificationBase<
|
|||||||
* @param {object} [request] the key verification request object related to
|
* @param {object} [request] the key verification request object related to
|
||||||
* this verification, if any
|
* this verification, if any
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly channel: IVerificationChannel,
|
public readonly channel: IVerificationChannel,
|
||||||
public readonly baseApis: MatrixClient,
|
public readonly baseApis: MatrixClient,
|
||||||
public readonly userId: string,
|
public readonly userId: string,
|
||||||
@@ -286,12 +286,12 @@ export class VerificationBase<
|
|||||||
if (this.promise) return this.promise;
|
if (this.promise) return this.promise;
|
||||||
|
|
||||||
this.promise = new Promise((resolve, reject) => {
|
this.promise = new Promise((resolve, reject) => {
|
||||||
this.resolve = (...args) => {
|
this.resolve = (...args): void => {
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this.endTimer();
|
this.endTimer();
|
||||||
resolve(...args);
|
resolve(...args);
|
||||||
};
|
};
|
||||||
this.reject = (e: Error | MatrixEvent) => {
|
this.reject = (e: Error | MatrixEvent): void => {
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this.endTimer();
|
this.endTimer();
|
||||||
reject(e);
|
reject(e);
|
||||||
|
@@ -154,7 +154,7 @@ interface IQrData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class QRCodeData {
|
export class QRCodeData {
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly mode: Mode,
|
public readonly mode: Mode,
|
||||||
private readonly sharedSecret: string,
|
private readonly sharedSecret: string,
|
||||||
// only set when mode is MODE_VERIFY_OTHER_USER, master key of other party at time of generating QR code
|
// only set when mode is MODE_VERIFY_OTHER_USER, master key of other party at time of generating QR code
|
||||||
@@ -283,21 +283,21 @@ export class QRCodeData {
|
|||||||
private static generateBuffer(qrData: IQrData): Buffer {
|
private static generateBuffer(qrData: IQrData): Buffer {
|
||||||
let buf = Buffer.alloc(0); // we'll concat our way through life
|
let buf = Buffer.alloc(0); // we'll concat our way through life
|
||||||
|
|
||||||
const appendByte = (b) => {
|
const appendByte = (b): void => {
|
||||||
const tmpBuf = Buffer.from([b]);
|
const tmpBuf = Buffer.from([b]);
|
||||||
buf = Buffer.concat([buf, tmpBuf]);
|
buf = Buffer.concat([buf, tmpBuf]);
|
||||||
};
|
};
|
||||||
const appendInt = (i) => {
|
const appendInt = (i): void => {
|
||||||
const tmpBuf = Buffer.alloc(2);
|
const tmpBuf = Buffer.alloc(2);
|
||||||
tmpBuf.writeInt16BE(i, 0);
|
tmpBuf.writeInt16BE(i, 0);
|
||||||
buf = Buffer.concat([buf, tmpBuf]);
|
buf = Buffer.concat([buf, tmpBuf]);
|
||||||
};
|
};
|
||||||
const appendStr = (s, enc, withLengthPrefix = true) => {
|
const appendStr = (s, enc, withLengthPrefix = true): void => {
|
||||||
const tmpBuf = Buffer.from(s, enc);
|
const tmpBuf = Buffer.from(s, enc);
|
||||||
if (withLengthPrefix) appendInt(tmpBuf.byteLength);
|
if (withLengthPrefix) appendInt(tmpBuf.byteLength);
|
||||||
buf = Buffer.concat([buf, tmpBuf]);
|
buf = Buffer.concat([buf, tmpBuf]);
|
||||||
};
|
};
|
||||||
const appendEncBase64 = (b64) => {
|
const appendEncBase64 = (b64): void => {
|
||||||
const b = decodeBase64(b64);
|
const b = decodeBase64(b64);
|
||||||
const tmpBuf = Buffer.from(b);
|
const tmpBuf = Buffer.from(b);
|
||||||
buf = Buffer.concat([buf, tmpBuf]);
|
buf = Buffer.concat([buf, tmpBuf]);
|
||||||
|
@@ -170,10 +170,12 @@ const macMethods = {
|
|||||||
"hmac-sha256": "calculate_mac_long_kdf",
|
"hmac-sha256": "calculate_mac_long_kdf",
|
||||||
};
|
};
|
||||||
|
|
||||||
function calculateMAC(olmSAS: OlmSAS, method: string) {
|
type Method = keyof typeof macMethods;
|
||||||
return function(...args) {
|
|
||||||
|
function calculateMAC(olmSAS: OlmSAS, method: Method) {
|
||||||
|
return function(...args): string {
|
||||||
const macFunction = olmSAS[macMethods[method]];
|
const macFunction = olmSAS[macMethods[method]];
|
||||||
const mac = macFunction.apply(olmSAS, args);
|
const mac: string = macFunction.apply(olmSAS, args);
|
||||||
logger.log("SAS calculateMAC:", method, args, mac);
|
logger.log("SAS calculateMAC:", method, args, mac);
|
||||||
return mac;
|
return mac;
|
||||||
};
|
};
|
||||||
@@ -208,7 +210,7 @@ const calculateKeyAgreement = {
|
|||||||
*/
|
*/
|
||||||
const KEY_AGREEMENT_LIST = ["curve25519-hkdf-sha256", "curve25519"];
|
const KEY_AGREEMENT_LIST = ["curve25519-hkdf-sha256", "curve25519"];
|
||||||
const HASHES_LIST = ["sha256"];
|
const HASHES_LIST = ["sha256"];
|
||||||
const MAC_LIST = ["org.matrix.msc3783.hkdf-hmac-sha256", "hkdf-hmac-sha256", "hmac-sha256"];
|
const MAC_LIST: Method[] = ["org.matrix.msc3783.hkdf-hmac-sha256", "hkdf-hmac-sha256", "hmac-sha256"];
|
||||||
const SAS_LIST = Object.keys(sasGenerators);
|
const SAS_LIST = Object.keys(sasGenerators);
|
||||||
|
|
||||||
const KEY_AGREEMENT_SET = new Set(KEY_AGREEMENT_LIST);
|
const KEY_AGREEMENT_SET = new Set(KEY_AGREEMENT_LIST);
|
||||||
@@ -300,13 +302,13 @@ export class SAS extends Base<SasEvent, EventHandlerMap> {
|
|||||||
keyAgreement: string,
|
keyAgreement: string,
|
||||||
sasMethods: string[],
|
sasMethods: string[],
|
||||||
olmSAS: OlmSAS,
|
olmSAS: OlmSAS,
|
||||||
macMethod: string,
|
macMethod: Method,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const sasBytes = calculateKeyAgreement[keyAgreement](this, olmSAS, 6);
|
const sasBytes = calculateKeyAgreement[keyAgreement](this, olmSAS, 6);
|
||||||
const verifySAS = new Promise<void>((resolve, reject) => {
|
const verifySAS = new Promise<void>((resolve, reject) => {
|
||||||
this.sasEvent = {
|
this.sasEvent = {
|
||||||
sas: generateSas(sasBytes, sasMethods),
|
sas: generateSas(sasBytes, sasMethods),
|
||||||
confirm: async () => {
|
confirm: async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
await this.sendMAC(olmSAS, macMethod);
|
await this.sendMAC(olmSAS, macMethod);
|
||||||
resolve();
|
resolve();
|
||||||
@@ -443,7 +445,7 @@ export class SAS extends Base<SasEvent, EventHandlerMap> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendMAC(olmSAS: OlmSAS, method: string): Promise<void> {
|
private sendMAC(olmSAS: OlmSAS, method: Method): Promise<void> {
|
||||||
const mac = {};
|
const mac = {};
|
||||||
const keyList: string[] = [];
|
const keyList: string[] = [];
|
||||||
const baseInfo = "MATRIX_KEY_VERIFICATION_MAC"
|
const baseInfo = "MATRIX_KEY_VERIFICATION_MAC"
|
||||||
@@ -475,7 +477,7 @@ export class SAS extends Base<SasEvent, EventHandlerMap> {
|
|||||||
return this.send(EventType.KeyVerificationMac, { mac, keys });
|
return this.send(EventType.KeyVerificationMac, { mac, keys });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checkMAC(olmSAS: OlmSAS, content: IContent, method: string): Promise<void> {
|
private async checkMAC(olmSAS: OlmSAS, content: IContent, method: Method): Promise<void> {
|
||||||
const baseInfo = "MATRIX_KEY_VERIFICATION_MAC"
|
const baseInfo = "MATRIX_KEY_VERIFICATION_MAC"
|
||||||
+ this.userId + this.deviceId
|
+ this.userId + this.deviceId
|
||||||
+ this.baseApis.getUserId() + this.baseApis.deviceId
|
+ this.baseApis.getUserId() + this.baseApis.deviceId
|
||||||
|
@@ -44,7 +44,7 @@ export class InRoomChannel implements IVerificationChannel {
|
|||||||
* @param {string} roomId id of the room where verification events should be posted in, should be a DM with the given user.
|
* @param {string} roomId id of the room where verification events should be posted in, should be a DM with the given user.
|
||||||
* @param {string} userId id of user that the verification request is directed at, should be present in the room.
|
* @param {string} userId id of user that the verification request is directed at, should be present in the room.
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly client: MatrixClient,
|
private readonly client: MatrixClient,
|
||||||
public readonly roomId: string,
|
public readonly roomId: string,
|
||||||
public userId?: string,
|
public userId?: string,
|
||||||
|
@@ -42,7 +42,7 @@ export class ToDeviceChannel implements IVerificationChannel {
|
|||||||
public request?: VerificationRequest;
|
public request?: VerificationRequest;
|
||||||
|
|
||||||
// userId and devices of user we're about to verify
|
// userId and devices of user we're about to verify
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly client: MatrixClient,
|
private readonly client: MatrixClient,
|
||||||
public readonly userId: string,
|
public readonly userId: string,
|
||||||
private readonly devices: string[],
|
private readonly devices: string[],
|
||||||
|
@@ -116,7 +116,7 @@ export class VerificationRequest<
|
|||||||
public _cancellingUserId?: string; // Used in tests only
|
public _cancellingUserId?: string; // Used in tests only
|
||||||
private _verifier?: VerificationBase<any, any>;
|
private _verifier?: VerificationBase<any, any>;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly channel: C,
|
public readonly channel: C,
|
||||||
private readonly verificationMethods: Map<VerificationMethod, typeof VerificationBase>,
|
private readonly verificationMethods: Map<VerificationMethod, typeof VerificationBase>,
|
||||||
private readonly client: MatrixClient,
|
private readonly client: MatrixClient,
|
||||||
@@ -498,7 +498,7 @@ export class VerificationRequest<
|
|||||||
*/
|
*/
|
||||||
public waitFor(fn: (request: VerificationRequest) => boolean): Promise<VerificationRequest> {
|
public waitFor(fn: (request: VerificationRequest) => boolean): Promise<VerificationRequest> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const check = () => {
|
const check = (): boolean => {
|
||||||
let handled = false;
|
let handled = false;
|
||||||
if (fn(this)) {
|
if (fn(this)) {
|
||||||
resolve(this);
|
resolve(this);
|
||||||
@@ -539,7 +539,7 @@ export class VerificationRequest<
|
|||||||
|
|
||||||
private calculatePhaseTransitions(): ITransition[] {
|
private calculatePhaseTransitions(): ITransition[] {
|
||||||
const transitions: ITransition[] = [{ phase: PHASE_UNSENT }];
|
const transitions: ITransition[] = [{ phase: PHASE_UNSENT }];
|
||||||
const phase = () => transitions[transitions.length - 1].phase;
|
const phase = (): Phase => transitions[transitions.length - 1].phase;
|
||||||
|
|
||||||
// always pass by .request first to be sure channel.userId has been set
|
// always pass by .request first to be sure channel.userId has been set
|
||||||
const hasRequestByThem = this.eventsByThem.has(REQUEST_TYPE);
|
const hasRequestByThem = this.eventsByThem.has(REQUEST_TYPE);
|
||||||
@@ -816,7 +816,7 @@ export class VerificationRequest<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private cancelOnTimeout = async () => {
|
private cancelOnTimeout = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
if (this.initiatedByMe) {
|
if (this.initiatedByMe) {
|
||||||
await this.cancel({
|
await this.cancel({
|
||||||
|
@@ -101,7 +101,7 @@ export class RoomWidgetClient extends MatrixClient {
|
|||||||
private lifecycle?: AbortController;
|
private lifecycle?: AbortController;
|
||||||
private syncState: SyncState | null = null;
|
private syncState: SyncState | null = null;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly widgetApi: WidgetApi,
|
private readonly widgetApi: WidgetApi,
|
||||||
private readonly capabilities: ICapabilities,
|
private readonly capabilities: ICapabilities,
|
||||||
private readonly roomId: string,
|
private readonly roomId: string,
|
||||||
@@ -211,7 +211,7 @@ export class RoomWidgetClient extends MatrixClient {
|
|||||||
if (this.capabilities.turnServers) this.watchTurnServers();
|
if (this.capabilities.turnServers) this.watchTurnServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public stopClient() {
|
public stopClient(): void {
|
||||||
this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);
|
this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendEvent}`, this.onEvent);
|
||||||
this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);
|
this.widgetApi.off(`action:${WidgetApiToWidgetAction.SendToDevice}`, this.onToDevice);
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ export class RoomWidgetClient extends MatrixClient {
|
|||||||
return this.syncState;
|
return this.syncState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setSyncState(state: SyncState) {
|
private setSyncState(state: SyncState): void {
|
||||||
const oldState = this.syncState;
|
const oldState = this.syncState;
|
||||||
this.syncState = state;
|
this.syncState = state;
|
||||||
this.emit(ClientEvent.Sync, state, oldState);
|
this.emit(ClientEvent.Sync, state, oldState);
|
||||||
@@ -298,7 +298,7 @@ export class RoomWidgetClient extends MatrixClient {
|
|||||||
await this.widgetApi.transport.reply<IWidgetApiAcknowledgeResponseData>(ev.detail, {});
|
await this.widgetApi.transport.reply<IWidgetApiAcknowledgeResponseData>(ev.detail, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEvent = async (ev: CustomEvent<ISendEventToWidgetActionRequest>) => {
|
private onEvent = async (ev: CustomEvent<ISendEventToWidgetActionRequest>): Promise<void> => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
// Verify the room ID matches, since it's possible for the client to
|
// Verify the room ID matches, since it's possible for the client to
|
||||||
@@ -317,7 +317,7 @@ export class RoomWidgetClient extends MatrixClient {
|
|||||||
await this.ack(ev);
|
await this.ack(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
private onToDevice = async (ev: CustomEvent<ISendToDeviceToWidgetActionRequest>) => {
|
private onToDevice = async (ev: CustomEvent<ISendToDeviceToWidgetActionRequest>): Promise<void> => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
const event = new MatrixEvent({
|
const event = new MatrixEvent({
|
||||||
@@ -333,9 +333,11 @@ export class RoomWidgetClient extends MatrixClient {
|
|||||||
await this.ack(ev);
|
await this.ack(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
private async watchTurnServers() {
|
private async watchTurnServers(): Promise<void> {
|
||||||
const servers = this.widgetApi.getTurnServers();
|
const servers = this.widgetApi.getTurnServers();
|
||||||
const onClientStopped = () => servers.return(undefined);
|
const onClientStopped = (): void => {
|
||||||
|
servers.return(undefined);
|
||||||
|
};
|
||||||
this.lifecycle!.signal.addEventListener("abort", onClientStopped);
|
this.lifecycle!.signal.addEventListener("abort", onClientStopped);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@@ -29,7 +29,7 @@ export function eventMapperFor(client: MatrixClient, options: MapperOpts): Event
|
|||||||
let preventReEmit = Boolean(options.preventReEmit);
|
let preventReEmit = Boolean(options.preventReEmit);
|
||||||
const decrypt = options.decrypt !== false;
|
const decrypt = options.decrypt !== false;
|
||||||
|
|
||||||
function mapper(plainOldJsObject: Partial<IEvent>) {
|
function mapper(plainOldJsObject: Partial<IEvent>): MatrixEvent {
|
||||||
if (options.toDevice) {
|
if (options.toDevice) {
|
||||||
delete plainOldJsObject.room_id;
|
delete plainOldJsObject.room_id;
|
||||||
}
|
}
|
||||||
|
@@ -73,7 +73,7 @@ export interface IFilterComponent {
|
|||||||
* @param {Object} filterJson the definition of this filter JSON, e.g. { 'contains_url': true }
|
* @param {Object} filterJson the definition of this filter JSON, e.g. { 'contains_url': true }
|
||||||
*/
|
*/
|
||||||
export class FilterComponent {
|
export class FilterComponent {
|
||||||
constructor(private filterJson: IFilterComponent, public readonly userId?: string | undefined | null) {}
|
public constructor(private filterJson: IFilterComponent, public readonly userId?: string | undefined | null) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks with the filter component matches the given event
|
* Checks with the filter component matches the given event
|
||||||
|
@@ -31,7 +31,7 @@ import { MatrixEvent } from "./models/event";
|
|||||||
* @param {string} keyNesting
|
* @param {string} keyNesting
|
||||||
* @param {*} val
|
* @param {*} val
|
||||||
*/
|
*/
|
||||||
function setProp(obj: object, keyNesting: string, val: any) {
|
function setProp(obj: object, keyNesting: string, val: any): void {
|
||||||
const nestedKeys = keyNesting.split(".");
|
const nestedKeys = keyNesting.split(".");
|
||||||
let currentObj = obj;
|
let currentObj = obj;
|
||||||
for (let i = 0; i < (nestedKeys.length - 1); i++) {
|
for (let i = 0; i < (nestedKeys.length - 1); i++) {
|
||||||
@@ -88,7 +88,7 @@ interface IRoomFilter {
|
|||||||
* @prop {?string} filterId The filter ID
|
* @prop {?string} filterId The filter ID
|
||||||
*/
|
*/
|
||||||
export class Filter {
|
export class Filter {
|
||||||
static LAZY_LOADING_MESSAGES_FILTER = {
|
public static LAZY_LOADING_MESSAGES_FILTER = {
|
||||||
lazy_load_members: true,
|
lazy_load_members: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ export class Filter {
|
|||||||
private roomFilter?: FilterComponent;
|
private roomFilter?: FilterComponent;
|
||||||
private roomTimelineFilter?: FilterComponent;
|
private roomTimelineFilter?: FilterComponent;
|
||||||
|
|
||||||
constructor(public readonly userId: string | undefined | null, public filterId?: string) {}
|
public constructor(public readonly userId: string | undefined | null, public filterId?: string) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ID of this filter on your homeserver (if known)
|
* Get the ID of this filter on your homeserver (if known)
|
||||||
@@ -132,7 +132,7 @@ export class Filter {
|
|||||||
* Set the JSON body of the filter
|
* Set the JSON body of the filter
|
||||||
* @param {Object} definition The filter definition
|
* @param {Object} definition The filter definition
|
||||||
*/
|
*/
|
||||||
public setDefinition(definition: IFilterDefinition) {
|
public setDefinition(definition: IFilterDefinition): void {
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
|
|
||||||
// This is all ported from synapse's FilterCollection()
|
// This is all ported from synapse's FilterCollection()
|
||||||
@@ -225,7 +225,7 @@ export class Filter {
|
|||||||
* Set the max number of events to return for each room's timeline.
|
* Set the max number of events to return for each room's timeline.
|
||||||
* @param {Number} limit The max number of events to return for each room.
|
* @param {Number} limit The max number of events to return for each room.
|
||||||
*/
|
*/
|
||||||
public setTimelineLimit(limit: number) {
|
public setTimelineLimit(limit: number): void {
|
||||||
setProp(this.definition, "room.timeline.limit", limit);
|
setProp(this.definition, "room.timeline.limit", limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ export class Filter {
|
|||||||
* @param {boolean} includeLeave True to make rooms the user has left appear
|
* @param {boolean} includeLeave True to make rooms the user has left appear
|
||||||
* in responses.
|
* in responses.
|
||||||
*/
|
*/
|
||||||
public setIncludeLeaveRooms(includeLeave: boolean) {
|
public setIncludeLeaveRooms(includeLeave: boolean): void {
|
||||||
setProp(this.definition, "room.include_leave", includeLeave);
|
setProp(this.definition, "room.include_leave", includeLeave);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,7 @@ interface IErrorJson extends Partial<IUsageLimit> {
|
|||||||
* @param {number} httpStatus The HTTP response status code.
|
* @param {number} httpStatus The HTTP response status code.
|
||||||
*/
|
*/
|
||||||
export class HTTPError extends Error {
|
export class HTTPError extends Error {
|
||||||
constructor(msg: string, public readonly httpStatus?: number) {
|
public constructor(msg: string, public readonly httpStatus?: number) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ export class MatrixError extends HTTPError {
|
|||||||
public readonly errcode?: string;
|
public readonly errcode?: string;
|
||||||
public data: IErrorJson;
|
public data: IErrorJson;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
errorJson: IErrorJson = {},
|
errorJson: IErrorJson = {},
|
||||||
public readonly httpStatus?: number,
|
public readonly httpStatus?: number,
|
||||||
public url?: string,
|
public url?: string,
|
||||||
@@ -79,11 +79,11 @@ export class MatrixError extends HTTPError {
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export class ConnectionError extends Error {
|
export class ConnectionError extends Error {
|
||||||
constructor(message: string, cause?: Error) {
|
public constructor(message: string, cause?: Error) {
|
||||||
super(message + (cause ? `: ${cause.message}` : ""));
|
super(message + (cause ? `: ${cause.message}` : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
public get name(): string {
|
||||||
return "ConnectionError";
|
return "ConnectionError";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ export type ResponseType<T, O extends IHttpOpts> =
|
|||||||
export class FetchHttpApi<O extends IHttpOpts> {
|
export class FetchHttpApi<O extends IHttpOpts> {
|
||||||
private abortController = new AbortController();
|
private abortController = new AbortController();
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
private eventEmitter: TypedEventEmitter<HttpApiEvent, HttpApiEventHandlerMap>,
|
private eventEmitter: TypedEventEmitter<HttpApiEvent, HttpApiEventHandlerMap>,
|
||||||
public readonly opts: O,
|
public readonly opts: O,
|
||||||
) {
|
) {
|
||||||
|
@@ -77,7 +77,7 @@ export class MatrixHttpApi<O extends IHttpOpts> extends FetchHttpApi<O> {
|
|||||||
if (global.XMLHttpRequest) {
|
if (global.XMLHttpRequest) {
|
||||||
const xhr = new global.XMLHttpRequest();
|
const xhr = new global.XMLHttpRequest();
|
||||||
|
|
||||||
const timeoutFn = function() {
|
const timeoutFn = function(): void {
|
||||||
xhr.abort();
|
xhr.abort();
|
||||||
defer.reject(new Error("Timeout"));
|
defer.reject(new Error("Timeout"));
|
||||||
};
|
};
|
||||||
@@ -85,7 +85,7 @@ export class MatrixHttpApi<O extends IHttpOpts> extends FetchHttpApi<O> {
|
|||||||
// set an initial timeout of 30s; we'll advance it each time we get a progress notification
|
// set an initial timeout of 30s; we'll advance it each time we get a progress notification
|
||||||
let timeoutTimer = callbacks.setTimeout(timeoutFn, 30000);
|
let timeoutTimer = callbacks.setTimeout(timeoutFn, 30000);
|
||||||
|
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function(): void {
|
||||||
switch (xhr.readyState) {
|
switch (xhr.readyState) {
|
||||||
case global.XMLHttpRequest.DONE:
|
case global.XMLHttpRequest.DONE:
|
||||||
callbacks.clearTimeout(timeoutTimer);
|
callbacks.clearTimeout(timeoutTimer);
|
||||||
@@ -113,7 +113,7 @@ export class MatrixHttpApi<O extends IHttpOpts> extends FetchHttpApi<O> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.upload.onprogress = (ev: ProgressEvent) => {
|
xhr.upload.onprogress = (ev: ProgressEvent): void => {
|
||||||
callbacks.clearTimeout(timeoutTimer);
|
callbacks.clearTimeout(timeoutTimer);
|
||||||
upload.loaded = ev.loaded;
|
upload.loaded = ev.loaded;
|
||||||
upload.total = ev.total;
|
upload.total = ev.total;
|
||||||
|
@@ -36,13 +36,13 @@ export function anySignal(signals: AbortSignal[]): {
|
|||||||
} {
|
} {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup(): void {
|
||||||
for (const signal of signals) {
|
for (const signal of signals) {
|
||||||
signal.removeEventListener("abort", onAbort);
|
signal.removeEventListener("abort", onAbort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAbort() {
|
function onAbort(): void {
|
||||||
controller.abort();
|
controller.abort();
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
@@ -26,13 +26,13 @@ export function exists(indexedDB: IDBFactory, dbName: string): Promise<boolean>
|
|||||||
return new Promise<boolean>((resolve, reject) => {
|
return new Promise<boolean>((resolve, reject) => {
|
||||||
let exists = true;
|
let exists = true;
|
||||||
const req = indexedDB.open(dbName);
|
const req = indexedDB.open(dbName);
|
||||||
req.onupgradeneeded = () => {
|
req.onupgradeneeded = (): void => {
|
||||||
// Since we did not provide an explicit version when opening, this event
|
// Since we did not provide an explicit version when opening, this event
|
||||||
// should only fire if the DB did not exist before at any version.
|
// should only fire if the DB did not exist before at any version.
|
||||||
exists = false;
|
exists = false;
|
||||||
};
|
};
|
||||||
req.onblocked = () => reject(req.error);
|
req.onblocked = (): void => reject(req.error);
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
const db = req.result;
|
const db = req.result;
|
||||||
db.close();
|
db.close();
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
@@ -45,6 +45,6 @@ export function exists(indexedDB: IDBFactory, dbName: string): Promise<boolean>
|
|||||||
}
|
}
|
||||||
resolve(exists);
|
resolve(exists);
|
||||||
};
|
};
|
||||||
req.onerror = ev => reject(req.error);
|
req.onerror = (): void => reject(req.error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -100,7 +100,7 @@ class NoAuthFlowFoundError extends Error {
|
|||||||
public name = "NoAuthFlowFoundError";
|
public name = "NoAuthFlowFoundError";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention, camelcase
|
// eslint-disable-next-line @typescript-eslint/naming-convention, camelcase
|
||||||
constructor(m: string, public readonly required_stages: string[], public readonly flows: IFlow[]) {
|
public constructor(m: string, public readonly required_stages: string[], public readonly flows: IFlow[]) {
|
||||||
super(m);
|
super(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ export class InteractiveAuth {
|
|||||||
// the promise the will resolve/reject when it completes
|
// the promise the will resolve/reject when it completes
|
||||||
private submitPromise: Promise<void> | null = null;
|
private submitPromise: Promise<void> | null = null;
|
||||||
|
|
||||||
constructor(opts: IOpts) {
|
public constructor(opts: IOpts) {
|
||||||
this.matrixClient = opts.matrixClient;
|
this.matrixClient = opts.matrixClient;
|
||||||
this.data = opts.authData || {};
|
this.data = opts.authData || {};
|
||||||
this.requestCallback = opts.doRequest;
|
this.requestCallback = opts.doRequest;
|
||||||
@@ -419,7 +419,7 @@ export class InteractiveAuth {
|
|||||||
/**
|
/**
|
||||||
* Requests a new email token and sets the email sid for the validation session
|
* Requests a new email token and sets the email sid for the validation session
|
||||||
*/
|
*/
|
||||||
public requestEmailToken = async () => {
|
public requestEmailToken = async (): Promise<void> => {
|
||||||
if (!this.requestingEmailToken) {
|
if (!this.requestingEmailToken) {
|
||||||
logger.trace("Requesting email token. Attempt: " + this.emailAttempt);
|
logger.trace("Requesting email token. Attempt: " + this.emailAttempt);
|
||||||
// If we've picked a flow with email auth, we send the email
|
// If we've picked a flow with email auth, we send the email
|
||||||
|
@@ -35,7 +35,7 @@ const DEFAULT_NAMESPACE = "matrix";
|
|||||||
// console methods at initialization time by a factory that looks up the console methods
|
// console methods at initialization time by a factory that looks up the console methods
|
||||||
// when logging so we always get the current value of console methods.
|
// when logging so we always get the current value of console methods.
|
||||||
log.methodFactory = function(methodName, logLevel, loggerName) {
|
log.methodFactory = function(methodName, logLevel, loggerName) {
|
||||||
return function(this: PrefixedLogger, ...args) {
|
return function(this: PrefixedLogger, ...args): void {
|
||||||
/* eslint-disable @typescript-eslint/no-invalid-this */
|
/* eslint-disable @typescript-eslint/no-invalid-this */
|
||||||
if (this.prefix) {
|
if (this.prefix) {
|
||||||
args.unshift(this.prefix);
|
args.unshift(this.prefix);
|
||||||
@@ -67,7 +67,7 @@ export interface PrefixedLogger extends Logger {
|
|||||||
prefix: string;
|
prefix: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extendLogger(logger: Logger) {
|
function extendLogger(logger: Logger): void {
|
||||||
(<PrefixedLogger>logger).withPrefix = function(prefix: string): PrefixedLogger {
|
(<PrefixedLogger>logger).withPrefix = function(prefix: string): PrefixedLogger {
|
||||||
const existingPrefix = this.prefix || "";
|
const existingPrefix = this.prefix || "";
|
||||||
return getPrefixedLogger(existingPrefix + prefix);
|
return getPrefixedLogger(existingPrefix + prefix);
|
||||||
|
@@ -21,6 +21,7 @@ import { MemoryStore } from "./store/memory";
|
|||||||
import { MatrixScheduler } from "./scheduler";
|
import { MatrixScheduler } from "./scheduler";
|
||||||
import { MatrixClient, ICreateClientOpts } from "./client";
|
import { MatrixClient, ICreateClientOpts } from "./client";
|
||||||
import { RoomWidgetClient, ICapabilities } from "./embedded";
|
import { RoomWidgetClient, ICapabilities } from "./embedded";
|
||||||
|
import { CryptoStore } from "./crypto/store/base";
|
||||||
|
|
||||||
export * from "./client";
|
export * from "./client";
|
||||||
export * from "./embedded";
|
export * from "./embedded";
|
||||||
@@ -64,7 +65,7 @@ export {
|
|||||||
} from "./webrtc/groupCall";
|
} from "./webrtc/groupCall";
|
||||||
export type { GroupCall } from "./webrtc/groupCall";
|
export type { GroupCall } from "./webrtc/groupCall";
|
||||||
|
|
||||||
let cryptoStoreFactory = () => new MemoryCryptoStore;
|
let cryptoStoreFactory = (): CryptoStore => new MemoryCryptoStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure a different factory to be used for creating crypto stores
|
* Configure a different factory to be used for creating crypto stores
|
||||||
@@ -72,7 +73,7 @@ let cryptoStoreFactory = () => new MemoryCryptoStore;
|
|||||||
* @param {Function} fac a function which will return a new
|
* @param {Function} fac a function which will return a new
|
||||||
* {@link module:crypto.store.base~CryptoStore}.
|
* {@link module:crypto.store.base~CryptoStore}.
|
||||||
*/
|
*/
|
||||||
export function setCryptoStoreFactory(fac) {
|
export function setCryptoStoreFactory(fac: () => CryptoStore): void {
|
||||||
cryptoStoreFactory = fac;
|
cryptoStoreFactory = fac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -172,7 +172,7 @@ export class MSC3089TreeSpace {
|
|||||||
const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
|
const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
|
||||||
if (Array.isArray(currentPls)) throw new Error("Unexpected return type for power levels");
|
if (Array.isArray(currentPls)) throw new Error("Unexpected return type for power levels");
|
||||||
|
|
||||||
const pls = currentPls.getContent() || {};
|
const pls = currentPls?.getContent() || {};
|
||||||
const viewLevel = pls['users_default'] || 0;
|
const viewLevel = pls['users_default'] || 0;
|
||||||
const editLevel = pls['events_default'] || 50;
|
const editLevel = pls['events_default'] || 50;
|
||||||
const adminLevel = pls['events']?.[EventType.RoomPowerLevels] || 100;
|
const adminLevel = pls['events']?.[EventType.RoomPowerLevels] || 100;
|
||||||
@@ -207,7 +207,7 @@ export class MSC3089TreeSpace {
|
|||||||
const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
|
const currentPls = this.room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
|
||||||
if (Array.isArray(currentPls)) throw new Error("Unexpected return type for power levels");
|
if (Array.isArray(currentPls)) throw new Error("Unexpected return type for power levels");
|
||||||
|
|
||||||
const pls = currentPls.getContent() || {};
|
const pls = currentPls?.getContent() || {};
|
||||||
const viewLevel = pls['users_default'] || 0;
|
const viewLevel = pls['users_default'] || 0;
|
||||||
const editLevel = pls['events_default'] || 50;
|
const editLevel = pls['events_default'] || 50;
|
||||||
const adminLevel = pls['events']?.[EventType.RoomPowerLevels] || 100;
|
const adminLevel = pls['events']?.[EventType.RoomPowerLevels] || 100;
|
||||||
|
@@ -56,7 +56,7 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
|
|||||||
private livenessWatchTimeout?: ReturnType<typeof setTimeout>;
|
private livenessWatchTimeout?: ReturnType<typeof setTimeout>;
|
||||||
private _latestLocationEvent?: MatrixEvent;
|
private _latestLocationEvent?: MatrixEvent;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
private rootEvent: MatrixEvent,
|
private rootEvent: MatrixEvent,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -180,7 +180,7 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private clearLatestLocation = () => {
|
private clearLatestLocation = (): void => {
|
||||||
this._latestLocationEvent = undefined;
|
this._latestLocationEvent = undefined;
|
||||||
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState!);
|
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState!);
|
||||||
};
|
};
|
||||||
|
@@ -42,7 +42,7 @@ export class EventContext {
|
|||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor(public readonly ourEvent: MatrixEvent) {
|
public constructor(public readonly ourEvent: MatrixEvent) {
|
||||||
this.timeline = [ourEvent];
|
this.timeline = [ourEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@ if (DEBUG) {
|
|||||||
// using bind means that we get to keep useful line numbers in the console
|
// using bind means that we get to keep useful line numbers in the console
|
||||||
debuglog = logger.log.bind(logger);
|
debuglog = logger.log.bind(logger);
|
||||||
} else {
|
} else {
|
||||||
debuglog = function() {};
|
debuglog = function(): void {};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IOpts {
|
interface IOpts {
|
||||||
@@ -135,7 +135,7 @@ export class EventTimelineSet extends TypedEventEmitter<EmittedEvents, EventTime
|
|||||||
* @param {boolean} isThreadTimeline Whether this timeline set relates to a thread list timeline
|
* @param {boolean} isThreadTimeline Whether this timeline set relates to a thread list timeline
|
||||||
* (e.g., All threads or My threads)
|
* (e.g., All threads or My threads)
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly room: Room | undefined,
|
public readonly room: Room | undefined,
|
||||||
opts: IOpts = {},
|
opts: IOpts = {},
|
||||||
client?: MatrixClient,
|
client?: MatrixClient,
|
||||||
@@ -702,7 +702,7 @@ export class EventTimelineSet extends TypedEventEmitter<EmittedEvents, EventTime
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (timeline.getTimelineSet() !== this) {
|
if (timeline.getTimelineSet() !== this) {
|
||||||
throw new Error(`EventTimelineSet.addEventToTimeline: Timeline=${timeline.toString()} does not belong " +
|
throw new Error(`EventTimelineSet.addEventToTimeline: Timeline=${timeline.toString()} does not belong " +
|
||||||
"in timelineSet(threadId=${this.thread?.id})`);
|
"in timelineSet(threadId=${this.thread?.id})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -67,7 +67,7 @@ export class EventTimeline {
|
|||||||
* @param {RoomState} stateContext the room state to be queried
|
* @param {RoomState} stateContext the room state to be queried
|
||||||
* @param {boolean} toStartOfTimeline if true the event's forwardLooking flag is set false
|
* @param {boolean} toStartOfTimeline if true the event's forwardLooking flag is set false
|
||||||
*/
|
*/
|
||||||
static setEventMetadata(event: MatrixEvent, stateContext: RoomState, toStartOfTimeline: boolean): void {
|
public static setEventMetadata(event: MatrixEvent, stateContext: RoomState, toStartOfTimeline: boolean): void {
|
||||||
// When we try to generate a sentinel member before we have that member
|
// When we try to generate a sentinel member before we have that member
|
||||||
// in the members object, we still generate a sentinel but it doesn't
|
// in the members object, we still generate a sentinel but it doesn't
|
||||||
// have a membership event, so test to see if events.member is set. We
|
// have a membership event, so test to see if events.member is set. We
|
||||||
@@ -130,7 +130,7 @@ export class EventTimeline {
|
|||||||
* @param {EventTimelineSet} eventTimelineSet the set of timelines this is part of
|
* @param {EventTimelineSet} eventTimelineSet the set of timelines this is part of
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor(private readonly eventTimelineSet: EventTimelineSet) {
|
public constructor(private readonly eventTimelineSet: EventTimelineSet) {
|
||||||
this.roomId = eventTimelineSet.room?.roomId ?? null;
|
this.roomId = eventTimelineSet.room?.roomId ?? null;
|
||||||
if (this.roomId) {
|
if (this.roomId) {
|
||||||
this.startState = new RoomState(this.roomId);
|
this.startState = new RoomState(this.roomId);
|
||||||
|
@@ -309,7 +309,7 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
|||||||
* that getDirectionalContent() will return event.content and not event.prev_content.
|
* that getDirectionalContent() will return event.content and not event.prev_content.
|
||||||
* Default: true. <strong>This property is experimental and may change.</strong>
|
* Default: true. <strong>This property is experimental and may change.</strong>
|
||||||
*/
|
*/
|
||||||
constructor(public event: Partial<IEvent> = {}) {
|
public constructor(public event: Partial<IEvent> = {}) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// intern the values of matrix events to force share strings and reduce the
|
// intern the values of matrix events to force share strings and reduce the
|
||||||
@@ -352,7 +352,7 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
|||||||
return this._cachedExtEv;
|
return this._cachedExtEv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private invalidateExtensibleEvent() {
|
private invalidateExtensibleEvent(): void {
|
||||||
// just reset the flag - that'll trick the getter into parsing a new event
|
// just reset the flag - that'll trick the getter into parsing a new event
|
||||||
this._hasCachedExtEv = false;
|
this._hasCachedExtEv = false;
|
||||||
}
|
}
|
||||||
@@ -679,7 +679,7 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
|||||||
return this.clearEvent?.content?.msgtype === "m.bad.encrypted";
|
return this.clearEvent?.content?.msgtype === "m.bad.encrypted";
|
||||||
}
|
}
|
||||||
|
|
||||||
public shouldAttemptDecryption() {
|
public shouldAttemptDecryption(): boolean {
|
||||||
if (this.isRedacted()) return false;
|
if (this.isRedacted()) return false;
|
||||||
if (this.isBeingDecrypted()) return false;
|
if (this.isBeingDecrypted()) return false;
|
||||||
if (this.clearEvent) return false;
|
if (this.clearEvent) return false;
|
||||||
@@ -1480,7 +1480,7 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
|||||||
* more information.
|
* more information.
|
||||||
* @returns {boolean} True if the event is cancelled, false otherwise.
|
* @returns {boolean} True if the event is cancelled, false otherwise.
|
||||||
*/
|
*/
|
||||||
isCancelled(): boolean {
|
public isCancelled(): boolean {
|
||||||
return this._isCancelled;
|
return this._isCancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1498,7 +1498,7 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
|||||||
* features (such as sender) surrounding the event.
|
* features (such as sender) surrounding the event.
|
||||||
* @returns {MatrixEvent} A snapshot of this event.
|
* @returns {MatrixEvent} A snapshot of this event.
|
||||||
*/
|
*/
|
||||||
toSnapshot(): MatrixEvent {
|
public toSnapshot(): MatrixEvent {
|
||||||
const ev = new MatrixEvent(JSON.parse(JSON.stringify(this.event)));
|
const ev = new MatrixEvent(JSON.parse(JSON.stringify(this.event)));
|
||||||
for (const [p, v] of Object.entries(this)) {
|
for (const [p, v] of Object.entries(this)) {
|
||||||
if (p !== "event") { // exclude the thing we just cloned
|
if (p !== "event") { // exclude the thing we just cloned
|
||||||
@@ -1515,7 +1515,7 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
|
|||||||
* @param {MatrixEvent} otherEvent The other event to check against.
|
* @param {MatrixEvent} otherEvent The other event to check against.
|
||||||
* @returns {boolean} True if the events are the same, false otherwise.
|
* @returns {boolean} True if the events are the same, false otherwise.
|
||||||
*/
|
*/
|
||||||
isEquivalentTo(otherEvent: MatrixEvent): boolean {
|
public isEquivalentTo(otherEvent: MatrixEvent): boolean {
|
||||||
if (!otherEvent) return false;
|
if (!otherEvent) return false;
|
||||||
if (otherEvent === this) return true;
|
if (otherEvent === this) return true;
|
||||||
const myProps = deepSortedObjectEntries(this.event);
|
const myProps = deepSortedObjectEntries(this.event);
|
||||||
|
@@ -73,7 +73,7 @@ export enum PolicyScope {
|
|||||||
* our data structures.
|
* our data structures.
|
||||||
*/
|
*/
|
||||||
export class IgnoredInvites {
|
export class IgnoredInvites {
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly client: MatrixClient,
|
private readonly client: MatrixClient,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ export class IgnoredInvites {
|
|||||||
/**
|
/**
|
||||||
* Remove a rule.
|
* Remove a rule.
|
||||||
*/
|
*/
|
||||||
public async removeRule(event: MatrixEvent) {
|
public async removeRule(event: MatrixEvent): Promise<void> {
|
||||||
await this.client.redactEvent(event.getRoomId()!, event.getId()!);
|
await this.client.redactEvent(event.getRoomId()!, event.getId()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ export class IgnoredInvites {
|
|||||||
/**
|
/**
|
||||||
* Modify in place the `IGNORE_INVITES_POLICIES` object from account data.
|
* Modify in place the `IGNORE_INVITES_POLICIES` object from account data.
|
||||||
*/
|
*/
|
||||||
private async withIgnoreInvitesPolicies(cb: (ignoreInvitesPolicies: {[key: string]: any}) => void) {
|
private async withIgnoreInvitesPolicies(cb: (ignoreInvitesPolicies: {[key: string]: any}) => void): Promise<void> {
|
||||||
const { policies, ignoreInvitesPolicies } = this.getPoliciesAndIgnoreInvitesPolicies();
|
const { policies, ignoreInvitesPolicies } = this.getPoliciesAndIgnoreInvitesPolicies();
|
||||||
cb(ignoreInvitesPolicies);
|
cb(ignoreInvitesPolicies);
|
||||||
policies[IGNORE_INVITES_ACCOUNT_EVENT_KEY.name] = ignoreInvitesPolicies;
|
policies[IGNORE_INVITES_ACCOUNT_EVENT_KEY.name] = ignoreInvitesPolicies;
|
||||||
|
@@ -29,11 +29,11 @@ export class RelatedRelations {
|
|||||||
return this.relations.reduce<MatrixEvent[]>((c, p) => [...c, ...p.getRelations()], []);
|
return this.relations.reduce<MatrixEvent[]>((c, p) => [...c, ...p.getRelations()], []);
|
||||||
}
|
}
|
||||||
|
|
||||||
public on<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>) {
|
public on<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>): void {
|
||||||
this.relations.forEach(r => r.on(ev, fn));
|
this.relations.forEach(r => r.on(ev, fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
public off<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>) {
|
public off<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>): void {
|
||||||
this.relations.forEach(r => r.off(ev, fn));
|
this.relations.forEach(r => r.off(ev, fn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ export class RelationsContainer {
|
|||||||
// this.relations.get(parentEventId).get(relationType).get(relationEventType)
|
// this.relations.get(parentEventId).get(relationType).get(relationEventType)
|
||||||
private relations = new Map<string, Map<RelationType | string, Map<EventType | string, Relations>>>();
|
private relations = new Map<string, Map<RelationType | string, Map<EventType | string, Relations>>>();
|
||||||
|
|
||||||
constructor(private readonly client: MatrixClient, private readonly room?: Room) {
|
public constructor(private readonly client: MatrixClient, private readonly room?: Room) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,7 +98,7 @@ export class RelationsContainer {
|
|||||||
const relation = event.getRelation();
|
const relation = event.getRelation();
|
||||||
if (!relation) return;
|
if (!relation) return;
|
||||||
|
|
||||||
const onEventDecrypted = () => {
|
const onEventDecrypted = (): void => {
|
||||||
if (event.isDecryptionFailure()) {
|
if (event.isDecryptionFailure()) {
|
||||||
// This could for example happen if the encryption keys are not yet available.
|
// This could for example happen if the encryption keys are not yet available.
|
||||||
// The event may still be decrypted later. Register the listener again.
|
// The event may still be decrypted later. Register the listener again.
|
||||||
|
@@ -60,7 +60,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
* @param {MatrixClient|Room} client
|
* @param {MatrixClient|Room} client
|
||||||
* The client which created this instance. For backwards compatibility also accepts a Room.
|
* The client which created this instance. For backwards compatibility also accepts a Room.
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly relationType: RelationType | string,
|
public readonly relationType: RelationType | string,
|
||||||
public readonly eventType: string,
|
public readonly eventType: string,
|
||||||
client: MatrixClient | Room,
|
client: MatrixClient | Room,
|
||||||
@@ -75,7 +75,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
* @param {MatrixEvent} event
|
* @param {MatrixEvent} event
|
||||||
* The new relation event to be added.
|
* The new relation event to be added.
|
||||||
*/
|
*/
|
||||||
public async addEvent(event: MatrixEvent) {
|
public async addEvent(event: MatrixEvent): Promise<void> {
|
||||||
if (this.relationEventIds.has(event.getId()!)) {
|
if (this.relationEventIds.has(event.getId()!)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
* @param {MatrixEvent} event
|
* @param {MatrixEvent} event
|
||||||
* The relation event to remove.
|
* The relation event to remove.
|
||||||
*/
|
*/
|
||||||
private async removeEvent(event: MatrixEvent) {
|
private async removeEvent(event: MatrixEvent): Promise<void> {
|
||||||
if (!this.relations.has(event)) {
|
if (!this.relations.has(event)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
* @param {MatrixEvent} event The event whose status has changed
|
* @param {MatrixEvent} event The event whose status has changed
|
||||||
* @param {EventStatus} status The new status
|
* @param {EventStatus} status The new status
|
||||||
*/
|
*/
|
||||||
private onEventStatus = (event: MatrixEvent, status: EventStatus | null) => {
|
private onEventStatus = (event: MatrixEvent, status: EventStatus | null): void => {
|
||||||
if (!event.isSending()) {
|
if (!event.isSending()) {
|
||||||
// Sending is done, so we don't need to listen anymore
|
// Sending is done, so we don't need to listen anymore
|
||||||
event.removeListener(MatrixEventEvent.Status, this.onEventStatus);
|
event.removeListener(MatrixEventEvent.Status, this.onEventStatus);
|
||||||
@@ -356,7 +356,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
/*
|
/*
|
||||||
* @param {MatrixEvent} targetEvent the event the relations are related to.
|
* @param {MatrixEvent} targetEvent the event the relations are related to.
|
||||||
*/
|
*/
|
||||||
public async setTargetEvent(event: MatrixEvent) {
|
public async setTargetEvent(event: MatrixEvent): Promise<void> {
|
||||||
if (this.targetEvent) {
|
if (this.targetEvent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -374,7 +374,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
this.maybeEmitCreated();
|
this.maybeEmitCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
private maybeEmitCreated() {
|
private maybeEmitCreated(): void {
|
||||||
if (this.creationEmitted) {
|
if (this.creationEmitted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -83,7 +83,7 @@ export class RoomMember extends TypedEventEmitter<RoomMemberEvent, RoomMemberEve
|
|||||||
* @prop {MatrixEvent} events.member The m.room.member event for this RoomMember.
|
* @prop {MatrixEvent} events.member The m.room.member event for this RoomMember.
|
||||||
* @prop {boolean} disambiguate True if the member's name is disambiguated.
|
* @prop {boolean} disambiguate True if the member's name is disambiguated.
|
||||||
*/
|
*/
|
||||||
constructor(public readonly roomId: string, public readonly userId: string) {
|
public constructor(public readonly roomId: string, public readonly userId: string) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.name = userId;
|
this.name = userId;
|
||||||
@@ -232,7 +232,7 @@ export class RoomMember extends TypedEventEmitter<RoomMemberEvent, RoomMemberEve
|
|||||||
/**
|
/**
|
||||||
* Update the last modified time to the current time.
|
* Update the last modified time to the current time.
|
||||||
*/
|
*/
|
||||||
private updateModifiedTime() {
|
private updateModifiedTime(): void {
|
||||||
this.modified = Date.now();
|
this.modified = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -136,7 +136,7 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
|
|||||||
* events dictionary, keyed on the event type and then the state_key value.
|
* events dictionary, keyed on the event type and then the state_key value.
|
||||||
* @prop {string} paginationToken The pagination token for this state.
|
* @prop {string} paginationToken The pagination token for this state.
|
||||||
*/
|
*/
|
||||||
constructor(public readonly roomId: string, private oobMemberFlags = { status: OobStatus.NotStarted }) {
|
public constructor(public readonly roomId: string, private oobMemberFlags = { status: OobStatus.NotStarted }) {
|
||||||
super();
|
super();
|
||||||
this.updateModifiedTime();
|
this.updateModifiedTime();
|
||||||
}
|
}
|
||||||
@@ -250,8 +250,8 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
|
|||||||
* <code>undefined</code>, else a single event (or null if no match found).
|
* <code>undefined</code>, else a single event (or null if no match found).
|
||||||
*/
|
*/
|
||||||
public getStateEvents(eventType: EventType | string): MatrixEvent[];
|
public getStateEvents(eventType: EventType | string): MatrixEvent[];
|
||||||
public getStateEvents(eventType: EventType | string, stateKey: string): MatrixEvent;
|
public getStateEvents(eventType: EventType | string, stateKey: string): MatrixEvent | null;
|
||||||
public getStateEvents(eventType: EventType | string, stateKey?: string) {
|
public getStateEvents(eventType: EventType | string, stateKey?: string): MatrixEvent[] | MatrixEvent | null {
|
||||||
if (!this.events.has(eventType)) {
|
if (!this.events.has(eventType)) {
|
||||||
// no match
|
// no match
|
||||||
return stateKey === undefined ? [] : null;
|
return stateKey === undefined ? [] : null;
|
||||||
@@ -342,7 +342,7 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
|
|||||||
* @fires module:client~MatrixClient#event:"RoomState.events"
|
* @fires module:client~MatrixClient#event:"RoomState.events"
|
||||||
* @fires module:client~MatrixClient#event:"RoomStateEvent.Marker"
|
* @fires module:client~MatrixClient#event:"RoomStateEvent.Marker"
|
||||||
*/
|
*/
|
||||||
public setStateEvents(stateEvents: MatrixEvent[], markerFoundOptions?: IMarkerFoundOptions) {
|
public setStateEvents(stateEvents: MatrixEvent[], markerFoundOptions?: IMarkerFoundOptions): void {
|
||||||
this.updateModifiedTime();
|
this.updateModifiedTime();
|
||||||
|
|
||||||
// update the core event dict
|
// update the core event dict
|
||||||
|
@@ -46,6 +46,6 @@ interface IInfo {
|
|||||||
* @param {Number} info.timestamp The timestamp for this room.
|
* @param {Number} info.timestamp The timestamp for this room.
|
||||||
*/
|
*/
|
||||||
export class RoomSummary {
|
export class RoomSummary {
|
||||||
constructor(public readonly roomId: string, info?: IInfo) {}
|
public constructor(public readonly roomId: string, info?: IInfo) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -317,7 +317,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|||||||
* @param {boolean} [opts.timelineSupport = false] Set to true to enable improved
|
* @param {boolean} [opts.timelineSupport = false] Set to true to enable improved
|
||||||
* timeline support.
|
* timeline support.
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly roomId: string,
|
public readonly roomId: string,
|
||||||
public readonly client: MatrixClient,
|
public readonly client: MatrixClient,
|
||||||
public readonly myUserId: string,
|
public readonly myUserId: string,
|
||||||
@@ -1950,7 +1950,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateThreadRootEvents = (thread: Thread, toStartOfTimeline: boolean) => {
|
private updateThreadRootEvents = (thread: Thread, toStartOfTimeline: boolean): void => {
|
||||||
if (thread.length) {
|
if (thread.length) {
|
||||||
this.updateThreadRootEvent(this.threadsTimelineSets?.[0], thread, toStartOfTimeline);
|
this.updateThreadRootEvent(this.threadsTimelineSets?.[0], thread, toStartOfTimeline);
|
||||||
if (thread.hasCurrentUserParticipated) {
|
if (thread.hasCurrentUserParticipated) {
|
||||||
@@ -1963,7 +1963,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|||||||
timelineSet: Optional<EventTimelineSet>,
|
timelineSet: Optional<EventTimelineSet>,
|
||||||
thread: Thread,
|
thread: Thread,
|
||||||
toStartOfTimeline: boolean,
|
toStartOfTimeline: boolean,
|
||||||
) => {
|
): void => {
|
||||||
if (timelineSet && thread.rootEvent) {
|
if (timelineSet && thread.rootEvent) {
|
||||||
if (Thread.hasServerSideSupport) {
|
if (Thread.hasServerSideSupport) {
|
||||||
timelineSet.addLiveEvent(thread.rootEvent, {
|
timelineSet.addLiveEvent(thread.rootEvent, {
|
||||||
@@ -2050,7 +2050,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|||||||
redactedEvent.getType(),
|
redactedEvent.getType(),
|
||||||
redactedEvent.getStateKey()!,
|
redactedEvent.getStateKey()!,
|
||||||
);
|
);
|
||||||
if (currentStateEvent.getId() === redactedEvent.getId()) {
|
if (currentStateEvent?.getId() === redactedEvent.getId()) {
|
||||||
this.currentState.setStateEvents([redactedEvent]);
|
this.currentState.setStateEvents([redactedEvent]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2913,7 +2913,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|||||||
let excludedUserIds: string[] = [];
|
let excludedUserIds: string[] = [];
|
||||||
const mFunctionalMembers = this.currentState.getStateEvents(UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, "");
|
const mFunctionalMembers = this.currentState.getStateEvents(UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, "");
|
||||||
if (Array.isArray(mFunctionalMembers?.getContent().service_members)) {
|
if (Array.isArray(mFunctionalMembers?.getContent().service_members)) {
|
||||||
excludedUserIds = mFunctionalMembers.getContent().service_members;
|
excludedUserIds = mFunctionalMembers!.getContent().service_members;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get members that are NOT ourselves and are actually in the room.
|
// get members that are NOT ourselves and are actually in the room.
|
||||||
@@ -3077,7 +3077,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
|||||||
originalEvent.applyVisibilityEvent(visibilityChange);
|
originalEvent.applyVisibilityEvent(visibilityChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private redactVisibilityChangeEvent(event: MatrixEvent) {
|
private redactVisibilityChangeEvent(event: MatrixEvent): void {
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
if (!event.isVisibilityEvent) {
|
if (!event.isVisibilityEvent) {
|
||||||
throw new Error("expected a visibility change event");
|
throw new Error("expected a visibility change event");
|
||||||
|
@@ -60,5 +60,5 @@ export class SearchResult {
|
|||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor(public readonly rank: number, public readonly context: EventContext) {}
|
public constructor(public readonly rank: number, public readonly context: EventContext) {}
|
||||||
}
|
}
|
||||||
|
@@ -94,7 +94,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
|||||||
|
|
||||||
public initialEventsFetched = !Thread.hasServerSideSupport;
|
public initialEventsFetched = !Thread.hasServerSideSupport;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly id: string,
|
public readonly id: string,
|
||||||
public rootEvent: MatrixEvent | undefined,
|
public rootEvent: MatrixEvent | undefined,
|
||||||
opts: IThreadOpts,
|
opts: IThreadOpts,
|
||||||
@@ -167,7 +167,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
|||||||
Thread.hasServerSideFwdPaginationSupport = status;
|
Thread.hasServerSideFwdPaginationSupport = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onBeforeRedaction = (event: MatrixEvent, redaction: MatrixEvent) => {
|
private onBeforeRedaction = (event: MatrixEvent, redaction: MatrixEvent): void => {
|
||||||
if (event?.isRelation(THREAD_RELATION_TYPE.name) &&
|
if (event?.isRelation(THREAD_RELATION_TYPE.name) &&
|
||||||
this.room.eventShouldLiveIn(event).threadId === this.id &&
|
this.room.eventShouldLiveIn(event).threadId === this.id &&
|
||||||
event.getId() !== this.id && // the root event isn't counted in the length so ignore this redaction
|
event.getId() !== this.id && // the root event isn't counted in the length so ignore this redaction
|
||||||
@@ -178,7 +178,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onRedaction = async (event: MatrixEvent) => {
|
private onRedaction = async (event: MatrixEvent): Promise<void> => {
|
||||||
if (event.threadRootId !== this.id) return; // ignore redactions for other timelines
|
if (event.threadRootId !== this.id) return; // ignore redactions for other timelines
|
||||||
if (this.replyCount <= 0) {
|
if (this.replyCount <= 0) {
|
||||||
for (const threadEvent of this.events) {
|
for (const threadEvent of this.events) {
|
||||||
@@ -192,7 +192,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onEcho = async (event: MatrixEvent) => {
|
private onEcho = async (event: MatrixEvent): Promise<void> => {
|
||||||
if (event.threadRootId !== this.id) return; // ignore echoes for other timelines
|
if (event.threadRootId !== this.id) return; // ignore echoes for other timelines
|
||||||
if (this.lastEvent === event) return;
|
if (this.lastEvent === event) return;
|
||||||
if (!event.isRelation(THREAD_RELATION_TYPE.name)) return;
|
if (!event.isRelation(THREAD_RELATION_TYPE.name)) return;
|
||||||
@@ -349,7 +349,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
|||||||
/**
|
/**
|
||||||
* Finds an event by ID in the current thread
|
* Finds an event by ID in the current thread
|
||||||
*/
|
*/
|
||||||
public findEventById(eventId: string) {
|
public findEventById(eventId: string): MatrixEvent | undefined {
|
||||||
// Check the lastEvent as it may have been created based on a bundled relationship and not in a timeline
|
// Check the lastEvent as it may have been created based on a bundled relationship and not in a timeline
|
||||||
if (this.lastEvent?.getId() === eventId) {
|
if (this.lastEvent?.getId() === eventId) {
|
||||||
return this.lastEvent;
|
return this.lastEvent;
|
||||||
@@ -361,7 +361,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
|||||||
/**
|
/**
|
||||||
* Return last reply to the thread, if known.
|
* Return last reply to the thread, if known.
|
||||||
*/
|
*/
|
||||||
public lastReply(matches: (ev: MatrixEvent) => boolean = () => true): MatrixEvent | null {
|
public lastReply(matches: (ev: MatrixEvent) => boolean = (): boolean => true): MatrixEvent | null {
|
||||||
for (let i = this.events.length - 1; i >= 0; i--) {
|
for (let i = this.events.length - 1; i >= 0; i--) {
|
||||||
const event = this.events[i];
|
const event = this.events[i];
|
||||||
if (matches(event)) {
|
if (matches(event)) {
|
||||||
|
@@ -76,7 +76,7 @@ export class User extends TypedEventEmitter<UserEvent, UserEventHandlerMap> {
|
|||||||
* @prop {Object} events The events describing this user.
|
* @prop {Object} events The events describing this user.
|
||||||
* @prop {MatrixEvent} events.presence The m.presence event for this user.
|
* @prop {MatrixEvent} events.presence The m.presence event for this user.
|
||||||
*/
|
*/
|
||||||
constructor(public readonly userId: string) {
|
public constructor(public readonly userId: string) {
|
||||||
super();
|
super();
|
||||||
this.displayName = userId;
|
this.displayName = userId;
|
||||||
this.rawDisplayName = userId;
|
this.rawDisplayName = userId;
|
||||||
|
@@ -126,7 +126,7 @@ export class PushProcessor {
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param {Object} client The Matrix client object to use
|
* @param {Object} client The Matrix client object to use
|
||||||
*/
|
*/
|
||||||
constructor(private readonly client: MatrixClient) {}
|
public constructor(private readonly client: MatrixClient) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a list of actions into a object with the actions as keys and their values
|
* Convert a list of actions into a object with the actions as keys and their values
|
||||||
|
@@ -48,7 +48,7 @@ type Callback = {
|
|||||||
const callbackList: Callback[] = [];
|
const callbackList: Callback[] = [];
|
||||||
|
|
||||||
// var debuglog = logger.log.bind(logger);
|
// var debuglog = logger.log.bind(logger);
|
||||||
const debuglog = function(...params: any[]) {};
|
const debuglog = function(...params: any[]): void {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reimplementation of window.setTimeout, which will call the callback if
|
* reimplementation of window.setTimeout, which will call the callback if
|
||||||
|
@@ -143,11 +143,11 @@ export class MSC3906Rendezvous {
|
|||||||
return await this.channel.receive() as MSC3906RendezvousPayload;
|
return await this.channel.receive() as MSC3906RendezvousPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async send(payload: MSC3906RendezvousPayload) {
|
private async send(payload: MSC3906RendezvousPayload): Promise<void> {
|
||||||
await this.channel.send(payload);
|
await this.channel.send(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async declineLoginOnExistingDevice() {
|
public async declineLoginOnExistingDevice(): Promise<void> {
|
||||||
logger.info('User declined sign in');
|
logger.info('User declined sign in');
|
||||||
await this.send({ type: PayloadType.Finish, outcome: Outcome.Declined });
|
await this.send({ type: PayloadType.Finish, outcome: Outcome.Declined });
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
import { RendezvousFailureReason } from ".";
|
import { RendezvousFailureReason } from ".";
|
||||||
|
|
||||||
export class RendezvousError extends Error {
|
export class RendezvousError extends Error {
|
||||||
constructor(message: string, public readonly code: RendezvousFailureReason) {
|
public constructor(message: string, public readonly code: RendezvousFailureReason) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@ export class RoomHierarchy {
|
|||||||
* @param {boolean} suggestedOnly whether to only return rooms with suggested=true.
|
* @param {boolean} suggestedOnly whether to only return rooms with suggested=true.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly root: Room,
|
public readonly root: Room,
|
||||||
private readonly pageSize?: number,
|
private readonly pageSize?: number,
|
||||||
private readonly maxDepth?: number,
|
private readonly maxDepth?: number,
|
||||||
|
@@ -97,7 +97,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
|||||||
* @see module:scheduler~queueAlgorithm
|
* @see module:scheduler~queueAlgorithm
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
public static QUEUE_MESSAGES(event: MatrixEvent) {
|
public static QUEUE_MESSAGES(event: MatrixEvent): "message" | null {
|
||||||
// enqueue messages or events that associate with another event (redactions and relations)
|
// enqueue messages or events that associate with another event (redactions and relations)
|
||||||
if (event.getType() === EventType.RoomMessage || event.hasAssocation()) {
|
if (event.getType() === EventType.RoomMessage || event.hasAssocation()) {
|
||||||
// put these events in the 'message' queue.
|
// put these events in the 'message' queue.
|
||||||
@@ -116,7 +116,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
|||||||
private activeQueues: string[] = [];
|
private activeQueues: string[] = [];
|
||||||
private procFn: ProcessFunction<T> | null = null;
|
private procFn: ProcessFunction<T> | null = null;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
public readonly retryAlgorithm = MatrixScheduler.RETRY_BACKOFF_RATELIMIT,
|
public readonly retryAlgorithm = MatrixScheduler.RETRY_BACKOFF_RATELIMIT,
|
||||||
public readonly queueAlgorithm = MatrixScheduler.QUEUE_MESSAGES,
|
public readonly queueAlgorithm = MatrixScheduler.QUEUE_MESSAGES,
|
||||||
) {}
|
) {}
|
||||||
@@ -283,7 +283,7 @@ export class MatrixScheduler<T = ISendEventResponse> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function debuglog(...args: any[]) {
|
function debuglog(...args: any[]): void {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
logger.log(...args);
|
logger.log(...args);
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,7 @@ import { RoomMemberEvent } from "./models/room-member";
|
|||||||
const FAILED_SYNC_ERROR_THRESHOLD = 3;
|
const FAILED_SYNC_ERROR_THRESHOLD = 3;
|
||||||
|
|
||||||
class ExtensionE2EE implements Extension {
|
class ExtensionE2EE implements Extension {
|
||||||
constructor(private readonly crypto: Crypto) {}
|
public constructor(private readonly crypto: Crypto) {}
|
||||||
|
|
||||||
public name(): string {
|
public name(): string {
|
||||||
return "e2ee";
|
return "e2ee";
|
||||||
@@ -95,7 +95,7 @@ class ExtensionE2EE implements Extension {
|
|||||||
class ExtensionToDevice implements Extension {
|
class ExtensionToDevice implements Extension {
|
||||||
private nextBatch: string | null = null;
|
private nextBatch: string | null = null;
|
||||||
|
|
||||||
constructor(private readonly client: MatrixClient) {}
|
public constructor(private readonly client: MatrixClient) {}
|
||||||
|
|
||||||
public name(): string {
|
public name(): string {
|
||||||
return "to_device";
|
return "to_device";
|
||||||
@@ -170,7 +170,7 @@ class ExtensionToDevice implements Extension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ExtensionAccountData implements Extension {
|
class ExtensionAccountData implements Extension {
|
||||||
constructor(private readonly client: MatrixClient) {}
|
public constructor(private readonly client: MatrixClient) {}
|
||||||
|
|
||||||
public name(): string {
|
public name(): string {
|
||||||
return "account_data";
|
return "account_data";
|
||||||
@@ -244,7 +244,7 @@ export class SlidingSyncSdk {
|
|||||||
private failCount = 0;
|
private failCount = 0;
|
||||||
private notifEvents: MatrixEvent[] = []; // accumulator of sync events in the current sync response
|
private notifEvents: MatrixEvent[] = []; // accumulator of sync events in the current sync response
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly slidingSync: SlidingSync,
|
private readonly slidingSync: SlidingSync,
|
||||||
private readonly client: MatrixClient,
|
private readonly client: MatrixClient,
|
||||||
private readonly opts: Partial<IStoredClientOpts> = {},
|
private readonly opts: Partial<IStoredClientOpts> = {},
|
||||||
@@ -256,7 +256,7 @@ export class SlidingSyncSdk {
|
|||||||
this.opts.experimentalThreadSupport = this.opts.experimentalThreadSupport === true;
|
this.opts.experimentalThreadSupport = this.opts.experimentalThreadSupport === true;
|
||||||
|
|
||||||
if (!opts.canResetEntireTimeline) {
|
if (!opts.canResetEntireTimeline) {
|
||||||
opts.canResetEntireTimeline = (_roomId: string) => {
|
opts.canResetEntireTimeline = (_roomId: string): boolean => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ export class SlidingSyncSdk {
|
|||||||
* Sync rooms the user has left.
|
* Sync rooms the user has left.
|
||||||
* @return {Promise} Resolved when they've been added to the store.
|
* @return {Promise} Resolved when they've been added to the store.
|
||||||
*/
|
*/
|
||||||
public async syncLeftRooms() {
|
public async syncLeftRooms(): Promise<Room[]> {
|
||||||
return []; // TODO
|
return []; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +457,7 @@ export class SlidingSyncSdk {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async processRoomData(client: MatrixClient, room: Room, roomData: MSC3575RoomData) {
|
private async processRoomData(client: MatrixClient, room: Room, roomData: MSC3575RoomData): Promise<void> {
|
||||||
roomData = ensureNameEvent(client, room.roomId, roomData);
|
roomData = ensureNameEvent(client, room.roomId, roomData);
|
||||||
const stateEvents = mapEvents(this.client, room.roomId, roomData.required_state);
|
const stateEvents = mapEvents(this.client, room.roomId, roomData.required_state);
|
||||||
// Prevent events from being decrypted ahead of time
|
// Prevent events from being decrypted ahead of time
|
||||||
@@ -632,7 +632,7 @@ export class SlidingSyncSdk {
|
|||||||
// we'll purge this once we've fully processed the sync response
|
// we'll purge this once we've fully processed the sync response
|
||||||
this.addNotifications(timelineEvents);
|
this.addNotifications(timelineEvents);
|
||||||
|
|
||||||
const processRoomEvent = async (e: MatrixEvent) => {
|
const processRoomEvent = async (e: MatrixEvent): Promise<void> => {
|
||||||
client.emit(ClientEvent.Event, e);
|
client.emit(ClientEvent.Event, e);
|
||||||
if (e.isState() && e.getType() == EventType.RoomEncryption && this.opts.crypto) {
|
if (e.isState() && e.getType() == EventType.RoomEncryption && this.opts.crypto) {
|
||||||
await this.opts.crypto.onCryptoEvent(e);
|
await this.opts.crypto.onCryptoEvent(e);
|
||||||
@@ -767,7 +767,7 @@ export class SlidingSyncSdk {
|
|||||||
/**
|
/**
|
||||||
* Main entry point. Blocks until stop() is called.
|
* Main entry point. Blocks until stop() is called.
|
||||||
*/
|
*/
|
||||||
public async sync() {
|
public async sync(): Promise<void> {
|
||||||
logger.debug("Sliding sync init loop");
|
logger.debug("Sliding sync init loop");
|
||||||
|
|
||||||
// 1) We need to get push rules so we can check if events should bing as we get
|
// 1) We need to get push rules so we can check if events should bing as we get
|
||||||
|
@@ -169,7 +169,7 @@ class SlidingList {
|
|||||||
* Construct a new sliding list.
|
* Construct a new sliding list.
|
||||||
* @param {MSC3575List} list The range, sort and filter values to use for this list.
|
* @param {MSC3575List} list The range, sort and filter values to use for this list.
|
||||||
*/
|
*/
|
||||||
constructor(list: MSC3575List) {
|
public constructor(list: MSC3575List) {
|
||||||
this.replaceList(list);
|
this.replaceList(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +373,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
* @param {MatrixClient} client The client to use for /sync calls.
|
* @param {MatrixClient} client The client to use for /sync calls.
|
||||||
* @param {number} timeoutMS The number of milliseconds to wait for a response.
|
* @param {number} timeoutMS The number of milliseconds to wait for a response.
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly proxyBaseUrl: string,
|
private readonly proxyBaseUrl: string,
|
||||||
lists: MSC3575List[],
|
lists: MSC3575List[],
|
||||||
private roomSubscriptionInfo: MSC3575RoomSubscription,
|
private roomSubscriptionInfo: MSC3575RoomSubscription,
|
||||||
@@ -391,7 +391,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
* useCustomSubscription.
|
* useCustomSubscription.
|
||||||
* @param sub The subscription information.
|
* @param sub The subscription information.
|
||||||
*/
|
*/
|
||||||
public addCustomSubscription(name: string, sub: MSC3575RoomSubscription) {
|
public addCustomSubscription(name: string, sub: MSC3575RoomSubscription): void {
|
||||||
this.customSubscriptions.set(name, sub);
|
this.customSubscriptions.set(name, sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
* @param name The name of the subscription. If this name is unknown, the default subscription
|
* @param name The name of the subscription. If this name is unknown, the default subscription
|
||||||
* will be used.
|
* will be used.
|
||||||
*/
|
*/
|
||||||
public useCustomSubscription(roomId: string, name: string) {
|
public useCustomSubscription(roomId: string, name: string): void {
|
||||||
this.roomIdToCustomSubscription.set(roomId, name);
|
this.roomIdToCustomSubscription.set(roomId, name);
|
||||||
// unconfirm this subscription so a resend() will send it up afresh.
|
// unconfirm this subscription so a resend() will send it up afresh.
|
||||||
this.confirmedRoomSubscriptions.delete(roomId);
|
this.confirmedRoomSubscriptions.delete(roomId);
|
||||||
@@ -574,7 +574,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
this.emit(SlidingSyncEvent.Lifecycle, state, resp, err);
|
this.emit(SlidingSyncEvent.Lifecycle, state, resp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
private shiftRight(listIndex: number, hi: number, low: number) {
|
private shiftRight(listIndex: number, hi: number, low: number): void {
|
||||||
// l h
|
// l h
|
||||||
// 0,1,2,3,4 <- before
|
// 0,1,2,3,4 <- before
|
||||||
// 0,1,2,2,3 <- after, hi is deleted and low is duplicated
|
// 0,1,2,2,3 <- after, hi is deleted and low is duplicated
|
||||||
@@ -588,7 +588,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private shiftLeft(listIndex: number, hi: number, low: number) {
|
private shiftLeft(listIndex: number, hi: number, low: number): void {
|
||||||
// l h
|
// l h
|
||||||
// 0,1,2,3,4 <- before
|
// 0,1,2,3,4 <- before
|
||||||
// 0,1,3,4,4 <- after, low is deleted and hi is duplicated
|
// 0,1,3,4,4 <- after, low is deleted and hi is duplicated
|
||||||
@@ -602,7 +602,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeEntry(listIndex: number, index: number) {
|
private removeEntry(listIndex: number, index: number): void {
|
||||||
// work out the max index
|
// work out the max index
|
||||||
let max = -1;
|
let max = -1;
|
||||||
for (const n in this.lists[listIndex].roomIndexToRoomId) {
|
for (const n in this.lists[listIndex].roomIndexToRoomId) {
|
||||||
@@ -618,7 +618,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
delete this.lists[listIndex].roomIndexToRoomId[max];
|
delete this.lists[listIndex].roomIndexToRoomId[max];
|
||||||
}
|
}
|
||||||
|
|
||||||
private addEntry(listIndex: number, index: number) {
|
private addEntry(listIndex: number, index: number): void {
|
||||||
// work out the max index
|
// work out the max index
|
||||||
let max = -1;
|
let max = -1;
|
||||||
for (const n in this.lists[listIndex].roomIndexToRoomId) {
|
for (const n in this.lists[listIndex].roomIndexToRoomId) {
|
||||||
@@ -747,7 +747,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
return d.promise;
|
return d.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveTransactionDefers(txnId?: string) {
|
private resolveTransactionDefers(txnId?: string): void {
|
||||||
if (!txnId) {
|
if (!txnId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -811,7 +811,7 @@ export class SlidingSync extends TypedEventEmitter<SlidingSyncEvent, SlidingSync
|
|||||||
/**
|
/**
|
||||||
* Start syncing with the server. Blocks until stopped.
|
* Start syncing with the server. Blocks until stopped.
|
||||||
*/
|
*/
|
||||||
public async start() {
|
public async start(): Promise<void> {
|
||||||
this.abortController = new AbortController();
|
this.abortController = new AbortController();
|
||||||
|
|
||||||
let currentPos: string | undefined;
|
let currentPos: string | undefined;
|
||||||
|
@@ -25,7 +25,7 @@ import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDevice
|
|||||||
|
|
||||||
type DbMigration = (db: IDBDatabase) => void;
|
type DbMigration = (db: IDBDatabase) => void;
|
||||||
const DB_MIGRATIONS: DbMigration[] = [
|
const DB_MIGRATIONS: DbMigration[] = [
|
||||||
(db) => {
|
(db): void => {
|
||||||
// Make user store, clobber based on user ID. (userId property of User objects)
|
// Make user store, clobber based on user ID. (userId property of User objects)
|
||||||
db.createObjectStore("users", { keyPath: ["userId"] });
|
db.createObjectStore("users", { keyPath: ["userId"] });
|
||||||
|
|
||||||
@@ -36,15 +36,15 @@ const DB_MIGRATIONS: DbMigration[] = [
|
|||||||
// Make /sync store (sync tokens, room data, etc), always clobber (const key).
|
// Make /sync store (sync tokens, room data, etc), always clobber (const key).
|
||||||
db.createObjectStore("sync", { keyPath: ["clobber"] });
|
db.createObjectStore("sync", { keyPath: ["clobber"] });
|
||||||
},
|
},
|
||||||
(db) => {
|
(db): void => {
|
||||||
const oobMembersStore = db.createObjectStore(
|
const oobMembersStore = db.createObjectStore(
|
||||||
"oob_membership_events", {
|
"oob_membership_events", {
|
||||||
keyPath: ["room_id", "state_key"],
|
keyPath: ["room_id", "state_key"],
|
||||||
});
|
});
|
||||||
oobMembersStore.createIndex("room", "room_id");
|
oobMembersStore.createIndex("room", "room_id");
|
||||||
},
|
},
|
||||||
(db) => { db.createObjectStore("client_options", { keyPath: ["clobber"] }); },
|
(db): void => { db.createObjectStore("client_options", { keyPath: ["clobber"] }); },
|
||||||
(db) => { db.createObjectStore("to_device_queue", { autoIncrement: true }); },
|
(db): void => { db.createObjectStore("to_device_queue", { autoIncrement: true }); },
|
||||||
// Expand as needed.
|
// Expand as needed.
|
||||||
];
|
];
|
||||||
const VERSION = DB_MIGRATIONS.length;
|
const VERSION = DB_MIGRATIONS.length;
|
||||||
@@ -67,11 +67,11 @@ function selectQuery<T>(
|
|||||||
const query = store.openCursor(keyRange);
|
const query = store.openCursor(keyRange);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const results: T[] = [];
|
const results: T[] = [];
|
||||||
query.onerror = () => {
|
query.onerror = (): void => {
|
||||||
reject(new Error("Query failed: " + query.error));
|
reject(new Error("Query failed: " + query.error));
|
||||||
};
|
};
|
||||||
// collect results
|
// collect results
|
||||||
query.onsuccess = () => {
|
query.onsuccess = (): void => {
|
||||||
const cursor = query.result;
|
const cursor = query.result;
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
resolve(results);
|
resolve(results);
|
||||||
@@ -85,10 +85,10 @@ function selectQuery<T>(
|
|||||||
|
|
||||||
function txnAsPromise(txn: IDBTransaction): Promise<Event> {
|
function txnAsPromise(txn: IDBTransaction): Promise<Event> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
txn.oncomplete = function(event) {
|
txn.oncomplete = function(event): void {
|
||||||
resolve(event);
|
resolve(event);
|
||||||
};
|
};
|
||||||
txn.onerror = function() {
|
txn.onerror = function(): void {
|
||||||
reject(txn.error);
|
reject(txn.error);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -96,10 +96,10 @@ function txnAsPromise(txn: IDBTransaction): Promise<Event> {
|
|||||||
|
|
||||||
function reqAsEventPromise(req: IDBRequest): Promise<Event> {
|
function reqAsEventPromise(req: IDBRequest): Promise<Event> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
req.onsuccess = function(event) {
|
req.onsuccess = function(event): void {
|
||||||
resolve(event);
|
resolve(event);
|
||||||
};
|
};
|
||||||
req.onerror = function() {
|
req.onerror = function(): void {
|
||||||
reject(req.error);
|
reject(req.error);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -107,8 +107,8 @@ function reqAsEventPromise(req: IDBRequest): Promise<Event> {
|
|||||||
|
|
||||||
function reqAsPromise(req: IDBRequest): Promise<IDBRequest> {
|
function reqAsPromise(req: IDBRequest): Promise<IDBRequest> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
req.onsuccess = () => resolve(req);
|
req.onsuccess = (): void => resolve(req);
|
||||||
req.onerror = (err) => reject(err);
|
req.onerror = (err): void => reject(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
* @param {string=} dbName Optional database name. The same name must be used
|
* @param {string=} dbName Optional database name. The same name must be used
|
||||||
* to open the same database.
|
* to open the same database.
|
||||||
*/
|
*/
|
||||||
constructor(private readonly indexedDB: IDBFactory, dbName = "default") {
|
public constructor(private readonly indexedDB: IDBFactory, dbName = "default") {
|
||||||
this.dbName = "matrix-js-sdk:" + dbName;
|
this.dbName = "matrix-js-sdk:" + dbName;
|
||||||
this.syncAccumulator = new SyncAccumulator();
|
this.syncAccumulator = new SyncAccumulator();
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
|
|
||||||
logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`);
|
logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`);
|
||||||
const req = this.indexedDB.open(this.dbName, VERSION);
|
const req = this.indexedDB.open(this.dbName, VERSION);
|
||||||
req.onupgradeneeded = (ev) => {
|
req.onupgradeneeded = (ev): void => {
|
||||||
const db = req.result;
|
const db = req.result;
|
||||||
const oldVersion = ev.oldVersion;
|
const oldVersion = ev.oldVersion;
|
||||||
logger.log(
|
logger.log(
|
||||||
@@ -176,22 +176,22 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onblocked = () => {
|
req.onblocked = (): void => {
|
||||||
logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`);
|
logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`);
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`);
|
logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`);
|
||||||
return reqAsEventPromise(req).then(() => {
|
return reqAsEventPromise(req).then(async () => {
|
||||||
logger.log(`LocalIndexedDBStoreBackend.connect: connected`);
|
logger.log(`LocalIndexedDBStoreBackend.connect: connected`);
|
||||||
this.db = req.result;
|
this.db = req.result;
|
||||||
|
|
||||||
// add a poorly-named listener for when deleteDatabase is called
|
// add a poorly-named listener for when deleteDatabase is called
|
||||||
// so we can close our db connections.
|
// so we can close our db connections.
|
||||||
this.db.onversionchange = () => {
|
this.db.onversionchange = (): void => {
|
||||||
this.db?.close();
|
this.db?.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.init();
|
await this.init();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
* Having connected, load initial data from the database and prepare for use
|
* Having connected, load initial data from the database and prepare for use
|
||||||
* @return {Promise} Resolves on success
|
* @return {Promise} Resolves on success
|
||||||
*/
|
*/
|
||||||
private init() {
|
private init(): Promise<unknown> {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
this.loadAccountData(),
|
this.loadAccountData(),
|
||||||
this.loadSyncData(),
|
this.loadSyncData(),
|
||||||
@@ -243,7 +243,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
// were all known already
|
// were all known already
|
||||||
let oobWritten = false;
|
let oobWritten = false;
|
||||||
|
|
||||||
request.onsuccess = () => {
|
request.onsuccess = (): void => {
|
||||||
const cursor = request.result;
|
const cursor = request.result;
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
// Unknown room
|
// Unknown room
|
||||||
@@ -260,7 +260,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
}
|
}
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
};
|
};
|
||||||
request.onerror = (err) => {
|
request.onerror = (err): void => {
|
||||||
reject(err);
|
reject(err);
|
||||||
};
|
};
|
||||||
}).then((events) => {
|
}).then((events) => {
|
||||||
@@ -346,11 +346,11 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
logger.log(`Removing indexeddb instance: ${this.dbName}`);
|
logger.log(`Removing indexeddb instance: ${this.dbName}`);
|
||||||
const req = this.indexedDB.deleteDatabase(this.dbName);
|
const req = this.indexedDB.deleteDatabase(this.dbName);
|
||||||
|
|
||||||
req.onblocked = () => {
|
req.onblocked = (): void => {
|
||||||
logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`);
|
logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onerror = () => {
|
req.onerror = (): void => {
|
||||||
// in firefox, with indexedDB disabled, this fails with a
|
// in firefox, with indexedDB disabled, this fails with a
|
||||||
// DOMError. We treat this as non-fatal, so that we can still
|
// DOMError. We treat this as non-fatal, so that we can still
|
||||||
// use the app.
|
// use the app.
|
||||||
@@ -358,7 +358,7 @@ export class LocalIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onsuccess = () => {
|
req.onsuccess = (): void => {
|
||||||
logger.log(`Removed indexeddb instance: ${this.dbName}`);
|
logger.log(`Removed indexeddb instance: ${this.dbName}`);
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
@@ -42,7 +42,7 @@ export class RemoteIndexedDBStoreBackend implements IIndexedDBBackend {
|
|||||||
* @param {string=} dbName Optional database name. The same name must be used
|
* @param {string=} dbName Optional database name. The same name must be used
|
||||||
* to open the same database.
|
* to open the same database.
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly workerFactory: () => Worker,
|
private readonly workerFactory: () => Worker,
|
||||||
private readonly dbName?: string,
|
private readonly dbName?: string,
|
||||||
) {}
|
) {}
|
||||||
|
@@ -45,7 +45,7 @@ export class IndexedDBStoreWorker {
|
|||||||
* @param {function} postMessage The web worker postMessage function that
|
* @param {function} postMessage The web worker postMessage function that
|
||||||
* should be used to communicate back to the main script.
|
* should be used to communicate back to the main script.
|
||||||
*/
|
*/
|
||||||
constructor(private readonly postMessage: InstanceType<typeof Worker>["postMessage"]) {}
|
public constructor(private readonly postMessage: InstanceType<typeof Worker>["postMessage"]) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passes a message event from the main script into the class. This method
|
* Passes a message event from the main script into the class. This method
|
||||||
|
@@ -53,7 +53,7 @@ type EventHandlerMap = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class IndexedDBStore extends MemoryStore {
|
export class IndexedDBStore extends MemoryStore {
|
||||||
static exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> {
|
public static exists(indexedDB: IDBFactory, dbName: string): Promise<boolean> {
|
||||||
return LocalIndexedDBStoreBackend.exists(indexedDB, dbName);
|
return LocalIndexedDBStoreBackend.exists(indexedDB, dbName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ export class IndexedDBStore extends MemoryStore {
|
|||||||
* this API if you need to perform specific indexeddb actions like deleting the
|
* this API if you need to perform specific indexeddb actions like deleting the
|
||||||
* database.
|
* database.
|
||||||
*/
|
*/
|
||||||
constructor(opts: IOpts) {
|
public constructor(opts: IOpts) {
|
||||||
super(opts);
|
super(opts);
|
||||||
|
|
||||||
if (!opts.indexedDB) {
|
if (!opts.indexedDB) {
|
||||||
|
@@ -69,7 +69,7 @@ export class MemoryStore implements IStore {
|
|||||||
private pendingToDeviceBatches: IndexedToDeviceBatch[] = [];
|
private pendingToDeviceBatches: IndexedToDeviceBatch[] = [];
|
||||||
private nextToDeviceBatchId = 0;
|
private nextToDeviceBatchId = 0;
|
||||||
|
|
||||||
constructor(opts: IOpts = {}) {
|
public constructor(opts: IOpts = {}) {
|
||||||
this.localStorage = opts.localStorage;
|
this.localStorage = opts.localStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ export class MemoryStore implements IStore {
|
|||||||
* Set the token to stream from.
|
* Set the token to stream from.
|
||||||
* @param {string} token The token to stream from.
|
* @param {string} token The token to stream from.
|
||||||
*/
|
*/
|
||||||
public setSyncToken(token: string) {
|
public setSyncToken(token: string): void {
|
||||||
this.syncToken = token;
|
this.syncToken = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ export class MemoryStore implements IStore {
|
|||||||
* Store the given room.
|
* Store the given room.
|
||||||
* @param {Room} room The room to be stored. All properties must be stored.
|
* @param {Room} room The room to be stored. All properties must be stored.
|
||||||
*/
|
*/
|
||||||
public storeRoom(room: Room) {
|
public storeRoom(room: Room): void {
|
||||||
this.rooms[room.roomId] = room;
|
this.rooms[room.roomId] = room;
|
||||||
// add listeners for room member changes so we can keep the room member
|
// add listeners for room member changes so we can keep the room member
|
||||||
// map up-to-date.
|
// map up-to-date.
|
||||||
@@ -116,7 +116,7 @@ export class MemoryStore implements IStore {
|
|||||||
* @param {RoomState} state
|
* @param {RoomState} state
|
||||||
* @param {RoomMember} member
|
* @param {RoomMember} member
|
||||||
*/
|
*/
|
||||||
private onRoomMember = (event: MatrixEvent | null, state: RoomState, member: RoomMember) => {
|
private onRoomMember = (event: MatrixEvent | null, state: RoomState, member: RoomMember): void => {
|
||||||
if (member.membership === "invite") {
|
if (member.membership === "invite") {
|
||||||
// We do NOT add invited members because people love to typo user IDs
|
// We do NOT add invited members because people love to typo user IDs
|
||||||
// which would then show up in these lists (!)
|
// which would then show up in these lists (!)
|
||||||
@@ -217,7 +217,7 @@ export class MemoryStore implements IStore {
|
|||||||
* @param {string} token The token associated with these events.
|
* @param {string} token The token associated with these events.
|
||||||
* @param {boolean} toStart True if these are paginated results.
|
* @param {boolean} toStart True if these are paginated results.
|
||||||
*/
|
*/
|
||||||
public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean) {
|
public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean): void {
|
||||||
// no-op because they've already been added to the room instance.
|
// no-op because they've already been added to the room instance.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ export class MemoryStore implements IStore {
|
|||||||
* @param {string} filterName
|
* @param {string} filterName
|
||||||
* @param {string} filterId
|
* @param {string} filterId
|
||||||
*/
|
*/
|
||||||
public setFilterIdByName(filterName: string, filterId?: string) {
|
public setFilterIdByName(filterName: string, filterId?: string): void {
|
||||||
if (!this.localStorage) {
|
if (!this.localStorage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -56,7 +56,7 @@ export class StubStore implements IStore {
|
|||||||
* Set the sync token.
|
* Set the sync token.
|
||||||
* @param {string} token
|
* @param {string} token
|
||||||
*/
|
*/
|
||||||
public setSyncToken(token: string) {
|
public setSyncToken(token: string): void {
|
||||||
this.fromToken = token;
|
this.fromToken = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export class StubStore implements IStore {
|
|||||||
* No-op.
|
* No-op.
|
||||||
* @param {Room} room
|
* @param {Room} room
|
||||||
*/
|
*/
|
||||||
public storeRoom(room: Room) {}
|
public storeRoom(room: Room): void {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No-op.
|
* No-op.
|
||||||
@@ -87,7 +87,7 @@ export class StubStore implements IStore {
|
|||||||
* Permanently delete a room.
|
* Permanently delete a room.
|
||||||
* @param {string} roomId
|
* @param {string} roomId
|
||||||
*/
|
*/
|
||||||
public removeRoom(roomId: string) {
|
public removeRoom(roomId: string): void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ export class StubStore implements IStore {
|
|||||||
* No-op.
|
* No-op.
|
||||||
* @param {User} user
|
* @param {User} user
|
||||||
*/
|
*/
|
||||||
public storeUser(user: User) {}
|
public storeUser(user: User): void {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No-op.
|
* No-op.
|
||||||
@@ -139,13 +139,13 @@ export class StubStore implements IStore {
|
|||||||
* @param {string} token The token associated with these events.
|
* @param {string} token The token associated with these events.
|
||||||
* @param {boolean} toStart True if these are paginated results.
|
* @param {boolean} toStart True if these are paginated results.
|
||||||
*/
|
*/
|
||||||
public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean) {}
|
public storeEvents(room: Room, events: MatrixEvent[], token: string, toStart: boolean): void {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a filter.
|
* Store a filter.
|
||||||
* @param {Filter} filter
|
* @param {Filter} filter
|
||||||
*/
|
*/
|
||||||
public storeFilter(filter: Filter) {}
|
public storeFilter(filter: Filter): void {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a filter.
|
* Retrieve a filter.
|
||||||
@@ -171,13 +171,13 @@ export class StubStore implements IStore {
|
|||||||
* @param {string} filterName
|
* @param {string} filterName
|
||||||
* @param {string} filterId
|
* @param {string} filterId
|
||||||
*/
|
*/
|
||||||
public setFilterIdByName(filterName: string, filterId?: string) {}
|
public setFilterIdByName(filterName: string, filterId?: string): void {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store user-scoped account data events
|
* Store user-scoped account data events
|
||||||
* @param {Array<MatrixEvent>} events The events to store.
|
* @param {Array<MatrixEvent>} events The events to store.
|
||||||
*/
|
*/
|
||||||
public storeAccountDataEvents(events: MatrixEvent[]) {}
|
public storeAccountDataEvents(events: MatrixEvent[]): void {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get account data event by event type
|
* Get account data event by event type
|
||||||
@@ -209,7 +209,7 @@ export class StubStore implements IStore {
|
|||||||
/**
|
/**
|
||||||
* Save does nothing as there is no backing data store.
|
* Save does nothing as there is no backing data store.
|
||||||
*/
|
*/
|
||||||
public save() {}
|
public save(): void {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Startup does nothing.
|
* Startup does nothing.
|
||||||
|
@@ -211,7 +211,7 @@ export class SyncAccumulator {
|
|||||||
* never be more. This cannot be 0 or else it makes it impossible to scroll
|
* never be more. This cannot be 0 or else it makes it impossible to scroll
|
||||||
* back in a room. Default: 50.
|
* back in a room. Default: 50.
|
||||||
*/
|
*/
|
||||||
constructor(private readonly opts: IOpts = {}) {
|
public constructor(private readonly opts: IOpts = {}) {
|
||||||
this.opts.maxTimelineEntries = this.opts.maxTimelineEntries || 50;
|
this.opts.maxTimelineEntries = this.opts.maxTimelineEntries || 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
src/sync.ts
16
src/sync.ts
@@ -106,7 +106,7 @@ function getFilterName(userId: string, suffix?: string): string {
|
|||||||
return `FILTER_SYNC_${userId}` + (suffix ? "_" + suffix : "");
|
return `FILTER_SYNC_${userId}` + (suffix ? "_" + suffix : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function debuglog(...params) {
|
function debuglog(...params): void {
|
||||||
if (!DEBUG) return;
|
if (!DEBUG) return;
|
||||||
logger.log(...params);
|
logger.log(...params);
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ export class SyncApi {
|
|||||||
private failedSyncCount = 0; // Number of consecutive failed /sync requests
|
private failedSyncCount = 0; // Number of consecutive failed /sync requests
|
||||||
private storeIsInvalid = false; // flag set if the store needs to be cleared before we can start
|
private storeIsInvalid = false; // flag set if the store needs to be cleared before we can start
|
||||||
|
|
||||||
constructor(private readonly client: MatrixClient, private readonly opts: Partial<IStoredClientOpts> = {}) {
|
public constructor(private readonly client: MatrixClient, private readonly opts: Partial<IStoredClientOpts> = {}) {
|
||||||
this.opts.initialSyncLimit = this.opts.initialSyncLimit ?? 8;
|
this.opts.initialSyncLimit = this.opts.initialSyncLimit ?? 8;
|
||||||
this.opts.resolveInvitesToProfiles = this.opts.resolveInvitesToProfiles || false;
|
this.opts.resolveInvitesToProfiles = this.opts.resolveInvitesToProfiles || false;
|
||||||
this.opts.pollTimeout = this.opts.pollTimeout || (30 * 1000);
|
this.opts.pollTimeout = this.opts.pollTimeout || (30 * 1000);
|
||||||
@@ -183,7 +183,7 @@ export class SyncApi {
|
|||||||
this.opts.experimentalThreadSupport = this.opts.experimentalThreadSupport === true;
|
this.opts.experimentalThreadSupport = this.opts.experimentalThreadSupport === true;
|
||||||
|
|
||||||
if (!opts.canResetEntireTimeline) {
|
if (!opts.canResetEntireTimeline) {
|
||||||
opts.canResetEntireTimeline = (roomId: string) => {
|
opts.canResetEntireTimeline = (roomId: string): boolean => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -554,7 +554,7 @@ export class SyncApi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPushRules = async () => {
|
private getPushRules = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
debuglog("Getting push rules...");
|
debuglog("Getting push rules...");
|
||||||
const result = await this.client.getPushRules();
|
const result = await this.client.getPushRules();
|
||||||
@@ -572,7 +572,7 @@ export class SyncApi {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private buildDefaultFilter = () => {
|
private buildDefaultFilter = (): Filter => {
|
||||||
const filter = new Filter(this.client.credentials.userId);
|
const filter = new Filter(this.client.credentials.userId);
|
||||||
if (this.client.canSupport.get(Feature.ThreadUnreadNotifications) !== ServerSupport.Unsupported) {
|
if (this.client.canSupport.get(Feature.ThreadUnreadNotifications) !== ServerSupport.Unsupported) {
|
||||||
filter.setUnreadThreadNotifications(true);
|
filter.setUnreadThreadNotifications(true);
|
||||||
@@ -580,7 +580,7 @@ export class SyncApi {
|
|||||||
return filter;
|
return filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
private checkLazyLoadStatus = async () => {
|
private checkLazyLoadStatus = async (): Promise<void> => {
|
||||||
debuglog("Checking lazy load status...");
|
debuglog("Checking lazy load status...");
|
||||||
if (this.opts.lazyLoadMembers && this.client.isGuest()) {
|
if (this.opts.lazyLoadMembers && this.client.isGuest()) {
|
||||||
this.opts.lazyLoadMembers = false;
|
this.opts.lazyLoadMembers = false;
|
||||||
@@ -1389,7 +1389,7 @@ export class SyncApi {
|
|||||||
|
|
||||||
this.processEventsForNotifs(room, events);
|
this.processEventsForNotifs(room, events);
|
||||||
|
|
||||||
const processRoomEvent = async (e) => {
|
const processRoomEvent = async (e): Promise<void> => {
|
||||||
client.emit(ClientEvent.Event, e);
|
client.emit(ClientEvent.Event, e);
|
||||||
if (e.isState() && e.getType() == "m.room.encryption" && this.opts.crypto) {
|
if (e.isState() && e.getType() == "m.room.encryption" && this.opts.crypto) {
|
||||||
await this.opts.crypto.onCryptoEvent(e);
|
await this.opts.crypto.onCryptoEvent(e);
|
||||||
@@ -1521,7 +1521,7 @@ export class SyncApi {
|
|||||||
* @param {boolean} connDidFail True if a connectivity failure has been detected. Optional.
|
* @param {boolean} connDidFail True if a connectivity failure has been detected. Optional.
|
||||||
*/
|
*/
|
||||||
private pokeKeepAlive(connDidFail = false): void {
|
private pokeKeepAlive(connDidFail = false): void {
|
||||||
const success = () => {
|
const success = (): void => {
|
||||||
clearTimeout(this.keepAliveTimer);
|
clearTimeout(this.keepAliveTimer);
|
||||||
if (this.connectionReturnedDefer) {
|
if (this.connectionReturnedDefer) {
|
||||||
this.connectionReturnedDefer.resolve(connDidFail);
|
this.connectionReturnedDefer.resolve(connDidFail);
|
||||||
|
@@ -32,7 +32,7 @@ const DEBUG = false;
|
|||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const debuglog = DEBUG ? logger.log.bind(logger) : function() {};
|
const debuglog = DEBUG ? logger.log.bind(logger) : function(): void {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the number of times we ask the server for more events before giving up
|
* the number of times we ask the server for more events before giving up
|
||||||
@@ -84,7 +84,7 @@ export class TimelineWindow {
|
|||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor(
|
public constructor(
|
||||||
private readonly client: MatrixClient,
|
private readonly client: MatrixClient,
|
||||||
private readonly timelineSet: EventTimelineSet,
|
private readonly timelineSet: EventTimelineSet,
|
||||||
opts: IOpts = {},
|
opts: IOpts = {},
|
||||||
@@ -104,7 +104,7 @@ export class TimelineWindow {
|
|||||||
public load(initialEventId?: string, initialWindowSize = 20): Promise<void> {
|
public load(initialEventId?: string, initialWindowSize = 20): Promise<void> {
|
||||||
// given an EventTimeline, find the event we were looking for, and initialise our
|
// given an EventTimeline, find the event we were looking for, and initialise our
|
||||||
// fields so that the event in question is in the middle of the window.
|
// fields so that the event in question is in the middle of the window.
|
||||||
const initFields = (timeline: Optional<EventTimeline>) => {
|
const initFields = (timeline: Optional<EventTimeline>): void => {
|
||||||
if (!timeline) {
|
if (!timeline) {
|
||||||
throw new Error("No timeline given to initFields");
|
throw new Error("No timeline given to initFields");
|
||||||
}
|
}
|
||||||
@@ -430,7 +430,7 @@ export class TimelineIndex {
|
|||||||
public pendingPaginate?: Promise<boolean>;
|
public pendingPaginate?: Promise<boolean>;
|
||||||
|
|
||||||
// index: the indexes are relative to BaseIndex, so could well be negative.
|
// index: the indexes are relative to BaseIndex, so could well be negative.
|
||||||
constructor(public timeline: EventTimeline, public index: number) {}
|
public constructor(public timeline: EventTimeline, public index: number) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {number} the minimum possible value for the index in the current
|
* @return {number} the minimum possible value for the index in the current
|
||||||
|
@@ -178,7 +178,7 @@ export function removeElement<T>(
|
|||||||
* @param {*} value The thing to check.
|
* @param {*} value The thing to check.
|
||||||
* @return {boolean} True if it is a function.
|
* @return {boolean} True if it is a function.
|
||||||
*/
|
*/
|
||||||
export function isFunction(value: any) {
|
export function isFunction(value: any): boolean {
|
||||||
return Object.prototype.toString.call(value) === "[object Function]";
|
return Object.prototype.toString.call(value) === "[object Function]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ export function isFunction(value: any) {
|
|||||||
* @throws If the object is missing keys.
|
* @throws If the object is missing keys.
|
||||||
*/
|
*/
|
||||||
// note using 'keys' here would shadow the 'keys' function defined above
|
// note using 'keys' here would shadow the 'keys' function defined above
|
||||||
export function checkObjectHasKeys(obj: object, keys: string[]) {
|
export function checkObjectHasKeys(obj: object, keys: string[]): void {
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
if (!obj.hasOwnProperty(key)) {
|
if (!obj.hasOwnProperty(key)) {
|
||||||
throw new Error("Missing required key: " + key);
|
throw new Error("Missing required key: " + key);
|
||||||
@@ -383,7 +383,7 @@ export function globToRegexp(glob: string, extended = false): string {
|
|||||||
if (!extended) {
|
if (!extended) {
|
||||||
replacements.push([
|
replacements.push([
|
||||||
/\\\[(!|)(.*)\\]/g,
|
/\\\[(!|)(.*)\\]/g,
|
||||||
(_match: string, neg: string, pat: string) => [
|
(_match: string, neg: string, pat: string): string => [
|
||||||
'[',
|
'[',
|
||||||
neg ? '^' : '',
|
neg ? '^' : '',
|
||||||
pat.replace(/\\-/, '-'),
|
pat.replace(/\\-/, '-'),
|
||||||
@@ -490,7 +490,7 @@ export function simpleRetryOperation<T>(promiseFn: (attempt: number) => Promise<
|
|||||||
* The default alphabet used by string averaging in this SDK. This matches
|
* The default alphabet used by string averaging in this SDK. This matches
|
||||||
* all usefully printable ASCII characters (0x20-0x7E, inclusive).
|
* all usefully printable ASCII characters (0x20-0x7E, inclusive).
|
||||||
*/
|
*/
|
||||||
export const DEFAULT_ALPHABET = (() => {
|
export const DEFAULT_ALPHABET = ((): string => {
|
||||||
let str = "";
|
let str = "";
|
||||||
for (let c = 0x20; c <= 0x7E; c++) {
|
for (let c = 0x20; c <= 0x7E; c++) {
|
||||||
str += String.fromCharCode(c);
|
str += String.fromCharCode(c);
|
||||||
|
@@ -35,7 +35,7 @@ export const acquireContext = (): AudioContext => {
|
|||||||
* released, allowing the context and associated hardware resources to be
|
* released, allowing the context and associated hardware resources to be
|
||||||
* cleaned up if nothing else is using it.
|
* cleaned up if nothing else is using it.
|
||||||
*/
|
*/
|
||||||
export const releaseContext = () => {
|
export const releaseContext = (): void => {
|
||||||
refCount--;
|
refCount--;
|
||||||
if (refCount === 0) {
|
if (refCount === 0) {
|
||||||
audioContext?.close();
|
audioContext?.close();
|
||||||
|
@@ -268,7 +268,7 @@ const CALL_TIMEOUT_MS = 60000;
|
|||||||
export class CallError extends Error {
|
export class CallError extends Error {
|
||||||
public readonly code: string;
|
public readonly code: string;
|
||||||
|
|
||||||
constructor(code: CallErrorCode, msg: string, err: Error) {
|
public constructor(code: CallErrorCode, msg: string, err: Error) {
|
||||||
// Still don't think there's any way to have proper nested errors
|
// Still don't think there's any way to have proper nested errors
|
||||||
super(msg + ": " + err);
|
super(msg + ": " + err);
|
||||||
|
|
||||||
@@ -404,7 +404,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
private opponentSessionId?: string;
|
private opponentSessionId?: string;
|
||||||
public groupCallId?: string;
|
public groupCallId?: string;
|
||||||
|
|
||||||
constructor(opts: CallOpts) {
|
public constructor(opts: CallOpts) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.roomId = opts.roomId;
|
this.roomId = opts.roomId;
|
||||||
@@ -452,7 +452,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
* @param label A human readable label for this datachannel
|
* @param label A human readable label for this datachannel
|
||||||
* @param options An object providing configuration options for the data channel.
|
* @param options An object providing configuration options for the data channel.
|
||||||
*/
|
*/
|
||||||
public createDataChannel(label: string, options: RTCDataChannelInit | undefined) {
|
public createDataChannel(label: string, options: RTCDataChannelInit | undefined): RTCDataChannel {
|
||||||
const dataChannel = this.peerConn!.createDataChannel(label, options);
|
const dataChannel = this.peerConn!.createDataChannel(label, options);
|
||||||
this.emit(CallEvent.DataChannel, dataChannel);
|
this.emit(CallEvent.DataChannel, dataChannel);
|
||||||
return dataChannel;
|
return dataChannel;
|
||||||
@@ -564,7 +564,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
return this.feeds.filter((feed) => !feed.isLocal());
|
return this.feeds.filter((feed) => !feed.isLocal());
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initOpponentCrypto() {
|
private async initOpponentCrypto(): Promise<void> {
|
||||||
if (!this.opponentDeviceId) return;
|
if (!this.opponentDeviceId) return;
|
||||||
if (!this.client.getUseE2eForGroupCall()) return;
|
if (!this.client.getUseE2eForGroupCall()) return;
|
||||||
// It's possible to want E2EE and yet not have the means to manage E2EE
|
// It's possible to want E2EE and yet not have the means to manage E2EE
|
||||||
@@ -938,7 +938,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
}
|
}
|
||||||
}, invite.lifetime - event.getLocalAge());
|
}, invite.lifetime - event.getLocalAge());
|
||||||
|
|
||||||
const onState = (state: CallState) => {
|
const onState = (state: CallState): void => {
|
||||||
if (state !== CallState.Ringing) {
|
if (state !== CallState.Ringing) {
|
||||||
clearTimeout(ringingTimer);
|
clearTimeout(ringingTimer);
|
||||||
this.off(CallEvent.State, onState);
|
this.off(CallEvent.State, onState);
|
||||||
@@ -2132,7 +2132,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
this.pushRemoteFeed(stream);
|
this.pushRemoteFeed(stream);
|
||||||
|
|
||||||
if (!this.removeTrackListeners.has(stream)) {
|
if (!this.removeTrackListeners.has(stream)) {
|
||||||
const onRemoveTrack = () => {
|
const onRemoveTrack = (): void => {
|
||||||
if (stream.getTracks().length === 0) {
|
if (stream.getTracks().length === 0) {
|
||||||
logger.info(`Call ${this.callId} removing track streamId: ${stream.id}`);
|
logger.info(`Call ${this.callId} removing track streamId: ${stream.id}`);
|
||||||
this.deleteFeedByStream(stream);
|
this.deleteFeedByStream(stream);
|
||||||
|
@@ -46,7 +46,7 @@ export class CallEventHandler {
|
|||||||
private candidateEventsByCall: Map<string, Array<MatrixEvent>>;
|
private candidateEventsByCall: Map<string, Array<MatrixEvent>>;
|
||||||
private eventBufferPromiseChain?: Promise<void>;
|
private eventBufferPromiseChain?: Promise<void>;
|
||||||
|
|
||||||
constructor(client: MatrixClient) {
|
public constructor(client: MatrixClient) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.calls = new Map<string, MatrixCall>();
|
this.calls = new Map<string, MatrixCall>();
|
||||||
// The sync code always emits one event at a time, so it will patiently
|
// The sync code always emits one event at a time, so it will patiently
|
||||||
@@ -61,13 +61,13 @@ export class CallEventHandler {
|
|||||||
this.candidateEventsByCall = new Map<string, Array<MatrixEvent>>();
|
this.candidateEventsByCall = new Map<string, Array<MatrixEvent>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public start() {
|
public start(): void {
|
||||||
this.client.on(ClientEvent.Sync, this.onSync);
|
this.client.on(ClientEvent.Sync, this.onSync);
|
||||||
this.client.on(RoomEvent.Timeline, this.onRoomTimeline);
|
this.client.on(RoomEvent.Timeline, this.onRoomTimeline);
|
||||||
this.client.on(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
|
this.client.on(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop() {
|
public stop(): void {
|
||||||
this.client.removeListener(ClientEvent.Sync, this.onSync);
|
this.client.removeListener(ClientEvent.Sync, this.onSync);
|
||||||
this.client.removeListener(RoomEvent.Timeline, this.onRoomTimeline);
|
this.client.removeListener(RoomEvent.Timeline, this.onRoomTimeline);
|
||||||
this.client.removeListener(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
|
this.client.removeListener(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
|
||||||
@@ -87,7 +87,7 @@ export class CallEventHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private async evaluateEventBuffer(eventBuffer: MatrixEvent[]) {
|
private async evaluateEventBuffer(eventBuffer: MatrixEvent[]): Promise<void> {
|
||||||
await Promise.all(eventBuffer.map((event) => this.client.decryptEventIfNeeded(event)));
|
await Promise.all(eventBuffer.map((event) => this.client.decryptEventIfNeeded(event)));
|
||||||
|
|
||||||
const callEvents = eventBuffer.filter((event) => {
|
const callEvents = eventBuffer.filter((event) => {
|
||||||
@@ -125,7 +125,7 @@ export class CallEventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onRoomTimeline = (event: MatrixEvent) => {
|
private onRoomTimeline = (event: MatrixEvent): void => {
|
||||||
this.callEventBuffer.push(event);
|
this.callEventBuffer.push(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ export class CallEventHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private async handleCallEvent(event: MatrixEvent) {
|
private async handleCallEvent(event: MatrixEvent): Promise<void> {
|
||||||
this.client.emit(ClientEvent.ReceivedVoipEvent, event);
|
this.client.emit(ClientEvent.ReceivedVoipEvent, event);
|
||||||
|
|
||||||
const content = event.getContent();
|
const content = event.getContent();
|
||||||
|
@@ -80,7 +80,7 @@ export class CallFeed extends TypedEventEmitter<CallFeedEvent, EventHandlerMap>
|
|||||||
private volumeLooperTimeout?: ReturnType<typeof setTimeout>;
|
private volumeLooperTimeout?: ReturnType<typeof setTimeout>;
|
||||||
private _disposed = false;
|
private _disposed = false;
|
||||||
|
|
||||||
constructor(opts: ICallFeedOpts) {
|
public constructor(opts: ICallFeedOpts) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.client = opts.client;
|
this.client = opts.client;
|
||||||
@@ -227,11 +227,11 @@ export class CallFeed extends TypedEventEmitter<CallFeedEvent, EventHandlerMap>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSpeakingThreshold(threshold: number) {
|
public setSpeakingThreshold(threshold: number): void {
|
||||||
this.speakingThreshold = threshold;
|
this.speakingThreshold = threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
private volumeLooper = () => {
|
private volumeLooper = (): void => {
|
||||||
if (!this.analyser) return;
|
if (!this.analyser) return;
|
||||||
|
|
||||||
if (!this.measuringVolumeActivity) return;
|
if (!this.measuringVolumeActivity) return;
|
||||||
|
@@ -73,7 +73,7 @@ export enum GroupCallErrorCode {
|
|||||||
export class GroupCallError extends Error {
|
export class GroupCallError extends Error {
|
||||||
public code: string;
|
public code: string;
|
||||||
|
|
||||||
constructor(code: GroupCallErrorCode, msg: string, err?: Error) {
|
public constructor(code: GroupCallErrorCode, msg: string, err?: Error) {
|
||||||
// Still don't think there's any way to have proper nested errors
|
// Still don't think there's any way to have proper nested errors
|
||||||
if (err) {
|
if (err) {
|
||||||
super(msg + ": " + err);
|
super(msg + ": " + err);
|
||||||
@@ -86,13 +86,13 @@ export class GroupCallError extends Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class GroupCallUnknownDeviceError extends GroupCallError {
|
export class GroupCallUnknownDeviceError extends GroupCallError {
|
||||||
constructor(public userId: string) {
|
public constructor(public userId: string) {
|
||||||
super(GroupCallErrorCode.UnknownDevice, "No device found for " + userId);
|
super(GroupCallErrorCode.UnknownDevice, "No device found for " + userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OtherUserSpeakingError extends Error {
|
export class OtherUserSpeakingError extends Error {
|
||||||
constructor() {
|
public constructor() {
|
||||||
super("Cannot unmute: another user is speaking");
|
super("Cannot unmute: another user is speaking");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
private initWithAudioMuted = false;
|
private initWithAudioMuted = false;
|
||||||
private initWithVideoMuted = false;
|
private initWithVideoMuted = false;
|
||||||
|
|
||||||
constructor(
|
public constructor(
|
||||||
private client: MatrixClient,
|
private client: MatrixClient,
|
||||||
public room: Room,
|
public room: Room,
|
||||||
public type: GroupCallType,
|
public type: GroupCallType,
|
||||||
@@ -206,7 +206,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async create() {
|
public async create(): Promise<GroupCall> {
|
||||||
this.client.groupCallEventHandler!.groupCalls.set(this.room.roomId, this);
|
this.client.groupCallEventHandler!.groupCalls.set(this.room.roomId, this);
|
||||||
|
|
||||||
await this.client.sendStateEvent(
|
await this.client.sendStateEvent(
|
||||||
@@ -258,7 +258,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
let stream: MediaStream;
|
let stream: MediaStream;
|
||||||
|
|
||||||
let disposed = false;
|
let disposed = false;
|
||||||
const onState = (state: GroupCallState) => {
|
const onState = (state: GroupCallState): void => {
|
||||||
if (state === GroupCallState.LocalCallFeedUninitialized) {
|
if (state === GroupCallState.LocalCallFeedUninitialized) {
|
||||||
disposed = true;
|
disposed = true;
|
||||||
}
|
}
|
||||||
@@ -300,7 +300,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
return callFeed;
|
return callFeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateLocalUsermediaStream(stream: MediaStream) {
|
public async updateLocalUsermediaStream(stream: MediaStream): Promise<void> {
|
||||||
if (this.localCallFeed) {
|
if (this.localCallFeed) {
|
||||||
const oldStream = this.localCallFeed.stream;
|
const oldStream = this.localCallFeed.stream;
|
||||||
this.localCallFeed.setNewStream(stream);
|
this.localCallFeed.setNewStream(stream);
|
||||||
@@ -315,7 +315,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async enter() {
|
public async enter(): Promise<void> {
|
||||||
if (!(this.state === GroupCallState.LocalCallFeedUninitialized ||
|
if (!(this.state === GroupCallState.LocalCallFeedUninitialized ||
|
||||||
this.state === GroupCallState.LocalCallFeedInitialized)) {
|
this.state === GroupCallState.LocalCallFeedInitialized)) {
|
||||||
throw new Error(`Cannot enter call in the "${this.state}" state`);
|
throw new Error(`Cannot enter call in the "${this.state}" state`);
|
||||||
@@ -354,7 +354,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.onActiveSpeakerLoop();
|
this.onActiveSpeakerLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private dispose() {
|
private dispose(): void {
|
||||||
if (this.localCallFeed) {
|
if (this.localCallFeed) {
|
||||||
this.removeUserMediaFeed(this.localCallFeed);
|
this.removeUserMediaFeed(this.localCallFeed);
|
||||||
this.localCallFeed = undefined;
|
this.localCallFeed = undefined;
|
||||||
@@ -400,7 +400,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.client.removeListener(CallEventHandlerEvent.Incoming, this.onIncomingCall);
|
this.client.removeListener(CallEventHandlerEvent.Incoming, this.onIncomingCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
public leave() {
|
public leave(): void {
|
||||||
if (this.transmitTimer !== null) {
|
if (this.transmitTimer !== null) {
|
||||||
clearTimeout(this.transmitTimer);
|
clearTimeout(this.transmitTimer);
|
||||||
this.transmitTimer = null;
|
this.transmitTimer = null;
|
||||||
@@ -410,7 +410,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.setState(GroupCallState.LocalCallFeedUninitialized);
|
this.setState(GroupCallState.LocalCallFeedUninitialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async terminate(emitStateEvent = true) {
|
public async terminate(emitStateEvent = true): Promise<void> {
|
||||||
this.dispose();
|
this.dispose();
|
||||||
|
|
||||||
if (this.transmitTimer !== null) {
|
if (this.transmitTimer !== null) {
|
||||||
@@ -430,7 +430,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.room.roomId,
|
this.room.roomId,
|
||||||
EventType.GroupCallPrefix,
|
EventType.GroupCallPrefix,
|
||||||
{
|
{
|
||||||
...existingStateEvent.getContent(),
|
...existingStateEvent!.getContent(),
|
||||||
["m.terminated"]: GroupCallTerminationReason.CallEnded,
|
["m.terminated"]: GroupCallTerminationReason.CallEnded,
|
||||||
},
|
},
|
||||||
this.groupCallId,
|
this.groupCallId,
|
||||||
@@ -445,7 +445,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
* Local Usermedia
|
* Local Usermedia
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public isLocalVideoMuted() {
|
public isLocalVideoMuted(): boolean {
|
||||||
if (this.localCallFeed) {
|
if (this.localCallFeed) {
|
||||||
return this.localCallFeed.isVideoMuted();
|
return this.localCallFeed.isVideoMuted();
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isMicrophoneMuted() {
|
public isMicrophoneMuted(): boolean {
|
||||||
if (this.localCallFeed) {
|
if (this.localCallFeed) {
|
||||||
return this.localCallFeed.isAudioMuted();
|
return this.localCallFeed.isAudioMuted();
|
||||||
}
|
}
|
||||||
@@ -576,7 +576,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
const stream = await this.client.getMediaHandler().getScreensharingStream(opts);
|
const stream = await this.client.getMediaHandler().getScreensharingStream(opts);
|
||||||
|
|
||||||
for (const track of stream.getTracks()) {
|
for (const track of stream.getTracks()) {
|
||||||
const onTrackEnded = () => {
|
const onTrackEnded = (): void => {
|
||||||
this.setScreensharingEnabled(false);
|
this.setScreensharingEnabled(false);
|
||||||
track.removeEventListener("ended", onTrackEnded);
|
track.removeEventListener("ended", onTrackEnded);
|
||||||
};
|
};
|
||||||
@@ -651,7 +651,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
* as they are observed by the RoomState.members event.
|
* as they are observed by the RoomState.members event.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private onIncomingCall = (newCall: MatrixCall) => {
|
private onIncomingCall = (newCall: MatrixCall): void => {
|
||||||
// The incoming calls may be for another room, which we will ignore.
|
// The incoming calls may be for another room, which we will ignore.
|
||||||
if (newCall.roomId !== this.room.roomId) {
|
if (newCall.roomId !== this.room.roomId) {
|
||||||
return;
|
return;
|
||||||
@@ -700,7 +700,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
private getMemberStateEvents(userId?: string): MatrixEvent[] | MatrixEvent | null {
|
private getMemberStateEvents(userId?: string): MatrixEvent[] | MatrixEvent | null {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
const event = this.room.currentState.getStateEvents(EventType.GroupCallMemberPrefix, userId);
|
const event = this.room.currentState.getStateEvents(EventType.GroupCallMemberPrefix, userId);
|
||||||
return callMemberStateIsExpired(event) ? null : event;
|
return callMemberStateIsExpired(event!) ? null : event;
|
||||||
} else {
|
} else {
|
||||||
return this.room.currentState.getStateEvents(EventType.GroupCallMemberPrefix)
|
return this.room.currentState.getStateEvents(EventType.GroupCallMemberPrefix)
|
||||||
.filter(event => !callMemberStateIsExpired(event));
|
.filter(event => !callMemberStateIsExpired(event));
|
||||||
@@ -708,7 +708,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async sendMemberStateEvent(): Promise<ISendEventResponse> {
|
private async sendMemberStateEvent(): Promise<ISendEventResponse> {
|
||||||
const send = () => this.updateMemberCallState({
|
const send = (): Promise<ISendEventResponse> => this.updateMemberCallState({
|
||||||
"m.call_id": this.groupCallId,
|
"m.call_id": this.groupCallId,
|
||||||
"m.devices": [
|
"m.devices": [
|
||||||
{
|
{
|
||||||
@@ -779,7 +779,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onMemberStateChanged = async (event: MatrixEvent) => {
|
public onMemberStateChanged = async (event: MatrixEvent): Promise<void> => {
|
||||||
// If we haven't entered the call yet, we don't care
|
// If we haven't entered the call yet, we don't care
|
||||||
if (this.state !== GroupCallState.Entered) {
|
if (this.state !== GroupCallState.Entered) {
|
||||||
return;
|
return;
|
||||||
@@ -800,7 +800,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
|
|
||||||
logger.debug(`Processing member state event for ${member.userId}`);
|
logger.debug(`Processing member state event for ${member.userId}`);
|
||||||
|
|
||||||
const ignore = () => {
|
const ignore = (): void => {
|
||||||
this.removeParticipant(member);
|
this.removeParticipant(member);
|
||||||
clearTimeout(this.memberStateExpirationTimers.get(member.userId));
|
clearTimeout(this.memberStateExpirationTimers.get(member.userId));
|
||||||
this.memberStateExpirationTimers.delete(member.userId);
|
this.memberStateExpirationTimers.delete(member.userId);
|
||||||
@@ -953,7 +953,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
return memberDevices[0];
|
return memberDevices[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private onRetryCallLoop = () => {
|
private onRetryCallLoop = (): void => {
|
||||||
for (const event of this.getMemberStateEvents()) {
|
for (const event of this.getMemberStateEvents()) {
|
||||||
const memberId = event.getStateKey()!;
|
const memberId = event.getStateKey()!;
|
||||||
const existingCall = this.calls.find((call) => getCallUserId(call) === memberId);
|
const existingCall = this.calls.find((call) => getCallUserId(call) === memberId);
|
||||||
@@ -976,13 +976,17 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
return this.calls.find((call) => getCallUserId(call) === userId);
|
return this.calls.find((call) => getCallUserId(call) === userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addCall(call: MatrixCall) {
|
private addCall(call: MatrixCall): void {
|
||||||
this.calls.push(call);
|
this.calls.push(call);
|
||||||
this.initCall(call);
|
this.initCall(call);
|
||||||
this.emit(GroupCallEvent.CallsChanged, this.calls);
|
this.emit(GroupCallEvent.CallsChanged, this.calls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private replaceCall(existingCall: MatrixCall, replacementCall: MatrixCall, hangupReason = CallErrorCode.Replaced) {
|
private replaceCall(
|
||||||
|
existingCall: MatrixCall,
|
||||||
|
replacementCall: MatrixCall,
|
||||||
|
hangupReason = CallErrorCode.Replaced,
|
||||||
|
): void {
|
||||||
const existingCallIndex = this.calls.indexOf(existingCall);
|
const existingCallIndex = this.calls.indexOf(existingCall);
|
||||||
|
|
||||||
if (existingCallIndex === -1) {
|
if (existingCallIndex === -1) {
|
||||||
@@ -997,7 +1001,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.emit(GroupCallEvent.CallsChanged, this.calls);
|
this.emit(GroupCallEvent.CallsChanged, this.calls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeCall(call: MatrixCall, hangupReason: CallErrorCode) {
|
private removeCall(call: MatrixCall, hangupReason: CallErrorCode): void {
|
||||||
this.disposeCall(call, hangupReason);
|
this.disposeCall(call, hangupReason);
|
||||||
|
|
||||||
const callIndex = this.calls.indexOf(call);
|
const callIndex = this.calls.indexOf(call);
|
||||||
@@ -1011,18 +1015,20 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.emit(GroupCallEvent.CallsChanged, this.calls);
|
this.emit(GroupCallEvent.CallsChanged, this.calls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initCall(call: MatrixCall) {
|
private initCall(call: MatrixCall): void {
|
||||||
const opponentMemberId = getCallUserId(call);
|
const opponentMemberId = getCallUserId(call);
|
||||||
|
|
||||||
if (!opponentMemberId) {
|
if (!opponentMemberId) {
|
||||||
throw new Error("Cannot init call without user id");
|
throw new Error("Cannot init call without user id");
|
||||||
}
|
}
|
||||||
|
|
||||||
const onCallFeedsChanged = () => this.onCallFeedsChanged(call);
|
const onCallFeedsChanged = (): void => this.onCallFeedsChanged(call);
|
||||||
const onCallStateChanged =
|
const onCallStateChanged = (
|
||||||
(state: CallState, oldState: CallState | undefined) => this.onCallStateChanged(call, state, oldState);
|
state: CallState,
|
||||||
|
oldState?: CallState,
|
||||||
|
): void => this.onCallStateChanged(call, state, oldState);
|
||||||
const onCallHangup = this.onCallHangup;
|
const onCallHangup = this.onCallHangup;
|
||||||
const onCallReplaced = (newCall: MatrixCall) => this.replaceCall(call, newCall);
|
const onCallReplaced = (newCall: MatrixCall): void => this.replaceCall(call, newCall);
|
||||||
|
|
||||||
this.callHandlers.set(opponentMemberId, {
|
this.callHandlers.set(opponentMemberId, {
|
||||||
onCallFeedsChanged,
|
onCallFeedsChanged,
|
||||||
@@ -1041,7 +1047,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
onCallFeedsChanged();
|
onCallFeedsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private disposeCall(call: MatrixCall, hangupReason: CallErrorCode) {
|
private disposeCall(call: MatrixCall, hangupReason: CallErrorCode): void {
|
||||||
const opponentMemberId = getCallUserId(call);
|
const opponentMemberId = getCallUserId(call);
|
||||||
|
|
||||||
if (!opponentMemberId) {
|
if (!opponentMemberId) {
|
||||||
@@ -1083,7 +1089,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onCallFeedsChanged = (call: MatrixCall) => {
|
private onCallFeedsChanged = (call: MatrixCall): void => {
|
||||||
const opponentMemberId = getCallUserId(call);
|
const opponentMemberId = getCallUserId(call);
|
||||||
|
|
||||||
if (!opponentMemberId) {
|
if (!opponentMemberId) {
|
||||||
@@ -1119,7 +1125,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onCallStateChanged = (call: MatrixCall, state: CallState, _oldState: CallState | undefined) => {
|
private onCallStateChanged = (call: MatrixCall, state: CallState, _oldState: CallState | undefined): void => {
|
||||||
const audioMuted = this.localCallFeed!.isAudioMuted();
|
const audioMuted = this.localCallFeed!.isAudioMuted();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -1143,7 +1149,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onCallHangup = (call: MatrixCall) => {
|
private onCallHangup = (call: MatrixCall): void => {
|
||||||
if (call.hangupReason === CallErrorCode.Replaced) {
|
if (call.hangupReason === CallErrorCode.Replaced) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1155,17 +1161,17 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
* UserMedia CallFeed Event Handlers
|
* UserMedia CallFeed Event Handlers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public getUserMediaFeedByUserId(userId: string) {
|
public getUserMediaFeedByUserId(userId: string): CallFeed | undefined {
|
||||||
return this.userMediaFeeds.find((feed) => feed.userId === userId);
|
return this.userMediaFeeds.find((feed) => feed.userId === userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addUserMediaFeed(callFeed: CallFeed) {
|
private addUserMediaFeed(callFeed: CallFeed): void {
|
||||||
this.userMediaFeeds.push(callFeed);
|
this.userMediaFeeds.push(callFeed);
|
||||||
callFeed.measureVolumeActivity(true);
|
callFeed.measureVolumeActivity(true);
|
||||||
this.emit(GroupCallEvent.UserMediaFeedsChanged, this.userMediaFeeds);
|
this.emit(GroupCallEvent.UserMediaFeedsChanged, this.userMediaFeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private replaceUserMediaFeed(existingFeed: CallFeed, replacementFeed: CallFeed) {
|
private replaceUserMediaFeed(existingFeed: CallFeed, replacementFeed: CallFeed): void {
|
||||||
const feedIndex = this.userMediaFeeds.findIndex((feed) => feed.userId === existingFeed.userId);
|
const feedIndex = this.userMediaFeeds.findIndex((feed) => feed.userId === existingFeed.userId);
|
||||||
|
|
||||||
if (feedIndex === -1) {
|
if (feedIndex === -1) {
|
||||||
@@ -1179,7 +1185,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.emit(GroupCallEvent.UserMediaFeedsChanged, this.userMediaFeeds);
|
this.emit(GroupCallEvent.UserMediaFeedsChanged, this.userMediaFeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeUserMediaFeed(callFeed: CallFeed) {
|
private removeUserMediaFeed(callFeed: CallFeed): void {
|
||||||
const feedIndex = this.userMediaFeeds.findIndex((feed) => feed.userId === callFeed.userId);
|
const feedIndex = this.userMediaFeeds.findIndex((feed) => feed.userId === callFeed.userId);
|
||||||
|
|
||||||
if (feedIndex === -1) {
|
if (feedIndex === -1) {
|
||||||
@@ -1200,7 +1206,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onActiveSpeakerLoop = () => {
|
private onActiveSpeakerLoop = (): void => {
|
||||||
let topAvg: number | undefined = undefined;
|
let topAvg: number | undefined = undefined;
|
||||||
let nextActiveSpeaker: string | undefined = undefined;
|
let nextActiveSpeaker: string | undefined = undefined;
|
||||||
|
|
||||||
@@ -1239,16 +1245,16 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
* Screenshare Call Feed Event Handlers
|
* Screenshare Call Feed Event Handlers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public getScreenshareFeedByUserId(userId: string) {
|
public getScreenshareFeedByUserId(userId: string): CallFeed | undefined {
|
||||||
return this.screenshareFeeds.find((feed) => feed.userId === userId);
|
return this.screenshareFeeds.find((feed) => feed.userId === userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addScreenshareFeed(callFeed: CallFeed) {
|
private addScreenshareFeed(callFeed: CallFeed): void {
|
||||||
this.screenshareFeeds.push(callFeed);
|
this.screenshareFeeds.push(callFeed);
|
||||||
this.emit(GroupCallEvent.ScreenshareFeedsChanged, this.screenshareFeeds);
|
this.emit(GroupCallEvent.ScreenshareFeedsChanged, this.screenshareFeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private replaceScreenshareFeed(existingFeed: CallFeed, replacementFeed: CallFeed) {
|
private replaceScreenshareFeed(existingFeed: CallFeed, replacementFeed: CallFeed): void {
|
||||||
const feedIndex = this.screenshareFeeds.findIndex((feed) => feed.userId === existingFeed.userId);
|
const feedIndex = this.screenshareFeeds.findIndex((feed) => feed.userId === existingFeed.userId);
|
||||||
|
|
||||||
if (feedIndex === -1) {
|
if (feedIndex === -1) {
|
||||||
@@ -1261,7 +1267,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.emit(GroupCallEvent.ScreenshareFeedsChanged, this.screenshareFeeds);
|
this.emit(GroupCallEvent.ScreenshareFeedsChanged, this.screenshareFeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeScreenshareFeed(callFeed: CallFeed) {
|
private removeScreenshareFeed(callFeed: CallFeed): void {
|
||||||
const feedIndex = this.screenshareFeeds.findIndex((feed) => feed.userId === callFeed.userId);
|
const feedIndex = this.screenshareFeeds.findIndex((feed) => feed.userId === callFeed.userId);
|
||||||
|
|
||||||
if (feedIndex === -1) {
|
if (feedIndex === -1) {
|
||||||
@@ -1278,7 +1284,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
* Participant Management
|
* Participant Management
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private addParticipant(member: RoomMember) {
|
private addParticipant(member: RoomMember): void {
|
||||||
if (this.participants.find((m) => m.userId === member.userId)) {
|
if (this.participants.find((m) => m.userId === member.userId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1289,7 +1295,7 @@ export class GroupCall extends TypedEventEmitter<
|
|||||||
this.client.emit(GroupCallEventHandlerEvent.Participants, this.participants, this);
|
this.client.emit(GroupCallEventHandlerEvent.Participants, this.participants, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeParticipant(member: RoomMember) {
|
private removeParticipant(member: RoomMember): void {
|
||||||
const index = this.participants.findIndex((m) => m.userId === member.userId);
|
const index = this.participants.findIndex((m) => m.userId === member.userId);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
|
@@ -55,7 +55,7 @@ export class GroupCallEventHandler {
|
|||||||
// and get
|
// and get
|
||||||
private roomDeferreds = new Map<string, RoomDeferred>();
|
private roomDeferreds = new Map<string, RoomDeferred>();
|
||||||
|
|
||||||
constructor(private client: MatrixClient) { }
|
public constructor(private client: MatrixClient) { }
|
||||||
|
|
||||||
public async start(): Promise<void> {
|
public async start(): Promise<void> {
|
||||||
// We wait until the client has started syncing for real.
|
// We wait until the client has started syncing for real.
|
||||||
@@ -66,7 +66,7 @@ export class GroupCallEventHandler {
|
|||||||
if (this.client.getSyncState() !== SyncState.Syncing) {
|
if (this.client.getSyncState() !== SyncState.Syncing) {
|
||||||
logger.debug("Waiting for client to start syncing...");
|
logger.debug("Waiting for client to start syncing...");
|
||||||
await new Promise<void>(resolve => {
|
await new Promise<void>(resolve => {
|
||||||
const onSync = () => {
|
const onSync = (): void => {
|
||||||
if (this.client.getSyncState() === SyncState.Syncing) {
|
if (this.client.getSyncState() === SyncState.Syncing) {
|
||||||
this.client.off(ClientEvent.Sync, onSync);
|
this.client.off(ClientEvent.Sync, onSync);
|
||||||
return resolve();
|
return resolve();
|
||||||
@@ -192,7 +192,7 @@ export class GroupCallEventHandler {
|
|||||||
return groupCall;
|
return groupCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onRoomsChanged = (room: Room) => {
|
private onRoomsChanged = (room: Room): void => {
|
||||||
this.createGroupCallForRoom(room);
|
this.createGroupCallForRoom(room);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -56,11 +56,11 @@ export class MediaHandler extends TypedEventEmitter<
|
|||||||
public userMediaStreams: MediaStream[] = [];
|
public userMediaStreams: MediaStream[] = [];
|
||||||
public screensharingStreams: MediaStream[] = [];
|
public screensharingStreams: MediaStream[] = [];
|
||||||
|
|
||||||
constructor(private client: MatrixClient) {
|
public constructor(private client: MatrixClient) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public restoreMediaSettings(audioInput: string, videoInput: string) {
|
public restoreMediaSettings(audioInput: string, videoInput: string): void {
|
||||||
this.audioInput = audioInput;
|
this.audioInput = audioInput;
|
||||||
this.videoInput = videoInput;
|
this.videoInput = videoInput;
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ export class MediaHandler extends TypedEventEmitter<
|
|||||||
/**
|
/**
|
||||||
* Stops all tracks on the provided usermedia stream
|
* Stops all tracks on the provided usermedia stream
|
||||||
*/
|
*/
|
||||||
public stopUserMediaStream(mediaStream: MediaStream) {
|
public stopUserMediaStream(mediaStream: MediaStream): void {
|
||||||
logger.log(`mediaHandler stopUserMediaStream stopping stream ${mediaStream.id}`);
|
logger.log(`mediaHandler stopUserMediaStream stopping stream ${mediaStream.id}`);
|
||||||
for (const track of mediaStream.getTracks()) {
|
for (const track of mediaStream.getTracks()) {
|
||||||
track.stop();
|
track.stop();
|
||||||
@@ -333,7 +333,7 @@ export class MediaHandler extends TypedEventEmitter<
|
|||||||
/**
|
/**
|
||||||
* Stops all tracks on the provided screensharing stream
|
* Stops all tracks on the provided screensharing stream
|
||||||
*/
|
*/
|
||||||
public stopScreensharingStream(mediaStream: MediaStream) {
|
public stopScreensharingStream(mediaStream: MediaStream): void {
|
||||||
logger.debug("Stopping screensharing stream", mediaStream.id);
|
logger.debug("Stopping screensharing stream", mediaStream.id);
|
||||||
for (const track of mediaStream.getTracks()) {
|
for (const track of mediaStream.getTracks()) {
|
||||||
track.stop();
|
track.stop();
|
||||||
@@ -352,7 +352,7 @@ export class MediaHandler extends TypedEventEmitter<
|
|||||||
/**
|
/**
|
||||||
* Stops all local media tracks
|
* Stops all local media tracks
|
||||||
*/
|
*/
|
||||||
public stopAllStreams() {
|
public stopAllStreams(): void {
|
||||||
for (const stream of this.userMediaStreams) {
|
for (const stream of this.userMediaStreams) {
|
||||||
logger.log(`mediaHandler stopAllStreams stopping stream ${stream.id}`);
|
logger.log(`mediaHandler stopAllStreams stopping stream ${stream.id}`);
|
||||||
for (const track of stream.getTracks()) {
|
for (const track of stream.getTracks()) {
|
||||||
|
@@ -3278,10 +3278,10 @@ eslint-plugin-import@^2.26.0:
|
|||||||
resolve "^1.22.0"
|
resolve "^1.22.0"
|
||||||
tsconfig-paths "^3.14.1"
|
tsconfig-paths "^3.14.1"
|
||||||
|
|
||||||
eslint-plugin-matrix-org@^0.7.0:
|
eslint-plugin-matrix-org@^0.8.0:
|
||||||
version "0.7.0"
|
version "0.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-0.7.0.tgz#4b7456b31e30e7575b62c2aada91915478829f88"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-0.8.0.tgz#daa1396900a8cb1c1d88f1a370e45fc32482cd9e"
|
||||||
integrity sha512-FLmwE4/cRalB7J+J1BBuTccaXvKtRgAoHlbqSCbdsRqhh27xpxEWXe08KlNiET7drEnnz+xMHXdmvW469gch7g==
|
integrity sha512-/Poz/F8lXYDsmQa29iPSt+kO+Jn7ArvRdq10g0CCk8wbRS0sb2zb6fvd9xL1BgR5UDQL771V0l8X32etvY5yKA==
|
||||||
|
|
||||||
eslint-plugin-unicorn@^44.0.2:
|
eslint-plugin-unicorn@^44.0.2:
|
||||||
version "44.0.2"
|
version "44.0.2"
|
||||||
|
Reference in New Issue
Block a user