Compare commits
63 Commits
v15.0.0-rc.1
...
v15.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
| f4839a3b4f | |||
| 4b21b67a45 | |||
| 799a83a115 | |||
| 45b7cab203 | |||
| 4dfc3b9dbb | |||
| 46a0645865 | |||
| 2b30f45f60 | |||
| 87b920698f | |||
| 4f4811e1d9 | |||
| db9936e07c | |||
| 7dcee2eb40 | |||
| 6b34ea6fe5 | |||
| b33b01df0f | |||
| 1c895432ed | |||
| ddd6a05198 | |||
| 0ccde7807f | |||
| 9f97992196 | |||
| 67b8da719f | |||
| 04fad564f7 | |||
| aee698c285 | |||
| 55b489b17a | |||
| c5d188c30a | |||
| 6fff3d6db5 | |||
| 8043d83921 | |||
| b2d83c1f80 | |||
| 1b91cd7037 | |||
| 0baf926c84 | |||
| 763e25e031 | |||
| 861023b3f6 | |||
| 1f5a83994b | |||
| af523522de | |||
| c3a266b3e7 | |||
| f41d815aa6 | |||
| ad8a93dde8 | |||
| b07d44a6c0 | |||
| 1dc899ba6e | |||
| 0b1e3edaff | |||
| 9fb4fed044 | |||
| 730b0b121d | |||
| 9d9d9e2cfa | |||
| 43bc09f392 | |||
| 195498e9db | |||
| 50332c4999 | |||
| 9e46646b16 | |||
| a74a03e414 | |||
| fe8b9eca8e | |||
| a7cc1ae630 | |||
| 14e008bbad | |||
| 6a12c265cf | |||
| c35cb57a79 | |||
| 51c776f51e | |||
| 7ce0eb26d4 | |||
| f0091fa811 | |||
| 25c88bc986 | |||
| ab06f57965 | |||
| c46209a159 | |||
| 0c47e27f9f | |||
| 0385f265e8 | |||
| 59b3960a42 | |||
| d5ab4ba2ef | |||
| f59b81f46b | |||
| 4c39ce8c96 | |||
| 94ff0ea4cd |
@@ -1,3 +1,91 @@
|
||||
Changes in [15.2.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.2.1) (2021-12-13)
|
||||
==================================================================================================
|
||||
|
||||
* Security release with updated version of Olm to fix https://matrix.org/blog/2021/12/03/pre-disclosure-upcoming-security-release-of-libolm-and-matrix-js-sdk
|
||||
|
||||
Changes in [15.2.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.2.0) (2021-12-06)
|
||||
==================================================================================================
|
||||
|
||||
## ✨ Features
|
||||
* Remove support for `ArrayBuffer` in unstable MSC3089 `createFile()` and `createNewVersion()` and instead use same content types as handled by `MatrixClient.uploadContent()`. This enables support for Node.js. ([\#2014](https://github.com/matrix-org/matrix-js-sdk/pull/2014)).
|
||||
* Support for password-based backup on Node.js ([\#2021](https://github.com/matrix-org/matrix-js-sdk/pull/2021)).
|
||||
* Add optional force parameter when ensuring Olm sessions ([\#2027](https://github.com/matrix-org/matrix-js-sdk/pull/2027)).
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Fix call upgrades ([\#2024](https://github.com/matrix-org/matrix-js-sdk/pull/2024)). Contributed by @SimonBrandner.
|
||||
|
||||
Changes in [15.2.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.2.0-rc.1) (2021-11-30)
|
||||
============================================================================================================
|
||||
|
||||
## ✨ Features
|
||||
* Remove support for `ArrayBuffer` in unstable MSC3089 `createFile()` and `createNewVersion()` and instead use same content types as handled by `MatrixClient.uploadContent()`. This enables support for Node.js. ([\#2014](https://github.com/matrix-org/matrix-js-sdk/pull/2014)).
|
||||
* Support for password-based backup on Node.js ([\#2021](https://github.com/matrix-org/matrix-js-sdk/pull/2021)).
|
||||
* Add optional force parameter when ensuring Olm sessions ([\#2027](https://github.com/matrix-org/matrix-js-sdk/pull/2027)).
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Fix call upgrades ([\#2024](https://github.com/matrix-org/matrix-js-sdk/pull/2024)). Contributed by @SimonBrandner.
|
||||
|
||||
Changes in [15.1.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.1) (2021-11-22)
|
||||
==================================================================================================
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Fix edit history being broken after editing an unencrypted event with an encrypted event ([\#2013](https://github.com/matrix-org/matrix-js-sdk/pull/2013)). Fixes vector-im/element-web#19651 and vector-im/element-web#19651. Contributed by @aaronraimist.
|
||||
* Make events pagination responses parse threads ([\#2011](https://github.com/matrix-org/matrix-js-sdk/pull/2011)). Fixes vector-im/element-web#19587 and vector-im/element-web#19587.
|
||||
|
||||
Changes in [15.1.1-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.1-rc.1) (2021-11-17)
|
||||
============================================================================================================
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Fix edit history being broken after editing an unencrypted event with an encrypted event ([\#2013](https://github.com/matrix-org/matrix-js-sdk/pull/2013)). Fixes vector-im/element-web#19651 and vector-im/element-web#19651. Contributed by @aaronraimist.
|
||||
* Make events pagination responses parse threads ([\#2011](https://github.com/matrix-org/matrix-js-sdk/pull/2011)). Fixes vector-im/element-web#19587 and vector-im/element-web#19587.
|
||||
|
||||
Changes in [15.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.0) (2021-11-08)
|
||||
==================================================================================================
|
||||
|
||||
## 🦖 Deprecations
|
||||
* Mark old verification methods as deprecated ([\#1994](https://github.com/matrix-org/matrix-js-sdk/pull/1994)).
|
||||
|
||||
## ✨ Features
|
||||
* Try to set a sender on search result events if possible ([\#2004](https://github.com/matrix-org/matrix-js-sdk/pull/2004)).
|
||||
* Port some changes from group calls branch to develop ([\#2001](https://github.com/matrix-org/matrix-js-sdk/pull/2001)). Contributed by @SimonBrandner.
|
||||
* Fetch room membership from server rather than relying on stored data ([\#1998](https://github.com/matrix-org/matrix-js-sdk/pull/1998)).
|
||||
* Add method to fetch the MSC3266 Room Summary of a Room ([\#1988](https://github.com/matrix-org/matrix-js-sdk/pull/1988)).
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Don't show `Unable to access microphone` when cancelling screensharing dialog ([\#2005](https://github.com/matrix-org/matrix-js-sdk/pull/2005)). Fixes vector-im/element-web#19533 and vector-im/element-web#19533. Contributed by @SimonBrandner.
|
||||
* Strip direction override characters from display names ([\#1992](https://github.com/matrix-org/matrix-js-sdk/pull/1992)). Fixes vector-im/element-web#1712 and vector-im/element-web#1712.
|
||||
|
||||
Changes in [15.1.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.0-rc.1) (2021-11-02)
|
||||
============================================================================================================
|
||||
|
||||
## 🦖 Deprecations
|
||||
* Mark old verification methods as deprecated ([\#1994](https://github.com/matrix-org/matrix-js-sdk/pull/1994)).
|
||||
|
||||
## ✨ Features
|
||||
* Try to set a sender on search result events if possible ([\#2004](https://github.com/matrix-org/matrix-js-sdk/pull/2004)).
|
||||
* Port some changes from group calls branch to develop ([\#2001](https://github.com/matrix-org/matrix-js-sdk/pull/2001)). Contributed by @SimonBrandner.
|
||||
* Fetch room membership from server rather than relying on stored data ([\#1998](https://github.com/matrix-org/matrix-js-sdk/pull/1998)).
|
||||
* Add method to fetch the MSC3266 Room Summary of a Room ([\#1988](https://github.com/matrix-org/matrix-js-sdk/pull/1988)).
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Don't show `Unable to access microphone` when cancelling screensharing dialog ([\#2005](https://github.com/matrix-org/matrix-js-sdk/pull/2005)). Fixes vector-im/element-web#19533 and vector-im/element-web#19533. Contributed by @SimonBrandner.
|
||||
* Strip direction override characters from display names ([\#1992](https://github.com/matrix-org/matrix-js-sdk/pull/1992)). Fixes vector-im/element-web#1712 and vector-im/element-web#1712.
|
||||
|
||||
Changes in [15.0.0](https://github.com/vector-im/element-desktop/releases/tag/v15.0.0) (2021-10-25)
|
||||
===================================================================================================
|
||||
|
||||
## 🚨 BREAKING CHANGES
|
||||
* Use `ICallFeedOpts` in the `CallFeed` constructor. To construct a new `CallFeed` object you have to pass `ICallFeedOpts` e.g. `const callFeed = new CallFeed({client ([\#1964](https://github.com/matrix-org/matrix-js-sdk/pull/1964)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
|
||||
|
||||
## ✨ Features
|
||||
* Make threads use 'm.thread' relation ([\#1980](https://github.com/matrix-org/matrix-js-sdk/pull/1980)).
|
||||
* Try to answer a call without video if we can't access the camera ([\#1972](https://github.com/matrix-org/matrix-js-sdk/pull/1972)). Fixes vector-im/element-web#17975 and vector-im/element-web#17975. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
|
||||
* Make `opts` in `importRoomKeys()` optional ([\#1974](https://github.com/matrix-org/matrix-js-sdk/pull/1974)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
|
||||
* Enable TypeScript declaration maps ([\#1966](https://github.com/matrix-org/matrix-js-sdk/pull/1966)). Contributed by [Alexendoo](https://github.com/Alexendoo).
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Fix `requestVerificationDM` with chronological `pendingEventOrdering` ([\#1943](https://github.com/matrix-org/matrix-js-sdk/pull/1943)). Contributed by [freaktechnik](https://github.com/freaktechnik).
|
||||
|
||||
Changes in [15.0.0-rc.1](https://github.com/vector-im/element-desktop/releases/tag/v15.0.0-rc.1) (2021-10-19)
|
||||
=============================================================================================================
|
||||
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "matrix-js-sdk",
|
||||
"version": "15.0.0-rc.1",
|
||||
"version": "15.2.1",
|
||||
"description": "Matrix Client-Server SDK for Javascript",
|
||||
"scripts": {
|
||||
"prepublishOnly": "yarn build",
|
||||
@@ -74,14 +74,14 @@
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@babel/register": "^7.12.10",
|
||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz",
|
||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
||||
"@types/bs58": "^4.0.1",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "12",
|
||||
"@types/request": "^2.48.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||
"@typescript-eslint/parser": "^4.17.0",
|
||||
"allchange": "^1.0.2",
|
||||
"allchange": "^1.0.6",
|
||||
"babel-jest": "^26.6.3",
|
||||
"babelify": "^10.0.0",
|
||||
"better-docs": "^2.4.0-beta.9",
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
export class MockBlob {
|
||||
private contents: number[] = [];
|
||||
|
||||
public constructor(private parts: ArrayLike<number>[]) {
|
||||
parts.forEach(p => Array.from(p).forEach(e => this.contents.push(e)));
|
||||
}
|
||||
|
||||
public get size(): number {
|
||||
return this.contents.length;
|
||||
}
|
||||
}
|
||||
+10
-4
@@ -23,7 +23,7 @@ describe("MatrixClient retrying", function() {
|
||||
);
|
||||
httpBackend = testClient.httpBackend;
|
||||
client = testClient.client;
|
||||
room = new Room(roomId);
|
||||
room = new Room(roomId, client, userId);
|
||||
client.store.storeRoom(room);
|
||||
});
|
||||
|
||||
@@ -50,7 +50,10 @@ describe("MatrixClient retrying", function() {
|
||||
|
||||
it("should mark events as EventStatus.CANCELLED when cancelled", function() {
|
||||
// send a couple of events; the second will be queued
|
||||
const p1 = client.sendMessage(roomId, "m1").then(function(ev) {
|
||||
const p1 = client.sendMessage(roomId, {
|
||||
"msgtype": "m.text",
|
||||
"body": "m1",
|
||||
}).then(function(ev) {
|
||||
// we expect the first message to fail
|
||||
throw new Error('Message 1 unexpectedly sent successfully');
|
||||
}, (e) => {
|
||||
@@ -60,7 +63,10 @@ describe("MatrixClient retrying", function() {
|
||||
// XXX: it turns out that the promise returned by this message
|
||||
// never gets resolved.
|
||||
// https://github.com/matrix-org/matrix-js-sdk/issues/496
|
||||
client.sendMessage(roomId, "m2");
|
||||
client.sendMessage(roomId, {
|
||||
"msgtype": "m.text",
|
||||
"body": "m2",
|
||||
});
|
||||
|
||||
// both events should be in the timeline at this point
|
||||
const tl = room.getLiveTimeline().getEvents();
|
||||
@@ -88,7 +94,7 @@ describe("MatrixClient retrying", function() {
|
||||
}).respond(400); // fail the first message
|
||||
|
||||
// wait for the localecho of ev1 to be updated
|
||||
const p3 = new Promise((resolve, reject) => {
|
||||
const p3 = new Promise<void>((resolve, reject) => {
|
||||
room.on("Room.localEchoUpdated", (ev0) => {
|
||||
if (ev0 === ev1) {
|
||||
resolve();
|
||||
@@ -244,8 +244,7 @@ describe("MSC3089Branch", () => {
|
||||
|
||||
it('should create new versions of itself', async () => {
|
||||
const canaryName = "canary";
|
||||
const fileContents = "contents go here";
|
||||
const canaryContents = Uint8Array.from(Array.from(fileContents).map((_, i) => fileContents.charCodeAt(i)));
|
||||
const canaryContents = "contents go here";
|
||||
const canaryFile = {} as IEncryptedFile;
|
||||
const canaryAddl = { canary: true };
|
||||
indexEvent.getContent = () => ({ active: true, retained: true });
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
TreePermissions,
|
||||
} from "../../../src/models/MSC3089TreeSpace";
|
||||
import { DEFAULT_ALPHABET } from "../../../src/utils";
|
||||
import { MockBlob } from "../../MockBlob";
|
||||
import { MatrixError } from "../../../src/http-api";
|
||||
|
||||
describe("MSC3089TreeSpace", () => {
|
||||
@@ -887,12 +886,8 @@ describe("MSC3089TreeSpace", () => {
|
||||
const fileName = "My File.txt";
|
||||
const fileContents = "This is a test file";
|
||||
|
||||
// Mock out Blob for the test environment
|
||||
(<any>global).Blob = MockBlob;
|
||||
|
||||
const uploadFn = jest.fn().mockImplementation((contents: Blob, opts: any) => {
|
||||
expect(contents).toBeInstanceOf(Blob);
|
||||
expect(contents.size).toEqual(fileContents.length);
|
||||
const uploadFn = jest.fn().mockImplementation((contents: Buffer, opts: any) => {
|
||||
expect(contents.length).toEqual(fileContents.length);
|
||||
expect(opts).toMatchObject({
|
||||
includeFilename: false,
|
||||
onlyContentUri: true, // because the tests rely on this - we shouldn't really be testing for this.
|
||||
@@ -930,7 +925,7 @@ describe("MSC3089TreeSpace", () => {
|
||||
});
|
||||
client.sendStateEvent = sendStateFn;
|
||||
|
||||
const buf = Uint8Array.from(Array.from(fileContents).map((_, i) => fileContents.charCodeAt(i)));
|
||||
const buf = Buffer.from(fileContents);
|
||||
|
||||
// We clone the file info just to make sure it doesn't get mutated for the test.
|
||||
const result = await tree.createFile(fileName, buf, Object.assign({}, fileInfo), { metadata: true });
|
||||
@@ -951,12 +946,8 @@ describe("MSC3089TreeSpace", () => {
|
||||
const fileName = "My File.txt";
|
||||
const fileContents = "This is a test file";
|
||||
|
||||
// Mock out Blob for the test environment
|
||||
(<any>global).Blob = MockBlob;
|
||||
|
||||
const uploadFn = jest.fn().mockImplementation((contents: Blob, opts: any) => {
|
||||
expect(contents).toBeInstanceOf(Blob);
|
||||
expect(contents.size).toEqual(fileContents.length);
|
||||
const uploadFn = jest.fn().mockImplementation((contents: Buffer, opts: any) => {
|
||||
expect(contents.length).toEqual(fileContents.length);
|
||||
expect(opts).toMatchObject({
|
||||
includeFilename: false,
|
||||
onlyContentUri: true, // because the tests rely on this - we shouldn't really be testing for this.
|
||||
@@ -997,7 +988,7 @@ describe("MSC3089TreeSpace", () => {
|
||||
});
|
||||
client.sendStateEvent = sendStateFn;
|
||||
|
||||
const buf = Uint8Array.from(Array.from(fileContents).map((_, i) => fileContents.charCodeAt(i)));
|
||||
const buf = Buffer.from(fileContents);
|
||||
|
||||
// We clone the file info just to make sure it doesn't get mutated for the test.
|
||||
const result = await tree.createFile(fileName, buf, Object.assign({}, fileInfo), { "m.new_content": true });
|
||||
|
||||
@@ -147,12 +147,12 @@ export interface IPusher {
|
||||
app_display_name: string;
|
||||
app_id: string;
|
||||
data: {
|
||||
format?: string; // TODO: Types
|
||||
format?: string;
|
||||
url?: string; // TODO: Required if kind==http
|
||||
brand?: string; // TODO: For email notifications only?
|
||||
brand?: string; // TODO: For email notifications only? Unspecced field
|
||||
};
|
||||
device_display_name: string;
|
||||
kind: string; // TODO: Types
|
||||
kind: "http" | string;
|
||||
lang: string;
|
||||
profile_tag?: string;
|
||||
pushkey: string;
|
||||
|
||||
@@ -111,6 +111,7 @@ export enum MsgType {
|
||||
Audio = "m.audio",
|
||||
Location = "m.location",
|
||||
Video = "m.video",
|
||||
KeyVerificationRequest = "m.key.verification.request",
|
||||
}
|
||||
|
||||
export const RoomCreateTypeField = "type";
|
||||
|
||||
+428
-57
@@ -75,11 +75,13 @@ import {
|
||||
IKeyBackupPrepareOpts,
|
||||
IKeyBackupRestoreOpts,
|
||||
IKeyBackupRestoreResult,
|
||||
IKeyBackupRoomSessions,
|
||||
IKeyBackupSession,
|
||||
} from "./crypto/keybackup";
|
||||
import { IIdentityServerProvider } from "./@types/IIdentityServerProvider";
|
||||
import type Request from "request";
|
||||
import { MatrixScheduler } from "./scheduler";
|
||||
import { ICryptoCallbacks, IMinimalEvent, IRoomEvent, IStateEvent, NotificationCountType } from "./matrix";
|
||||
import { IAuthData, ICryptoCallbacks, IMinimalEvent, IRoomEvent, IStateEvent, NotificationCountType } from "./matrix";
|
||||
import {
|
||||
CrossSigningKey,
|
||||
IAddSecretStorageKeyOpts,
|
||||
@@ -671,8 +673,28 @@ interface IThirdPartyUser {
|
||||
protocol: string;
|
||||
fields: object;
|
||||
}
|
||||
|
||||
interface IRoomSummary extends Omit<IPublicRoomsChunkRoom, "canonical_alias" | "aliases"> {
|
||||
room_type?: RoomType;
|
||||
membership?: string;
|
||||
is_encrypted: boolean;
|
||||
}
|
||||
|
||||
interface IRoomKeysResponse {
|
||||
sessions: IKeyBackupRoomSessions;
|
||||
}
|
||||
|
||||
interface IRoomsKeysResponse {
|
||||
rooms: Record<string, IRoomKeysResponse>;
|
||||
}
|
||||
/* eslint-enable camelcase */
|
||||
|
||||
// We're using this constant for methods overloading and inspect whether a variable
|
||||
// contains an eventId or not. This was required to ensure backwards compatibility
|
||||
// of methods for threads
|
||||
// Probably not the most graceful solution but does a good enough job for now
|
||||
const EVENT_ID_PREFIX = "$";
|
||||
|
||||
/**
|
||||
* Represents a Matrix Client. Only directly construct this if you want to use
|
||||
* custom modules. Normally, {@link createClient} should be used
|
||||
@@ -718,7 +740,7 @@ export class MatrixClient extends EventEmitter {
|
||||
protected fallbackICEServerAllowed = false;
|
||||
protected roomList: RoomList;
|
||||
protected syncApi: SyncApi;
|
||||
public pushRules: any; // TODO: Types
|
||||
public pushRules: IPushRules;
|
||||
protected syncLeftRoomsPromise: Promise<Room[]>;
|
||||
protected syncedLeftRooms = false;
|
||||
protected clientOpts: IStoredClientOpts;
|
||||
@@ -1749,6 +1771,7 @@ export class MatrixClient extends EventEmitter {
|
||||
* @param {string} deviceId the device to verify
|
||||
*
|
||||
* @returns {Verification} a verification object
|
||||
* @deprecated Use `requestVerification` instead.
|
||||
*/
|
||||
public beginKeyVerification(method: string, userId: string, deviceId: string): Verification {
|
||||
if (!this.crypto) {
|
||||
@@ -1911,6 +1934,7 @@ export class MatrixClient extends EventEmitter {
|
||||
return this.crypto.checkCrossSigningPrivateKey(privateKey, expectedPublicKey);
|
||||
}
|
||||
|
||||
// deprecated: use requestVerification instead
|
||||
public legacyDeviceVerification(
|
||||
userId: string,
|
||||
deviceId: string,
|
||||
@@ -2711,7 +2735,6 @@ export class MatrixClient extends EventEmitter {
|
||||
* @return {Promise<object>} Status of restoration with `total` and `imported`
|
||||
* key counts.
|
||||
*/
|
||||
// TODO: Types
|
||||
public async restoreKeyBackupWithPassword(
|
||||
password: string,
|
||||
targetRoomId: string,
|
||||
@@ -2738,7 +2761,6 @@ export class MatrixClient extends EventEmitter {
|
||||
* @return {Promise<object>} Status of restoration with `total` and `imported`
|
||||
* key counts.
|
||||
*/
|
||||
// TODO: Types
|
||||
public async restoreKeyBackupWithSecretStorage(
|
||||
backupInfo: IKeyBackupInfo,
|
||||
targetRoomId?: string,
|
||||
@@ -2775,7 +2797,6 @@ export class MatrixClient extends EventEmitter {
|
||||
* @return {Promise<object>} Status of restoration with `total` and `imported`
|
||||
* key counts.
|
||||
*/
|
||||
// TODO: Types
|
||||
public restoreKeyBackupWithRecoveryKey(
|
||||
recoveryKey: string,
|
||||
targetRoomId: string,
|
||||
@@ -2787,7 +2808,6 @@ export class MatrixClient extends EventEmitter {
|
||||
return this.restoreKeyBackup(privKey, targetRoomId, targetSessionId, backupInfo, opts);
|
||||
}
|
||||
|
||||
// TODO: Types
|
||||
public async restoreKeyBackupWithCache(
|
||||
targetRoomId: string,
|
||||
targetSessionId: string,
|
||||
@@ -2848,11 +2868,11 @@ export class MatrixClient extends EventEmitter {
|
||||
const res = await this.http.authedRequest(
|
||||
undefined, "GET", path.path, path.queryData, undefined,
|
||||
{ prefix: PREFIX_UNSTABLE },
|
||||
);
|
||||
) as IRoomsKeysResponse | IRoomKeysResponse | IKeyBackupSession;
|
||||
|
||||
if (res.rooms) {
|
||||
// TODO: Types
|
||||
for (const [roomId, roomData] of Object.entries<any>(res.rooms)) {
|
||||
if ((res as IRoomsKeysResponse).rooms) {
|
||||
const rooms = (res as IRoomsKeysResponse).rooms;
|
||||
for (const [roomId, roomData] of Object.entries(rooms)) {
|
||||
if (!roomData.sessions) continue;
|
||||
|
||||
totalKeyCount += Object.keys(roomData.sessions).length;
|
||||
@@ -2862,9 +2882,10 @@ export class MatrixClient extends EventEmitter {
|
||||
keys.push(k);
|
||||
}
|
||||
}
|
||||
} else if (res.sessions) {
|
||||
totalKeyCount = Object.keys(res.sessions).length;
|
||||
keys = await algorithm.decryptSessions(res.sessions);
|
||||
} else if ((res as IRoomKeysResponse).sessions) {
|
||||
const sessions = (res as IRoomKeysResponse).sessions;
|
||||
totalKeyCount = Object.keys(sessions).length;
|
||||
keys = await algorithm.decryptSessions(sessions);
|
||||
for (const k of keys) {
|
||||
k.room_id = targetRoomId;
|
||||
}
|
||||
@@ -2872,7 +2893,7 @@ export class MatrixClient extends EventEmitter {
|
||||
totalKeyCount = 1;
|
||||
try {
|
||||
const [key] = await algorithm.decryptSessions({
|
||||
[targetSessionId]: res,
|
||||
[targetSessionId]: res as IKeyBackupSession,
|
||||
});
|
||||
key.room_id = targetRoomId;
|
||||
key.session_id = targetSessionId;
|
||||
@@ -3377,10 +3398,11 @@ export class MatrixClient extends EventEmitter {
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} eventType
|
||||
* @param {Object} content
|
||||
* @param {string} txnId Optional.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to an empty object {}
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3390,22 +3412,47 @@ export class MatrixClient extends EventEmitter {
|
||||
content: IContent,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendEvent(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
eventType: string,
|
||||
content: IContent,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendEvent(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
eventType: string | IContent,
|
||||
content: IContent | string,
|
||||
txnId?: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
return this.sendCompleteEvent(roomId, { type: eventType, content }, txnId, callback);
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = txnId as Callback;
|
||||
txnId = content as string;
|
||||
content = eventType as IContent;
|
||||
eventType = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
return this.sendCompleteEvent(roomId, threadId, { type: eventType, content }, txnId as string, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {object} eventObject An object with the partial structure of an event, to which event_id, user_id, room_id and origin_server_ts will be added.
|
||||
* @param {string} txnId the txnId.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {string} txnId Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to an empty object {}
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
private sendCompleteEvent(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
eventObject: any,
|
||||
txnId: string,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (utils.isFunction(txnId)) {
|
||||
@@ -3429,6 +3476,10 @@ export class MatrixClient extends EventEmitter {
|
||||
}));
|
||||
|
||||
const room = this.getRoom(roomId);
|
||||
const thread = room?.threads.get(threadId);
|
||||
if (thread) {
|
||||
localEvent.setThread(thread);
|
||||
}
|
||||
|
||||
// if this is a relation or redaction of an event
|
||||
// that hasn't been sent yet (e.g. with a local id starting with a ~)
|
||||
@@ -3445,12 +3496,12 @@ export class MatrixClient extends EventEmitter {
|
||||
const type = localEvent.getType();
|
||||
logger.log(`sendEvent of type ${type} in ${roomId} with txnId ${txnId}`);
|
||||
|
||||
localEvent.setTxnId(txnId);
|
||||
localEvent.setTxnId(txnId as string);
|
||||
localEvent.setStatus(EventStatus.SENDING);
|
||||
|
||||
// add this event immediately to the local store as 'sending'.
|
||||
if (room) {
|
||||
room.addPendingEvent(localEvent, txnId);
|
||||
room.addPendingEvent(localEvent, txnId as string);
|
||||
}
|
||||
|
||||
// addPendingEvent can change the state to NOT_SENT if it believes
|
||||
@@ -3640,31 +3691,52 @@ export class MatrixClient extends EventEmitter {
|
||||
* supplied.
|
||||
* @param {object|module:client.callback} cbOrOpts
|
||||
* Options to pass on, may contain `reason`.
|
||||
* Can be callback for backwards compatibility.
|
||||
* Can be callback for backwards compatibility. Deprecated
|
||||
* @return {Promise} Resolves: TODO
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
public redactEvent(
|
||||
roomId: string,
|
||||
eventId: string,
|
||||
txnId?: string,
|
||||
txnId?: string | undefined,
|
||||
cbOrOpts?: Callback | IRedactOpts,
|
||||
);
|
||||
public redactEvent(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
eventId: string,
|
||||
txnId?: string | undefined,
|
||||
cbOrOpts?: Callback | IRedactOpts,
|
||||
);
|
||||
public redactEvent(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
eventId?: string,
|
||||
txnId?: string | Callback | IRedactOpts,
|
||||
cbOrOpts?: Callback | IRedactOpts,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (!eventId || eventId.startsWith(EVENT_ID_PREFIX)) {
|
||||
cbOrOpts = txnId as (Callback | IRedactOpts);
|
||||
txnId = eventId;
|
||||
eventId = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
const opts = typeof (cbOrOpts) === 'object' ? cbOrOpts : {};
|
||||
const reason = opts.reason;
|
||||
const callback = typeof (cbOrOpts) === 'function' ? cbOrOpts : undefined;
|
||||
return this.sendCompleteEvent(roomId, {
|
||||
return this.sendCompleteEvent(roomId, threadId, {
|
||||
type: EventType.RoomRedaction,
|
||||
content: { reason: reason },
|
||||
redacts: eventId,
|
||||
}, txnId, callback);
|
||||
}, txnId as string, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {Object} content
|
||||
* @param {string} txnId Optional.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to an ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3673,19 +3745,47 @@ export class MatrixClient extends EventEmitter {
|
||||
content: IContent,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
content: IContent,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendMessage(
|
||||
roomId: string,
|
||||
threadId: string | null | IContent,
|
||||
content: IContent | string,
|
||||
txnId?: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (typeof threadId !== "string" && threadId !== null) {
|
||||
callback = txnId as Callback;
|
||||
txnId = content as string;
|
||||
content = threadId as IContent;
|
||||
threadId = null;
|
||||
}
|
||||
if (utils.isFunction(txnId)) {
|
||||
callback = txnId as any as Callback; // for legacy
|
||||
txnId = undefined;
|
||||
}
|
||||
return this.sendEvent(roomId, EventType.RoomMessage, content, txnId, callback);
|
||||
return this.sendEvent(
|
||||
roomId,
|
||||
threadId as (string | null),
|
||||
EventType.RoomMessage,
|
||||
content as IContent,
|
||||
txnId as string,
|
||||
callback,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} body
|
||||
* @param {string} txnId Optional.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to an empty object {}
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3694,29 +3794,76 @@ export class MatrixClient extends EventEmitter {
|
||||
body: string,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendTextMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendTextMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
txnId?: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = txnId as Callback;
|
||||
txnId = body;
|
||||
body = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
const content = ContentHelpers.makeTextMessage(body);
|
||||
return this.sendMessage(roomId, content, txnId, callback);
|
||||
return this.sendMessage(roomId, threadId, content, txnId as string, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} body
|
||||
* @param {string} txnId Optional.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to a ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
public sendNotice(roomId: string, body: string, txnId?: string, callback?: Callback): Promise<ISendEventResponse> {
|
||||
public sendNotice(
|
||||
roomId: string,
|
||||
body: string,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendNotice(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendNotice(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
txnId?: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = txnId as Callback;
|
||||
txnId = body;
|
||||
body = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
const content = ContentHelpers.makeNotice(body);
|
||||
return this.sendMessage(roomId, content, txnId, callback);
|
||||
return this.sendMessage(roomId, threadId, content, txnId as string, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} body
|
||||
* @param {string} txnId Optional.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to a ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3725,17 +3872,38 @@ export class MatrixClient extends EventEmitter {
|
||||
body: string,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendEmoteMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
txnId?: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendEmoteMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
txnId?: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = txnId as Callback;
|
||||
txnId = body;
|
||||
body = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
const content = ContentHelpers.makeEmoteMessage(body);
|
||||
return this.sendMessage(roomId, content, txnId, callback);
|
||||
return this.sendMessage(roomId, threadId, content, txnId as string, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} url
|
||||
* @param {Object} info
|
||||
* @param {string} text
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to a ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3743,9 +3911,32 @@ export class MatrixClient extends EventEmitter {
|
||||
roomId: string,
|
||||
url: string,
|
||||
info?: IImageInfo,
|
||||
text = "Image",
|
||||
text?: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendImageMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
url: string,
|
||||
info?: IImageInfo,
|
||||
text?: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendImageMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
url: string | IImageInfo,
|
||||
info?: IImageInfo | string,
|
||||
text: Callback | string = "Image",
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = text as Callback;
|
||||
text = info as string || "Image";
|
||||
info = url as IImageInfo;
|
||||
url = threadId as string;
|
||||
threadId = null;
|
||||
}
|
||||
if (utils.isFunction(text)) {
|
||||
callback = text as any as Callback; // legacy
|
||||
text = undefined;
|
||||
@@ -3756,15 +3947,16 @@ export class MatrixClient extends EventEmitter {
|
||||
info: info,
|
||||
body: text,
|
||||
};
|
||||
return this.sendMessage(roomId, content, undefined, callback);
|
||||
return this.sendMessage(roomId, threadId, content, undefined, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} url
|
||||
* @param {Object} info
|
||||
* @param {string} text
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to a ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3772,9 +3964,32 @@ export class MatrixClient extends EventEmitter {
|
||||
roomId: string,
|
||||
url: string,
|
||||
info?: IImageInfo,
|
||||
text = "Sticker",
|
||||
text?: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendStickerMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
url: string,
|
||||
info?: IImageInfo,
|
||||
text?: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendStickerMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
url: string | IImageInfo,
|
||||
info?: IImageInfo | string,
|
||||
text: Callback | string = "Sticker",
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = text as Callback;
|
||||
text = info as string || "Sticker";
|
||||
info = url as IImageInfo;
|
||||
url = threadId as string;
|
||||
threadId = null;
|
||||
}
|
||||
if (utils.isFunction(text)) {
|
||||
callback = text as any as Callback; // legacy
|
||||
text = undefined;
|
||||
@@ -3784,14 +3999,15 @@ export class MatrixClient extends EventEmitter {
|
||||
info: info,
|
||||
body: text,
|
||||
};
|
||||
return this.sendEvent(roomId, EventType.Sticker, content, undefined, callback);
|
||||
return this.sendEvent(roomId, threadId, EventType.Sticker, content, undefined, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} body
|
||||
* @param {string} htmlBody
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to a ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3800,16 +4016,36 @@ export class MatrixClient extends EventEmitter {
|
||||
body: string,
|
||||
htmlBody: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendHtmlMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
htmlBody: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendHtmlMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
htmlBody: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
const content = ContentHelpers.makeHtmlMessage(body, htmlBody);
|
||||
return this.sendMessage(roomId, content, undefined, callback);
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = htmlBody as Callback;
|
||||
htmlBody = body as string;
|
||||
body = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
const content = ContentHelpers.makeHtmlMessage(body, htmlBody as string);
|
||||
return this.sendMessage(roomId, threadId, content, undefined, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} body
|
||||
* @param {string} htmlBody
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to a ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3818,16 +4054,37 @@ export class MatrixClient extends EventEmitter {
|
||||
body: string,
|
||||
htmlBody: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendHtmlNotice(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
htmlBody: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendHtmlNotice(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
htmlBody: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
const content = ContentHelpers.makeHtmlNotice(body, htmlBody);
|
||||
return this.sendMessage(roomId, content, undefined, callback);
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = htmlBody as Callback;
|
||||
htmlBody = body as string;
|
||||
body = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
const content = ContentHelpers.makeHtmlNotice(body, htmlBody as string);
|
||||
return this.sendMessage(roomId, threadId, content, undefined, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} threadId
|
||||
* @param {string} body
|
||||
* @param {string} htmlBody
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @param {module:client.callback} callback Optional. Deprecated
|
||||
* @return {Promise} Resolves: to a ISendEventResponse object
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
@@ -3836,9 +4093,29 @@ export class MatrixClient extends EventEmitter {
|
||||
body: string,
|
||||
htmlBody: string,
|
||||
callback?: Callback,
|
||||
);
|
||||
public sendHtmlEmote(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
htmlBody: string,
|
||||
callback?: Callback,
|
||||
)
|
||||
public sendHtmlEmote(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
body: string,
|
||||
htmlBody: string | Callback,
|
||||
callback?: Callback,
|
||||
): Promise<ISendEventResponse> {
|
||||
const content = ContentHelpers.makeHtmlEmote(body, htmlBody);
|
||||
return this.sendMessage(roomId, content, undefined, callback);
|
||||
if (!threadId?.startsWith(EVENT_ID_PREFIX) && threadId !== null) {
|
||||
callback = htmlBody as Callback;
|
||||
htmlBody = body as string;
|
||||
body = threadId;
|
||||
threadId = null;
|
||||
}
|
||||
const content = ContentHelpers.makeHtmlEmote(body, htmlBody as string);
|
||||
return this.sendMessage(roomId, threadId, content, undefined, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4570,7 +4847,12 @@ export class MatrixClient extends EventEmitter {
|
||||
const stateEvents = res.state.map(this.getEventMapper());
|
||||
room.currentState.setUnknownStateEvents(stateEvents);
|
||||
}
|
||||
room.addEventsToTimeline(matrixEvents, true, room.getLiveTimeline());
|
||||
|
||||
const [timelineEvents, threadedEvents] = this.partitionThreadedEvents(matrixEvents);
|
||||
|
||||
room.addEventsToTimeline(timelineEvents, true, room.getLiveTimeline());
|
||||
this.processThreadEvents(room, threadedEvents);
|
||||
|
||||
room.oldState.paginationToken = res.end;
|
||||
if (res.chunk.length === 0) {
|
||||
room.oldState.paginationToken = null;
|
||||
@@ -4676,7 +4958,11 @@ export class MatrixClient extends EventEmitter {
|
||||
const stateEvents = res.state.map(this.getEventMapper());
|
||||
timeline.getState(EventTimeline.BACKWARDS).setUnknownStateEvents(stateEvents);
|
||||
}
|
||||
timelineSet.addEventsToTimeline(matrixEvents, true, timeline, res.start);
|
||||
|
||||
const [timelineEvents, threadedEvents] = this.partitionThreadedEvents(matrixEvents);
|
||||
|
||||
timelineSet.addEventsToTimeline(timelineEvents, true, timeline, res.start);
|
||||
this.processThreadEvents(timelineSet.room, threadedEvents);
|
||||
|
||||
// there is no guarantee that the event ended up in "timeline" (we
|
||||
// might have switched to a neighbouring timeline) - so check the
|
||||
@@ -4809,8 +5095,11 @@ export class MatrixClient extends EventEmitter {
|
||||
matrixEvents[i] = event;
|
||||
}
|
||||
|
||||
eventTimeline.getTimelineSet()
|
||||
.addEventsToTimeline(matrixEvents, backwards, eventTimeline, token);
|
||||
const [timelineEvents, threadedEvents] = this.partitionThreadedEvents(matrixEvents);
|
||||
|
||||
const timelineSet = eventTimeline.getTimelineSet();
|
||||
timelineSet.addEventsToTimeline(timelineEvents, backwards, eventTimeline, token);
|
||||
this.processThreadEvents(timelineSet.room, threadedEvents);
|
||||
|
||||
// if we've hit the end of the timeline, we need to stop trying to
|
||||
// paginate. We need to keep the 'forwards' token though, to make sure
|
||||
@@ -4843,8 +5132,12 @@ export class MatrixClient extends EventEmitter {
|
||||
}
|
||||
const token = res.end;
|
||||
const matrixEvents = res.chunk.map(this.getEventMapper());
|
||||
|
||||
const [timelineEvents, threadedEvents] = this.partitionThreadedEvents(matrixEvents);
|
||||
|
||||
eventTimeline.getTimelineSet()
|
||||
.addEventsToTimeline(matrixEvents, backwards, eventTimeline, token);
|
||||
.addEventsToTimeline(timelineEvents, backwards, eventTimeline, token);
|
||||
this.processThreadEvents(room, threadedEvents);
|
||||
|
||||
// if we've hit the end of the timeline, we need to stop trying to
|
||||
// paginate. We need to keep the 'forwards' token though, to make sure
|
||||
@@ -5414,6 +5707,14 @@ export class MatrixClient extends EventEmitter {
|
||||
const resultsLength = roomEvents.results ? roomEvents.results.length : 0;
|
||||
for (let i = 0; i < resultsLength; i++) {
|
||||
const sr = SearchResult.fromJson(roomEvents.results[i], this.getEventMapper());
|
||||
const room = this.getRoom(sr.context.getEvent().getRoomId());
|
||||
if (room) {
|
||||
// Copy over a known event sender if we can
|
||||
for (const ev of sr.context.getTimeline()) {
|
||||
const sender = room.getMember(ev.getSender());
|
||||
if (!ev.sender && sender) ev.sender = sender;
|
||||
}
|
||||
}
|
||||
searchResults.results.push(sr);
|
||||
}
|
||||
return searchResults;
|
||||
@@ -5983,7 +6284,9 @@ export class MatrixClient extends EventEmitter {
|
||||
if (fetchedEventType === EventType.RoomMessageEncrypted) {
|
||||
const allEvents = originalEvent ? events.concat(originalEvent) : events;
|
||||
await Promise.all(allEvents.map(e => {
|
||||
return new Promise(resolve => e.once("Event.decrypted", resolve));
|
||||
if (e.isEncrypted()) {
|
||||
return new Promise(resolve => e.once("Event.decrypted", resolve));
|
||||
}
|
||||
}));
|
||||
events = events.filter(e => e.getType() === eventType);
|
||||
}
|
||||
@@ -6572,7 +6875,7 @@ export class MatrixClient extends EventEmitter {
|
||||
eventType: string,
|
||||
stateKey: string,
|
||||
callback?: Callback,
|
||||
): Promise<IStateEventWithRoomId> {
|
||||
): Promise<Record<string, any>> {
|
||||
const pathParams = {
|
||||
$roomId: roomId,
|
||||
$eventType: eventType,
|
||||
@@ -7476,7 +7779,7 @@ export class MatrixClient extends EventEmitter {
|
||||
return this.http.authedRequest(undefined, "GET", path, qps, undefined);
|
||||
}
|
||||
|
||||
public uploadDeviceSigningKeys(auth: any, keys?: CrossSigningKeys): Promise<{}> { // TODO: types
|
||||
public uploadDeviceSigningKeys(auth?: IAuthData, keys?: CrossSigningKeys): Promise<{}> {
|
||||
const data = Object.assign({}, keys);
|
||||
if (auth) Object.assign(data, { auth });
|
||||
return this.http.authedRequest(
|
||||
@@ -8521,6 +8824,74 @@ export class MatrixClient extends EventEmitter {
|
||||
public supportsExperimentalThreads(): boolean {
|
||||
return this.clientOpts?.experimentalThreadSupport || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the summary of a room as defined by an initial version of MSC3266 and implemented in Synapse
|
||||
* Proposed at https://github.com/matrix-org/matrix-doc/pull/3266
|
||||
* @param {string} roomIdOrAlias The ID or alias of the room to get the summary of.
|
||||
* @param {string[]?} via The list of servers which know about the room if only an ID was provided.
|
||||
*/
|
||||
public async getRoomSummary(roomIdOrAlias: string, via?: string[]): Promise<IRoomSummary> {
|
||||
const path = utils.encodeUri("/rooms/$roomid/summary", { $roomid: roomIdOrAlias });
|
||||
return this.http.authedRequest(undefined, "GET", path, { via }, null, {
|
||||
qsStringifyOptions: { arrayFormat: 'repeat' },
|
||||
prefix: "/_matrix/client/unstable/im.nheko.summary",
|
||||
});
|
||||
}
|
||||
|
||||
public partitionThreadedEvents(events: MatrixEvent[]): [MatrixEvent[], MatrixEvent[]] {
|
||||
// Indices to the events array, for readibility
|
||||
const ROOM = 0;
|
||||
const THREAD = 1;
|
||||
const threadRoots = new Set<string>();
|
||||
if (this.supportsExperimentalThreads()) {
|
||||
return events.reduce((memo, event: MatrixEvent) => {
|
||||
const room = this.getRoom(event.getRoomId());
|
||||
// An event should live in the thread timeline if
|
||||
// - It's a reply in thread event
|
||||
// - It's related to a reply in thread event
|
||||
let shouldLiveInThreadTimeline = event.isThreadRelation;
|
||||
if (shouldLiveInThreadTimeline) {
|
||||
threadRoots.add(event.relationEventId);
|
||||
} else {
|
||||
const parentEventId = event.parentEventId;
|
||||
const parentEvent = room?.findEventById(parentEventId) || events.find((mxEv: MatrixEvent) => {
|
||||
return mxEv.getId() === parentEventId;
|
||||
});
|
||||
shouldLiveInThreadTimeline = parentEvent?.isThreadRelation;
|
||||
|
||||
// Copy all the reactions and annotations to the root event
|
||||
// to the thread timeline. They will end up living in both
|
||||
// timelines at the same time
|
||||
const targetingThreadRoot = parentEvent?.isThreadRoot || threadRoots.has(event.relationEventId);
|
||||
if (targetingThreadRoot && !event.isThreadRelation && event.relationEventId) {
|
||||
memo[THREAD].push(event);
|
||||
}
|
||||
}
|
||||
const targetTimeline = shouldLiveInThreadTimeline ? THREAD : ROOM;
|
||||
memo[targetTimeline].push(event);
|
||||
return memo;
|
||||
}, [[], []]);
|
||||
} else {
|
||||
// When `experimentalThreadSupport` is disabled
|
||||
// treat all events as timelineEvents
|
||||
return [
|
||||
events,
|
||||
[],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
public processThreadEvents(room: Room, threadedEvents: MatrixEvent[]): void {
|
||||
threadedEvents
|
||||
.sort((a, b) => a.getTs() - b.getTs())
|
||||
.forEach(event => {
|
||||
room.addThreadedEvent(event);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -304,7 +304,7 @@ export class CrossSigningInfo extends EventEmitter {
|
||||
}
|
||||
|
||||
const privateKeys: Record<string, Uint8Array> = {};
|
||||
const keys: Record<string, any> = {}; // TODO types
|
||||
const keys: Record<string, ICrossSigningKey> = {};
|
||||
let masterSigning;
|
||||
let masterPub;
|
||||
|
||||
|
||||
+5
-11
@@ -58,14 +58,7 @@ export interface IEncryptedEventInfo {
|
||||
}
|
||||
|
||||
export interface IRecoveryKey {
|
||||
keyInfo?: {
|
||||
pubkey: string;
|
||||
passphrase?: {
|
||||
algorithm: string;
|
||||
iterations: number;
|
||||
salt: string;
|
||||
};
|
||||
};
|
||||
keyInfo?: IAddSecretStorageKeyOpts;
|
||||
privateKey: Uint8Array;
|
||||
encodedPrivateKey?: string;
|
||||
}
|
||||
@@ -125,12 +118,13 @@ export interface IPassphraseInfo {
|
||||
algorithm: "m.pbkdf2";
|
||||
iterations: number;
|
||||
salt: string;
|
||||
bits: number;
|
||||
bits?: number;
|
||||
}
|
||||
|
||||
export interface IAddSecretStorageKeyOpts {
|
||||
name: string;
|
||||
passphrase: IPassphraseInfo;
|
||||
pubkey: string;
|
||||
passphrase?: IPassphraseInfo;
|
||||
name?: string;
|
||||
key: Uint8Array;
|
||||
}
|
||||
|
||||
|
||||
+18
-28
@@ -40,7 +40,7 @@ import {
|
||||
ISecretRequest,
|
||||
SecretStorageKeyObject,
|
||||
} from './SecretStorage';
|
||||
import { IAddSecretStorageKeyOpts, IImportRoomKeysOpts, ISecretStorageKeyInfo } from "./api";
|
||||
import { IAddSecretStorageKeyOpts, ICreateSecretStorageOpts, IImportRoomKeysOpts, ISecretStorageKeyInfo } from "./api";
|
||||
import { OutgoingRoomKeyRequestManager } from './OutgoingRoomKeyRequestManager';
|
||||
import { IndexedDBCryptoStore } from './store/indexeddb-crypto-store';
|
||||
import { ReciprocateQRCode, SCAN_QR_CODE_METHOD, SHOW_QR_CODE_METHOD } from './verification/QRCode';
|
||||
@@ -59,7 +59,7 @@ import { IStore } from "../store";
|
||||
import { Room } from "../models/room";
|
||||
import { RoomMember } from "../models/room-member";
|
||||
import { MatrixEvent, EventStatus } from "../models/event";
|
||||
import { MatrixClient, IKeysUploadResponse, SessionStore, ISignedKey } from "../client";
|
||||
import { MatrixClient, IKeysUploadResponse, SessionStore, ISignedKey, ICrossSigningKey } from "../client";
|
||||
import type { EncryptionAlgorithm, DecryptionAlgorithm } from "./algorithms/base";
|
||||
import type { IRoomEncryption, RoomList } from "./RoomList";
|
||||
import { IRecoveryKey, IEncryptedEventInfo } from "./api";
|
||||
@@ -108,17 +108,6 @@ export interface IBootstrapCrossSigningOpts {
|
||||
authUploadDeviceSigningKeys?(makeRequest: (authData: any) => {}): Promise<void>;
|
||||
}
|
||||
|
||||
interface IBootstrapSecretStorageOpts {
|
||||
keyBackupInfo?: any; // TODO types
|
||||
setupNewKeyBackup?: boolean;
|
||||
setupNewSecretStorage?: boolean;
|
||||
createSecretStorageKey?(): Promise<{
|
||||
keyInfo?: any; // TODO types
|
||||
privateKey?: Uint8Array;
|
||||
}>;
|
||||
getKeyBackupPassphrase?(): Promise<Uint8Array | null>;
|
||||
}
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
interface IRoomKey {
|
||||
room_id: string;
|
||||
@@ -762,12 +751,12 @@ export class Crypto extends EventEmitter {
|
||||
*/
|
||||
// TODO this does not resolve with what it says it does
|
||||
public async bootstrapSecretStorage({
|
||||
createSecretStorageKey = async () => ({ }),
|
||||
createSecretStorageKey = async () => ({} as IRecoveryKey),
|
||||
keyBackupInfo,
|
||||
setupNewKeyBackup,
|
||||
setupNewSecretStorage,
|
||||
getKeyBackupPassphrase,
|
||||
}: IBootstrapSecretStorageOpts = {}) {
|
||||
}: ICreateSecretStorageOpts = {}) {
|
||||
logger.log("Bootstrapping Secure Secret Storage");
|
||||
const delegateCryptoCallbacks = this.baseApis.cryptoCallbacks;
|
||||
const builder = new EncryptionSetupBuilder(
|
||||
@@ -783,8 +772,7 @@ export class Crypto extends EventEmitter {
|
||||
let newKeyId = null;
|
||||
|
||||
// create a new SSSS key and set it as default
|
||||
const createSSSS = async (opts, privateKey: Uint8Array) => {
|
||||
opts = opts || {};
|
||||
const createSSSS = async (opts: IAddSecretStorageKeyOpts, privateKey: Uint8Array) => {
|
||||
if (privateKey) {
|
||||
opts.key = privateKey;
|
||||
}
|
||||
@@ -800,7 +788,7 @@ export class Crypto extends EventEmitter {
|
||||
return keyId;
|
||||
};
|
||||
|
||||
const ensureCanCheckPassphrase = async (keyId, keyInfo) => {
|
||||
const ensureCanCheckPassphrase = async (keyId: string, keyInfo: ISecretStorageKeyInfo) => {
|
||||
if (!keyInfo.mac) {
|
||||
const key = await this.baseApis.cryptoCallbacks.getSecretStorageKey(
|
||||
{ keys: { [keyId]: keyInfo } }, "",
|
||||
@@ -880,7 +868,7 @@ export class Crypto extends EventEmitter {
|
||||
const backupKey = await this.getSessionBackupPrivateKey() || await getKeyBackupPassphrase();
|
||||
|
||||
// create a new SSSS key and use the backup key as the new SSSS key
|
||||
const opts: any = {}; // TODO types
|
||||
const opts = {} as IAddSecretStorageKeyOpts;
|
||||
|
||||
if (
|
||||
keyBackupInfo.auth_data.private_key_salt &&
|
||||
@@ -898,9 +886,7 @@ export class Crypto extends EventEmitter {
|
||||
newKeyId = await createSSSS(opts, backupKey);
|
||||
|
||||
// store the backup key in secret storage
|
||||
await secretStorage.store(
|
||||
"m.megolm_backup.v1", olmlib.encodeBase64(backupKey), [newKeyId],
|
||||
);
|
||||
await secretStorage.store("m.megolm_backup.v1", olmlib.encodeBase64(backupKey), [newKeyId]);
|
||||
|
||||
// The backup is trusted because the user provided the private key.
|
||||
// Sign the backup with the cross-signing key so the key backup can
|
||||
@@ -1274,7 +1260,7 @@ export class Crypto extends EventEmitter {
|
||||
*/
|
||||
private async checkForValidDeviceSignature(
|
||||
userId: string,
|
||||
key: any, // TODO types
|
||||
key: ICrossSigningKey,
|
||||
devices: Record<string, IDevice>,
|
||||
): Promise<string[]> {
|
||||
const deviceIds: string[] = [];
|
||||
@@ -1609,7 +1595,7 @@ export class Crypto extends EventEmitter {
|
||||
*
|
||||
* @param {object} keys The new trusted set of keys
|
||||
*/
|
||||
private async storeTrustedSelfKeys(keys: any): Promise<void> { // TODO types
|
||||
private async storeTrustedSelfKeys(keys: Record<string, ICrossSigningKey>): Promise<void> {
|
||||
if (keys) {
|
||||
this.crossSigningInfo.setKeys(keys);
|
||||
} else {
|
||||
@@ -2592,12 +2578,16 @@ export class Crypto extends EventEmitter {
|
||||
* the given users.
|
||||
*
|
||||
* @param {string[]} users list of user ids
|
||||
* @param {boolean} force If true, force a new Olm session to be created. Default false.
|
||||
*
|
||||
* @return {Promise} resolves once the sessions are complete, to
|
||||
* an Object mapping from userId to deviceId to
|
||||
* {@link module:crypto~OlmSessionResult}
|
||||
*/
|
||||
ensureOlmSessionsForUsers(users: string[]): Promise<Record<string, Record<string, olmlib.IOlmSessionResult>>> {
|
||||
public ensureOlmSessionsForUsers(
|
||||
users: string[],
|
||||
force?: boolean,
|
||||
): Promise<Record<string, Record<string, olmlib.IOlmSessionResult>>> {
|
||||
const devicesByUser = {};
|
||||
|
||||
for (let i = 0; i < users.length; ++i) {
|
||||
@@ -2622,7 +2612,7 @@ export class Crypto extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
return olmlib.ensureOlmSessionsForDevices(this.olmDevice, this.baseApis, devicesByUser);
|
||||
return olmlib.ensureOlmSessionsForDevices(this.olmDevice, this.baseApis, devicesByUser, force);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2658,7 +2648,7 @@ export class Crypto extends EventEmitter {
|
||||
* @param {Function} opts.progressCallback called with an object which has a stage param
|
||||
* @return {Promise} a promise which resolves once the keys have been imported
|
||||
*/
|
||||
public importRoomKeys(keys: IMegolmSessionData[], opts: IImportRoomKeysOpts = {}): Promise<any> { // TODO types
|
||||
public importRoomKeys(keys: IMegolmSessionData[], opts: IImportRoomKeysOpts = {}): Promise<void> {
|
||||
let successes = 0;
|
||||
let failures = 0;
|
||||
const total = keys.length;
|
||||
@@ -2685,7 +2675,7 @@ export class Crypto extends EventEmitter {
|
||||
successes++;
|
||||
if (opts.progressCallback) { updateProgress(); }
|
||||
});
|
||||
}));
|
||||
})).then();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,10 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { randomString } from '../randomstring';
|
||||
import { getCrypto } from '../utils';
|
||||
|
||||
const subtleCrypto = (typeof window !== "undefined" && window.crypto) ?
|
||||
(window.crypto.subtle || window.crypto.webkitSubtle) : null;
|
||||
|
||||
const DEFAULT_ITERATIONS = 500000;
|
||||
|
||||
@@ -70,11 +74,21 @@ export async function deriveKey(
|
||||
salt: string,
|
||||
iterations: number,
|
||||
numBits = DEFAULT_BITSIZE,
|
||||
): Promise<Uint8Array> {
|
||||
return subtleCrypto
|
||||
? deriveKeyBrowser(password, salt, iterations, numBits)
|
||||
: deriveKeyNode(password, salt, iterations, numBits);
|
||||
}
|
||||
|
||||
async function deriveKeyBrowser(
|
||||
password: string,
|
||||
salt: string,
|
||||
iterations: number,
|
||||
numBits: number,
|
||||
): Promise<Uint8Array> {
|
||||
const subtleCrypto = global.crypto.subtle;
|
||||
const TextEncoder = global.TextEncoder;
|
||||
if (!subtleCrypto || !TextEncoder) {
|
||||
// TODO: Implement this for node
|
||||
throw new Error("Password-based backup is not avaiable on this platform");
|
||||
}
|
||||
|
||||
@@ -99,3 +113,17 @@ export async function deriveKey(
|
||||
|
||||
return new Uint8Array(keybits);
|
||||
}
|
||||
|
||||
async function deriveKeyNode(
|
||||
password: string,
|
||||
salt: string,
|
||||
iterations: number,
|
||||
numBits: number,
|
||||
): Promise<Uint8Array> {
|
||||
const crypto = getCrypto();
|
||||
if (!crypto) {
|
||||
throw new Error("No usable crypto implementation");
|
||||
}
|
||||
|
||||
return crypto.pbkdf2Sync(password, Buffer.from(salt, 'binary'), iterations, numBits, 'sha512');
|
||||
}
|
||||
|
||||
@@ -31,3 +31,9 @@ try {
|
||||
|
||||
export * from "./matrix";
|
||||
export default matrixcs;
|
||||
|
||||
export * from './@types/event';
|
||||
export * from './@types/PushRules';
|
||||
export * from './@types/requests';
|
||||
export * from './@types/search';
|
||||
export * from './models/room-summary';
|
||||
|
||||
@@ -61,6 +61,7 @@ export enum AuthType {
|
||||
Sso = "m.login.sso",
|
||||
SsoUnstable = "org.matrix.login.sso",
|
||||
Dummy = "m.login.dummy",
|
||||
RegistrationToken = "org.matrix.msc3231.login.registration_token",
|
||||
}
|
||||
|
||||
export interface IAuthDict {
|
||||
@@ -449,6 +450,7 @@ export class InteractiveAuth {
|
||||
} catch (e) {
|
||||
this.attemptAuthDeferred.reject(e);
|
||||
this.attemptAuthDeferred = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
@@ -18,6 +18,7 @@ import { MatrixClient } from "../client";
|
||||
import { IEncryptedFile, RelationType, UNSTABLE_MSC3089_BRANCH } from "../@types/event";
|
||||
import { IContent, MatrixEvent } from "./event";
|
||||
import { MSC3089TreeSpace } from "./MSC3089TreeSpace";
|
||||
import type { ReadStream } from "fs";
|
||||
|
||||
/**
|
||||
* Represents a [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089) branch - a reference
|
||||
@@ -142,16 +143,16 @@ export class MSC3089Branch {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new version of this file.
|
||||
* Creates a new version of this file with contents in a type that is compatible with MatrixClient.uploadContent().
|
||||
* @param {string} name The name of the file.
|
||||
* @param {ArrayBuffer} encryptedContents The encrypted contents.
|
||||
* @param {File | String | Buffer | ReadStream | Blob} encryptedContents The encrypted contents.
|
||||
* @param {Partial<IEncryptedFile>} info The encrypted file information.
|
||||
* @param {IContent} additionalContent Optional event content fields to include in the message.
|
||||
* @returns {Promise<void>} Resolves when uploaded.
|
||||
*/
|
||||
public async createNewVersion(
|
||||
name: string,
|
||||
encryptedContents: ArrayBuffer,
|
||||
encryptedContents: File | String | Buffer | ReadStream | Blob,
|
||||
info: Partial<IEncryptedFile>,
|
||||
additionalContent?: IContent,
|
||||
): Promise<void> {
|
||||
|
||||
@@ -31,6 +31,7 @@ import { MSC3089Branch } from "./MSC3089Branch";
|
||||
import promiseRetry from "p-retry";
|
||||
import { isRoomSharedHistory } from "../crypto/algorithms/megolm";
|
||||
import { ISendEventResponse } from "../@types/requests";
|
||||
import type { ReadStream } from "fs";
|
||||
|
||||
/**
|
||||
* The recommended defaults for a tree space's power levels. Note that this
|
||||
@@ -449,21 +450,23 @@ export class MSC3089TreeSpace {
|
||||
|
||||
/**
|
||||
* Creates (uploads) a new file to this tree. The file must have already been encrypted for the room.
|
||||
* The file contents are in a type that is compatible with MatrixClient.uploadContent().
|
||||
* @param {string} name The name of the file.
|
||||
* @param {ArrayBuffer} encryptedContents The encrypted contents.
|
||||
* @param {File | String | Buffer | ReadStream | Blob} encryptedContents The encrypted contents.
|
||||
* @param {Partial<IEncryptedFile>} info The encrypted file information.
|
||||
* @param {IContent} additionalContent Optional event content fields to include in the message.
|
||||
* @returns {Promise<ISendEventResponse>} Resolves to the file event's sent response.
|
||||
*/
|
||||
public async createFile(
|
||||
name: string,
|
||||
encryptedContents: ArrayBuffer,
|
||||
encryptedContents: File | String | Buffer | ReadStream | Blob,
|
||||
info: Partial<IEncryptedFile>,
|
||||
additionalContent?: IContent,
|
||||
): Promise<ISendEventResponse> {
|
||||
const mxc = await this.client.uploadContent(new Blob([encryptedContents]), {
|
||||
const mxc = await this.client.uploadContent(encryptedContents, {
|
||||
includeFilename: false,
|
||||
onlyContentUri: true,
|
||||
rawResponse: false, // make this explicit otherwise behaviour is different on browser vs NodeJS
|
||||
});
|
||||
info.url = mxc;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import { Room } from "./room";
|
||||
import { Filter } from "../filter";
|
||||
import { EventType, RelationType } from "../@types/event";
|
||||
import { RoomState } from "./room-state";
|
||||
import { Thread } from "./thread";
|
||||
|
||||
// var DEBUG = false;
|
||||
const DEBUG = true;
|
||||
@@ -44,6 +45,7 @@ interface IOpts {
|
||||
timelineSupport?: boolean;
|
||||
filter?: Filter;
|
||||
unstableClientRelationAggregation?: boolean;
|
||||
pendingEvents?: boolean;
|
||||
}
|
||||
|
||||
export enum DuplicateStrategy {
|
||||
@@ -54,6 +56,7 @@ export enum DuplicateStrategy {
|
||||
export class EventTimelineSet extends EventEmitter {
|
||||
private readonly timelineSupport: boolean;
|
||||
private unstableClientRelationAggregation: boolean;
|
||||
private displayPendingEvents: boolean;
|
||||
private liveTimeline: EventTimeline;
|
||||
private timelines: EventTimeline[];
|
||||
private _eventIdToTimeline: Record<string, EventTimeline>;
|
||||
@@ -102,6 +105,7 @@ export class EventTimelineSet extends EventEmitter {
|
||||
this.timelineSupport = Boolean(opts.timelineSupport);
|
||||
this.liveTimeline = new EventTimeline(this);
|
||||
this.unstableClientRelationAggregation = !!opts.unstableClientRelationAggregation;
|
||||
this.displayPendingEvents = opts.pendingEvents !== false;
|
||||
|
||||
// just a list - *not* ordered.
|
||||
this.timelines = [this.liveTimeline];
|
||||
@@ -150,18 +154,18 @@ export class EventTimelineSet extends EventEmitter {
|
||||
*
|
||||
* @throws If <code>opts.pendingEventOrdering</code> was not 'detached'
|
||||
*/
|
||||
public getPendingEvents(): MatrixEvent[] {
|
||||
if (!this.room) {
|
||||
public getPendingEvents(thread?: Thread): MatrixEvent[] {
|
||||
if (!this.room || !this.displayPendingEvents) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const pendingEvents = this.room.getPendingEvents(thread);
|
||||
if (this.filter) {
|
||||
return this.filter.filterRoomTimeline(this.room.getPendingEvents());
|
||||
return this.filter.filterRoomTimeline(pendingEvents);
|
||||
} else {
|
||||
return this.room.getPendingEvents();
|
||||
return pendingEvents;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the live timeline for this room.
|
||||
*
|
||||
|
||||
+9
-3
@@ -438,14 +438,14 @@ export class MatrixEvent extends EventEmitter {
|
||||
* @experimental
|
||||
*/
|
||||
public get isThreadRoot(): boolean {
|
||||
// TODO, change the inner working of this getter for it to use the
|
||||
// bundled relationship return on the event, view MSC3440
|
||||
const thread = this.getThread();
|
||||
return thread?.id === this.getId();
|
||||
}
|
||||
|
||||
public get parentEventId(): string {
|
||||
const relations = this.getWireContent()["m.relates_to"];
|
||||
return relations?.["m.in_reply_to"]?.["event_id"]
|
||||
|| relations?.event_id;
|
||||
return this.replyEventId || this.relationEventId;
|
||||
}
|
||||
|
||||
public get replyEventId(): string {
|
||||
@@ -453,6 +453,12 @@ export class MatrixEvent extends EventEmitter {
|
||||
return relations?.["m.in_reply_to"]?.["event_id"];
|
||||
}
|
||||
|
||||
public get relationEventId(): string {
|
||||
return this.getWireContent()
|
||||
?.["m.relates_to"]
|
||||
?.event_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous event content JSON. This will only return something for
|
||||
* state events which exist in the timeline.
|
||||
|
||||
@@ -131,7 +131,9 @@ export class RoomMember extends EventEmitter {
|
||||
this.disambiguate,
|
||||
);
|
||||
|
||||
this.rawDisplayName = event.getDirectionalContent().displayname;
|
||||
// not quite raw: we strip direction override chars so it can safely be inserted into
|
||||
// blocks of text without breaking the text direction
|
||||
this.rawDisplayName = utils.removeDirectionOverrideChars(event.getDirectionalContent().displayname);
|
||||
if (!this.rawDisplayName || !utils.removeHiddenChars(this.rawDisplayName)) {
|
||||
this.rawDisplayName = this.userId;
|
||||
}
|
||||
@@ -355,7 +357,7 @@ function calculateDisplayName(
|
||||
roomState: RoomState,
|
||||
disambiguate: boolean,
|
||||
): string {
|
||||
if (disambiguate) return displayName + " (" + selfUserId + ")";
|
||||
if (disambiguate) return utils.removeDirectionOverrideChars(displayName) + " (" + selfUserId + ")";
|
||||
|
||||
if (!displayName || displayName === selfUserId) return selfUserId;
|
||||
|
||||
@@ -363,7 +365,18 @@ function calculateDisplayName(
|
||||
// after stripping it of zero width characters and padding spaces
|
||||
if (!utils.removeHiddenChars(displayName)) return selfUserId;
|
||||
|
||||
return displayName;
|
||||
// We always strip the direction override characters (LRO and RLO).
|
||||
// These override the text direction for all subsequent characters
|
||||
// in the paragraph so if display names contained these, they'd
|
||||
// need to be wrapped in something to prevent this from leaking out
|
||||
// (which we can do in HTML but not text) or we'd need to add
|
||||
// control characters to the string to reset any overrides (eg.
|
||||
// adding PDF characters at the end). As far as we can see,
|
||||
// there should be no reason these would be necessary - rtl display
|
||||
// names should flip into the correct direction automatically based on
|
||||
// the characters, and you can still embed rtl in ltr or vice versa
|
||||
// with the embed chars or marker chars.
|
||||
return utils.removeDirectionOverrideChars(displayName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+94
-56
@@ -225,12 +225,6 @@ export class Room extends EventEmitter {
|
||||
this.reEmitter = new ReEmitter(this);
|
||||
|
||||
opts.pendingEventOrdering = opts.pendingEventOrdering || PendingEventOrdering.Chronological;
|
||||
if (["chronological", "detached"].indexOf(opts.pendingEventOrdering) === -1) {
|
||||
throw new Error(
|
||||
"opts.pendingEventOrdering MUST be either 'chronological' or " +
|
||||
"'detached'. Got: '" + opts.pendingEventOrdering + "'",
|
||||
);
|
||||
}
|
||||
|
||||
this.name = roomId;
|
||||
|
||||
@@ -241,7 +235,7 @@ export class Room extends EventEmitter {
|
||||
|
||||
this.fixUpLegacyTimelineFields();
|
||||
|
||||
if (this.opts.pendingEventOrdering == "detached") {
|
||||
if (this.opts.pendingEventOrdering === PendingEventOrdering.Detached) {
|
||||
this.pendingEventList = [];
|
||||
const serializedPendingEventList = client.sessionStore.store.getItem(pendingEventsKey(this.roomId));
|
||||
if (serializedPendingEventList) {
|
||||
@@ -452,14 +446,16 @@ export class Room extends EventEmitter {
|
||||
*
|
||||
* @throws If <code>opts.pendingEventOrdering</code> was not 'detached'
|
||||
*/
|
||||
public getPendingEvents(): MatrixEvent[] {
|
||||
if (this.opts.pendingEventOrdering !== "detached") {
|
||||
public getPendingEvents(thread?: Thread): MatrixEvent[] {
|
||||
if (this.opts.pendingEventOrdering !== PendingEventOrdering.Detached) {
|
||||
throw new Error(
|
||||
"Cannot call getPendingEvents with pendingEventOrdering == " +
|
||||
this.opts.pendingEventOrdering);
|
||||
}
|
||||
|
||||
return this.pendingEventList;
|
||||
return this.pendingEventList.filter(event => {
|
||||
return !thread || thread.id === event.threadRootId;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -469,7 +465,7 @@ export class Room extends EventEmitter {
|
||||
* @return {boolean} True if an element was removed.
|
||||
*/
|
||||
public removePendingEvent(eventId: string): boolean {
|
||||
if (this.opts.pendingEventOrdering !== "detached") {
|
||||
if (this.opts.pendingEventOrdering !== PendingEventOrdering.Detached) {
|
||||
throw new Error(
|
||||
"Cannot call removePendingEvent with pendingEventOrdering == " +
|
||||
this.opts.pendingEventOrdering);
|
||||
@@ -495,7 +491,7 @@ export class Room extends EventEmitter {
|
||||
* @return {boolean}
|
||||
*/
|
||||
public hasPendingEvent(eventId: string): boolean {
|
||||
if (this.opts.pendingEventOrdering !== "detached") {
|
||||
if (this.opts.pendingEventOrdering !== PendingEventOrdering.Detached) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -509,7 +505,7 @@ export class Room extends EventEmitter {
|
||||
* @return {MatrixEvent}
|
||||
*/
|
||||
public getPendingEvent(eventId: string): MatrixEvent | null {
|
||||
if (this.opts.pendingEventOrdering !== "detached") {
|
||||
if (this.opts.pendingEventOrdering !== PendingEventOrdering.Detached) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -672,7 +668,13 @@ export class Room extends EventEmitter {
|
||||
// were the members loaded from the server?
|
||||
let fromServer = false;
|
||||
let rawMembersEvents = await this.client.store.getOutOfBandMembers(this.roomId);
|
||||
if (rawMembersEvents === null) {
|
||||
// If the room is encrypted, we always fetch members from the server at
|
||||
// least once, in case the latest state wasn't persisted properly. Note
|
||||
// that this function is only called once (unless loading the members
|
||||
// fails), since loadMembersIfNeeded always returns this.membersPromise
|
||||
// if set, which will be the result of the first (successful) call.
|
||||
if (rawMembersEvents === null ||
|
||||
(this.client.isCryptoEnabled() && this.client.isRoomEncrypted(this.roomId))) {
|
||||
fromServer = true;
|
||||
rawMembersEvents = await this.loadMembersFromServer();
|
||||
logger.log(`LL: got ${rawMembersEvents.length} ` +
|
||||
@@ -850,7 +852,13 @@ export class Room extends EventEmitter {
|
||||
* the given event, or null if unknown
|
||||
*/
|
||||
public getTimelineForEvent(eventId: string): EventTimeline {
|
||||
return this.getUnfilteredTimelineSet().getTimelineForEvent(eventId);
|
||||
const event = this.findEventById(eventId);
|
||||
const thread = this.findThreadForEvent(event);
|
||||
if (thread) {
|
||||
return thread.timelineSet.getLiveTimeline();
|
||||
} else {
|
||||
return this.getUnfilteredTimelineSet().getTimelineForEvent(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1264,8 +1272,11 @@ export class Room extends EventEmitter {
|
||||
if (!event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (event.isThreadRelation) {
|
||||
return this.threads.get(event.threadRootId);
|
||||
} else if (event.isThreadRoot) {
|
||||
return this.threads.get(event.getId());
|
||||
} else {
|
||||
const parentEvent = this.findEventById(event.parentEventId);
|
||||
return this.findThreadForEvent(parentEvent);
|
||||
@@ -1276,21 +1287,35 @@ export class Room extends EventEmitter {
|
||||
* Add an event to a thread's timeline. Will fire "Thread.update"
|
||||
* @experimental
|
||||
*/
|
||||
public addThreadedEvent(event: MatrixEvent): void {
|
||||
public async addThreadedEvent(event: MatrixEvent): Promise<void> {
|
||||
let thread = this.findThreadForEvent(event);
|
||||
if (thread) {
|
||||
thread.addEvent(event);
|
||||
} else {
|
||||
const events = [event];
|
||||
const rootEvent = this.findEventById(event.threadRootId);
|
||||
if (rootEvent) {
|
||||
events.unshift(rootEvent);
|
||||
let rootEvent = this.findEventById(event.threadRootId);
|
||||
// If the rootEvent does not exist in the current sync, then look for
|
||||
// it over the network
|
||||
if (!rootEvent) {
|
||||
const eventData = await this.client.fetchRoomEvent(this.roomId, event.threadRootId);
|
||||
rootEvent = new MatrixEvent(eventData);
|
||||
}
|
||||
events.unshift(rootEvent);
|
||||
thread = new Thread(events, this, this.client);
|
||||
this.reEmitter.reEmit(thread, [ThreadEvent.Update, ThreadEvent.Ready]);
|
||||
this.threads.set(thread.id, thread);
|
||||
this.reEmitter.reEmit(thread, [ThreadEvent.Update, ThreadEvent.Ready]);
|
||||
this.emit(ThreadEvent.New, thread);
|
||||
}
|
||||
|
||||
if (event.getUnsigned().transaction_id) {
|
||||
const existingEvent = this.txnToEvent[event.getUnsigned().transaction_id];
|
||||
if (existingEvent) {
|
||||
// remote echo of an event we sent earlier
|
||||
this.handleRemoteEcho(event, existingEvent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.emit(ThreadEvent.Update, thread);
|
||||
}
|
||||
|
||||
@@ -1390,13 +1415,6 @@ export class Room extends EventEmitter {
|
||||
* unique transaction id.
|
||||
*/
|
||||
public addPendingEvent(event: MatrixEvent, txnId: string): void {
|
||||
// TODO: Enable "pending events" for threads
|
||||
// There's a fair few things to update to make them work with Threads
|
||||
// Will get back to it when the plan is to build a more polished UI ready for production
|
||||
if (this.client?.supportsExperimentalThreads() && event.threadRootId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.status !== EventStatus.SENDING && event.status !== EventStatus.NOT_SENT) {
|
||||
throw new Error("addPendingEvent called on an event with status " +
|
||||
event.status);
|
||||
@@ -1413,8 +1431,8 @@ export class Room extends EventEmitter {
|
||||
EventTimeline.setEventMetadata(event, this.getLiveTimeline().getState(EventTimeline.FORWARDS), false);
|
||||
|
||||
this.txnToEvent[txnId] = event;
|
||||
|
||||
if (this.opts.pendingEventOrdering == "detached") {
|
||||
const thread = this.threads.get(event.threadRootId);
|
||||
if (this.opts.pendingEventOrdering === PendingEventOrdering.Detached && !thread) {
|
||||
if (this.pendingEventList.some((e) => e.status === EventStatus.NOT_SENT)) {
|
||||
logger.warn("Setting event as NOT_SENT due to messages in the same state");
|
||||
event.setStatus(EventStatus.NOT_SENT);
|
||||
@@ -1433,7 +1451,7 @@ export class Room extends EventEmitter {
|
||||
let redactedEvent = this.pendingEventList &&
|
||||
this.pendingEventList.find(e => e.getId() === redactId);
|
||||
if (!redactedEvent) {
|
||||
redactedEvent = this.getUnfilteredTimelineSet().findEventById(redactId);
|
||||
redactedEvent = this.findEventById(redactId);
|
||||
}
|
||||
if (redactedEvent) {
|
||||
redactedEvent.markLocallyRedacted(event);
|
||||
@@ -1441,16 +1459,21 @@ export class Room extends EventEmitter {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
const timelineSet = this.timelineSets[i];
|
||||
if (timelineSet.getFilter()) {
|
||||
if (timelineSet.getFilter().filterRoomTimeline([event]).length) {
|
||||
if (thread) {
|
||||
thread.timelineSet.addEventToTimeline(event,
|
||||
thread.timelineSet.getLiveTimeline(), false);
|
||||
} else {
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
const timelineSet = this.timelineSets[i];
|
||||
if (timelineSet.getFilter()) {
|
||||
if (timelineSet.getFilter().filterRoomTimeline([event]).length) {
|
||||
timelineSet.addEventToTimeline(event,
|
||||
timelineSet.getLiveTimeline(), false);
|
||||
}
|
||||
} else {
|
||||
timelineSet.addEventToTimeline(event,
|
||||
timelineSet.getLiveTimeline(), false);
|
||||
}
|
||||
} else {
|
||||
timelineSet.addEventToTimeline(event,
|
||||
timelineSet.getLiveTimeline(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1508,16 +1531,21 @@ export class Room extends EventEmitter {
|
||||
* @param {module:models/event.MatrixEvent} event the relation event that needs to be aggregated.
|
||||
*/
|
||||
private aggregateNonLiveRelation(event: MatrixEvent): void {
|
||||
// TODO: We should consider whether this means it would be a better
|
||||
// design to lift the relations handling up to the room instead.
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
const timelineSet = this.timelineSets[i];
|
||||
if (timelineSet.getFilter()) {
|
||||
if (timelineSet.getFilter().filterRoomTimeline([event]).length) {
|
||||
const thread = this.findThreadForEvent(event);
|
||||
if (thread) {
|
||||
thread.timelineSet.aggregateRelations(event);
|
||||
} else {
|
||||
// TODO: We should consider whether this means it would be a better
|
||||
// design to lift the relations handling up to the room instead.
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
const timelineSet = this.timelineSets[i];
|
||||
if (timelineSet.getFilter()) {
|
||||
if (timelineSet.getFilter().filterRoomTimeline([event]).length) {
|
||||
timelineSet.aggregateRelations(event);
|
||||
}
|
||||
} else {
|
||||
timelineSet.aggregateRelations(event);
|
||||
}
|
||||
} else {
|
||||
timelineSet.aggregateRelations(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1558,11 +1586,16 @@ export class Room extends EventEmitter {
|
||||
// any, which is good, because we don't want to try decoding it again).
|
||||
localEvent.handleRemoteEcho(remoteEvent.event);
|
||||
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
const timelineSet = this.timelineSets[i];
|
||||
const thread = this.threads.get(remoteEvent.threadRootId);
|
||||
if (thread) {
|
||||
thread.timelineSet.handleRemoteEcho(localEvent, oldEventId, newEventId);
|
||||
} else {
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
const timelineSet = this.timelineSets[i];
|
||||
|
||||
// if it's already in the timeline, update the timeline map. If it's not, add it.
|
||||
timelineSet.handleRemoteEcho(localEvent, oldEventId, newEventId);
|
||||
// if it's already in the timeline, update the timeline map. If it's not, add it.
|
||||
timelineSet.handleRemoteEcho(localEvent, oldEventId, newEventId);
|
||||
}
|
||||
}
|
||||
|
||||
this.emit("Room.localEchoUpdated", localEvent, this,
|
||||
@@ -1595,7 +1628,7 @@ export class Room extends EventEmitter {
|
||||
|
||||
// SENT races against /sync, so we have to special-case it.
|
||||
if (newStatus == EventStatus.SENT) {
|
||||
const timeline = this.getUnfilteredTimelineSet().eventIdToTimeline(newEventId);
|
||||
const timeline = this.getTimelineForEvent(newEventId);
|
||||
if (timeline) {
|
||||
// we've already received the event via the event stream.
|
||||
// nothing more to do here.
|
||||
@@ -1623,11 +1656,16 @@ export class Room extends EventEmitter {
|
||||
// update the event id
|
||||
event.replaceLocalEventId(newEventId);
|
||||
|
||||
// if the event was already in the timeline (which will be the case if
|
||||
// opts.pendingEventOrdering==chronological), we need to update the
|
||||
// timeline map.
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
this.timelineSets[i].replaceEventId(oldEventId, newEventId);
|
||||
const thread = this.findThreadForEvent(event);
|
||||
if (thread) {
|
||||
thread.timelineSet.replaceEventId(oldEventId, newEventId);
|
||||
} else {
|
||||
// if the event was already in the timeline (which will be the case if
|
||||
// opts.pendingEventOrdering==chronological), we need to update the
|
||||
// timeline map.
|
||||
for (let i = 0; i < this.timelineSets.length; i++) {
|
||||
this.timelineSets[i].replaceEventId(oldEventId, newEventId);
|
||||
}
|
||||
}
|
||||
} else if (newStatus == EventStatus.CANCELLED) {
|
||||
// remove it from the pending event list, or the timeline.
|
||||
@@ -1710,7 +1748,7 @@ export class Room extends EventEmitter {
|
||||
// types X Y Z to the timeline".
|
||||
this.addLiveEvent(events[i], duplicateStrategy, fromCache);
|
||||
const thread = this.threads.get(events[i].getId());
|
||||
if (thread && !thread.ready) {
|
||||
if (thread) {
|
||||
thread.addEvent(events[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
+36
-52
@@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { EventEmitter } from "events";
|
||||
import { MatrixClient } from "../matrix";
|
||||
import { MatrixEvent } from "./event";
|
||||
import { EventTimeline } from "./event-timeline";
|
||||
import { EventTimelineSet } from './event-timeline-set';
|
||||
import { Room } from './room';
|
||||
import { TypedEventEmitter } from "./typed-event-emitter";
|
||||
|
||||
export enum ThreadEvent {
|
||||
New = "Thread.new",
|
||||
@@ -30,7 +30,7 @@ export enum ThreadEvent {
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export class Thread extends EventEmitter {
|
||||
export class Thread extends TypedEventEmitter<ThreadEvent> {
|
||||
/**
|
||||
* A reference to the event ID at the top of the thread
|
||||
*/
|
||||
@@ -38,7 +38,9 @@ export class Thread extends EventEmitter {
|
||||
/**
|
||||
* A reference to all the events ID at the bottom of the threads
|
||||
*/
|
||||
public readonly timelineSet: EventTimelineSet;
|
||||
public readonly timelineSet;
|
||||
|
||||
private _currentUserParticipated = false;
|
||||
|
||||
constructor(
|
||||
events: MatrixEvent[] = [],
|
||||
@@ -46,13 +48,27 @@ export class Thread extends EventEmitter {
|
||||
public readonly client: MatrixClient,
|
||||
) {
|
||||
super();
|
||||
this.timelineSet = new EventTimelineSet(room, {
|
||||
if (events.length === 0) {
|
||||
throw new Error("Can't create an empty thread");
|
||||
}
|
||||
|
||||
this.timelineSet = new EventTimelineSet(this.room, {
|
||||
unstableClientRelationAggregation: true,
|
||||
timelineSupport: true,
|
||||
pendingEvents: true,
|
||||
});
|
||||
events.forEach(event => this.addEvent(event));
|
||||
|
||||
room.on("Room.localEchoUpdated", this.onEcho);
|
||||
room.on("Room.timeline", this.onEcho);
|
||||
}
|
||||
|
||||
onEcho = (event: MatrixEvent) => {
|
||||
if (this.timelineSet.eventIdToTimeline(event.getId())) {
|
||||
this.emit(ThreadEvent.Update, this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an event to the thread and updates
|
||||
* the tail/root references if needed
|
||||
@@ -87,18 +103,12 @@ export class Thread extends EventEmitter {
|
||||
roomState,
|
||||
);
|
||||
|
||||
if (this.ready) {
|
||||
this.client.decryptEventIfNeeded(event, {});
|
||||
if (!this._currentUserParticipated && event.getSender() === this.client.getUserId()) {
|
||||
this._currentUserParticipated = true;
|
||||
}
|
||||
this.emit(ThreadEvent.Update, this);
|
||||
}
|
||||
|
||||
private async decryptEvents(): Promise<void> {
|
||||
await Promise.allSettled(
|
||||
Array.from(this.timelineSet.getLiveTimeline().getEvents()).map(event => {
|
||||
return this.client.decryptEventIfNeeded(event, {});
|
||||
}),
|
||||
);
|
||||
await this.client.decryptEventIfNeeded(event, {});
|
||||
this.emit(ThreadEvent.Update, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,10 +119,12 @@ export class Thread extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines thread's ready status
|
||||
* Return last reply to the thread
|
||||
*/
|
||||
public get ready(): boolean {
|
||||
return this.rootEvent !== undefined;
|
||||
public get lastReply(): MatrixEvent {
|
||||
const threadReplies = this.events
|
||||
.filter(event => event.isThreadRelation);
|
||||
return threadReplies[threadReplies.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,20 +147,13 @@ export class Thread extends EventEmitter {
|
||||
|
||||
/**
|
||||
* The number of messages in the thread
|
||||
* Only count rel_type=m.thread as we want to
|
||||
* exclude annotations from that number
|
||||
*/
|
||||
public get length(): number {
|
||||
return this.events.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of mxid participating to the thread
|
||||
*/
|
||||
public get participants(): Set<string> {
|
||||
const participants = new Set<string>();
|
||||
this.events.forEach(event => {
|
||||
participants.add(event.getSender());
|
||||
});
|
||||
return participants;
|
||||
return this.events
|
||||
.filter(event => event.isThreadRelation)
|
||||
.length;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,28 +179,7 @@ export class Thread extends EventEmitter {
|
||||
return this.timelineSet.findEventById(eventId) instanceof MatrixEvent;
|
||||
}
|
||||
|
||||
public on(event: ThreadEvent, listener: (...args: any[]) => void): this {
|
||||
super.on(event, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public once(event: ThreadEvent, listener: (...args: any[]) => void): this {
|
||||
super.once(event, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public off(event: ThreadEvent, listener: (...args: any[]) => void): this {
|
||||
super.off(event, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addListener(event: ThreadEvent, listener: (...args: any[]) => void): this {
|
||||
super.addListener(event, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public removeListener(event: ThreadEvent, listener: (...args: any[]) => void): this {
|
||||
super.removeListener(event, listener);
|
||||
return this;
|
||||
public get hasCurrentUserParticipated(): boolean {
|
||||
return this._currentUserParticipated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
enum EventEmitterEvents {
|
||||
NewListener = "newListener",
|
||||
RemoveListener = "removeListener",
|
||||
}
|
||||
|
||||
/**
|
||||
* Typed Event Emitter class which can act as a Base Model for all our model
|
||||
* and communication events.
|
||||
* This makes it much easier for us to distinguish between events, as we now need
|
||||
* to properly type this, so that our events are not stringly-based and prone
|
||||
* to silly typos.
|
||||
*/
|
||||
export abstract class TypedEventEmitter<Events extends string> extends EventEmitter {
|
||||
public addListener(event: Events | EventEmitterEvents, listener: (...args: any[]) => void): this {
|
||||
return super.addListener(event, listener);
|
||||
}
|
||||
|
||||
public emit(event: Events | EventEmitterEvents, ...args: any[]): boolean {
|
||||
return super.emit(event, ...args);
|
||||
}
|
||||
|
||||
public eventNames(): (Events | EventEmitterEvents)[] {
|
||||
return super.eventNames() as Events[];
|
||||
}
|
||||
|
||||
public listenerCount(event: Events | EventEmitterEvents): number {
|
||||
return super.listenerCount(event);
|
||||
}
|
||||
|
||||
public listeners(event: Events | EventEmitterEvents): Function[] {
|
||||
return super.listeners(event);
|
||||
}
|
||||
|
||||
public off(event: Events | EventEmitterEvents, listener: (...args: any[]) => void): this {
|
||||
return super.off(event, listener);
|
||||
}
|
||||
|
||||
public on(event: Events | EventEmitterEvents, listener: (...args: any[]) => void): this {
|
||||
return super.on(event, listener);
|
||||
}
|
||||
|
||||
public once(event: Events | EventEmitterEvents, listener: (...args: any[]) => void): this {
|
||||
return super.once(event, listener);
|
||||
}
|
||||
|
||||
public prependListener(event: Events | EventEmitterEvents, listener: (...args: any[]) => void): this {
|
||||
return super.prependListener(event, listener);
|
||||
}
|
||||
|
||||
public prependOnceListener(event: Events | EventEmitterEvents, listener: (...args: any[]) => void): this {
|
||||
return super.prependOnceListener(event, listener);
|
||||
}
|
||||
|
||||
public removeAllListeners(event?: Events | EventEmitterEvents): this {
|
||||
return super.removeAllListeners(event);
|
||||
}
|
||||
|
||||
public removeListener(event: Events | EventEmitterEvents, listener: (...args: any[]) => void): this {
|
||||
return super.removeListener(event, listener);
|
||||
}
|
||||
|
||||
public rawListeners(event: Events | EventEmitterEvents): Function[] {
|
||||
return super.rawListeners(event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { TypedEventEmitter } from "../models/typed-event-emitter";
|
||||
|
||||
export enum LocalStorageErrors {
|
||||
Global = 'Global',
|
||||
SetItemError = 'setItem',
|
||||
GetItemError = 'getItem',
|
||||
RemoveItemError = 'removeItem',
|
||||
ClearError = 'clear',
|
||||
QuotaExceededError = 'QuotaExceededError'
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in element-web as a temporary hack to handle all the localStorage errors on the highest level possible
|
||||
* As of 15.11.2021 (DD/MM/YYYY) we're not properly handling local storage exceptions anywhere.
|
||||
* This store, as an event emitter, is used to re-emit local storage exceptions so that we can handle them
|
||||
* and show some kind of a "It's dead Jim" modal to the users, telling them that hey,
|
||||
* maybe you should check out your disk, as it's probably dying and your session may die with it.
|
||||
* See: https://github.com/vector-im/element-web/issues/18423
|
||||
*/
|
||||
class LocalStorageErrorsEventsEmitter extends TypedEventEmitter<LocalStorageErrors> {}
|
||||
export const localStorageErrorsEventsEmitter = new LocalStorageErrorsEventsEmitter();
|
||||
+5
-41
@@ -285,7 +285,7 @@ export class SyncApi {
|
||||
}
|
||||
leaveObj.timeline = leaveObj.timeline || {};
|
||||
const events = this.mapSyncEventsFormat(leaveObj.timeline, room);
|
||||
const [timelineEvents, threadedEvents] = this.partitionThreadedEvents(events);
|
||||
const [timelineEvents, threadedEvents] = this.client.partitionThreadedEvents(events);
|
||||
|
||||
const stateEvents = this.mapSyncEventsFormat(leaveObj.state, room);
|
||||
|
||||
@@ -307,39 +307,6 @@ export class SyncApi {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Split events between the ones that will end up in the main
|
||||
* room timeline versus the one that need to be processed in a thread
|
||||
* @experimental
|
||||
*/
|
||||
public partitionThreadedEvents(events: MatrixEvent[]): [MatrixEvent[], MatrixEvent[]] {
|
||||
if (this.opts.experimentalThreadSupport) {
|
||||
return events.reduce((memo, event: MatrixEvent) => {
|
||||
const room = this.client.getRoom(event.getRoomId());
|
||||
// An event should live in the thread timeline if
|
||||
// - It's a reply in thread event
|
||||
// - It's related to a reply in thread event
|
||||
let shouldLiveInThreadTimeline = event.isThreadRelation;
|
||||
if (!shouldLiveInThreadTimeline) {
|
||||
const parentEventId = event.parentEventId;
|
||||
const parentEvent = room?.findEventById(parentEventId) || events.find((mxEv: MatrixEvent) => {
|
||||
return mxEv.getId() === parentEventId;
|
||||
});
|
||||
shouldLiveInThreadTimeline = parentEvent?.isThreadRelation;
|
||||
}
|
||||
memo[shouldLiveInThreadTimeline ? 1 : 0].push(event);
|
||||
return memo;
|
||||
}, [[], []]);
|
||||
} else {
|
||||
// When `experimentalThreadSupport` is disabled
|
||||
// treat all events as timelineEvents
|
||||
return [
|
||||
events,
|
||||
[],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek into a room. This will result in the room in question being synced so it
|
||||
* is accessible via getRooms(). Live updates for the room will be provided.
|
||||
@@ -538,6 +505,7 @@ export class SyncApi {
|
||||
// The logout already happened, we just need to stop.
|
||||
logger.warn("Token no longer valid - assuming logout");
|
||||
this.stop();
|
||||
this.updateSyncState(SyncState.Error, { error });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1320,7 +1288,7 @@ export class SyncApi {
|
||||
}
|
||||
}
|
||||
|
||||
const [timelineEvents, threadedEvents] = this.partitionThreadedEvents(events);
|
||||
const [timelineEvents, threadedEvents] = this.client.partitionThreadedEvents(events);
|
||||
|
||||
this.processRoomEvents(room, stateEvents, timelineEvents, syncEventData.fromCache);
|
||||
this.processThreadEvents(room, threadedEvents);
|
||||
@@ -1388,7 +1356,7 @@ export class SyncApi {
|
||||
const events = this.mapSyncEventsFormat(leaveObj.timeline, room);
|
||||
const accountDataEvents = this.mapSyncEventsFormat(leaveObj.account_data);
|
||||
|
||||
const [timelineEvents, threadedEvents] = this.partitionThreadedEvents(events);
|
||||
const [timelineEvents, threadedEvents] = this.client.partitionThreadedEvents(events);
|
||||
|
||||
this.processRoomEvents(room, stateEvents, timelineEvents);
|
||||
this.processThreadEvents(room, threadedEvents);
|
||||
@@ -1734,11 +1702,7 @@ export class SyncApi {
|
||||
* @experimental
|
||||
*/
|
||||
private processThreadEvents(room: Room, threadedEvents: MatrixEvent[]): void {
|
||||
threadedEvents
|
||||
.sort((a, b) => a.getTs() - b.getTs())
|
||||
.forEach(event => {
|
||||
room.addThreadedEvent(event);
|
||||
});
|
||||
return this.client.processThreadEvents(room, threadedEvents);
|
||||
}
|
||||
|
||||
// extractRelatedEvents(event: MatrixEvent, events: MatrixEvent[], relatedEvents: MatrixEvent[] = []): MatrixEvent[] {
|
||||
|
||||
@@ -99,7 +99,7 @@ export class TimelineWindow {
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
public load(initialEventId: string, initialWindowSize = 20): Promise<any> {
|
||||
public load(initialEventId?: string, initialWindowSize = 20): Promise<any> {
|
||||
// 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.
|
||||
const initFields = (timeline: EventTimeline) => {
|
||||
|
||||
@@ -387,6 +387,18 @@ export function removeHiddenChars(str: string): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the direction override characters from a string
|
||||
* @param {string} input
|
||||
* @returns string with chars removed
|
||||
*/
|
||||
export function removeDirectionOverrideChars(str: string): string {
|
||||
if (typeof str === "string") {
|
||||
return str.replace(/[\u202d-\u202e]/g, '');
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
export function normalize(str: string): string {
|
||||
// Note: we have to match the filter with the removeHiddenChars() because the
|
||||
// function strips spaces and other characters (M becomes RN for example, in lowercase).
|
||||
|
||||
+150
-57
@@ -416,10 +416,26 @@ export class MatrixCall extends EventEmitter {
|
||||
return this.localUsermediaFeed?.stream;
|
||||
}
|
||||
|
||||
private get localScreensharingStream(): MediaStream {
|
||||
public get localScreensharingStream(): MediaStream {
|
||||
return this.localScreensharingFeed?.stream;
|
||||
}
|
||||
|
||||
public get remoteUsermediaFeed(): CallFeed {
|
||||
return this.getRemoteFeeds().find((feed) => feed.purpose === SDPStreamMetadataPurpose.Usermedia);
|
||||
}
|
||||
|
||||
public get remoteScreensharingFeed(): CallFeed {
|
||||
return this.getRemoteFeeds().find((feed) => feed.purpose === SDPStreamMetadataPurpose.Screenshare);
|
||||
}
|
||||
|
||||
public get remoteUsermediaStream(): MediaStream {
|
||||
return this.remoteUsermediaFeed?.stream;
|
||||
}
|
||||
|
||||
public get remoteScreensharingStream(): MediaStream {
|
||||
return this.remoteScreensharingFeed?.stream;
|
||||
}
|
||||
|
||||
private getFeedByStreamId(streamId: string): CallFeed {
|
||||
return this.getFeeds().find((feed) => feed.stream.id === streamId);
|
||||
}
|
||||
@@ -551,51 +567,87 @@ export class MatrixCall extends EventEmitter {
|
||||
logger.info(`Pushed remote stream (id="${stream.id}", active="${stream.active}")`);
|
||||
}
|
||||
|
||||
private pushLocalFeed(stream: MediaStream, purpose: SDPStreamMetadataPurpose, addToPeerConnection = true): void {
|
||||
private pushNewLocalFeed(stream: MediaStream, purpose: SDPStreamMetadataPurpose, addToPeerConnection = true): void {
|
||||
const userId = this.client.getUserId();
|
||||
|
||||
// TODO: Find out what is going on here
|
||||
// why do we enable audio (and only audio) tracks here? -- matthew
|
||||
setTracksEnabled(stream.getAudioTracks(), true);
|
||||
|
||||
// We try to replace an existing feed if there already is one with the same purpose
|
||||
const existingFeed = this.getLocalFeeds().find((feed) => feed.purpose === purpose);
|
||||
if (existingFeed) {
|
||||
existingFeed.setNewStream(stream);
|
||||
} else {
|
||||
this.feeds.push(new CallFeed({
|
||||
client: this.client,
|
||||
roomId: this.roomId,
|
||||
audioMuted: stream.getAudioTracks().length === 0,
|
||||
videoMuted: stream.getVideoTracks().length === 0,
|
||||
userId,
|
||||
stream,
|
||||
purpose,
|
||||
}));
|
||||
this.pushLocalFeed(
|
||||
new CallFeed({
|
||||
client: this.client,
|
||||
roomId: this.roomId,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
userId,
|
||||
stream,
|
||||
purpose,
|
||||
}),
|
||||
addToPeerConnection,
|
||||
);
|
||||
this.emit(CallEvent.FeedsChanged, this.feeds);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Find out what is going on here
|
||||
// why do we enable audio (and only audio) tracks here? -- matthew
|
||||
setTracksEnabled(stream.getAudioTracks(), true);
|
||||
/**
|
||||
* Pushes supplied feed to the call
|
||||
* @param {CallFeed} callFeed to push
|
||||
* @param {boolean} addToPeerConnection whether to add the tracks to the peer connection
|
||||
*/
|
||||
public pushLocalFeed(callFeed: CallFeed, addToPeerConnection = true): void {
|
||||
this.feeds.push(callFeed);
|
||||
|
||||
if (addToPeerConnection) {
|
||||
const senderArray = purpose === SDPStreamMetadataPurpose.Usermedia ?
|
||||
const senderArray = callFeed.purpose === SDPStreamMetadataPurpose.Usermedia ?
|
||||
this.usermediaSenders : this.screensharingSenders;
|
||||
// Empty the array
|
||||
senderArray.splice(0, senderArray.length);
|
||||
|
||||
this.emit(CallEvent.FeedsChanged, this.feeds);
|
||||
for (const track of stream.getTracks()) {
|
||||
for (const track of callFeed.stream.getTracks()) {
|
||||
logger.info(
|
||||
`Adding track (` +
|
||||
`id="${track.id}", ` +
|
||||
`kind="${track.kind}", ` +
|
||||
`streamId="${stream.id}", ` +
|
||||
`streamPurpose="${purpose}"` +
|
||||
`streamId="${callFeed.stream.id}", ` +
|
||||
`streamPurpose="${callFeed.purpose}"` +
|
||||
`) to peer connection`,
|
||||
);
|
||||
senderArray.push(this.peerConn.addTrack(track, stream));
|
||||
senderArray.push(this.peerConn.addTrack(track, callFeed.stream));
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Pushed local stream (id="${stream.id}", active="${stream.active}", purpose="${purpose}")`);
|
||||
logger.info(
|
||||
`Pushed local stream ` +
|
||||
`(id="${callFeed.stream.id}", ` +
|
||||
`active="${callFeed.stream.active}", ` +
|
||||
`purpose="${callFeed.purpose}")`,
|
||||
);
|
||||
|
||||
this.emit(CallEvent.FeedsChanged, this.feeds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes local call feed from the call and its tracks from the peer
|
||||
* connection
|
||||
* @param callFeed to remove
|
||||
*/
|
||||
public removeLocalFeed(callFeed: CallFeed): void {
|
||||
const senderArray = callFeed.purpose === SDPStreamMetadataPurpose.Usermedia
|
||||
? this.usermediaSenders
|
||||
: this.screensharingSenders;
|
||||
|
||||
for (const sender of senderArray) {
|
||||
this.peerConn.removeTrack(sender);
|
||||
}
|
||||
// Empty the array
|
||||
senderArray.splice(0, senderArray.length);
|
||||
this.deleteFeedByStream(callFeed.stream);
|
||||
}
|
||||
|
||||
private deleteAllFeeds(): void {
|
||||
@@ -760,11 +812,27 @@ export class MatrixCall extends EventEmitter {
|
||||
this.waitForLocalAVStream = true;
|
||||
|
||||
try {
|
||||
const mediaStream = await this.client.getMediaHandler().getUserMediaStream(
|
||||
const stream = await this.client.getMediaHandler().getUserMediaStream(
|
||||
answerWithAudio, answerWithVideo,
|
||||
);
|
||||
this.waitForLocalAVStream = false;
|
||||
this.gotUserMediaForAnswer(mediaStream);
|
||||
const usermediaFeed = new CallFeed({
|
||||
client: this.client,
|
||||
roomId: this.roomId,
|
||||
userId: this.client.getUserId(),
|
||||
stream,
|
||||
purpose: SDPStreamMetadataPurpose.Usermedia,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
});
|
||||
|
||||
const feeds = [usermediaFeed];
|
||||
|
||||
if (this.localScreensharingFeed) {
|
||||
feeds.push(this.localScreensharingFeed);
|
||||
}
|
||||
|
||||
this.answerWithCallFeeds(feeds);
|
||||
} catch (e) {
|
||||
if (answerWithVideo) {
|
||||
// Try to answer without video
|
||||
@@ -782,6 +850,14 @@ export class MatrixCall extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
public answerWithCallFeeds(callFeeds: CallFeed[]): void {
|
||||
if (this.inviteOrAnswerSent) return;
|
||||
|
||||
logger.debug(`Answering call ${this.callId}`);
|
||||
|
||||
this.gotCallFeedsForAnswer(callFeeds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace this call with a new call, e.g. for glare resolution. Used by
|
||||
* MatrixClient.
|
||||
@@ -793,7 +869,7 @@ export class MatrixCall extends EventEmitter {
|
||||
newCall.waitForLocalAVStream = true;
|
||||
} else if ([CallState.CreateOffer, CallState.InviteSent].includes(this.state)) {
|
||||
logger.debug("Handing local stream to new call");
|
||||
newCall.gotUserMediaForAnswer(this.localUsermediaStream);
|
||||
newCall.gotCallFeedsForAnswer(this.getLocalFeeds());
|
||||
}
|
||||
this.successor = newCall;
|
||||
this.emit(CallEvent.Replaced, newCall);
|
||||
@@ -865,7 +941,7 @@ export class MatrixCall extends EventEmitter {
|
||||
if (this.hasLocalUserMediaAudioTrack) return;
|
||||
if (this.hasLocalUserMediaVideoTrack) return;
|
||||
|
||||
this.pushLocalFeed(stream, SDPStreamMetadataPurpose.Usermedia);
|
||||
this.pushNewLocalFeed(stream, SDPStreamMetadataPurpose.Usermedia);
|
||||
} else if (upgradeAudio) {
|
||||
if (this.hasLocalUserMediaAudioTrack) return;
|
||||
|
||||
@@ -931,12 +1007,10 @@ export class MatrixCall extends EventEmitter {
|
||||
try {
|
||||
const stream = await this.client.getMediaHandler().getScreensharingStream(desktopCapturerSourceId);
|
||||
if (!stream) return false;
|
||||
this.pushLocalFeed(stream, SDPStreamMetadataPurpose.Screenshare);
|
||||
this.pushNewLocalFeed(stream, SDPStreamMetadataPurpose.Screenshare);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.emit(CallEvent.Error,
|
||||
new CallError(CallErrorCode.NoUserMedia, "Failed to get screen-sharing stream: ", err),
|
||||
);
|
||||
logger.error("Failed to get screen-sharing stream:", err);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -973,13 +1047,11 @@ export class MatrixCall extends EventEmitter {
|
||||
});
|
||||
sender.replaceTrack(track);
|
||||
|
||||
this.pushLocalFeed(stream, SDPStreamMetadataPurpose.Screenshare, false);
|
||||
this.pushNewLocalFeed(stream, SDPStreamMetadataPurpose.Screenshare, false);
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.emit(CallEvent.Error,
|
||||
new CallError(CallErrorCode.NoUserMedia, "Failed to get screen-sharing stream: ", err),
|
||||
);
|
||||
logger.error("Failed to get screen-sharing stream:", err);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -1133,13 +1205,9 @@ export class MatrixCall extends EventEmitter {
|
||||
setTracksEnabled(this.localUsermediaStream.getVideoTracks(), !vidShouldBeMuted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal
|
||||
* @param {Object} stream
|
||||
*/
|
||||
private gotUserMediaForInvite = async (stream: MediaStream): Promise<void> => {
|
||||
private gotCallFeedsForInvite(callFeeds: CallFeed[]): void {
|
||||
if (this.successor) {
|
||||
this.successor.gotUserMediaForAnswer(stream);
|
||||
this.successor.gotCallFeedsForAnswer(callFeeds);
|
||||
return;
|
||||
}
|
||||
if (this.callHasEnded()) {
|
||||
@@ -1147,12 +1215,15 @@ export class MatrixCall extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pushLocalFeed(stream, SDPStreamMetadataPurpose.Usermedia);
|
||||
for (const feed of callFeeds) {
|
||||
this.pushLocalFeed(feed);
|
||||
}
|
||||
|
||||
this.setState(CallState.CreateOffer);
|
||||
|
||||
logger.debug("gotUserMediaForInvite");
|
||||
// Now we wait for the negotiationneeded event
|
||||
};
|
||||
}
|
||||
|
||||
private async sendAnswer(): Promise<void> {
|
||||
const answerContent = {
|
||||
@@ -1201,12 +1272,15 @@ export class MatrixCall extends EventEmitter {
|
||||
this.sendCandidateQueue();
|
||||
}
|
||||
|
||||
private gotUserMediaForAnswer = async (stream: MediaStream): Promise<void> => {
|
||||
if (this.callHasEnded()) {
|
||||
return;
|
||||
private async gotCallFeedsForAnswer(callFeeds: CallFeed[]): Promise<void> {
|
||||
if (this.callHasEnded()) return;
|
||||
|
||||
this.waitForLocalAVStream = false;
|
||||
|
||||
for (const feed of callFeeds) {
|
||||
this.pushLocalFeed(feed);
|
||||
}
|
||||
|
||||
this.pushLocalFeed(stream, SDPStreamMetadataPurpose.Usermedia);
|
||||
this.setState(CallState.CreateAnswer);
|
||||
|
||||
let myAnswer;
|
||||
@@ -1234,7 +1308,7 @@ export class MatrixCall extends EventEmitter {
|
||||
this.terminate(CallParty.Local, CallErrorCode.SetLocalDescription, true);
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal
|
||||
@@ -1976,15 +2050,41 @@ export class MatrixCall extends EventEmitter {
|
||||
* @throws if have passed audio=false.
|
||||
*/
|
||||
public async placeCall(audio: boolean, video: boolean): Promise<void> {
|
||||
logger.debug(`placeCall audio=${audio} video=${video}`);
|
||||
if (!audio) {
|
||||
throw new Error("You CANNOT start a call without audio");
|
||||
}
|
||||
this.setState(CallState.WaitLocalMedia);
|
||||
|
||||
try {
|
||||
const stream = await this.client.getMediaHandler().getUserMediaStream(audio, video);
|
||||
const callFeed = new CallFeed({
|
||||
client: this.client,
|
||||
roomId: this.roomId,
|
||||
userId: this.client.getUserId(),
|
||||
stream,
|
||||
purpose: SDPStreamMetadataPurpose.Usermedia,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
});
|
||||
await this.placeCallWithCallFeeds([callFeed]);
|
||||
} catch (e) {
|
||||
this.getUserMediaFailed(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Place a call to this room with call feed.
|
||||
* @param {CallFeed[]} callFeeds to use
|
||||
* @throws if you have not specified a listener for 'error' events.
|
||||
* @throws if have passed audio=false.
|
||||
*/
|
||||
public async placeCallWithCallFeeds(callFeeds: CallFeed[]): Promise<void> {
|
||||
this.checkForErrorListener();
|
||||
this.direction = CallDirection.Outbound;
|
||||
|
||||
// XXX Find a better way to do this
|
||||
this.client.callEventHandler.calls.set(this.callId, this);
|
||||
this.setState(CallState.WaitLocalMedia);
|
||||
this.direction = CallDirection.Outbound;
|
||||
|
||||
// make sure we have valid turn creds. Unless something's gone wrong, it should
|
||||
// poll and keep the credentials valid so this should be instant.
|
||||
@@ -1996,14 +2096,7 @@ export class MatrixCall extends EventEmitter {
|
||||
// create the peer connection now so it can be gathering candidates while we get user
|
||||
// media (assuming a candidate pool size is configured)
|
||||
this.peerConn = this.createPeerConnection();
|
||||
|
||||
try {
|
||||
const mediaStream = await this.client.getMediaHandler().getUserMediaStream(audio, video);
|
||||
this.gotUserMediaForInvite(mediaStream);
|
||||
} catch (e) {
|
||||
this.getUserMediaFailed(e);
|
||||
return;
|
||||
}
|
||||
this.gotCallFeedsForInvite(callFeeds);
|
||||
}
|
||||
|
||||
private createPeerConnection(): RTCPeerConnection {
|
||||
|
||||
+48
-19
@@ -19,8 +19,9 @@ import { SDPStreamMetadataPurpose } from "./callEventTypes";
|
||||
import { MatrixClient } from "../client";
|
||||
import { RoomMember } from "../models/room-member";
|
||||
|
||||
const POLLING_INTERVAL = 250; // ms
|
||||
const SPEAKING_THRESHOLD = -60; // dB
|
||||
const POLLING_INTERVAL = 200; // ms
|
||||
export const SPEAKING_THRESHOLD = -60; // dB
|
||||
const SPEAKING_SAMPLE_COUNT = 8; // samples
|
||||
|
||||
export interface ICallFeedOpts {
|
||||
client: MatrixClient;
|
||||
@@ -28,7 +29,13 @@ export interface ICallFeedOpts {
|
||||
userId: string;
|
||||
stream: MediaStream;
|
||||
purpose: SDPStreamMetadataPurpose;
|
||||
/**
|
||||
* Whether or not the remote SDPStreamMetadata says audio is muted
|
||||
*/
|
||||
audioMuted: boolean;
|
||||
/**
|
||||
* Whether or not the remote SDPStreamMetadata says video is muted
|
||||
*/
|
||||
videoMuted: boolean;
|
||||
}
|
||||
|
||||
@@ -43,6 +50,7 @@ export class CallFeed extends EventEmitter {
|
||||
public stream: MediaStream;
|
||||
public userId: string;
|
||||
public purpose: SDPStreamMetadataPurpose;
|
||||
public speakingVolumeSamples: number[];
|
||||
|
||||
private client: MatrixClient;
|
||||
private roomId: string;
|
||||
@@ -65,6 +73,7 @@ export class CallFeed extends EventEmitter {
|
||||
this.purpose = opts.purpose;
|
||||
this.audioMuted = opts.audioMuted;
|
||||
this.videoMuted = opts.videoMuted;
|
||||
this.speakingVolumeSamples = new Array(SPEAKING_SAMPLE_COUNT).fill(-Infinity);
|
||||
|
||||
this.updateStream(null, opts.stream);
|
||||
|
||||
@@ -78,6 +87,8 @@ export class CallFeed extends EventEmitter {
|
||||
}
|
||||
|
||||
private updateStream(oldStream: MediaStream, newStream: MediaStream): void {
|
||||
if (newStream === oldStream) return;
|
||||
|
||||
if (oldStream) {
|
||||
oldStream.removeEventListener("addtrack", this.onAddTrack);
|
||||
this.measureVolumeActivity(false);
|
||||
@@ -152,6 +163,10 @@ export class CallFeed extends EventEmitter {
|
||||
return this.stream.getVideoTracks().length === 0 || this.videoMuted;
|
||||
}
|
||||
|
||||
public isSpeaking(): boolean {
|
||||
return this.speaking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current MediaStream with a new one.
|
||||
* This method should be only used by MatrixCall.
|
||||
@@ -167,6 +182,7 @@ export class CallFeed extends EventEmitter {
|
||||
*/
|
||||
public setAudioMuted(muted: boolean): void {
|
||||
this.audioMuted = muted;
|
||||
this.speakingVolumeSamples.fill(-Infinity);
|
||||
this.emit(CallFeedEvent.MuteStateChanged, this.audioMuted, this.videoMuted);
|
||||
}
|
||||
|
||||
@@ -191,6 +207,7 @@ export class CallFeed extends EventEmitter {
|
||||
this.volumeLooper();
|
||||
} else {
|
||||
this.measuringVolumeActivity = false;
|
||||
this.speakingVolumeSamples.fill(-Infinity);
|
||||
this.emit(CallFeedEvent.VolumeChanged, -Infinity);
|
||||
}
|
||||
}
|
||||
@@ -199,31 +216,43 @@ export class CallFeed extends EventEmitter {
|
||||
this.speakingThreshold = threshold;
|
||||
}
|
||||
|
||||
private volumeLooper(): void {
|
||||
private volumeLooper = () => {
|
||||
if (!this.analyser) return;
|
||||
|
||||
this.volumeLooperTimeout = setTimeout(() => {
|
||||
if (!this.measuringVolumeActivity) return;
|
||||
if (!this.measuringVolumeActivity) return;
|
||||
|
||||
this.analyser.getFloatFrequencyData(this.frequencyBinCount);
|
||||
this.analyser.getFloatFrequencyData(this.frequencyBinCount);
|
||||
|
||||
let maxVolume = -Infinity;
|
||||
for (let i = 0; i < this.frequencyBinCount.length; i++) {
|
||||
if (this.frequencyBinCount[i] > maxVolume) {
|
||||
maxVolume = this.frequencyBinCount[i];
|
||||
}
|
||||
let maxVolume = -Infinity;
|
||||
for (let i = 0; i < this.frequencyBinCount.length; i++) {
|
||||
if (this.frequencyBinCount[i] > maxVolume) {
|
||||
maxVolume = this.frequencyBinCount[i];
|
||||
}
|
||||
}
|
||||
|
||||
this.emit(CallFeedEvent.VolumeChanged, maxVolume);
|
||||
const newSpeaking = maxVolume > this.speakingThreshold;
|
||||
if (this.speaking !== newSpeaking) {
|
||||
this.speaking = newSpeaking;
|
||||
this.emit(CallFeedEvent.Speaking, this.speaking);
|
||||
this.speakingVolumeSamples.shift();
|
||||
this.speakingVolumeSamples.push(maxVolume);
|
||||
|
||||
this.emit(CallFeedEvent.VolumeChanged, maxVolume);
|
||||
|
||||
let newSpeaking = false;
|
||||
|
||||
for (let i = 0; i < this.speakingVolumeSamples.length; i++) {
|
||||
const volume = this.speakingVolumeSamples[i];
|
||||
|
||||
if (volume > this.speakingThreshold) {
|
||||
newSpeaking = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.volumeLooper();
|
||||
}, POLLING_INTERVAL);
|
||||
}
|
||||
if (this.speaking !== newSpeaking) {
|
||||
this.speaking = newSpeaking;
|
||||
this.emit(CallFeedEvent.Speaking, this.speaking);
|
||||
}
|
||||
|
||||
this.volumeLooperTimeout = setTimeout(this.volumeLooper, POLLING_INTERVAL);
|
||||
};
|
||||
|
||||
public dispose(): void {
|
||||
clearTimeout(this.volumeLooperTimeout);
|
||||
|
||||
@@ -42,10 +42,10 @@
|
||||
"@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3"
|
||||
chokidar "^3.4.0"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
|
||||
integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.15.8":
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503"
|
||||
integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.14.5"
|
||||
|
||||
@@ -54,20 +54,20 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
|
||||
integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==
|
||||
|
||||
"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.7.5":
|
||||
version "7.15.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.5.tgz#f8ed9ace730722544609f90c9bb49162dc3bf5b9"
|
||||
integrity sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==
|
||||
"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.7.5":
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10"
|
||||
integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.14.5"
|
||||
"@babel/generator" "^7.15.4"
|
||||
"@babel/code-frame" "^7.15.8"
|
||||
"@babel/generator" "^7.15.8"
|
||||
"@babel/helper-compilation-targets" "^7.15.4"
|
||||
"@babel/helper-module-transforms" "^7.15.4"
|
||||
"@babel/helper-module-transforms" "^7.15.8"
|
||||
"@babel/helpers" "^7.15.4"
|
||||
"@babel/parser" "^7.15.5"
|
||||
"@babel/parser" "^7.15.8"
|
||||
"@babel/template" "^7.15.4"
|
||||
"@babel/traverse" "^7.15.4"
|
||||
"@babel/types" "^7.15.4"
|
||||
"@babel/types" "^7.15.6"
|
||||
convert-source-map "^1.7.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
@@ -76,9 +76,9 @@
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/eslint-parser@^7.12.10":
|
||||
version "7.15.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.7.tgz#2dc3d0ff0ea22bb1e08d93b4eeb1149bf1c75f2d"
|
||||
integrity sha512-yJkHyomClm6A2Xzb8pdAo4HzYMSXFn1O5zrCYvbFP0yQFvHueLedV8WiEno8yJOKStjUXzBZzJFeWQ7b3YMsqQ==
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz#8988660b59d739500b67d0585fd4daca218d9f11"
|
||||
integrity sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==
|
||||
dependencies:
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-visitor-keys "^2.1.0"
|
||||
@@ -91,12 +91,12 @@
|
||||
dependencies:
|
||||
eslint-rule-composer "^0.3.0"
|
||||
|
||||
"@babel/generator@^7.12.11", "@babel/generator@^7.15.4":
|
||||
version "7.15.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0"
|
||||
integrity sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==
|
||||
"@babel/generator@^7.12.11", "@babel/generator@^7.15.4", "@babel/generator@^7.15.8":
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1"
|
||||
integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==
|
||||
dependencies:
|
||||
"@babel/types" "^7.15.4"
|
||||
"@babel/types" "^7.15.6"
|
||||
jsesc "^2.5.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
@@ -203,10 +203,10 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.15.4"
|
||||
|
||||
"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4":
|
||||
version "7.15.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz#7da80c8cbc1f02655d83f8b79d25866afe50d226"
|
||||
integrity sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw==
|
||||
"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4", "@babel/helper-module-transforms@^7.15.8":
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2"
|
||||
integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.15.4"
|
||||
"@babel/helper-replace-supers" "^7.15.4"
|
||||
@@ -307,10 +307,10 @@
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.15.4", "@babel/parser@^7.15.5", "@babel/parser@^7.2.3", "@babel/parser@^7.9.4":
|
||||
version "7.15.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae"
|
||||
integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g==
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.15.4", "@babel/parser@^7.15.8", "@babel/parser@^7.2.3", "@babel/parser@^7.9.4":
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016"
|
||||
integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==
|
||||
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.15.4":
|
||||
version "7.15.4"
|
||||
@@ -321,10 +321,10 @@
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.15.4"
|
||||
"@babel/plugin-proposal-optional-chaining" "^7.14.5"
|
||||
|
||||
"@babel/plugin-proposal-async-generator-functions@^7.15.4":
|
||||
version "7.15.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.4.tgz#f82aabe96c135d2ceaa917feb9f5fca31635277e"
|
||||
integrity sha512-2zt2g5vTXpMC3OmK6uyjvdXptbhBXfA77XGrd3gh93zwG8lZYBLOBImiGBEG0RANu3JqKEACCz5CGk73OJROBw==
|
||||
"@babel/plugin-proposal-async-generator-functions@^7.15.8":
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.8.tgz#a3100f785fab4357987c4223ab1b02b599048403"
|
||||
integrity sha512-2Z5F2R2ibINTc63mY7FLqGfEbmofrHU9FitJW1Q7aPaKFhiPvSq6QEt/BoWN5oME3GVyjcRuNNSRbb9LC0CSWA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
"@babel/helper-remap-async-to-generator" "^7.15.4"
|
||||
@@ -766,14 +766,14 @@
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
|
||||
"@babel/plugin-transform-runtime@^7.12.10":
|
||||
version "7.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz#d3aa650d11678ca76ce294071fda53d7804183b3"
|
||||
integrity sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.8.tgz#9d15b1e94e1c7f6344f65a8d573597d93c6cd886"
|
||||
integrity sha512-+6zsde91jMzzvkzuEA3k63zCw+tm/GvuuabkpisgbDMTPQsIMHllE3XczJFFtEHLjjhKQFZmGQVRdELetlWpVw==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.14.5"
|
||||
"@babel/helper-module-imports" "^7.15.4"
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
babel-plugin-polyfill-corejs2 "^0.2.2"
|
||||
babel-plugin-polyfill-corejs3 "^0.2.2"
|
||||
babel-plugin-polyfill-corejs3 "^0.2.5"
|
||||
babel-plugin-polyfill-regenerator "^0.2.2"
|
||||
semver "^6.3.0"
|
||||
|
||||
@@ -784,13 +784,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
|
||||
"@babel/plugin-transform-spread@^7.14.6":
|
||||
version "7.14.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz#6bd40e57fe7de94aa904851963b5616652f73144"
|
||||
integrity sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==
|
||||
"@babel/plugin-transform-spread@^7.15.8":
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.15.8.tgz#79d5aa27f68d700449b2da07691dfa32d2f6d468"
|
||||
integrity sha512-/daZ8s2tNaRekl9YJa9X4bzjpeRZLt122cpgFnQPLGUe61PH8zMEBmYqKkW5xF5JUEh5buEGXJoQpqBmIbpmEQ==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.14.5"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.15.4"
|
||||
|
||||
"@babel/plugin-transform-sticky-regex@^7.14.5":
|
||||
version "7.14.5"
|
||||
@@ -814,9 +814,9 @@
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
|
||||
"@babel/plugin-transform-typescript@^7.15.0":
|
||||
version "7.15.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.4.tgz#db7a062dcf8be5fc096bc0eeb40a13fbfa1fa251"
|
||||
integrity sha512-sM1/FEjwYjXvMwu1PJStH11kJ154zd/lpY56NQJ5qH2D0mabMv1CAy/kdvS9RP4Xgfj9fBBA3JiSLdDHgXdzOA==
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.8.tgz#ff0e6a47de9b2d58652123ab5a879b2ff20665d8"
|
||||
integrity sha512-ZXIkJpbaf6/EsmjeTbiJN/yMxWPFWvlr7sEG1P95Xb4S4IBcrf2n7s/fItIhsAmOf8oSh3VJPDppO6ExfAfKRQ==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.15.4"
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
@@ -846,16 +846,16 @@
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/preset-env@^7.12.11":
|
||||
version "7.15.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.6.tgz#0f3898db9d63d320f21b17380d8462779de57659"
|
||||
integrity sha512-L+6jcGn7EWu7zqaO2uoTDjjMBW+88FXzV8KvrBl2z6MtRNxlsmUNRlZPaNNPUTgqhyC5DHNFk/2Jmra+ublZWw==
|
||||
version "7.15.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.8.tgz#f527ce5bcb121cd199f6b502bf23e420b3ff8dba"
|
||||
integrity sha512-rCC0wH8husJgY4FPbHsiYyiLxSY8oMDJH7Rl6RQMknbN9oDDHhM9RDFvnGM2MgkbUJzSQB4gtuwygY5mCqGSsA==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.15.0"
|
||||
"@babel/helper-compilation-targets" "^7.15.4"
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
"@babel/helper-validator-option" "^7.14.5"
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.15.4"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.15.4"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.15.8"
|
||||
"@babel/plugin-proposal-class-properties" "^7.14.5"
|
||||
"@babel/plugin-proposal-class-static-block" "^7.15.4"
|
||||
"@babel/plugin-proposal-dynamic-import" "^7.14.5"
|
||||
@@ -910,7 +910,7 @@
|
||||
"@babel/plugin-transform-regenerator" "^7.14.5"
|
||||
"@babel/plugin-transform-reserved-words" "^7.14.5"
|
||||
"@babel/plugin-transform-shorthand-properties" "^7.14.5"
|
||||
"@babel/plugin-transform-spread" "^7.14.6"
|
||||
"@babel/plugin-transform-spread" "^7.15.8"
|
||||
"@babel/plugin-transform-sticky-regex" "^7.14.5"
|
||||
"@babel/plugin-transform-template-literals" "^7.14.5"
|
||||
"@babel/plugin-transform-typeof-symbol" "^7.14.5"
|
||||
@@ -919,7 +919,7 @@
|
||||
"@babel/preset-modules" "^0.1.4"
|
||||
"@babel/types" "^7.15.6"
|
||||
babel-plugin-polyfill-corejs2 "^0.2.2"
|
||||
babel-plugin-polyfill-corejs3 "^0.2.2"
|
||||
babel-plugin-polyfill-corejs3 "^0.2.5"
|
||||
babel-plugin-polyfill-regenerator "^0.2.2"
|
||||
core-js-compat "^3.16.0"
|
||||
semver "^6.3.0"
|
||||
@@ -1210,9 +1210,9 @@
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@matrix-org/olm@https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz":
|
||||
version "3.2.3"
|
||||
resolved "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz#cc332fdd25c08ef0e40f4d33fc3f822a0f98b6f4"
|
||||
"@matrix-org/olm@https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz":
|
||||
version "3.2.8"
|
||||
resolved "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz#8d53636d045e1776e2a2ec6613e57330dd9ce856"
|
||||
|
||||
"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3":
|
||||
version "2.1.8-no-fsevents.3"
|
||||
@@ -1278,29 +1278,29 @@
|
||||
"@octokit/types" "^6.0.3"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/openapi-types@^10.6.4":
|
||||
version "10.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-10.6.4.tgz#c8b5b1f5c60ab7c62858abe2ef57bc709f426a30"
|
||||
integrity sha512-JVmwWzYTIs6jACYOwD6zu5rdrqGIYsiAsLzTCxdrWIPNKNVjEF6vPTL20shmgJ4qZsq7WPBcLXLsaQD+NLChfg==
|
||||
"@octokit/openapi-types@^11.2.0":
|
||||
version "11.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6"
|
||||
integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==
|
||||
|
||||
"@octokit/plugin-paginate-rest@^2.13.3", "@octokit/plugin-paginate-rest@^2.16.4":
|
||||
version "2.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.7.tgz#d25b6e650ba5a007002986f5fda66958d44e70a4"
|
||||
integrity sha512-TMlyVhMPx6La1Ud4PSY4YxqAvb9YPEMs/7R1nBSbsw4wNqG73aBqls0r0dRRCWe5Pm0ZUGS9a94N46iAxlOR8A==
|
||||
"@octokit/plugin-paginate-rest@^2.13.3", "@octokit/plugin-paginate-rest@^2.16.8":
|
||||
version "2.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz#32e9c7cab2a374421d3d0de239102287d791bce7"
|
||||
integrity sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.31.3"
|
||||
"@octokit/types" "^6.34.0"
|
||||
|
||||
"@octokit/plugin-request-log@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
|
||||
integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
|
||||
|
||||
"@octokit/plugin-rest-endpoint-methods@5.11.4", "@octokit/plugin-rest-endpoint-methods@^5.1.1":
|
||||
version "5.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.11.4.tgz#221dedcbdc45d6bfa54228d469e8c34acb4e0e34"
|
||||
integrity sha512-iS+GYTijrPUiEiLoDsGJhrbXIvOPfm2+schvr+FxNMs7PeE9Nl4bAMhE8ftfNX3Z1xLxSKwEZh0O7GbWurX5HQ==
|
||||
"@octokit/plugin-rest-endpoint-methods@^5.1.1", "@octokit/plugin-rest-endpoint-methods@^5.12.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz#8c46109021a3412233f6f50d28786f8e552427ba"
|
||||
integrity sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==
|
||||
dependencies:
|
||||
"@octokit/types" "^6.31.2"
|
||||
"@octokit/types" "^6.34.0"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0":
|
||||
@@ -1325,21 +1325,21 @@
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/rest@^18.6.7":
|
||||
version "18.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.11.4.tgz#9fb6d826244554fbf8c110b9064018d7198eec51"
|
||||
integrity sha512-QplypCyYxqMK05JdMSm/bDWZO8VWWaBdzQ9tbF9rEV9rIEiICh+v6q+Vu/Y5hdze8JJaxfUC+PBC7vrnEkZvZg==
|
||||
version "18.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881"
|
||||
integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==
|
||||
dependencies:
|
||||
"@octokit/core" "^3.5.1"
|
||||
"@octokit/plugin-paginate-rest" "^2.16.4"
|
||||
"@octokit/plugin-paginate-rest" "^2.16.8"
|
||||
"@octokit/plugin-request-log" "^1.0.4"
|
||||
"@octokit/plugin-rest-endpoint-methods" "5.11.4"
|
||||
"@octokit/plugin-rest-endpoint-methods" "^5.12.0"
|
||||
|
||||
"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.31.2", "@octokit/types@^6.31.3":
|
||||
version "6.31.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.31.3.tgz#14c2961baea853b2bf148d892256357a936343f8"
|
||||
integrity sha512-IUG3uMpsLHrtEL6sCVXbxCgnbKcgpkS4K7gVEytLDvYYalkK3XcuMCHK1YPD8xJglSJAOAbL4MgXp47rS9G49w==
|
||||
"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.34.0":
|
||||
version "6.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218"
|
||||
integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^10.6.4"
|
||||
"@octokit/openapi-types" "^11.2.0"
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
version "1.8.3"
|
||||
@@ -1464,14 +1464,14 @@
|
||||
integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
|
||||
|
||||
"@types/node@*":
|
||||
version "16.10.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.2.tgz#5764ca9aa94470adb4e1185fe2e9f19458992b2e"
|
||||
integrity sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ==
|
||||
version "16.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.1.tgz#2e50a649a50fc403433a14f829eface1a3443e97"
|
||||
integrity sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==
|
||||
|
||||
"@types/node@12":
|
||||
version "12.20.27"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.27.tgz#4141fcad57c332a120591de883e26fe4bb14aaea"
|
||||
integrity sha512-qZdePUDSLAZRXXV234bLBEUM0nAQjoxbcSwp1rqSMUe1rZ47mwU6OjciR/JvF1Oo8mc0ys6GE0ks0HGgqAZoGg==
|
||||
version "12.20.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.33.tgz#24927446e8b7669d10abacedd16077359678f436"
|
||||
integrity sha512-5XmYX2GECSa+CxMYaFsr2mrql71Q4EvHjKS+ox/SiwSdaASMoBIWE6UmZqFO+VX1jIcsYLStI4FFoB6V7FeIYw==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.1"
|
||||
@@ -1521,12 +1521,12 @@
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^4.17.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.32.0.tgz#46d2370ae9311092f2a6f7246d28357daf2d4e89"
|
||||
integrity sha512-+OWTuWRSbWI1KDK8iEyG/6uK2rTm3kpS38wuVifGUTDB6kjEuNrzBI1MUtxnkneuWG/23QehABe2zHHrj+4yuA==
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276"
|
||||
integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "4.32.0"
|
||||
"@typescript-eslint/scope-manager" "4.32.0"
|
||||
"@typescript-eslint/experimental-utils" "4.33.0"
|
||||
"@typescript-eslint/scope-manager" "4.33.0"
|
||||
debug "^4.3.1"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
ignore "^5.1.8"
|
||||
@@ -1534,60 +1534,60 @@
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/experimental-utils@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.32.0.tgz#53a8267d16ca5a79134739129871966c56a59dc4"
|
||||
integrity sha512-WLoXcc+cQufxRYjTWr4kFt0DyEv6hDgSaFqYhIzQZ05cF+kXfqXdUh+//kgquPJVUBbL3oQGKQxwPbLxHRqm6A==
|
||||
"@typescript-eslint/experimental-utils@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd"
|
||||
integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.7"
|
||||
"@typescript-eslint/scope-manager" "4.32.0"
|
||||
"@typescript-eslint/types" "4.32.0"
|
||||
"@typescript-eslint/typescript-estree" "4.32.0"
|
||||
"@typescript-eslint/scope-manager" "4.33.0"
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
"@typescript-eslint/typescript-estree" "4.33.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
|
||||
"@typescript-eslint/parser@^4.17.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.32.0.tgz#751ecca0e2fecd3d44484a9b3049ffc1871616e5"
|
||||
integrity sha512-lhtYqQ2iEPV5JqV7K+uOVlPePjClj4dOw7K4/Z1F2yvjIUvyr13yJnDzkK6uon4BjHYuHy3EG0c2Z9jEhFk56w==
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899"
|
||||
integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "4.32.0"
|
||||
"@typescript-eslint/types" "4.32.0"
|
||||
"@typescript-eslint/typescript-estree" "4.32.0"
|
||||
"@typescript-eslint/scope-manager" "4.33.0"
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
"@typescript-eslint/typescript-estree" "4.33.0"
|
||||
debug "^4.3.1"
|
||||
|
||||
"@typescript-eslint/scope-manager@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.32.0.tgz#e03c8668f8b954072b3f944d5b799c0c9225a7d5"
|
||||
integrity sha512-DK+fMSHdM216C0OM/KR1lHXjP1CNtVIhJ54kQxfOE6x8UGFAjha8cXgDMBEIYS2XCYjjCtvTkjQYwL3uvGOo0w==
|
||||
"@typescript-eslint/scope-manager@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3"
|
||||
integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.32.0"
|
||||
"@typescript-eslint/visitor-keys" "4.32.0"
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
"@typescript-eslint/visitor-keys" "4.33.0"
|
||||
|
||||
"@typescript-eslint/types@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.32.0.tgz#52c633c18da47aee09449144bf59565ab36df00d"
|
||||
integrity sha512-LE7Z7BAv0E2UvqzogssGf1x7GPpUalgG07nGCBYb1oK4mFsOiFC/VrSMKbZQzFJdN2JL5XYmsx7C7FX9p9ns0w==
|
||||
"@typescript-eslint/types@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72"
|
||||
integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==
|
||||
|
||||
"@typescript-eslint/typescript-estree@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.32.0.tgz#db00ccc41ccedc8d7367ea3f50c6994b8efa9f3b"
|
||||
integrity sha512-tRYCgJ3g1UjMw1cGG8Yn1KzOzNlQ6u1h9AmEtPhb5V5a1TmiHWcRyF/Ic+91M4f43QeChyYlVTcf3DvDTZR9vw==
|
||||
"@typescript-eslint/typescript-estree@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609"
|
||||
integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.32.0"
|
||||
"@typescript-eslint/visitor-keys" "4.32.0"
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
"@typescript-eslint/visitor-keys" "4.33.0"
|
||||
debug "^4.3.1"
|
||||
globby "^11.0.3"
|
||||
is-glob "^4.0.1"
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.32.0.tgz#455ba8b51242f2722a497ffae29313f33b14cb7f"
|
||||
integrity sha512-e7NE0qz8W+atzv3Cy9qaQ7BTLwWsm084Z0c4nIO2l3Bp6u9WIgdqCgyPyV5oSPDMIW3b20H59OOCmVk3jw3Ptw==
|
||||
"@typescript-eslint/visitor-keys@4.33.0":
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd"
|
||||
integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.32.0"
|
||||
"@typescript-eslint/types" "4.33.0"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
JSONStream@^1.0.3:
|
||||
@@ -1693,10 +1693,10 @@ align-text@^0.1.1, align-text@^0.1.3:
|
||||
longest "^1.0.1"
|
||||
repeat-string "^1.5.2"
|
||||
|
||||
allchange@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/allchange/-/allchange-1.0.3.tgz#f8814ddfbcfe39a01bf4570778ee7e6d9ff0ebb3"
|
||||
integrity sha512-UZkfz5SkNEMFQFLr8vZcXHaph2EbJxmkVNF5Nt6D9RIa5pmAar7oAMfNdda714jg7IQijvaFty5PYazXLgd5WA==
|
||||
allchange@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/allchange/-/allchange-1.0.6.tgz#f905918255541dc92d6a1f5cdf758db4597f569c"
|
||||
integrity sha512-37a4J55oSxhLmlS/DeBOKjKn5dbjkyR4qMJ9is8+CKLPTe7NybcWBYvrPLr9kVLBa6aigWrdovRHrQj/4v6k4w==
|
||||
dependencies:
|
||||
"@actions/core" "^1.4.0"
|
||||
"@actions/github" "^5.0.0"
|
||||
@@ -1724,11 +1724,6 @@ ansi-escapes@^4.2.1:
|
||||
dependencies:
|
||||
type-fest "^0.21.3"
|
||||
|
||||
ansi-regex@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
|
||||
|
||||
ansi-regex@^5.0.0, ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
@@ -1910,14 +1905,14 @@ babel-plugin-dynamic-import-node@^2.3.3:
|
||||
object.assign "^4.1.0"
|
||||
|
||||
babel-plugin-istanbul@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765"
|
||||
integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73"
|
||||
integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@istanbuljs/load-nyc-config" "^1.0.0"
|
||||
"@istanbuljs/schema" "^0.1.2"
|
||||
istanbul-lib-instrument "^4.0.0"
|
||||
istanbul-lib-instrument "^5.0.4"
|
||||
test-exclude "^6.0.0"
|
||||
|
||||
babel-plugin-jest-hoist@^26.6.2:
|
||||
@@ -1939,7 +1934,7 @@ babel-plugin-polyfill-corejs2@^0.2.2:
|
||||
"@babel/helper-define-polyfill-provider" "^0.2.2"
|
||||
semver "^6.1.1"
|
||||
|
||||
babel-plugin-polyfill-corejs3@^0.2.2:
|
||||
babel-plugin-polyfill-corejs3@^0.2.5:
|
||||
version "0.2.5"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92"
|
||||
integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw==
|
||||
@@ -2277,16 +2272,16 @@ browserify@^17.0.0:
|
||||
vm-browserify "^1.0.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
browserslist@^4.16.6, browserslist@^4.17.1:
|
||||
version "4.17.2"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.2.tgz#aa15dbd2fab399a399fe4df601bb09363c5458a6"
|
||||
integrity sha512-jSDZyqJmkKMEMi7SZAgX5UltFdR5NAO43vY0AwTpu4X3sGH7GLLQ83KiUomgrnvZRCeW0yPPnKqnxPqQOER9zQ==
|
||||
browserslist@^4.16.6, browserslist@^4.17.3:
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.4.tgz#72e2508af2a403aec0a49847ef31bd823c57ead4"
|
||||
integrity sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001261"
|
||||
electron-to-chromium "^1.3.854"
|
||||
caniuse-lite "^1.0.30001265"
|
||||
electron-to-chromium "^1.3.867"
|
||||
escalade "^3.1.1"
|
||||
nanocolors "^0.2.12"
|
||||
node-releases "^1.1.76"
|
||||
node-releases "^2.0.0"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
bs58@^4.0.1:
|
||||
version "4.0.1"
|
||||
@@ -2338,15 +2333,15 @@ builtin-status-codes@^3.0.0:
|
||||
integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
|
||||
|
||||
c8@^7.6.0:
|
||||
version "7.9.0"
|
||||
resolved "https://registry.yarnpkg.com/c8/-/c8-7.9.0.tgz#e63b9a22c8b4adbf6a8c8cb6194ee086b3e13c24"
|
||||
integrity sha512-aQ7dC8gASnKdBwHUuYuzsdKCEDrKnWr7ZuZUnf4CNAL81oyKloKrs7H7zYvcrmCtIrMToudBSUhq2q+LLBMvgg==
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/c8/-/c8-7.10.0.tgz#c539ebb15d246b03b0c887165982c49293958a73"
|
||||
integrity sha512-OAwfC5+emvA6R7pkYFVBTOtI5ruf9DahffGmIqUc9l6wEh0h7iAFP6dt/V9Ioqlr2zW5avX9U9/w1I4alTRHkA==
|
||||
dependencies:
|
||||
"@bcoe/v8-coverage" "^0.2.3"
|
||||
"@istanbuljs/schema" "^0.1.2"
|
||||
find-up "^5.0.0"
|
||||
foreground-child "^2.0.0"
|
||||
istanbul-lib-coverage "^3.0.0"
|
||||
istanbul-lib-coverage "^3.0.1"
|
||||
istanbul-lib-report "^3.0.0"
|
||||
istanbul-reports "^3.0.2"
|
||||
rimraf "^3.0.0"
|
||||
@@ -2403,10 +2398,10 @@ camelcase@^6.0.0:
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
|
||||
integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
|
||||
|
||||
caniuse-lite@^1.0.30001261:
|
||||
version "1.0.30001264"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001264.tgz#88f625a60efb6724c7c62ac698bc8dbd9757e55b"
|
||||
integrity sha512-Ftfqqfcs/ePiUmyaySsQ4PUsdcYyXG2rfoBVsk3iY1ahHaJEw65vfb7Suzqm+cEkwwPIv/XWkg27iCpRavH4zA==
|
||||
caniuse-lite@^1.0.30001265:
|
||||
version "1.0.30001269"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001269.tgz#3a71bee03df627364418f9fd31adfc7aa1cc2d56"
|
||||
integrity sha512-UOy8okEVs48MyHYgV+RdW1Oiudl1H6KolybD6ZquD0VcrPSgj25omXO1S7rDydjpqaISCwA8Pyx+jUQKZwWO5w==
|
||||
|
||||
capture-exit@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -2515,15 +2510,14 @@ clean-css@^4.1.11:
|
||||
source-map "~0.6.0"
|
||||
|
||||
cli-color@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.0.tgz#11ecfb58a79278cf6035a60c54e338f9d837897c"
|
||||
integrity sha512-a0VZ8LeraW0jTuCkuAGMNufareGHhyZU9z8OGsW0gXd1hZGi1SRuNRXdbGkraBBKnhyUhyebFWnRbp+dIn0f0A==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.1.tgz#93e3491308691f1e46beb78b63d0fb2585e42ba6"
|
||||
integrity sha512-eBbxZF6fqPUNnf7CLAFOersUnyYzv83tHFLSlts+OAHsNendaqv2tHCq+/MO+b3Y+9JeoUlIvobyxG/Z8GNeOg==
|
||||
dependencies:
|
||||
ansi-regex "^2.1.1"
|
||||
d "^1.0.1"
|
||||
es5-ext "^0.10.51"
|
||||
es5-ext "^0.10.53"
|
||||
es6-iterator "^2.0.3"
|
||||
memoizee "^0.4.14"
|
||||
memoizee "^0.4.15"
|
||||
timers-ext "^0.1.7"
|
||||
|
||||
cliui@^2.1.0:
|
||||
@@ -2709,11 +2703,11 @@ copy-descriptor@^0.1.0:
|
||||
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
||||
|
||||
core-js-compat@^3.16.0, core-js-compat@^3.16.2:
|
||||
version "3.18.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.1.tgz#01942a0877caf9c6e5007c027183cf0bdae6a191"
|
||||
integrity sha512-XJMYx58zo4W0kLPmIingVZA10+7TuKrMLPt83+EzDmxFJQUMcTVVmQ+n5JP4r6Z14qSzhQBRi3NSWoeVyKKXUg==
|
||||
version "3.18.3"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.3.tgz#e0e7e87abc55efb547e7fa19169e45fa9df27a67"
|
||||
integrity sha512-4zP6/y0a2RTHN5bRGT7PTq9lVt3WzvffTNjqnTKsXhkAYNDTkdCLOIfAdOLcQ/7TDdyRj3c+NeHe1NmF1eDScw==
|
||||
dependencies:
|
||||
browserslist "^4.17.1"
|
||||
browserslist "^4.17.3"
|
||||
semver "7.0.0"
|
||||
|
||||
core-js@^2.4.0, core-js@^2.5.3, core-js@^2.6.5:
|
||||
@@ -2722,9 +2716,9 @@ core-js@^2.4.0, core-js@^2.5.3, core-js@^2.6.5:
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-js@^3.14.0:
|
||||
version "3.18.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.1.tgz#289d4be2ce0085d40fc1244c0b1a54c00454622f"
|
||||
integrity sha512-vJlUi/7YdlCZeL6fXvWNaLUPh/id12WXj3MbkMw5uOyF0PfWPBNOCNbs53YqgrvtujLNlt9JQpruyIKkUZ+PKA==
|
||||
version "3.18.3"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.3.tgz#86a0bba2d8ec3df860fefcc07a8d119779f01509"
|
||||
integrity sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw==
|
||||
|
||||
core-util-is@1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -3055,10 +3049,10 @@ ecc-jsbn@~0.1.1:
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
electron-to-chromium@^1.3.854:
|
||||
version "1.3.857"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.857.tgz#dcc239ff8a12b6e4b501e6a5ad20fd0d5a3210f9"
|
||||
integrity sha512-a5kIr2lajm4bJ5E4D3fp8Y/BRB0Dx2VOcCRE5Gtb679mXIME/OFhWler8Gy2ksrf8gFX+EFCSIGA33FB3gqYpg==
|
||||
electron-to-chromium@^1.3.867:
|
||||
version "1.3.872"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.872.tgz#2311a82f344d828bab6904818adc4afb57b35369"
|
||||
integrity sha512-qG96atLFY0agKyEETiBFNhpRLSXGSXOBuhXWpbkYqrLKKASpRyRBUtfkn0ZjIf/yXfA7FA4nScVOMpXSHFlUCQ==
|
||||
|
||||
elliptic@^6.5.3:
|
||||
version "6.5.4"
|
||||
@@ -3158,7 +3152,7 @@ es-to-primitive@^1.2.1:
|
||||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.51, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
|
||||
es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
|
||||
version "0.10.53"
|
||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
|
||||
integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
|
||||
@@ -3521,12 +3515,11 @@ extsprintf@^1.2.0:
|
||||
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||
|
||||
fake-indexeddb@^3.1.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-3.1.3.tgz#76d59146a6b994b9bb50ac9949cbd96ad6cca760"
|
||||
integrity sha512-kpWYPIUGmxW8Q7xG7ampGL63fU/kYNukrIyy9KFj3+KVlFbE/SmvWebzWXBiCMeR0cPK6ufDoGC7MFkPhPLH9w==
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-3.1.4.tgz#39644c3fb4b64e28fca64a6ccf18f265827e18e7"
|
||||
integrity sha512-kweAGUKgo/NLHZpyMcgYk2ihDrWQcpzwZ3Y2Ag6/Wo3h8F/ts0onw0nTEth8YjWzzBY+sxSSKFn69vc7xcK0Qg==
|
||||
dependencies:
|
||||
realistic-structured-clone "^2.0.1"
|
||||
setimmediate "^1.0.5"
|
||||
|
||||
fast-deep-equal@^3.1.1:
|
||||
version "3.1.3"
|
||||
@@ -4199,9 +4192,9 @@ is-ci@^2.0.0:
|
||||
ci-info "^2.0.0"
|
||||
|
||||
is-core-module@^2.2.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3"
|
||||
integrity sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
|
||||
integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
@@ -4302,9 +4295,11 @@ is-extglob@^2.1.1:
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-finalizationregistry@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.1.tgz#4c8a8d4a72c49ea4b0f7e4f82203373abd4b8e38"
|
||||
integrity sha512-7ljq3NfRoVd2mwe9CvvU6Io1ZtdLf8x9MUMYC6vATTKTciKVS6c0ZOAHf2YAD9woY7afIhv+rchAYXxkCn0ubg==
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6"
|
||||
integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
@@ -4505,12 +4500,12 @@ isstream@~0.1.2:
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||
|
||||
istanbul-lib-coverage@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz#e8900b3ed6069759229cf30f7067388d148aeb5e"
|
||||
integrity sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ==
|
||||
istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.1:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3"
|
||||
integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==
|
||||
|
||||
istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3:
|
||||
istanbul-lib-instrument@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d"
|
||||
integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==
|
||||
@@ -4520,6 +4515,17 @@ istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3:
|
||||
istanbul-lib-coverage "^3.0.0"
|
||||
semver "^6.3.0"
|
||||
|
||||
istanbul-lib-instrument@^5.0.4:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.0.4.tgz#e976f2aa66ebc6737f236d3ab05b76e36f885c80"
|
||||
integrity sha512-W6jJF9rLGEISGoCyXRqa/JCGQGmmxPO10TMu7izaUTynxvBvTjqzAIIGCK9USBmIbQAaSWD6XJPrM9Pv5INknw==
|
||||
dependencies:
|
||||
"@babel/core" "^7.12.3"
|
||||
"@babel/parser" "^7.14.7"
|
||||
"@istanbuljs/schema" "^0.1.2"
|
||||
istanbul-lib-coverage "^3.0.0"
|
||||
semver "^6.3.0"
|
||||
|
||||
istanbul-lib-report@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6"
|
||||
@@ -4530,18 +4536,18 @@ istanbul-lib-report@^3.0.0:
|
||||
supports-color "^7.1.0"
|
||||
|
||||
istanbul-lib-source-maps@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9"
|
||||
integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551"
|
||||
integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
istanbul-lib-coverage "^3.0.0"
|
||||
source-map "^0.6.1"
|
||||
|
||||
istanbul-reports@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b"
|
||||
integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.5.tgz#a2580107e71279ea6d661ddede929ffc6d693384"
|
||||
integrity sha512-5+19PlhnGabNWB7kOFnuxT8H3T/iIyQzIbQMxXsURmmvKg86P2sbkrGOT77VnHw0Qr0gc2XzRaRfMZYYbSQCJQ==
|
||||
dependencies:
|
||||
html-escaper "^2.0.0"
|
||||
istanbul-lib-report "^3.0.0"
|
||||
@@ -5351,7 +5357,7 @@ mdurl@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
|
||||
|
||||
memoizee@^0.4.14:
|
||||
memoizee@^0.4.15:
|
||||
version "0.4.15"
|
||||
resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72"
|
||||
integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==
|
||||
@@ -5523,11 +5529,6 @@ ms@2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
nanocolors@^0.2.12:
|
||||
version "0.2.12"
|
||||
resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.2.12.tgz#4d05932e70116078673ea4cc6699a1c56cc77777"
|
||||
integrity sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug==
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||
@@ -5606,10 +5607,10 @@ node-notifier@^8.0.0:
|
||||
uuid "^8.3.0"
|
||||
which "^2.0.2"
|
||||
|
||||
node-releases@^1.1.76:
|
||||
version "1.1.77"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e"
|
||||
integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==
|
||||
node-releases@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.0.tgz#67dc74903100a7deb044037b8a2e5f453bb05400"
|
||||
integrity sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA==
|
||||
|
||||
normalize-package-data@^2.5.0:
|
||||
version "2.5.0"
|
||||
@@ -5948,6 +5949,11 @@ performance-now@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||
@@ -6037,9 +6043,9 @@ promise@^7.0.1:
|
||||
asap "~2.0.3"
|
||||
|
||||
prompts@^2.0.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61"
|
||||
integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
|
||||
integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
|
||||
dependencies:
|
||||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.5"
|
||||
@@ -6682,11 +6688,6 @@ set-value@^2.0.0, set-value@^2.0.1:
|
||||
is-plain-object "^2.0.3"
|
||||
split-string "^3.0.1"
|
||||
|
||||
setimmediate@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
|
||||
|
||||
sha.js@^2.4.0, sha.js@^2.4.8:
|
||||
version "2.4.11"
|
||||
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
|
||||
@@ -7396,9 +7397,9 @@ typescript@^3.2.2:
|
||||
integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
|
||||
|
||||
typescript@^4.1.3:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
|
||||
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
|
||||
version "4.4.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c"
|
||||
integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==
|
||||
|
||||
typeson-registry@^1.0.0-alpha.20:
|
||||
version "1.0.0-alpha.39"
|
||||
|
||||
Reference in New Issue
Block a user