1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-25 05:23:13 +03:00

Merge branch 'develop' into gsouquet/fix-call-handlers

This commit is contained in:
Germain Souquet
2021-05-19 16:51:29 +01:00
7 changed files with 156 additions and 15 deletions

View File

@@ -1,3 +1,34 @@
Changes in [11.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.0.0) (2021-05-17)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v11.0.0-rc.1...v11.0.0)
* [Release] Fix regressed glare
[\#1695](https://github.com/matrix-org/matrix-js-sdk/pull/1695)
Changes in [11.0.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.0.0-rc.1) (2021-05-11)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v10.1.0...v11.0.0-rc.1)
BREAKING CHANGES
---
* `MatrixCall` and related APIs have been redesigned to support multiple streams
(see [\#1660](https://github.com/matrix-org/matrix-js-sdk/pull/1660) for more details)
All changes
---
* Switch from MSC1772 unstable prefixes to stable
[\#1679](https://github.com/matrix-org/matrix-js-sdk/pull/1679)
* Update the VoIP example to work with the new changes
[\#1680](https://github.com/matrix-org/matrix-js-sdk/pull/1680)
* Bump hosted-git-info from 2.8.8 to 2.8.9
[\#1687](https://github.com/matrix-org/matrix-js-sdk/pull/1687)
* Support for multiple streams (not MSC3077)
[\#1660](https://github.com/matrix-org/matrix-js-sdk/pull/1660)
* Tweak missing m.room.create errors to describe their source
[\#1683](https://github.com/matrix-org/matrix-js-sdk/pull/1683)
Changes in [10.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v10.1.0) (2021-05-10)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v10.1.0-rc.1...v10.1.0)

View File

@@ -1,6 +1,6 @@
{
"name": "matrix-js-sdk",
"version": "10.1.0",
"version": "11.0.0",
"description": "Matrix Client-Server SDK for Javascript",
"scripts": {
"prepublishOnly": "yarn build",

View File

@@ -0,0 +1,73 @@
/*
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 { MatrixEvent } from "../../src/models/event";
import { Relations } from "../../src/models/relations";
describe("Relations", function() {
it("should deduplicate annotations", function() {
const relations = new Relations("m.annotation", "m.reaction");
// Create an instance of an annotation
const eventData = {
"sender": "@bob:example.com",
"type": "m.reaction",
"event_id": "$cZ1biX33ENJqIm00ks0W_hgiO_6CHrsAc3ZQrnLeNTw",
"room_id": "!pzVjCQSoQPpXQeHpmK:example.com",
"content": {
"m.relates_to": {
"event_id": "$2s4yYpEkVQrPglSCSqB_m6E8vDhWsg0yFNyOJdVIb_o",
"key": "👍️",
"rel_type": "m.annotation",
},
},
};
const eventA = new MatrixEvent(eventData);
// Add the event once and check results
{
relations.addEvent(eventA);
const annotationsByKey = relations.getSortedAnnotationsByKey();
expect(annotationsByKey.length).toEqual(1);
const [key, events] = annotationsByKey[0];
expect(key).toEqual("👍️");
expect(events.size).toEqual(1);
}
// Add the event again and expect the same
{
relations.addEvent(eventA);
const annotationsByKey = relations.getSortedAnnotationsByKey();
expect(annotationsByKey.length).toEqual(1);
const [key, events] = annotationsByKey[0];
expect(key).toEqual("👍️");
expect(events.size).toEqual(1);
}
// Create a fresh object with the same event content
const eventB = new MatrixEvent(eventData);
// Add the event again and expect the same
{
relations.addEvent(eventB);
const annotationsByKey = relations.getSortedAnnotationsByKey();
expect(annotationsByKey.length).toEqual(1);
const [key, events] = annotationsByKey[0];
expect(key).toEqual("👍️");
expect(events.size).toEqual(1);
}
});
});

View File

@@ -5570,7 +5570,7 @@ function _PojoToMatrixEventMapper(client, options = {}) {
]);
}
if (decrypt) {
event.attemptDecryption(client._crypto);
client.decryptEventIfNeeded(event);
}
}
if (!preventReEmit) {
@@ -5612,6 +5612,26 @@ MatrixClient.prototype.generateClientSecret = function() {
return randomString(32);
};
/**
* Attempts to decrypt an event
* @param {MatrixEvent} event The event to decrypt
* @returns {Promise<void>} A decryption promise
* @param {object} options
* @param {bool} options.isRetry True if this is a retry (enables more logging)
* @param {bool} options.emit Emits "event.decrypted" if set to true
*/
MatrixClient.prototype.decryptEventIfNeeded = function(event, options) {
if (event.shouldAttemptDecryption()) {
event.attemptDecryption(this._crypto, options);
}
if (event.isBeingDecrypted()) {
return event._decryptionPromise;
} else {
return Promise.resolve();
}
};
// MatrixClient Event JSDocs
/**

View File

@@ -3322,7 +3322,10 @@ Crypto.prototype._onToDeviceEvent = function(event) {
this._onKeyVerificationMessage(event);
} else if (event.getContent().msgtype === "m.bad.encrypted") {
this._onToDeviceBadEncrypted(event);
} else if (event.isBeingDecrypted()) {
} else if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {
if (!event.isBeingDecrypted()) {
event.attemptDecryption(this);
}
// once the event has been decrypted, try again
event.once('Event.decrypted', (ev) => {
this._onToDeviceEvent(ev);

View File

@@ -769,7 +769,7 @@ EventTimelineSet.prototype.aggregateRelations = function(event) {
}
// If the event is currently encrypted, wait until it has been decrypted.
if (event.isBeingDecrypted()) {
if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {
event.once("Event.decrypted", () => {
this.aggregateRelations(event);
});

View File

@@ -41,11 +41,13 @@ export class Relations extends EventEmitter {
super();
this.relationType = relationType;
this.eventType = eventType;
this._relationEventIds = new Set();
this._relations = new Set();
this._annotationsByKey = {};
this._annotationsBySender = {};
this._sortedAnnotationsByKey = [];
this._targetEvent = null;
this._room = room;
}
/**
@@ -54,8 +56,8 @@ export class Relations extends EventEmitter {
* @param {MatrixEvent} event
* The new relation event to be added.
*/
addEvent(event) {
if (this._relations.has(event)) {
async addEvent(event) {
if (this._relationEventIds.has(event.getId())) {
return;
}
@@ -80,11 +82,13 @@ export class Relations extends EventEmitter {
}
this._relations.add(event);
this._relationEventIds.add(event.getId());
if (this.relationType === "m.annotation") {
this._addAnnotationToAggregation(event);
} else if (this.relationType === "m.replace" && this._targetEvent) {
this._targetEvent.makeReplaced(this.getLastReplacement());
const lastReplacement = await this.getLastReplacement();
this._targetEvent.makeReplaced(lastReplacement);
}
event.on("Event.beforeRedaction", this._onBeforeRedaction);
@@ -98,7 +102,7 @@ export class Relations extends EventEmitter {
* @param {MatrixEvent} event
* The relation event to remove.
*/
_removeEvent(event) {
async _removeEvent(event) {
if (!this._relations.has(event)) {
return;
}
@@ -122,7 +126,8 @@ export class Relations extends EventEmitter {
if (this.relationType === "m.annotation") {
this._removeAnnotationFromAggregation(event);
} else if (this.relationType === "m.replace" && this._targetEvent) {
this._targetEvent.makeReplaced(this.getLastReplacement());
const lastReplacement = await this.getLastReplacement();
this._targetEvent.makeReplaced(lastReplacement);
}
this.emit("Relations.remove", event);
@@ -227,7 +232,7 @@ export class Relations extends EventEmitter {
* @param {MatrixEvent} redactedEvent
* The original relation event that is about to be redacted.
*/
_onBeforeRedaction = (redactedEvent) => {
_onBeforeRedaction = async (redactedEvent) => {
if (!this._relations.has(redactedEvent)) {
return;
}
@@ -238,7 +243,8 @@ export class Relations extends EventEmitter {
// Remove the redacted annotation from aggregation by key
this._removeAnnotationFromAggregation(redactedEvent);
} else if (this.relationType === "m.replace" && this._targetEvent) {
this._targetEvent.makeReplaced(this.getLastReplacement());
const lastReplacement = await this.getLastReplacement();
this._targetEvent.makeReplaced(lastReplacement);
}
redactedEvent.removeListener("Event.beforeRedaction", this._onBeforeRedaction);
@@ -291,7 +297,7 @@ export class Relations extends EventEmitter {
*
* @return {MatrixEvent?}
*/
getLastReplacement() {
async getLastReplacement() {
if (this.relationType !== "m.replace") {
// Aggregating on last only makes sense for this relation type
return null;
@@ -309,7 +315,7 @@ export class Relations extends EventEmitter {
this._targetEvent.getServerAggregatedRelation("m.replace");
const minTs = replaceRelation && replaceRelation.origin_server_ts;
return this.getRelations().reduce((last, event) => {
const lastReplacement = this.getRelations().reduce((last, event) => {
if (event.getSender() !== this._targetEvent.getSender()) {
return last;
}
@@ -321,18 +327,26 @@ export class Relations extends EventEmitter {
}
return event;
}, null);
if (lastReplacement?.shouldAttemptDecryption()) {
await lastReplacement.attemptDecryption(this._room._client._crypto);
} else if (lastReplacement?.isBeingDecrypted()) {
await lastReplacement._decryptionPromise;
}
return lastReplacement;
}
/*
* @param {MatrixEvent} targetEvent the event the relations are related to.
*/
setTargetEvent(event) {
async setTargetEvent(event) {
if (this._targetEvent) {
return;
}
this._targetEvent = event;
if (this.relationType === "m.replace") {
const replacement = this.getLastReplacement();
const replacement = await this.getLastReplacement();
// this is the initial update, so only call it if we already have something
// to not emit Event.replaced needlessly
if (replacement) {