You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-26 17:03:12 +03:00
Merge branch 'develop' into feed
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
module.exports = {
|
||||
extends: ["matrix-org"],
|
||||
plugins: [
|
||||
"babel",
|
||||
"matrix-org",
|
||||
],
|
||||
extends: ["plugin:matrix-org/javascript"],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
},
|
||||
|
||||
rules: {
|
||||
"no-var": ["warn"],
|
||||
"prefer-rest-params": ["warn"],
|
||||
@@ -33,7 +32,7 @@ module.exports = {
|
||||
},
|
||||
overrides: [{
|
||||
"files": ["src/**/*.ts"],
|
||||
"extends": ["matrix-org/ts"],
|
||||
"extends": ["plugin:matrix-org/typescript"],
|
||||
"rules": {
|
||||
// We're okay being explicit at the moment
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
|
||||
25
CHANGELOG.md
25
CHANGELOG.md
@@ -1,3 +1,28 @@
|
||||
Changes in [9.11.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.11.0) (2021-04-12)
|
||||
==================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.11.0-rc.1...v9.11.0)
|
||||
|
||||
* No changes since rc.1
|
||||
|
||||
Changes in [9.11.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.11.0-rc.1) (2021-04-07)
|
||||
============================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.10.0...v9.11.0-rc.1)
|
||||
|
||||
* Only try to cache private keys we know exist
|
||||
[\#1657](https://github.com/matrix-org/matrix-js-sdk/pull/1657)
|
||||
* Properly terminate screen-share calls if NoUserMedia
|
||||
[\#1654](https://github.com/matrix-org/matrix-js-sdk/pull/1654)
|
||||
* Attended transfer
|
||||
[\#1652](https://github.com/matrix-org/matrix-js-sdk/pull/1652)
|
||||
* Remove catch handlers in private key retrieval
|
||||
[\#1653](https://github.com/matrix-org/matrix-js-sdk/pull/1653)
|
||||
* Fixed the media fail error on caller's side
|
||||
[\#1651](https://github.com/matrix-org/matrix-js-sdk/pull/1651)
|
||||
* Add function to share megolm keys for historical messages, take 2
|
||||
[\#1640](https://github.com/matrix-org/matrix-js-sdk/pull/1640)
|
||||
* Cache cross-signing private keys if needed on bootstrap
|
||||
[\#1649](https://github.com/matrix-org/matrix-js-sdk/pull/1649)
|
||||
|
||||
Changes in [9.10.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.10.0) (2021-03-29)
|
||||
==================================================================================================
|
||||
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.10.0-rc.1...v9.10.0)
|
||||
|
||||
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "matrix-js-sdk",
|
||||
"version": "9.10.0",
|
||||
"version": "9.11.0",
|
||||
"description": "Matrix Client-Server SDK for Javascript",
|
||||
"scripts": {
|
||||
"prepublishOnly": "yarn build",
|
||||
@@ -61,6 +61,8 @@
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.12.10",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/eslint-parser": "^7.12.10",
|
||||
"@babel/eslint-plugin": "^7.12.10",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.12.7",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
|
||||
@@ -72,15 +74,16 @@
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "12",
|
||||
"@types/request": "^2.48.5",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||
"@typescript-eslint/parser": "^4.17.0",
|
||||
"babel-jest": "^26.6.3",
|
||||
"babelify": "^10.0.0",
|
||||
"better-docs": "^2.3.2",
|
||||
"browserify": "^17.0.0",
|
||||
"docdash": "^1.2.0",
|
||||
"eslint": "7.18.0",
|
||||
"eslint-config-matrix-org": "^0.2.0",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main",
|
||||
"exorcist": "^1.0.1",
|
||||
"fake-indexeddb": "^3.1.2",
|
||||
"jest": "^26.6.3",
|
||||
|
||||
@@ -30,7 +30,7 @@ export async function makeTestClients(userInfos, options) {
|
||||
for (const [deviceId, msg] of Object.entries(devMap)) {
|
||||
if (deviceId in clientMap[userId]) {
|
||||
const event = new MatrixEvent({
|
||||
sender: this.getUserId(), // eslint-disable-line babel/no-invalid-this
|
||||
sender: this.getUserId(), // eslint-disable-line @babel/no-invalid-this
|
||||
type: type,
|
||||
content: msg,
|
||||
});
|
||||
@@ -49,9 +49,9 @@ export async function makeTestClients(userInfos, options) {
|
||||
};
|
||||
const sendEvent = function(room, type, content) {
|
||||
// make up a unique ID as the event ID
|
||||
const eventId = "$" + this.makeTxnId(); // eslint-disable-line babel/no-invalid-this
|
||||
const eventId = "$" + this.makeTxnId(); // eslint-disable-line @babel/no-invalid-this
|
||||
const rawEvent = {
|
||||
sender: this.getUserId(), // eslint-disable-line babel/no-invalid-this
|
||||
sender: this.getUserId(), // eslint-disable-line @babel/no-invalid-this
|
||||
type: type,
|
||||
content: content,
|
||||
room_id: room,
|
||||
@@ -61,13 +61,13 @@ export async function makeTestClients(userInfos, options) {
|
||||
const event = new MatrixEvent(rawEvent);
|
||||
const remoteEcho = new MatrixEvent(Object.assign({}, rawEvent, {
|
||||
unsigned: {
|
||||
transaction_id: this.makeTxnId(), // eslint-disable-line babel/no-invalid-this
|
||||
transaction_id: this.makeTxnId(), // eslint-disable-line @babel/no-invalid-this
|
||||
},
|
||||
}));
|
||||
|
||||
setImmediate(() => {
|
||||
for (const tc of clients) {
|
||||
if (tc.client === this) { // eslint-disable-line babel/no-invalid-this
|
||||
if (tc.client === this) { // eslint-disable-line @babel/no-invalid-this
|
||||
logger.log("sending remote echo!!");
|
||||
tc.client.emit("Room.timeline", remoteEcho);
|
||||
} else {
|
||||
|
||||
@@ -46,8 +46,8 @@ describe("realtime-callbacks", function() {
|
||||
it("should set 'this' to the global object", function() {
|
||||
let passed = false;
|
||||
const callback = function() {
|
||||
expect(this).toBe(global); // eslint-disable-line babel/no-invalid-this
|
||||
expect(this.console).toBeTruthy(); // eslint-disable-line babel/no-invalid-this
|
||||
expect(this).toBe(global); // eslint-disable-line @babel/no-invalid-this
|
||||
expect(this.console).toBeTruthy(); // eslint-disable-line @babel/no-invalid-this
|
||||
passed = true;
|
||||
};
|
||||
callbacks.setTimeout(callback);
|
||||
|
||||
@@ -3,6 +3,7 @@ import {EventStatus, MatrixEvent} from "../../src/models/event";
|
||||
import {EventTimeline} from "../../src/models/event-timeline";
|
||||
import {RoomState} from "../../src/models/room-state";
|
||||
import {Room} from "../../src/models/room";
|
||||
import {TestClient} from "../TestClient";
|
||||
|
||||
describe("Room", function() {
|
||||
const roomId = "!foo:bar";
|
||||
@@ -1176,7 +1177,10 @@ describe("Room", function() {
|
||||
describe("addPendingEvent", function() {
|
||||
it("should add pending events to the pendingEventList if " +
|
||||
"pendingEventOrdering == 'detached'", function() {
|
||||
const room = new Room(roomId, null, userA, {
|
||||
const client = (new TestClient(
|
||||
"@alice:example.com", "alicedevice",
|
||||
)).client;
|
||||
const room = new Room(roomId, client, userA, {
|
||||
pendingEventOrdering: "detached",
|
||||
});
|
||||
const eventA = utils.mkMessage({
|
||||
@@ -1226,7 +1230,10 @@ describe("Room", function() {
|
||||
|
||||
describe("updatePendingEvent", function() {
|
||||
it("should remove cancelled events from the pending list", function() {
|
||||
const room = new Room(roomId, null, userA, {
|
||||
const client = (new TestClient(
|
||||
"@alice:example.com", "alicedevice",
|
||||
)).client;
|
||||
const room = new Room(roomId, client, userA, {
|
||||
pendingEventOrdering: "detached",
|
||||
});
|
||||
const eventA = utils.mkMessage({
|
||||
|
||||
@@ -57,6 +57,7 @@ export enum EventType {
|
||||
KeyVerificationStart = "m.key.verification.start",
|
||||
KeyVerificationCancel = "m.key.verification.cancel",
|
||||
KeyVerificationMac = "m.key.verification.mac",
|
||||
KeyVerificationDone = "m.key.verification.done",
|
||||
// use of this is discouraged https://matrix.org/docs/spec/client_server/r0.6.1#m-room-message-feedback
|
||||
RoomMessageFeedback = "m.room.message.feedback",
|
||||
|
||||
|
||||
@@ -36,11 +36,11 @@ const DEFAULT_NAMESPACE = "matrix";
|
||||
// when logging so we always get the current value of console methods.
|
||||
log.methodFactory = function(methodName, logLevel, loggerName) {
|
||||
return function(...args) {
|
||||
/* eslint-disable babel/no-invalid-this */
|
||||
/* eslint-disable @babel/no-invalid-this */
|
||||
if (this.prefix) {
|
||||
args.unshift(this.prefix);
|
||||
}
|
||||
/* eslint-enable babel/no-invalid-this */
|
||||
/* eslint-enable @babel/no-invalid-this */
|
||||
const supportedByConsole = methodName === "error" ||
|
||||
methodName === "warn" ||
|
||||
methodName === "trace" ||
|
||||
|
||||
@@ -168,7 +168,7 @@ export const MatrixEvent = function(
|
||||
/* The txnId with which this event was sent if it was during this session,
|
||||
allows for a unique ID which does not change when the event comes back down sync.
|
||||
*/
|
||||
this._txnId = null;
|
||||
this._txnId = event.txn_id || null;
|
||||
|
||||
/* Set an approximate timestamp for the event relative the local clock.
|
||||
* This will inherently be approximate because it doesn't take into account
|
||||
|
||||
@@ -123,6 +123,8 @@ export function Room(roomId, client, myUserId, opts) {
|
||||
opts = opts || {};
|
||||
opts.pendingEventOrdering = opts.pendingEventOrdering || "chronological";
|
||||
|
||||
this._client = client;
|
||||
|
||||
// In some cases, we add listeners for every displayed Matrix event, so it's
|
||||
// common to have quite a few more than the default limit.
|
||||
this.setMaxListeners(100);
|
||||
@@ -189,6 +191,18 @@ export function Room(roomId, client, myUserId, opts) {
|
||||
|
||||
if (this._opts.pendingEventOrdering == "detached") {
|
||||
this._pendingEventList = [];
|
||||
const serializedPendingEventList = client._sessionStore.store.getItem(pendingEventsKey(this.roomId));
|
||||
if (serializedPendingEventList) {
|
||||
JSON.parse(serializedPendingEventList)
|
||||
.forEach(async serializedEvent => {
|
||||
const event = new MatrixEvent(serializedEvent);
|
||||
if (event.getType() === "m.room.encrypted") {
|
||||
await event.attemptDecryption(this._client._crypto);
|
||||
}
|
||||
event.setStatus(EventStatus.NOT_SENT);
|
||||
this.addPendingEvent(event, event.getTxnId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// read by megolm; boolean value - null indicates "use global value"
|
||||
@@ -197,7 +211,6 @@ export function Room(roomId, client, myUserId, opts) {
|
||||
this._summaryHeroes = null;
|
||||
// awaited by getEncryptionTargetMembers while room members are loading
|
||||
|
||||
this._client = client;
|
||||
if (!this._opts.lazyLoadMembers) {
|
||||
this._membersPromise = Promise.resolve();
|
||||
} else {
|
||||
@@ -205,6 +218,14 @@ export function Room(roomId, client, myUserId, opts) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId ID of the current room
|
||||
* @returns {string} Storage key to retrieve pending events
|
||||
*/
|
||||
function pendingEventsKey(roomId) {
|
||||
return `mx_pending_events_${roomId}`;
|
||||
}
|
||||
|
||||
utils.inherits(Room, EventEmitter);
|
||||
|
||||
/**
|
||||
@@ -357,6 +378,31 @@ Room.prototype.getPendingEvents = function() {
|
||||
return this._pendingEventList;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a pending event for this room
|
||||
*
|
||||
* @param {string} eventId
|
||||
* @return {boolean} True if an element was removed.
|
||||
*/
|
||||
Room.prototype.removePendingEvent = function(eventId) {
|
||||
if (this._opts.pendingEventOrdering !== "detached") {
|
||||
throw new Error(
|
||||
"Cannot call removePendingEvent with pendingEventOrdering == " +
|
||||
this._opts.pendingEventOrdering);
|
||||
}
|
||||
|
||||
const removed = utils.removeElement(
|
||||
this._pendingEventList,
|
||||
function(ev) {
|
||||
return ev.getId() == eventId;
|
||||
}, false,
|
||||
);
|
||||
|
||||
this._savePendingEvents();
|
||||
|
||||
return removed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether the pending event list contains a given event by ID.
|
||||
* If pending event ordering is not "detached" then this returns false.
|
||||
@@ -1192,7 +1238,7 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy, fromCache) {
|
||||
* unique transaction id.
|
||||
*/
|
||||
Room.prototype.addPendingEvent = function(event, txnId) {
|
||||
if (event.status !== EventStatus.SENDING) {
|
||||
if (event.status !== EventStatus.SENDING && event.status !== EventStatus.NOT_SENT) {
|
||||
throw new Error("addPendingEvent called on an event with status " +
|
||||
event.status);
|
||||
}
|
||||
@@ -1219,7 +1265,7 @@ Room.prototype.addPendingEvent = function(event, txnId) {
|
||||
event.setStatus(EventStatus.NOT_SENT);
|
||||
}
|
||||
this._pendingEventList.push(event);
|
||||
|
||||
this._savePendingEvents();
|
||||
if (event.isRelation()) {
|
||||
// For pending events, add them to the relations collection immediately.
|
||||
// (The alternate case below already covers this as part of adding to
|
||||
@@ -1256,6 +1302,46 @@ Room.prototype.addPendingEvent = function(event, txnId) {
|
||||
|
||||
this.emit("Room.localEchoUpdated", event, this, null, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Persists all pending events to local storage
|
||||
*
|
||||
* If the current room is encrypted only encrypted events will be persisted
|
||||
* all messages that are not yet encrypted will be discarded
|
||||
*
|
||||
* This is because the flow of EVENT_STATUS transition is
|
||||
* queued => sending => encrypting => sending => sent
|
||||
*
|
||||
* Steps 3 and 4 are skipped for unencrypted room.
|
||||
* It is better to discard an unencrypted message rather than persisting
|
||||
* it locally for everyone to read
|
||||
*/
|
||||
Room.prototype._savePendingEvents = function() {
|
||||
if (this._pendingEventList) {
|
||||
const pendingEvents = this._pendingEventList.map(event => {
|
||||
return {
|
||||
...event.event,
|
||||
txn_id: event.getTxnId(),
|
||||
};
|
||||
}).filter(event => {
|
||||
// Filter out the unencrypted messages if the room is encrypted
|
||||
const isEventEncrypted = event.type === "m.room.encrypted";
|
||||
const isRoomEncrypted = this._client.isRoomEncrypted(this.roomId);
|
||||
return isEventEncrypted || !isRoomEncrypted;
|
||||
});
|
||||
|
||||
const { store } = this._client._sessionStore;
|
||||
if (this._pendingEventList.length > 0) {
|
||||
store.setItem(
|
||||
pendingEventsKey(this.roomId),
|
||||
JSON.stringify(pendingEvents),
|
||||
);
|
||||
} else {
|
||||
store.removeItem(pendingEventsKey(this.roomId));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to aggregate the local echo for a relation, and also
|
||||
* for re-applying a relation after it's redaction has been cancelled,
|
||||
@@ -1310,12 +1396,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) {
|
||||
|
||||
// if it's in the pending list, remove it
|
||||
if (this._pendingEventList) {
|
||||
utils.removeElement(
|
||||
this._pendingEventList,
|
||||
function(ev) {
|
||||
return ev.getId() == oldEventId;
|
||||
}, false,
|
||||
);
|
||||
this.removePendingEvent(oldEventId);
|
||||
}
|
||||
|
||||
// replace the event source (this will preserve the plaintext payload if
|
||||
@@ -1434,6 +1515,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
|
||||
}
|
||||
this.removeEvent(oldEventId);
|
||||
}
|
||||
this._savePendingEvents();
|
||||
|
||||
this.emit("Room.localEchoUpdated", event, this, oldEventId, oldStatus);
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable babel/no-invalid-this */
|
||||
/* eslint-disable @babel/no-invalid-this */
|
||||
|
||||
import {MemoryStore} from "./memory";
|
||||
import * as utils from "../utils";
|
||||
|
||||
@@ -476,7 +476,7 @@ SyncApi.prototype.sync = function() {
|
||||
|
||||
this._running = true;
|
||||
|
||||
if (global.window) {
|
||||
if (global.window && global.window.addEventListener) {
|
||||
this._onOnlineBound = this._onOnline.bind(this);
|
||||
global.window.addEventListener("online", this._onOnlineBound, false);
|
||||
}
|
||||
|
||||
@@ -216,9 +216,9 @@ export function getDesktopCapturerSources(): Promise<Array<DesktopCapturerSource
|
||||
}
|
||||
|
||||
export class CallError extends Error {
|
||||
code : string;
|
||||
code: string;
|
||||
|
||||
constructor(code : CallErrorCode, msg: string, err: Error) {
|
||||
constructor(code: CallErrorCode, msg: string, err: Error) {
|
||||
// Stil ldon't think there's any way to have proper nested errors
|
||||
super(msg + ": " + err);
|
||||
|
||||
@@ -1104,7 +1104,7 @@ export class MatrixCall extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
private callHasEnded() : boolean {
|
||||
private callHasEnded(): boolean {
|
||||
// This exists as workaround to typescript trying to be clever and erroring
|
||||
// when putting if (this.state === CallState.Ended) return; twice in the same
|
||||
// function, even though that function is async.
|
||||
|
||||
Reference in New Issue
Block a user