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)
|
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)
|
[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",
|
"name": "matrix-js-sdk",
|
||||||
"version": "10.1.0",
|
"version": "11.0.0",
|
||||||
"description": "Matrix Client-Server SDK for Javascript",
|
"description": "Matrix Client-Server SDK for Javascript",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepublishOnly": "yarn build",
|
"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) {
|
if (decrypt) {
|
||||||
event.attemptDecryption(client._crypto);
|
client.decryptEventIfNeeded(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!preventReEmit) {
|
if (!preventReEmit) {
|
||||||
@@ -5612,6 +5612,26 @@ MatrixClient.prototype.generateClientSecret = function() {
|
|||||||
return randomString(32);
|
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
|
// MatrixClient Event JSDocs
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3322,7 +3322,10 @@ Crypto.prototype._onToDeviceEvent = function(event) {
|
|||||||
this._onKeyVerificationMessage(event);
|
this._onKeyVerificationMessage(event);
|
||||||
} else if (event.getContent().msgtype === "m.bad.encrypted") {
|
} else if (event.getContent().msgtype === "m.bad.encrypted") {
|
||||||
this._onToDeviceBadEncrypted(event);
|
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
|
// once the event has been decrypted, try again
|
||||||
event.once('Event.decrypted', (ev) => {
|
event.once('Event.decrypted', (ev) => {
|
||||||
this._onToDeviceEvent(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 the event is currently encrypted, wait until it has been decrypted.
|
||||||
if (event.isBeingDecrypted()) {
|
if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {
|
||||||
event.once("Event.decrypted", () => {
|
event.once("Event.decrypted", () => {
|
||||||
this.aggregateRelations(event);
|
this.aggregateRelations(event);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,11 +41,13 @@ export class Relations extends EventEmitter {
|
|||||||
super();
|
super();
|
||||||
this.relationType = relationType;
|
this.relationType = relationType;
|
||||||
this.eventType = eventType;
|
this.eventType = eventType;
|
||||||
|
this._relationEventIds = new Set();
|
||||||
this._relations = new Set();
|
this._relations = new Set();
|
||||||
this._annotationsByKey = {};
|
this._annotationsByKey = {};
|
||||||
this._annotationsBySender = {};
|
this._annotationsBySender = {};
|
||||||
this._sortedAnnotationsByKey = [];
|
this._sortedAnnotationsByKey = [];
|
||||||
this._targetEvent = null;
|
this._targetEvent = null;
|
||||||
|
this._room = room;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,8 +56,8 @@ export class Relations extends EventEmitter {
|
|||||||
* @param {MatrixEvent} event
|
* @param {MatrixEvent} event
|
||||||
* The new relation event to be added.
|
* The new relation event to be added.
|
||||||
*/
|
*/
|
||||||
addEvent(event) {
|
async addEvent(event) {
|
||||||
if (this._relations.has(event)) {
|
if (this._relationEventIds.has(event.getId())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,11 +82,13 @@ export class Relations extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._relations.add(event);
|
this._relations.add(event);
|
||||||
|
this._relationEventIds.add(event.getId());
|
||||||
|
|
||||||
if (this.relationType === "m.annotation") {
|
if (this.relationType === "m.annotation") {
|
||||||
this._addAnnotationToAggregation(event);
|
this._addAnnotationToAggregation(event);
|
||||||
} else if (this.relationType === "m.replace" && this._targetEvent) {
|
} 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);
|
event.on("Event.beforeRedaction", this._onBeforeRedaction);
|
||||||
@@ -98,7 +102,7 @@ export class Relations extends EventEmitter {
|
|||||||
* @param {MatrixEvent} event
|
* @param {MatrixEvent} event
|
||||||
* The relation event to remove.
|
* The relation event to remove.
|
||||||
*/
|
*/
|
||||||
_removeEvent(event) {
|
async _removeEvent(event) {
|
||||||
if (!this._relations.has(event)) {
|
if (!this._relations.has(event)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -122,7 +126,8 @@ export class Relations extends EventEmitter {
|
|||||||
if (this.relationType === "m.annotation") {
|
if (this.relationType === "m.annotation") {
|
||||||
this._removeAnnotationFromAggregation(event);
|
this._removeAnnotationFromAggregation(event);
|
||||||
} else if (this.relationType === "m.replace" && this._targetEvent) {
|
} 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);
|
this.emit("Relations.remove", event);
|
||||||
@@ -227,7 +232,7 @@ export class Relations extends EventEmitter {
|
|||||||
* @param {MatrixEvent} redactedEvent
|
* @param {MatrixEvent} redactedEvent
|
||||||
* The original relation event that is about to be redacted.
|
* The original relation event that is about to be redacted.
|
||||||
*/
|
*/
|
||||||
_onBeforeRedaction = (redactedEvent) => {
|
_onBeforeRedaction = async (redactedEvent) => {
|
||||||
if (!this._relations.has(redactedEvent)) {
|
if (!this._relations.has(redactedEvent)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -238,7 +243,8 @@ export class Relations extends EventEmitter {
|
|||||||
// Remove the redacted annotation from aggregation by key
|
// Remove the redacted annotation from aggregation by key
|
||||||
this._removeAnnotationFromAggregation(redactedEvent);
|
this._removeAnnotationFromAggregation(redactedEvent);
|
||||||
} else if (this.relationType === "m.replace" && this._targetEvent) {
|
} 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);
|
redactedEvent.removeListener("Event.beforeRedaction", this._onBeforeRedaction);
|
||||||
@@ -291,7 +297,7 @@ export class Relations extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @return {MatrixEvent?}
|
* @return {MatrixEvent?}
|
||||||
*/
|
*/
|
||||||
getLastReplacement() {
|
async getLastReplacement() {
|
||||||
if (this.relationType !== "m.replace") {
|
if (this.relationType !== "m.replace") {
|
||||||
// Aggregating on last only makes sense for this relation type
|
// Aggregating on last only makes sense for this relation type
|
||||||
return null;
|
return null;
|
||||||
@@ -309,7 +315,7 @@ export class Relations extends EventEmitter {
|
|||||||
this._targetEvent.getServerAggregatedRelation("m.replace");
|
this._targetEvent.getServerAggregatedRelation("m.replace");
|
||||||
const minTs = replaceRelation && replaceRelation.origin_server_ts;
|
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()) {
|
if (event.getSender() !== this._targetEvent.getSender()) {
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
@@ -321,18 +327,26 @@ export class Relations extends EventEmitter {
|
|||||||
}
|
}
|
||||||
return event;
|
return event;
|
||||||
}, null);
|
}, 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.
|
* @param {MatrixEvent} targetEvent the event the relations are related to.
|
||||||
*/
|
*/
|
||||||
setTargetEvent(event) {
|
async setTargetEvent(event) {
|
||||||
if (this._targetEvent) {
|
if (this._targetEvent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._targetEvent = event;
|
this._targetEvent = event;
|
||||||
if (this.relationType === "m.replace") {
|
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
|
// this is the initial update, so only call it if we already have something
|
||||||
// to not emit Event.replaced needlessly
|
// to not emit Event.replaced needlessly
|
||||||
if (replacement) {
|
if (replacement) {
|
||||||
|
|||||||
Reference in New Issue
Block a user