You've already forked matrix-js-sdk
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:
31
CHANGELOG.md
31
CHANGELOG.md
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
73
spec/unit/relations.spec.ts
Normal file
73
spec/unit/relations.spec.ts
Normal 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);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user